JUCE-7.0.12-0-g4f43011b96 JUCE-7.0.12-0-g4f43011b96
JUCE — C++ application framework with suport for VST, VST3, LV2 audio plug-ins

« « « Anklang Documentation
Loading...
Searching...
No Matches
funknown.cpp
Go to the documentation of this file.
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//-----------------------------------------------------------------------------
16
17#include "funknown.h"
18
19#include "fstrdefs.h"
20
21#include <cstdio>
22
23#if SMTG_OS_WINDOWS
24#include <objbase.h>
25#endif
26
27#if SMTG_OS_MACOS
28#include <CoreFoundation/CoreFoundation.h>
29
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)
37
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
46
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
57
58#if defined (SMTG_USE_STDATOMIC_H) && SMTG_USE_STDATOMIC_H
59#include <stdatomic.h>
60#endif
61
62namespace Steinberg {
63
64//------------------------------------------------------------------------
65#if COM_COMPATIBLE
66#if SMTG_OS_WINDOWS
67#define GuidStruct GUID
68#else
69struct GuidStruct
70{
71 uint32 Data1;
72 uint16 Data2;
73 uint16 Data3;
74 uint8 Data4[8];
75};
76#endif
77#endif
78
79static void toString8 (char8* string, const char* data, int32 i1, int32 i2);
80static void fromString8 (const char8* string, char* data, int32 i1, int32 i2);
81static uint32 makeLong (uint8 b1, uint8 b2, uint8 b3, uint8 b4);
82
83//------------------------------------------------------------------------
84// FUnknownPrivate
85//------------------------------------------------------------------------
86namespace FUnknownPrivate {
87//------------------------------------------------------------------------
88int32 PLUGIN_API atomicAdd (int32& var, int32 d)
89{
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
112}
113} // FUnknownPrivate
114
115//------------------------------------------------------------------------
116// FUID implementation
117//------------------------------------------------------------------------
118
119FUID::FUID ()
120{
121 memset (data, 0, sizeof (TUID));
122}
123
124//------------------------------------------------------------------------
125FUID::FUID (uint32 l1, uint32 l2, uint32 l3, uint32 l4)
126{
127 from4Int (l1, l2, l3, l4);
128}
129
130//------------------------------------------------------------------------
131FUID::FUID (const FUID& f)
132{
133 memcpy (data, f.data, sizeof (TUID));
134}
135
136//------------------------------------------------------------------------
137#if SMTG_CPP11_STDLIBSUPPORT
138FUID::FUID (FUID&& other)
139{
140 memcpy (data, other.data, sizeof (TUID));
141}
142
143FUID& FUID::operator= (FUID&& other)
144{
145 memcpy (data, other.data, sizeof (TUID));
146 return *this;
147}
148#endif
149
150//------------------------------------------------------------------------
152{
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)
161 {
162 case RPC_S_OK: memcpy (data, (char*)&guid, sizeof (TUID)); return true;
163
164 case (HRESULT)RPC_S_UUID_LOCAL_ONLY:
165 default: return false;
166 }
167#endif
168
169#elif SMTG_OS_MACOS
170 CFUUIDRef uuid = CFUUIDCreate (kCFAllocatorDefault);
171 if (uuid)
172 {
173 CFUUIDBytes bytes = CFUUIDGetUUIDBytes (uuid);
174 memcpy (data, (char*)&bytes, sizeof (TUID));
175 CFRelease (uuid);
176 return true;
177 }
178 return false;
179
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
189}
190
191//------------------------------------------------------------------------
192bool FUID::isValid () const
193{
194 TUID nulluid = {0};
195
196 return memcmp (data, nulluid, sizeof (TUID)) != 0;
197}
198
199//------------------------------------------------------------------------
200FUID& FUID::operator= (const FUID& f)
201{
202 memcpy (data, f.data, sizeof (TUID));
203 return *this;
204}
205
206//------------------------------------------------------------------------
207void FUID::from4Int (uint32 l1, uint32 l2, uint32 l3, uint32 l4)
208{
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
244}
245
246//------------------------------------------------------------------------
247void FUID::to4Int (uint32& d1, uint32& d2, uint32& d3, uint32& d4) const
248{
249 d1 = getLong1 ();
250 d2 = getLong2 ();
251 d3 = getLong3 ();
252 d4 = getLong4 ();
253}
254
255//------------------------------------------------------------------------
256uint32 FUID::getLong1 () const
257{
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
263}
264
265//------------------------------------------------------------------------
266uint32 FUID::getLong2 () const
267{
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
273}
274
275//------------------------------------------------------------------------
276uint32 FUID::getLong3 () const
277{
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
283}
284
285//------------------------------------------------------------------------
286uint32 FUID::getLong4 () const
287{
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
293}
294
295//------------------------------------------------------------------------
296void FUID::toString (char8* string) const
297{
298 if (!string)
299 return;
300
301#if COM_COMPATIBLE
302 auto* g = (GuidStruct*)data;
303
304 char8 s[17];
305 Steinberg::toString8 (s, data, 8, 16);
306
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
311}
312
313//------------------------------------------------------------------------
314bool FUID::fromString (const char8* string)
315{
316 if (!string || !*string)
317 return false;
318 if (strlen (string) != 32)
319 return false;
320
321#if COM_COMPATIBLE
322 GuidStruct g;
323 char s[33];
324
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);
334
335 memcpy (data, &g, 8);
336 Steinberg::fromString8 (string + 16, data, 8, 16);
337#else
338 Steinberg::fromString8 (string, data, 0, 16);
339#endif
340
341 return true;
342}
343
344//------------------------------------------------------------------------
345bool FUID::fromRegistryString (const char8* string)
346{
347 if (!string || !*string)
348 return false;
349 if (strlen (string) != 38)
350 return false;
351
352// e.g. {c200e360-38c5-11ce-ae62-08002b2b79ef}
353
354#if COM_COMPATIBLE
355 GuidStruct g;
356 char8 s[10];
357
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);
368
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
378
379 return true;
380}
381
382//------------------------------------------------------------------------
383void FUID::toRegistryString (char8* string) const
384{
385// e.g. {c200e360-38c5-11ce-ae62-08002b2b79ef}
386
387#if COM_COMPATIBLE
388 auto* g = (GuidStruct*)data;
389
390 char8 s1[5];
391 Steinberg::toString8 (s1, data, 8, 10);
392
393 char8 s2[13];
394 Steinberg::toString8 (s2, data, 10, 16);
395
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);
408
409 snprintf (string, 40, "{%s-%s-%s-%s-%s}", s1, s2, s3, s4, s5);
410#endif
411}
412
413//------------------------------------------------------------------------
414void FUID::print (char8* string, int32 style) const
415{
416 print (style, string, 62);
417}
418
419//------------------------------------------------------------------------
420void FUID::print (int32 style, char8* string, size_t stringBufferSize) const
421{
422 if (!string || stringBufferSize == 0) // no string: debug output
423 {
424 char8 str[128];
425 print (style, str, 128);
426
427#if SMTG_OS_WINDOWS
428 OutputDebugStringA (str);
429 OutputDebugStringA ("\n");
430#else
431 fprintf (stdout, "%s\n", str);
432#endif
433 return;
434 }
435
436 uint32 l1, l2, l3, l4;
437 to4Int (l1, l2, l3, l4);
438
439 switch (style)
440 {
441 case kINLINE_UID:
442 snprintf (string, stringBufferSize, "INLINE_UID (0x%08X, 0x%08X, 0x%08X, 0x%08X)", l1,
443 l2, l3, l4);
444 break;
445
446 case kDECLARE_UID:
447 snprintf (string, stringBufferSize, "DECLARE_UID (0x%08X, 0x%08X, 0x%08X, 0x%08X)", l1,
448 l2, l3, l4);
449 break;
450
451 case kFUID:
452 snprintf (string, stringBufferSize, "FUID (0x%08X, 0x%08X, 0x%08X, 0x%08X)", l1, l2, l3,
453 l4);
454 break;
455
456 case kCLASS_UID:
457 default:
458 snprintf (string, stringBufferSize,
459 "DECLARE_CLASS_IID (Interface, 0x%08X, 0x%08X, 0x%08X, 0x%08X)", l1, l2, l3,
460 l4);
461 break;
462 }
463}
464
465//------------------------------------------------------------------------
466// helpers
467//------------------------------------------------------------------------
468static uint32 makeLong (uint8 b1, uint8 b2, uint8 b3, uint8 b4)
469{
470 return (uint32 (b1) << 24) | (uint32 (b2) << 16) | (uint32 (b3) << 8) | uint32 (b4);
471}
472
473//------------------------------------------------------------------------
474static void toString8 (char8* string, const char* data, int32 i1, int32 i2)
475{
476 *string = 0;
477 for (int32 i = i1; i < i2; i++)
478 {
479 char8 s[3];
480 snprintf (s, 3, "%02X", (uint8)data[i]);
481 strcat (string, s);
482 }
483}
484
485//------------------------------------------------------------------------
486static void fromString8 (const char8* string, char* data, int32 i1, int32 i2)
487{
488 for (int32 i = i1; i < i2; i++)
489 {
490 char8 s[3];
491 s[0] = *string++;
492 s[1] = *string++;
493 s[2] = 0;
494
495 int32 d = 0;
496 sscanf (s, "%2x", &d);
497 data[i] = (char)d;
498 }
499}
500
501//------------------------------------------------------------------------
502} // namespace Steinberg
T atomic_fetch_add(T... args)
Handling 16 Byte Globally Unique Identifiers.
Definition funknown.h:241
void toString(char8 *string) const
Converts UID to a string.
Definition funknown.cpp:296
bool fromRegistryString(const char8 *string)
Sets the UID data from a string in Microsoft(R) OLE format.
Definition funknown.cpp:345
bool fromString(const char8 *string)
Sets the UID data from a string.
Definition funknown.cpp:314
bool isValid() const
Checks if the UID data is valid.
Definition funknown.cpp:192
void toRegistryString(char8 *string) const
Converts UID to a string in Microsoft(R) OLE format.
Definition funknown.cpp:383
void print(int32 style, char8 *string=nullptr, size_t stringBufferSize=0) const
Prints the UID to a string (or debug output if string is NULL).
Definition funknown.cpp:420
@ kCLASS_UID
"DECLARE_CLASS_IID (Interface, 0x00000000, 0x00000000, 0x00000000, 0x00000000)"
Definition funknown.h:309
@ kDECLARE_UID
"DECLARE_UID (0x00000000, 0x00000000, 0x00000000, 0x00000000)"
Definition funknown.h:307
@ kINLINE_UID
"INLINE_UID (0x00000000, 0x00000000, 0x00000000, 0x00000000)"
Definition funknown.h:306
@ kFUID
"FUID (0x00000000, 0x00000000, 0x00000000, 0x00000000)"
Definition funknown.h:308
bool generate()
Generates a new Unique Identifier (UID).
Definition funknown.cpp:151
T data(T... args)
sprintf
sscanf
char TUID[16]
plain UID type
Definition funknown.h:209
typedef char
memcmp
memcpy
memset
srand
stdout
strcpy
strncpy
strcat
strlen