Fix last commit
[carla.git] / source / includes / vst3sdk / pluginterfaces / base / funknown.h
blobd5a5cfc62fa5effe9e82889b786f035198664952
1 //-----------------------------------------------------------------------------
2 // Project : SDK Core
3 //
4 // Category : SDK Core Interfaces
5 // Filename : pluginterfaces/base/funknown.h
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 #pragma once
19 #include "pluginterfaces/base/fplatform.h"
20 #include "pluginterfaces/base/ftypes.h"
21 #include "pluginterfaces/base/smartpointer.h"
22 #include <cstring>
24 #if SMTG_CPP11_STDLIBSUPPORT
25 #include <type_traits>
26 #endif
28 //------------------------------------------------------------------------
29 /*! \defgroup pluginBase Basic Interfaces
32 //------------------------------------------------------------------------
33 // Unique Identifier macros
34 //------------------------------------------------------------------------
36 #if COM_COMPATIBLE
37 #define INLINE_UID(l1, l2, l3, l4) \
38 { \
39 (::Steinberg::int8)(((::Steinberg::uint32)(l1) & 0x000000FF) ), (::Steinberg::int8)(((::Steinberg::uint32)(l1) & 0x0000FF00) >> 8), \
40 (::Steinberg::int8)(((::Steinberg::uint32)(l1) & 0x00FF0000) >> 16), (::Steinberg::int8)(((::Steinberg::uint32)(l1) & 0xFF000000) >> 24), \
41 (::Steinberg::int8)(((::Steinberg::uint32)(l2) & 0x00FF0000) >> 16), (::Steinberg::int8)(((::Steinberg::uint32)(l2) & 0xFF000000) >> 24), \
42 (::Steinberg::int8)(((::Steinberg::uint32)(l2) & 0x000000FF) ), (::Steinberg::int8)(((::Steinberg::uint32)(l2) & 0x0000FF00) >> 8), \
43 (::Steinberg::int8)(((::Steinberg::uint32)(l3) & 0xFF000000) >> 24), (::Steinberg::int8)(((::Steinberg::uint32)(l3) & 0x00FF0000) >> 16), \
44 (::Steinberg::int8)(((::Steinberg::uint32)(l3) & 0x0000FF00) >> 8), (::Steinberg::int8)(((::Steinberg::uint32)(l3) & 0x000000FF) ), \
45 (::Steinberg::int8)(((::Steinberg::uint32)(l4) & 0xFF000000) >> 24), (::Steinberg::int8)(((::Steinberg::uint32)(l4) & 0x00FF0000) >> 16), \
46 (::Steinberg::int8)(((::Steinberg::uint32)(l4) & 0x0000FF00) >> 8), (::Steinberg::int8)(((::Steinberg::uint32)(l4) & 0x000000FF) ) \
48 #else
49 #define INLINE_UID(l1, l2, l3, l4) \
50 { \
51 (::Steinberg::int8)(((::Steinberg::uint32)(l1) & 0xFF000000) >> 24), (::Steinberg::int8)(((::Steinberg::uint32)(l1) & 0x00FF0000) >> 16), \
52 (::Steinberg::int8)(((::Steinberg::uint32)(l1) & 0x0000FF00) >> 8), (::Steinberg::int8)(((::Steinberg::uint32)(l1) & 0x000000FF) ), \
53 (::Steinberg::int8)(((::Steinberg::uint32)(l2) & 0xFF000000) >> 24), (::Steinberg::int8)(((::Steinberg::uint32)(l2) & 0x00FF0000) >> 16), \
54 (::Steinberg::int8)(((::Steinberg::uint32)(l2) & 0x0000FF00) >> 8), (::Steinberg::int8)(((::Steinberg::uint32)(l2) & 0x000000FF) ), \
55 (::Steinberg::int8)(((::Steinberg::uint32)(l3) & 0xFF000000) >> 24), (::Steinberg::int8)(((::Steinberg::uint32)(l3) & 0x00FF0000) >> 16), \
56 (::Steinberg::int8)(((::Steinberg::uint32)(l3) & 0x0000FF00) >> 8), (::Steinberg::int8)(((::Steinberg::uint32)(l3) & 0x000000FF) ), \
57 (::Steinberg::int8)(((::Steinberg::uint32)(l4) & 0xFF000000) >> 24), (::Steinberg::int8)(((::Steinberg::uint32)(l4) & 0x00FF0000) >> 16), \
58 (::Steinberg::int8)(((::Steinberg::uint32)(l4) & 0x0000FF00) >> 8), (::Steinberg::int8)(((::Steinberg::uint32)(l4) & 0x000000FF) ) \
60 #endif
62 //------------------------------------------------------------------------
63 #define DECLARE_UID(name, l1, l2, l3, l4) ::Steinberg::TUID name = INLINE_UID (l1, l2, l3, l4);
65 //------------------------------------------------------------------------
66 #define EXTERN_UID(name) extern const ::Steinberg::TUID name;
68 #ifdef INIT_CLASS_IID
69 #define DECLARE_CLASS_IID(ClassName, l1, l2, l3, l4) \
70 static const ::Steinberg::TUID ClassName##_iid = INLINE_UID (l1, l2, l3, l4); \
72 const ::Steinberg::FUID ClassName::iid (ClassName##_iid);
73 #else
74 #define DECLARE_CLASS_IID(ClassName, l1, l2, l3, l4) \
75 static const ::Steinberg::TUID ClassName##_iid = INLINE_UID (l1, l2, l3, l4);
76 #endif
78 #define DEF_CLASS_IID(ClassName) const ::Steinberg::FUID ClassName::iid (ClassName##_iid);
80 #define INLINE_UID_OF(ClassName) ClassName##_iid
82 #define INLINE_UID_FROM_FUID(x) \
83 INLINE_UID (x.getLong1 (), x.getLong2 (), x.getLong3 (), x.getLong4 ())
85 //------------------------------------------------------------------------
86 // FUnknown implementation macros
87 //------------------------------------------------------------------------
89 #define DECLARE_FUNKNOWN_METHODS \
90 public: \
91 virtual ::Steinberg::tresult PLUGIN_API queryInterface (const ::Steinberg::TUID _iid, void** obj) SMTG_OVERRIDE; \
92 virtual ::Steinberg::uint32 PLUGIN_API addRef () SMTG_OVERRIDE; \
93 virtual ::Steinberg::uint32 PLUGIN_API release () SMTG_OVERRIDE; \
94 protected : \
95 ::Steinberg::int32 __funknownRefCount; \
96 public:
98 //------------------------------------------------------------------------
100 #define DELEGATE_REFCOUNT(ClassName) \
101 public: \
102 virtual ::Steinberg::uint32 PLUGIN_API addRef () SMTG_OVERRIDE { return ClassName::addRef (); } \
103 virtual ::Steinberg::uint32 PLUGIN_API release () SMTG_OVERRIDE { return ClassName::release (); }
105 //------------------------------------------------------------------------
106 #define IMPLEMENT_REFCOUNT(ClassName) \
107 ::Steinberg::uint32 PLUGIN_API ClassName::addRef () \
109 return ::Steinberg::FUnknownPrivate::atomicAdd (__funknownRefCount, 1); \
111 ::Steinberg::uint32 PLUGIN_API ClassName::release () \
113 if (::Steinberg::FUnknownPrivate::atomicAdd (__funknownRefCount, -1) == 0) \
115 delete this; \
116 return 0; \
118 return __funknownRefCount; \
121 //------------------------------------------------------------------------
122 #define FUNKNOWN_CTOR { __funknownRefCount = 1; }
123 #if SMTG_FUNKNOWN_DTOR_ASSERT
124 #include <cassert>
125 #define FUNKNOWN_DTOR { assert (__funknownRefCount == 0); }
126 #else
127 #define FUNKNOWN_DTOR
128 #endif
130 //------------------------------------------------------------------------
131 #define QUERY_INTERFACE(iid, obj, InterfaceIID, InterfaceName) \
132 if (::Steinberg::FUnknownPrivate::iidEqual (iid, InterfaceIID)) \
134 addRef (); \
135 *obj = static_cast< InterfaceName* >(this); \
136 return ::Steinberg::kResultOk; \
139 //------------------------------------------------------------------------
140 #define IMPLEMENT_QUERYINTERFACE(ClassName, InterfaceName, ClassIID) \
141 ::Steinberg::tresult PLUGIN_API ClassName::queryInterface (const ::Steinberg::TUID _iid, void** obj)\
143 QUERY_INTERFACE (_iid, obj, ::Steinberg::FUnknown::iid, InterfaceName) \
144 QUERY_INTERFACE (_iid, obj, ClassIID, InterfaceName) \
145 *obj = nullptr; \
146 return ::Steinberg::kNoInterface; \
149 //------------------------------------------------------------------------
150 #define IMPLEMENT_FUNKNOWN_METHODS(ClassName,InterfaceName,ClassIID) \
151 IMPLEMENT_REFCOUNT (ClassName) \
152 IMPLEMENT_QUERYINTERFACE (ClassName, InterfaceName, ClassIID)
154 //------------------------------------------------------------------------
155 // Result Codes
156 //------------------------------------------------------------------------
158 namespace Steinberg {
160 //------------------------------------------------------------------------
161 #if COM_COMPATIBLE
162 #if SMTG_OS_WINDOWS
163 enum
165 kNoInterface = static_cast<tresult>(0x80004002L), // E_NOINTERFACE
166 kResultOk = static_cast<tresult>(0x00000000L), // S_OK
167 kResultTrue = kResultOk,
168 kResultFalse = static_cast<tresult>(0x00000001L), // S_FALSE
169 kInvalidArgument = static_cast<tresult>(0x80070057L), // E_INVALIDARG
170 kNotImplemented = static_cast<tresult>(0x80004001L), // E_NOTIMPL
171 kInternalError = static_cast<tresult>(0x80004005L), // E_FAIL
172 kNotInitialized = static_cast<tresult>(0x8000FFFFL), // E_UNEXPECTED
173 kOutOfMemory = static_cast<tresult>(0x8007000EL) // E_OUTOFMEMORY
175 #else
176 enum
178 kNoInterface = static_cast<tresult>(0x80000004L), // E_NOINTERFACE
179 kResultOk = static_cast<tresult>(0x00000000L), // S_OK
180 kResultTrue = kResultOk,
181 kResultFalse = static_cast<tresult>(0x00000001L), // S_FALSE
182 kInvalidArgument = static_cast<tresult>(0x80000003L), // E_INVALIDARG
183 kNotImplemented = static_cast<tresult>(0x80000001L), // E_NOTIMPL
184 kInternalError = static_cast<tresult>(0x80000008L), // E_FAIL
185 kNotInitialized = static_cast<tresult>(0x8000FFFFL), // E_UNEXPECTED
186 kOutOfMemory = static_cast<tresult>(0x80000002L) // E_OUTOFMEMORY
188 #endif
189 #else
190 enum
192 kNoInterface = -1,
193 kResultOk,
194 kResultTrue = kResultOk,
195 kResultFalse,
196 kInvalidArgument,
197 kNotImplemented,
198 kInternalError,
199 kNotInitialized,
200 kOutOfMemory
202 #endif
204 //------------------------------------------------------------------------
205 typedef int64 LARGE_INT; // obsolete
207 //------------------------------------------------------------------------
208 // FUID class declaration
209 //------------------------------------------------------------------------
210 typedef int8 TUID[16]; ///< plain UID type
212 //------------------------------------------------------------------------
213 /* FUnknown private */
214 namespace FUnknownPrivate {
215 SMTG_ALWAYS_INLINE bool iidEqual (const void* iid1, const void* iid2)
217 const uint64* p1 = reinterpret_cast<const uint64*> (iid1);
218 const uint64* p2 = reinterpret_cast<const uint64*> (iid2);
219 return p1[0] == p2[0] && p1[1] == p2[1];
222 int32 PLUGIN_API atomicAdd (int32& value, int32 amount);
225 //------------------------------------------------------------------------
226 /** Handling 16 Byte Globally Unique Identifiers.
227 \ingroup pluginBase
229 Each interface declares its identifier as static member inside the interface
230 namespace (e.g. FUnknown::iid).
232 class FUID
234 public:
235 //------------------------------------------------------------------------
236 FUID ();
237 FUID (uint32 l1, uint32 l2, uint32 l3, uint32 l4);
238 FUID (const FUID&);
239 virtual ~FUID () {}
241 #if SMTG_CPP11_STDLIBSUPPORT
242 FUID (FUID&& other);
243 FUID& operator= (FUID&& other);
244 #endif
246 /** Generates a new Unique Identifier (UID).
247 Will return true for success. If the return value is false, either no
248 UID is generated or the UID is not guaranteed to be unique worldwide. */
249 bool generate ();
251 /** Checks if the UID data is valid.
252 The default constructor initializes the memory with zeros. */
253 bool isValid () const;
255 FUID& operator = (const FUID& f);
256 bool operator == (const FUID& f) const { return ::Steinberg::FUnknownPrivate::iidEqual (data, f.data); }
257 bool operator < (const FUID& f) const { return memcmp (data, f.data, sizeof (TUID)) < 0; }
258 bool operator != (const FUID& f) const { return !::Steinberg::FUnknownPrivate::iidEqual (data, f.data); }
260 uint32 getLong1 () const;
261 uint32 getLong2 () const;
262 uint32 getLong3 () const;
263 uint32 getLong4 () const;
265 void from4Int (uint32 d1, uint32 d2, uint32 d3, uint32 d4);
266 void to4Int (uint32& d1, uint32& d2, uint32& d3, uint32& d4) const;
268 typedef char8 String[33];
270 /** Converts UID to a string.
271 The string will be 32 characters long, representing the hexadecimal values
272 of each data byte (e.g. "9127BE30160E4BB69966670AA6087880").
274 Typical use-case is:
275 \code{.cpp}
276 char8[33] strUID = {0};
277 FUID uid;
278 if (uid.generate ())
279 uid.toString (strUID);
280 \endcode
282 void toString (char8* string) const;
284 /** Sets the UID data from a string.
285 The string has to be 32 characters long, where each character-pair is
286 the ASCII-encoded hexadecimal value of the corresponding data byte. */
287 bool fromString (const char8* string);
289 /** Converts UID to a string in Microsoft(R) OLE format.
290 (e.g. "{c200e360-38c5-11ce-ae62-08002b2b79ef}") */
291 void toRegistryString (char8* string) const;
293 /** Sets the UID data from a string in Microsoft(R) OLE format. */
294 bool fromRegistryString (const char8* string);
296 enum UIDPrintStyle
298 kINLINE_UID, ///< "INLINE_UID (0x00000000, 0x00000000, 0x00000000, 0x00000000)"
299 kDECLARE_UID, ///< "DECLARE_UID (0x00000000, 0x00000000, 0x00000000, 0x00000000)"
300 kFUID, ///< "FUID (0x00000000, 0x00000000, 0x00000000, 0x00000000)"
301 kCLASS_UID ///< "DECLARE_CLASS_IID (Interface, 0x00000000, 0x00000000, 0x00000000, 0x00000000)"
303 /** Prints the UID to a string (or debug output if string is NULL).
304 \param string is the output string if not NULL.
305 \param style can be chosen from the FUID::UIDPrintStyle enumeration. */
306 void print (char8* string = nullptr, int32 style = kINLINE_UID) const;
308 template <size_t N>
309 inline explicit FUID (const int8 (&uid)[N])
311 #if SMTG_CPP11_STDLIBSUPPORT
312 static_assert (N == sizeof (TUID), "only TUID allowed");
313 #endif
314 memcpy (data, uid, sizeof (TUID));
316 inline void toTUID (TUID result) const { memcpy (result, data, sizeof (TUID)); }
317 inline operator const TUID& () const { return data; }
318 inline const TUID& toTUID () const { return data; }
320 static FUID fromTUID (const TUID uid)
322 FUID res;
323 if (uid)
324 memcpy (res.data, uid, sizeof (TUID));
325 return res;
328 //------------------------------------------------------------------------
329 protected:
330 TUID data;
333 #if SMTG_CPP11_STDLIBSUPPORT
334 template <typename T>
335 inline bool operator== (const FUID& f1, T f2)
337 static_assert (
338 std::is_same<typename std::remove_cv<T>::type, FUID>::value,
339 "Do not compare a FUID with a TUID directly. Either convert the TUID to a FUID and compare them or use FUnknownPrivate::iidEqual");
340 return f1.operator== (f2);
342 #endif
344 //------------------------------------------------------------------------
345 // FUnknown
346 //------------------------------------------------------------------------
347 /** The basic interface of all interfaces.
348 \ingroup pluginBase
350 - The FUnknown::queryInterface method is used to retrieve pointers to other
351 interfaces of the object.
352 - FUnknown::addRef and FUnknown::release manage the lifetime of the object.
353 If no more references exist, the object is destroyed in memory.
355 Interfaces are identified by 16 byte Globally Unique Identifiers.
356 The SDK provides a class called FUID for this purpose.
358 \ref howtoClass
360 class FUnknown
362 public:
364 //------------------------------------------------------------------------
365 /** Query for a pointer to the specified interface.
366 Returns kResultOk on success or kNoInterface if the object does not implement the interface.
367 The object has to call addRef when returning an interface.
368 \param _iid : (in) 16 Byte interface identifier (-> FUID)
369 \param obj : (out) On return, *obj points to the requested interface */
370 virtual tresult PLUGIN_API queryInterface (const TUID _iid, void** obj) = 0;
372 /** Adds a reference and returns the new reference count.
373 \par Remarks:
374 The initial reference count after creating an object is 1. */
375 virtual uint32 PLUGIN_API addRef () = 0;
377 /** Releases a reference and returns the new reference count.
378 If the reference count reaches zero, the object will be destroyed in memory. */
379 virtual uint32 PLUGIN_API release () = 0;
381 //------------------------------------------------------------------------
382 static const FUID iid;
383 //------------------------------------------------------------------------
387 DECLARE_CLASS_IID (FUnknown, 0x00000000, 0x00000000, 0xC0000000, 0x00000046)
389 //------------------------------------------------------------------------
390 // FUnknownPtr
391 //------------------------------------------------------------------------
392 /** FUnknownPtr - automatic interface conversion and smart pointer in one.
393 This template class can be used for interface conversion like this:
394 \code{.cpp}
395 IPtr<IPath> path = owned (FHostCreate (IPath, hostClasses));
396 FUnknownPtr<IPath2> path2 (path); // does a query interface for IPath2
397 if (path2)
399 \endcode
401 template <class I>
402 class FUnknownPtr : public IPtr<I>
404 public:
405 //------------------------------------------------------------------------
406 inline FUnknownPtr (FUnknown* unknown); // query interface
407 inline FUnknownPtr (const FUnknownPtr& p) : IPtr<I> (p) {}
408 inline FUnknownPtr () {}
410 inline FUnknownPtr& operator= (const FUnknownPtr& p)
412 IPtr<I>::operator= (p);
413 return *this;
415 inline I* operator= (FUnknown* unknown);
416 inline I* getInterface () { return this->ptr; }
418 #if SMTG_CPP11_STDLIBSUPPORT
419 inline FUnknownPtr (FUnknownPtr&& p) SMTG_NOEXCEPT : IPtr<I> (std::move (p)) {}
420 inline FUnknownPtr& operator= (FUnknownPtr&& p) SMTG_NOEXCEPT
422 IPtr<I>::operator= (std::move (p));
423 return *this;
425 #endif
428 #if SMTG_CPP11_STDLIBSUPPORT
430 //------------------------------------------------------------------------
431 namespace FUnknownPrivate {
433 template <typename T>
434 struct Void : std::false_type
436 using Type = void;
439 template <typename T>
440 using VoidT = typename Void<T>::Type;
442 //------------------------------------------------------------------------
444 * This type trait detects if a class has an @c iid member variable. It is used to detect if
445 * the FUID and DECLARE_CLASS_IID method or the SKI::UID method is used.
447 template <typename T, typename U = void>
448 struct HasIIDType : std::false_type
452 //------------------------------------------------------------------------
453 template <typename T>
454 struct HasIIDType<T, FUnknownPrivate::VoidT<typename T::IID>> : std::true_type
458 //------------------------------------------------------------------------
459 } // FUnknownPrivate
461 //------------------------------------------------------------------------
462 /** @return the TUID for a SKI interface which uses the SKI::UID method. */
463 template <typename T,
464 typename std::enable_if<FUnknownPrivate::HasIIDType<T>::value>::type* = nullptr>
465 const TUID& getTUID ()
467 return T::IID::toTUID ();
470 //------------------------------------------------------------------------
471 /** @return the TUID for a SKI interface which uses the FUID and DECLARE_CLASS_IID method. */
472 template <typename T,
473 typename std::enable_if<!FUnknownPrivate::HasIIDType<T>::value>::type* = nullptr>
474 const TUID& getTUID ()
476 return T::iid.toTUID ();
479 #else // SMTG_CPP11_STDLIBSUPPORT
481 template<typename T>
482 const TUID& getTUID ()
484 return T::iid.toTUID ();
487 #endif // SMTG_CPP11_STDLIBSUPPORT
489 //------------------------------------------------------------------------
490 template <class I>
491 inline FUnknownPtr<I>::FUnknownPtr (FUnknown* unknown)
493 if (unknown && unknown->queryInterface (getTUID<I> (), (void**)&this->ptr) != kResultOk)
494 this->ptr = 0;
497 //------------------------------------------------------------------------
498 template <class I>
499 inline I* FUnknownPtr<I>::operator= (FUnknown* unknown)
501 I* newPtr = 0;
502 if (unknown && unknown->queryInterface (getTUID<I> (), (void**)&newPtr) == kResultOk)
504 OPtr<I> rel (newPtr);
505 return IPtr<I>::operator= (newPtr);
508 return IPtr<I>::operator= (0);
511 //------------------------------------------------------------------------
512 // FReleaser (obsolete)
513 //------------------------------------------------------------------------
514 /** Release an interface using automatic object (obsolete).
515 This class is obsolete and is only kept for compatibility.
516 The replacement for FReleaser is OPtr.
518 Usage example with FReleaser:
519 \code{.cpp}
520 void someFunction ()
522 IPath* path = pathCreateMethod ();
523 FReleaser releaser (path);
524 .... do something with path...
525 .... path not used anymore, releaser will destroy it when leaving function scope
527 \endcode
528 Usage example with OPtr:
529 \code{.cpp}
530 void someFunction ()
532 OPtr<IPath> path = pathCreateMethod ();
533 .... do something with path...
534 .... path not used anymore, OPtr will destroy it when leaving function scope
536 \endcode
538 struct FReleaser
540 FReleaser (FUnknown* u) : u (u) {}
541 ~FReleaser ()
543 if (u)
544 u->release ();
546 FUnknown* u;
549 //------------------------------------------------------------------------
550 } // namespace Steinberg