Add initial bits for Qt6 support
[carla.git] / source / includes / vst3sdk / pluginterfaces / base / funknown.cpp
blob23ca64e6cb424d81d9943d97415dc5d86f4adbe3
1 //-----------------------------------------------------------------------------
2 // Project : SDK Core
3 //
4 // Category : SDK Core Interfaces
5 // Filename : pluginterfaces/base/funknown.cpp
6 // Created by : Steinberg, 01/2004
7 // Description : Basic Interface
8 //
9 //-----------------------------------------------------------------------------
10 // This file is part of a Steinberg SDK. It is subject to the license terms
11 // in the LICENSE file found in the top-level directory of this distribution
12 // and at www.steinberg.net/sdklicenses.
13 // No part of the SDK, including this file, may be copied, modified, propagated,
14 // or distributed except according to the terms contained in the LICENSE file.
15 //-----------------------------------------------------------------------------
17 #include "funknown.h"
19 #include "fstrdefs.h"
21 #include <cstdio>
23 #if SMTG_OS_WINDOWS
24 #include <objbase.h>
25 #endif
27 #if SMTG_OS_MACOS
28 #include <CoreFoundation/CoreFoundation.h>
30 #if !defined (SMTG_USE_STDATOMIC_H)
31 #if defined(MAC_OS_X_VERSION_10_11) && defined(MAC_OS_X_VERSION_MIN_REQUIRED)
32 #define SMTG_USE_STDATOMIC_H (MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_11)
33 #else
34 #define SMTG_USE_STDATOMIC_H 0
35 #endif
36 #endif // !defined (SMTG_USE_STDATOMIC_H)
38 #if !SMTG_USE_STDATOMIC_H
39 #include <libkern/OSAtomic.h>
40 #if defined(__GNUC__) && (__GNUC__ >= 4) && !__LP64__
41 // on 32 bit Mac OS X we can safely ignore the format warnings as sizeof(int) == sizeof(long)
42 #pragma GCC diagnostic ignored "-Wformat"
43 #endif
44 #endif // !SMTG_USE_STDATOMIC_H
45 #endif // SMTG_OS_MACOS
47 #if SMTG_OS_LINUX
48 #if !defined (SMTG_USE_STDATOMIC_H)
49 #if defined (__ANDROID__) || defined(_LIBCPP_VERSION)
50 #define SMTG_USE_STDATOMIC_H 1
51 #else
52 #include <ext/atomicity.h>
53 #endif
54 #endif // !defined (SMTG_USE_STDATOMIC_H)
55 #include <stdlib.h>
56 #endif
58 #if defined (SMTG_USE_STDATOMIC_H) && SMTG_USE_STDATOMIC_H
59 #include <stdatomic.h>
60 #endif
62 namespace Steinberg {
64 //------------------------------------------------------------------------
65 #if COM_COMPATIBLE
66 #if SMTG_OS_WINDOWS
67 #define GuidStruct GUID
68 #else
69 struct GuidStruct
71 uint32 Data1;
72 uint16 Data2;
73 uint16 Data3;
74 uint8 Data4[8];
76 #endif
77 #endif
79 static void toString8 (char8* string, const char* data, int32 i1, int32 i2);
80 static void fromString8 (const char8* string, char* data, int32 i1, int32 i2);
81 static uint32 makeLong (uint8 b1, uint8 b2, uint8 b3, uint8 b4);
83 //------------------------------------------------------------------------
84 // FUnknownPrivate
85 //------------------------------------------------------------------------
86 namespace FUnknownPrivate {
87 //------------------------------------------------------------------------
88 int32 PLUGIN_API atomicAdd (int32& var, int32 d)
90 #if SMTG_USE_STDATOMIC_H
91 return atomic_fetch_add (reinterpret_cast<atomic_int_least32_t*> (&var), d) + d;
92 #else
93 #if SMTG_OS_WINDOWS
94 #ifdef __MINGW32__
95 return InterlockedExchangeAdd (reinterpret_cast<long volatile*>(&var), d) + d;
96 #else
97 return InterlockedExchangeAdd ((LONG*)&var, d) + d;
98 #endif
99 #elif SMTG_OS_MACOS
100 return OSAtomicAdd32Barrier (d, (int32_t*)&var);
101 #elif defined(__ANDROID__)
102 return atomic_fetch_add ((atomic_int*)&var, d) + d;
103 #elif SMTG_OS_LINUX
104 __gnu_cxx::__atomic_add (&var, d);
105 return var;
106 #else
107 #warning implement me!
108 var += d;
109 return var;
110 #endif
111 #endif
113 } // FUnknownPrivate
115 //------------------------------------------------------------------------
116 // FUID implementation
117 //------------------------------------------------------------------------
119 FUID::FUID ()
121 memset (data, 0, sizeof (TUID));
124 //------------------------------------------------------------------------
125 FUID::FUID (uint32 l1, uint32 l2, uint32 l3, uint32 l4)
127 from4Int (l1, l2, l3, l4);
130 //------------------------------------------------------------------------
131 FUID::FUID (const FUID& f)
133 memcpy (data, f.data, sizeof (TUID));
136 //------------------------------------------------------------------------
137 #if SMTG_CPP11_STDLIBSUPPORT
138 FUID::FUID (FUID&& other)
140 memcpy (data, other.data, sizeof (TUID));
143 FUID& FUID::operator= (FUID&& other)
145 memcpy (data, other.data, sizeof (TUID));
146 return *this;
148 #endif
150 //------------------------------------------------------------------------
151 bool FUID::generate ()
153 #if SMTG_OS_WINDOWS
154 #if defined(_M_ARM64) || defined(_M_ARM)
155 //#warning implement me!
156 return false;
157 #else
158 GUID guid;
159 HRESULT hr = CoCreateGuid (&guid);
160 switch (hr)
162 case RPC_S_OK: memcpy (data, (char*)&guid, sizeof (TUID)); return true;
164 case (HRESULT)RPC_S_UUID_LOCAL_ONLY:
165 default: return false;
167 #endif
169 #elif SMTG_OS_MACOS
170 CFUUIDRef uuid = CFUUIDCreate (kCFAllocatorDefault);
171 if (uuid)
173 CFUUIDBytes bytes = CFUUIDGetUUIDBytes (uuid);
174 memcpy (data, (char*)&bytes, sizeof (TUID));
175 CFRelease (uuid);
176 return true;
178 return false;
180 #elif SMTG_OS_LINUX
181 srand ((size_t)this);
182 for (int32 i = 0; i < 16; i++)
183 data[i] = static_cast<unsigned char>(rand ());
184 return true;
185 #else
186 #warning implement me!
187 return false;
188 #endif
191 //------------------------------------------------------------------------
192 bool FUID::isValid () const
194 TUID nulluid = {0};
196 return memcmp (data, nulluid, sizeof (TUID)) != 0;
199 //------------------------------------------------------------------------
200 FUID& FUID::operator= (const FUID& f)
202 memcpy (data, f.data, sizeof (TUID));
203 return *this;
206 //------------------------------------------------------------------------
207 void FUID::from4Int (uint32 l1, uint32 l2, uint32 l3, uint32 l4)
209 #if COM_COMPATIBLE
210 data [0] = (char)((l1 & 0x000000FF) );
211 data [1] = (char)((l1 & 0x0000FF00) >> 8);
212 data [2] = (char)((l1 & 0x00FF0000) >> 16);
213 data [3] = (char)((l1 & 0xFF000000) >> 24);
214 data [4] = (char)((l2 & 0x00FF0000) >> 16);
215 data [5] = (char)((l2 & 0xFF000000) >> 24);
216 data [6] = (char)((l2 & 0x000000FF) );
217 data [7] = (char)((l2 & 0x0000FF00) >> 8);
218 data [8] = (char)((l3 & 0xFF000000) >> 24);
219 data [9] = (char)((l3 & 0x00FF0000) >> 16);
220 data [10] = (char)((l3 & 0x0000FF00) >> 8);
221 data [11] = (char)((l3 & 0x000000FF) );
222 data [12] = (char)((l4 & 0xFF000000) >> 24);
223 data [13] = (char)((l4 & 0x00FF0000) >> 16);
224 data [14] = (char)((l4 & 0x0000FF00) >> 8);
225 data [15] = (char)((l4 & 0x000000FF) );
226 #else
227 data [0] = (char)((l1 & 0xFF000000) >> 24);
228 data [1] = (char)((l1 & 0x00FF0000) >> 16);
229 data [2] = (char)((l1 & 0x0000FF00) >> 8);
230 data [3] = (char)((l1 & 0x000000FF) );
231 data [4] = (char)((l2 & 0xFF000000) >> 24);
232 data [5] = (char)((l2 & 0x00FF0000) >> 16);
233 data [6] = (char)((l2 & 0x0000FF00) >> 8);
234 data [7] = (char)((l2 & 0x000000FF) );
235 data [8] = (char)((l3 & 0xFF000000) >> 24);
236 data [9] = (char)((l3 & 0x00FF0000) >> 16);
237 data [10] = (char)((l3 & 0x0000FF00) >> 8);
238 data [11] = (char)((l3 & 0x000000FF) );
239 data [12] = (char)((l4 & 0xFF000000) >> 24);
240 data [13] = (char)((l4 & 0x00FF0000) >> 16);
241 data [14] = (char)((l4 & 0x0000FF00) >> 8);
242 data [15] = (char)((l4 & 0x000000FF) );
243 #endif
246 //------------------------------------------------------------------------
247 void FUID::to4Int (uint32& d1, uint32& d2, uint32& d3, uint32& d4) const
249 d1 = getLong1 ();
250 d2 = getLong2 ();
251 d3 = getLong3 ();
252 d4 = getLong4 ();
255 //------------------------------------------------------------------------
256 uint32 FUID::getLong1 () const
258 #if COM_COMPATIBLE
259 return makeLong (data[3], data[2], data[1], data[0]);
260 #else
261 return makeLong (data[0], data[1], data[2], data[3]);
262 #endif
265 //------------------------------------------------------------------------
266 uint32 FUID::getLong2 () const
268 #if COM_COMPATIBLE
269 return makeLong (data[5], data[4], data[7], data[6]);
270 #else
271 return makeLong (data[4], data[5], data[6], data[7]);
272 #endif
275 //------------------------------------------------------------------------
276 uint32 FUID::getLong3 () const
278 #if COM_COMPATIBLE
279 return makeLong (data[8], data[9], data[10], data[11]);
280 #else
281 return makeLong (data[8], data[9], data[10], data[11]);
282 #endif
285 //------------------------------------------------------------------------
286 uint32 FUID::getLong4 () const
288 #if COM_COMPATIBLE
289 return makeLong (data[12], data[13], data[14], data[15]);
290 #else
291 return makeLong (data[12], data[13], data[14], data[15]);
292 #endif
295 //------------------------------------------------------------------------
296 void FUID::toString (char8* string) const
298 if (!string)
299 return;
301 #if COM_COMPATIBLE
302 auto* g = (GuidStruct*)data;
304 char8 s[17];
305 Steinberg::toString8 (s, data, 8, 16);
307 sprintf (string, "%08X%04X%04X%s", g->Data1, g->Data2, g->Data3, s);
308 #else
309 Steinberg::toString8 (string, data, 0, 16);
310 #endif
313 //------------------------------------------------------------------------
314 bool FUID::fromString (const char8* string)
316 if (!string || !*string)
317 return false;
318 if (strlen (string) != 32)
319 return false;
321 #if COM_COMPATIBLE
322 GuidStruct g;
323 char s[33];
325 strcpy (s, string);
326 s[8] = 0;
327 sscanf (s, "%x", &g.Data1);
328 strcpy (s, string + 8);
329 s[4] = 0;
330 sscanf (s, "%hx", &g.Data2);
331 strcpy (s, string + 12);
332 s[4] = 0;
333 sscanf (s, "%hx", &g.Data3);
335 memcpy (data, &g, 8);
336 Steinberg::fromString8 (string + 16, data, 8, 16);
337 #else
338 Steinberg::fromString8 (string, data, 0, 16);
339 #endif
341 return true;
344 //------------------------------------------------------------------------
345 bool FUID::fromRegistryString (const char8* string)
347 if (!string || !*string)
348 return false;
349 if (strlen (string) != 38)
350 return false;
352 // e.g. {c200e360-38c5-11ce-ae62-08002b2b79ef}
354 #if COM_COMPATIBLE
355 GuidStruct g;
356 char8 s[10];
358 strncpy (s, string + 1, 8);
359 s[8] = 0;
360 sscanf (s, "%x", &g.Data1);
361 strncpy (s, string + 10, 4);
362 s[4] = 0;
363 sscanf (s, "%hx", &g.Data2);
364 strncpy (s, string + 15, 4);
365 s[4] = 0;
366 sscanf (s, "%hx", &g.Data3);
367 memcpy (data, &g, 8);
369 Steinberg::fromString8 (string + 20, data, 8, 10);
370 Steinberg::fromString8 (string + 25, data, 10, 16);
371 #else
372 Steinberg::fromString8 (string + 1, data, 0, 4);
373 Steinberg::fromString8 (string + 10, data, 4, 6);
374 Steinberg::fromString8 (string + 15, data, 6, 8);
375 Steinberg::fromString8 (string + 20, data, 8, 10);
376 Steinberg::fromString8 (string + 25, data, 10, 16);
377 #endif
379 return true;
382 //------------------------------------------------------------------------
383 void FUID::toRegistryString (char8* string) const
385 // e.g. {c200e360-38c5-11ce-ae62-08002b2b79ef}
387 #if COM_COMPATIBLE
388 auto* g = (GuidStruct*)data;
390 char8 s1[5];
391 Steinberg::toString8 (s1, data, 8, 10);
393 char8 s2[13];
394 Steinberg::toString8 (s2, data, 10, 16);
396 sprintf (string, "{%08X-%04X-%04X-%s-%s}", g->Data1, g->Data2, g->Data3, s1, s2);
397 #else
398 char8 s1[9];
399 Steinberg::toString8 (s1, data, 0, 4);
400 char8 s2[5];
401 Steinberg::toString8 (s2, data, 4, 6);
402 char8 s3[5];
403 Steinberg::toString8 (s3, data, 6, 8);
404 char8 s4[5];
405 Steinberg::toString8 (s4, data, 8, 10);
406 char8 s5[13];
407 Steinberg::toString8 (s5, data, 10, 16);
409 sprintf (string, "{%s-%s-%s-%s-%s}", s1, s2, s3, s4, s5);
410 #endif
413 //------------------------------------------------------------------------
414 void FUID::print (char8* string, int32 style) const
416 if (!string) // no string: debug output
418 char8 str[128];
419 print (str, style);
421 #if SMTG_OS_WINDOWS
422 OutputDebugStringA (str);
423 OutputDebugStringA ("\n");
424 #else
425 fprintf (stdout, "%s\n", str);
426 #endif
427 return;
430 uint32 l1, l2, l3, l4;
431 to4Int (l1, l2, l3, l4);
433 switch (style)
435 case kINLINE_UID:
436 sprintf (string, "INLINE_UID (0x%08X, 0x%08X, 0x%08X, 0x%08X)", l1, l2, l3, l4);
437 break;
439 case kDECLARE_UID:
440 sprintf (string, "DECLARE_UID (0x%08X, 0x%08X, 0x%08X, 0x%08X)", l1, l2, l3, l4);
441 break;
443 case kFUID:
444 sprintf (string, "FUID (0x%08X, 0x%08X, 0x%08X, 0x%08X)", l1, l2, l3, l4);
445 break;
447 case kCLASS_UID:
448 default:
449 sprintf (string, "DECLARE_CLASS_IID (Interface, 0x%08X, 0x%08X, 0x%08X, 0x%08X)", l1,
450 l2, l3, l4);
451 break;
455 //------------------------------------------------------------------------
456 // helpers
457 //------------------------------------------------------------------------
458 static uint32 makeLong (uint8 b1, uint8 b2, uint8 b3, uint8 b4)
460 return (uint32 (b1) << 24) | (uint32 (b2) << 16) | (uint32 (b3) << 8) | uint32 (b4);
463 //------------------------------------------------------------------------
464 static void toString8 (char8* string, const char* data, int32 i1, int32 i2)
466 *string = 0;
467 for (int32 i = i1; i < i2; i++)
469 char8 s[3];
470 sprintf (s, "%02X", (uint8)data[i]);
471 strcat (string, s);
475 //------------------------------------------------------------------------
476 static void fromString8 (const char8* string, char* data, int32 i1, int32 i2)
478 for (int32 i = i1; i < i2; i++)
480 char8 s[3];
481 s[0] = *string++;
482 s[1] = *string++;
483 s[2] = 0;
485 int32 d = 0;
486 sscanf (s, "%2x", &d);
487 data[i] = (char)d;
491 //------------------------------------------------------------------------
492 } // namespace Steinberg