5050#define _countof (a ) (sizeof (a) / sizeof (*(a)))
5151
5252// If it is GCC, there is no UUID support and we must emulate it.
53- #ifdef __APPLE__
54- #define __EMULATE_UUID 1
55- #else // __APPLE__
56- #ifdef __GNUC__
5753#ifndef __clang__
5854#define __EMULATE_UUID 1
59- #endif // __GNUC__
6055#endif // __clang__
61- #endif // __APPLE__
6256
6357#ifdef __EMULATE_UUID
6458#define __declspec (x )
@@ -452,15 +446,14 @@ typedef GUID CLSID;
452446typedef const GUID &REFGUID;
453447typedef const GUID &REFCLSID;
454448
455- #ifdef __EMULATE_UUID
456- typedef const void *REFIID;
457- #define IsEqualIID (a, b ) a == b
458- #define IsEqualCLSID (a, b ) !memcmp(&a, &b, sizeof (GUID))
459- #else // __EMULATE_UUID
460449typedef GUID IID;
461450typedef IID *LPIID;
462451typedef const IID &REFIID;
463452inline bool IsEqualGUID (REFGUID rguid1, REFGUID rguid2) {
453+ // Optimization:
454+ if (&rguid1 == &rguid2)
455+ return true ;
456+
464457 return !memcmp (&rguid1, &rguid2, sizeof (GUID));
465458}
466459
@@ -479,7 +472,6 @@ inline bool IsEqualIID(REFIID riid1, REFIID riid2) {
479472inline bool IsEqualCLSID (REFCLSID rclsid1, REFCLSID rclsid2) {
480473 return IsEqualGUID (rclsid1, rclsid2);
481474}
482- #endif // __EMULATE_UUID
483475
484476// ===--------------------- Struct Types -----------------------------------===//
485477
@@ -559,27 +551,63 @@ enum tagSTATFLAG {
559551
560552#ifdef __EMULATE_UUID
561553
562- size_t UuidStrHash (const char * k);
563-
564554// The following macros are defined to facilitate the lack of 'uuid' on Linux.
565- #define DECLARE_CROSS_PLATFORM_UUIDOF (T ) \
566- public: \
567- static REFIID uuidof () { return reinterpret_cast <REFIID>(T##_ID); } \
568- \
569- private: \
570- __attribute__ ((visibility(" default" ))) static const size_t T##_ID;
571-
572- #define DEFINE_CROSS_PLATFORM_UUIDOF (T ) \
573- __attribute__ ((visibility(" default" ))) const size_t T::T##_ID = \
574- UuidStrHash (#T);
575- #define __uuidof (T ) T::uuidof()
555+
556+ constexpr uint8_t nybble_from_hex (char c) {
557+ return ((c >= ' 0' && c <= ' 9' )
558+ ? (c - ' 0' )
559+ : ((c >= ' a' && c <= ' f' )
560+ ? (c - ' a' + 10 )
561+ : ((c >= ' A' && c <= ' F' ) ? (c - ' A' + 10 )
562+ : /* Should be an error */ -1 )));
563+ }
564+
565+ constexpr uint8_t byte_from_hex (char c1, char c2) {
566+ return nybble_from_hex (c1) << 4 | nybble_from_hex (c2);
567+ }
568+
569+ constexpr uint8_t byte_from_hexstr (const char str[2 ]) {
570+ return nybble_from_hex (str[0 ]) << 4 | nybble_from_hex (str[1 ]);
571+ }
572+
573+ constexpr GUID guid_from_string (const char str[37 ]) {
574+ return GUID{static_cast <uint32_t >(byte_from_hexstr (str)) << 24 |
575+ static_cast <uint32_t >(byte_from_hexstr (str + 2 )) << 16 |
576+ static_cast <uint32_t >(byte_from_hexstr (str + 4 )) << 8 |
577+ byte_from_hexstr (str + 6 ),
578+ static_cast <uint16_t >(
579+ static_cast <uint16_t >(byte_from_hexstr (str + 9 )) << 8 |
580+ byte_from_hexstr (str + 11 )),
581+ static_cast <uint16_t >(
582+ static_cast <uint16_t >(byte_from_hexstr (str + 14 )) << 8 |
583+ byte_from_hexstr (str + 16 )),
584+ {byte_from_hexstr (str + 19 ), byte_from_hexstr (str + 21 ),
585+ byte_from_hexstr (str + 24 ), byte_from_hexstr (str + 26 ),
586+ byte_from_hexstr (str + 28 ), byte_from_hexstr (str + 30 ),
587+ byte_from_hexstr (str + 32 ), byte_from_hexstr (str + 34 )}};
588+ }
589+
590+ template <typename interface> inline GUID __emulated_uuidof ();
591+
592+ #define CROSS_PLATFORM_UUIDOF (interface, spec ) \
593+ struct interface ; \
594+ template <> inline GUID __emulated_uuidof<interface>() { \
595+ static const IID _IID = guid_from_string (spec); \
596+ return _IID; \
597+ }
598+
599+ #define __uuidof (T ) __emulated_uuidof<typename std::decay<T>::type>()
600+
576601#define IID_PPV_ARGS (ppType ) \
577- ( **(ppType)).uuidof( ), reinterpret_cast <void **>(ppType)
602+ __uuidof ( decltype ( **(ppType))), reinterpret_cast<void **>(ppType)
578603
579604#else // __EMULATE_UUID
580605
581- #define DECLARE_CROSS_PLATFORM_UUIDOF (T )
582- #define DEFINE_CROSS_PLATFORM_UUIDOF (T )
606+ #ifndef CROSS_PLATFORM_UUIDOF
607+ // Warning: This macro exists in dxcapi.h as well
608+ #define CROSS_PLATFORM_UUIDOF (interface, spec ) \
609+ struct __declspec (uuid(spec)) interface;
610+ #endif
583611
584612template <typename T> inline void **IID_PPV_ARGS_Helper (T **pp) {
585613 return reinterpret_cast <void **>(pp);
@@ -590,8 +618,9 @@ template <typename T> inline void **IID_PPV_ARGS_Helper(T **pp) {
590618
591619// ===--------------------- COM Interfaces ---------------------------------===//
592620
593- struct __declspec (uuid(" 00000000-0000-0000-C000-000000000046" )) IUnknown {
594- IUnknown () : m_count (0 ){};
621+ CROSS_PLATFORM_UUIDOF (IUnknown, " 00000000-0000-0000-C000-000000000046" )
622+ struct IUnknown {
623+ IUnknown () : m_count (0 ) {};
595624 virtual HRESULT QueryInterface (REFIID riid, void **ppvObject) = 0 ;
596625 virtual ULONG AddRef ();
597626 virtual ULONG Release ();
@@ -602,33 +631,27 @@ struct __declspec(uuid("00000000-0000-0000-C000-000000000046")) IUnknown {
602631
603632private:
604633 std::atomic<unsigned long > m_count;
605-
606- DECLARE_CROSS_PLATFORM_UUIDOF (IUnknown)
607634};
608635
609- struct __declspec (uuid(" ECC8691B-C1DB-4DC0-855E-65F6C551AF49" )) INoMarshal
610- : public IUnknown {
611- DECLARE_CROSS_PLATFORM_UUIDOF (INoMarshal)
612- };
636+ CROSS_PLATFORM_UUIDOF (INoMarshal, " ECC8691B-C1DB-4DC0-855E-65F6C551AF49" )
637+ struct INoMarshal : public IUnknown {};
613638
614- struct __declspec (uuid( " 00000002-0000-0000-C000-000000000046" )) IMalloc
615- : public IUnknown {
639+ CROSS_PLATFORM_UUIDOF (IMalloc, " 00000002-0000-0000-C000-000000000046" )
640+ struct IMalloc : public IUnknown {
616641 virtual void *Alloc (size_t size);
617642 virtual void *Realloc (void *ptr, size_t size);
618643 virtual void Free (void *ptr);
619644 virtual HRESULT QueryInterface (REFIID riid, void **ppvObject);
620645};
621646
622- struct __declspec (uuid( " 0C733A30-2A1C-11CE-ADE5-00AA0044773D" ) )
623- ISequentialStream : public IUnknown {
647+ CROSS_PLATFORM_UUIDOF (ISequentialStream, " 0C733A30-2A1C-11CE-ADE5-00AA0044773D" )
648+ struct ISequentialStream : public IUnknown {
624649 virtual HRESULT Read (void *pv, ULONG cb, ULONG *pcbRead) = 0 ;
625650 virtual HRESULT Write (const void *pv, ULONG cb, ULONG *pcbWritten) = 0 ;
626-
627- DECLARE_CROSS_PLATFORM_UUIDOF (ISequentialStream)
628651};
629652
630- struct __declspec (uuid( " 0000000c-0000-0000-C000-000000000046" )) IStream
631- : public ISequentialStream {
653+ CROSS_PLATFORM_UUIDOF (IStream, " 0000000c-0000-0000-C000-000000000046" )
654+ struct IStream : public ISequentialStream {
632655 virtual HRESULT Seek (LARGE_INTEGER dlibMove, DWORD dwOrigin,
633656 ULARGE_INTEGER *plibNewPosition) = 0 ;
634657 virtual HRESULT SetSize (ULARGE_INTEGER libNewSize) = 0 ;
@@ -649,8 +672,6 @@ struct __declspec(uuid("0000000c-0000-0000-C000-000000000046")) IStream
649672 virtual HRESULT Stat (STATSTG *pstatstg, DWORD grfStatFlag) = 0 ;
650673
651674 virtual HRESULT Clone (IStream **ppstm) = 0 ;
652-
653- DECLARE_CROSS_PLATFORM_UUIDOF (IStream)
654675};
655676
656677// ===--------------------- COM Pointer Types ------------------------------===//
0 commit comments