1 //-----------------------------------------------------------------------------
4 // Category : SDK Core Interfaces
5 // Filename : pluginterfaces/base/funknown.cpp
6 // Created by : Steinberg, 01/2004
7 // Description : Basic Interface
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 //-----------------------------------------------------------------------------
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)
34 #define SMTG_USE_STDATOMIC_H 0
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"
44 #endif // !SMTG_USE_STDATOMIC_H
45 #endif // SMTG_OS_MACOS
48 #if !defined (SMTG_USE_STDATOMIC_H)
49 #if defined (__ANDROID__) || defined(_LIBCPP_VERSION)
50 #define SMTG_USE_STDATOMIC_H 1
52 #include <ext/atomicity.h>
54 #endif // !defined (SMTG_USE_STDATOMIC_H)
58 #if defined (SMTG_USE_STDATOMIC_H) && SMTG_USE_STDATOMIC_H
59 #include <stdatomic.h>
64 //------------------------------------------------------------------------
67 #define GuidStruct GUID
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 //------------------------------------------------------------------------
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
;
95 return InterlockedExchangeAdd (reinterpret_cast<long volatile*>(&var
), d
) + d
;
97 return InterlockedExchangeAdd ((LONG
*)&var
, d
) + d
;
100 return OSAtomicAdd32Barrier (d
, (int32_t*)&var
);
101 #elif defined(__ANDROID__)
102 return atomic_fetch_add ((atomic_int
*)&var
, d
) + d
;
104 __gnu_cxx::__atomic_add (&var
, d
);
107 #warning implement me!
115 //------------------------------------------------------------------------
116 // FUID implementation
117 //------------------------------------------------------------------------
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
));
150 //------------------------------------------------------------------------
151 bool FUID::generate ()
154 #if defined(_M_ARM64) || defined(_M_ARM)
155 //#warning implement me!
159 HRESULT hr
= CoCreateGuid (&guid
);
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;
170 CFUUIDRef uuid
= CFUUIDCreate (kCFAllocatorDefault
);
173 CFUUIDBytes bytes
= CFUUIDGetUUIDBytes (uuid
);
174 memcpy (data
, (char*)&bytes
, sizeof (TUID
));
181 srand ((size_t)this);
182 for (int32 i
= 0; i
< 16; i
++)
183 data
[i
] = static_cast<unsigned char>(rand ());
186 #warning implement me!
191 //------------------------------------------------------------------------
192 bool FUID::isValid () const
196 return memcmp (data
, nulluid
, sizeof (TUID
)) != 0;
199 //------------------------------------------------------------------------
200 FUID
& FUID::operator= (const FUID
& f
)
202 memcpy (data
, f
.data
, sizeof (TUID
));
206 //------------------------------------------------------------------------
207 void FUID::from4Int (uint32 l1
, uint32 l2
, uint32 l3
, uint32 l4
)
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) );
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) );
246 //------------------------------------------------------------------------
247 void FUID::to4Int (uint32
& d1
, uint32
& d2
, uint32
& d3
, uint32
& d4
) const
255 //------------------------------------------------------------------------
256 uint32
FUID::getLong1 () const
259 return makeLong (data
[3], data
[2], data
[1], data
[0]);
261 return makeLong (data
[0], data
[1], data
[2], data
[3]);
265 //------------------------------------------------------------------------
266 uint32
FUID::getLong2 () const
269 return makeLong (data
[5], data
[4], data
[7], data
[6]);
271 return makeLong (data
[4], data
[5], data
[6], data
[7]);
275 //------------------------------------------------------------------------
276 uint32
FUID::getLong3 () const
279 return makeLong (data
[8], data
[9], data
[10], data
[11]);
281 return makeLong (data
[8], data
[9], data
[10], data
[11]);
285 //------------------------------------------------------------------------
286 uint32
FUID::getLong4 () const
289 return makeLong (data
[12], data
[13], data
[14], data
[15]);
291 return makeLong (data
[12], data
[13], data
[14], data
[15]);
295 //------------------------------------------------------------------------
296 void FUID::toString (char8
* string
) const
302 auto* g
= (GuidStruct
*)data
;
305 Steinberg::toString8 (s
, data
, 8, 16);
307 sprintf (string
, "%08X%04X%04X%s", g
->Data1
, g
->Data2
, g
->Data3
, s
);
309 Steinberg::toString8 (string
, data
, 0, 16);
313 //------------------------------------------------------------------------
314 bool FUID::fromString (const char8
* string
)
316 if (!string
|| !*string
)
318 if (strlen (string
) != 32)
327 sscanf (s
, "%x", &g
.Data1
);
328 strcpy (s
, string
+ 8);
330 sscanf (s
, "%hx", &g
.Data2
);
331 strcpy (s
, string
+ 12);
333 sscanf (s
, "%hx", &g
.Data3
);
335 memcpy (data
, &g
, 8);
336 Steinberg::fromString8 (string
+ 16, data
, 8, 16);
338 Steinberg::fromString8 (string
, data
, 0, 16);
344 //------------------------------------------------------------------------
345 bool FUID::fromRegistryString (const char8
* string
)
347 if (!string
|| !*string
)
349 if (strlen (string
) != 38)
352 // e.g. {c200e360-38c5-11ce-ae62-08002b2b79ef}
358 strncpy (s
, string
+ 1, 8);
360 sscanf (s
, "%x", &g
.Data1
);
361 strncpy (s
, string
+ 10, 4);
363 sscanf (s
, "%hx", &g
.Data2
);
364 strncpy (s
, string
+ 15, 4);
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);
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);
382 //------------------------------------------------------------------------
383 void FUID::toRegistryString (char8
* string
) const
385 // e.g. {c200e360-38c5-11ce-ae62-08002b2b79ef}
388 auto* g
= (GuidStruct
*)data
;
391 Steinberg::toString8 (s1
, data
, 8, 10);
394 Steinberg::toString8 (s2
, data
, 10, 16);
396 sprintf (string
, "{%08X-%04X-%04X-%s-%s}", g
->Data1
, g
->Data2
, g
->Data3
, s1
, s2
);
399 Steinberg::toString8 (s1
, data
, 0, 4);
401 Steinberg::toString8 (s2
, data
, 4, 6);
403 Steinberg::toString8 (s3
, data
, 6, 8);
405 Steinberg::toString8 (s4
, data
, 8, 10);
407 Steinberg::toString8 (s5
, data
, 10, 16);
409 sprintf (string
, "{%s-%s-%s-%s-%s}", s1
, s2
, s3
, s4
, s5
);
413 //------------------------------------------------------------------------
414 void FUID::print (char8
* string
, int32 style
) const
416 if (!string
) // no string: debug output
422 OutputDebugStringA (str
);
423 OutputDebugStringA ("\n");
425 fprintf (stdout
, "%s\n", str
);
430 uint32 l1
, l2
, l3
, l4
;
431 to4Int (l1
, l2
, l3
, l4
);
436 sprintf (string
, "INLINE_UID (0x%08X, 0x%08X, 0x%08X, 0x%08X)", l1
, l2
, l3
, l4
);
440 sprintf (string
, "DECLARE_UID (0x%08X, 0x%08X, 0x%08X, 0x%08X)", l1
, l2
, l3
, l4
);
444 sprintf (string
, "FUID (0x%08X, 0x%08X, 0x%08X, 0x%08X)", l1
, l2
, l3
, l4
);
449 sprintf (string
, "DECLARE_CLASS_IID (Interface, 0x%08X, 0x%08X, 0x%08X, 0x%08X)", l1
,
455 //------------------------------------------------------------------------
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
)
467 for (int32 i
= i1
; i
< i2
; i
++)
470 sprintf (s
, "%02X", (uint8
)data
[i
]);
475 //------------------------------------------------------------------------
476 static void fromString8 (const char8
* string
, char* data
, int32 i1
, int32 i2
)
478 for (int32 i
= i1
; i
< i2
; i
++)
486 sscanf (s
, "%2x", &d
);
491 //------------------------------------------------------------------------
492 } // namespace Steinberg