Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

298 lines
7.2KB

  1. //-----------------------------------------------------------------------------
  2. // Project : SDK Core
  3. //
  4. // Category : SDK Core Interfaces
  5. // Filename : pluginterfaces/base/fvariant.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. //-----------------------------------------------------------------------------
  16. #pragma once
  17. #include "pluginterfaces/base/fstrdefs.h"
  18. #include "pluginterfaces/base/funknown.h"
  19. //------------------------------------------------------------------------
  20. namespace Steinberg {
  21. class FUnknown;
  22. //------------------------------------------------------------------------
  23. // FVariant struct declaration
  24. //------------------------------------------------------------------------
  25. /** A Value of variable type.
  26. \ingroup pluginBase
  27. */
  28. class FVariant
  29. {
  30. //------------------------------------------------------------------------
  31. public:
  32. enum
  33. {
  34. kEmpty = 0,
  35. kInteger = 1 << 0,
  36. kFloat = 1 << 1,
  37. kString8 = 1 << 2,
  38. kObject = 1 << 3,
  39. kOwner = 1 << 4,
  40. kString16 = 1 << 5
  41. };
  42. //------------------------------------------------------------------------
  43. // ctors
  44. inline FVariant () { memset (this, 0, sizeof (FVariant)); }
  45. inline FVariant (const FVariant& variant);
  46. inline FVariant (bool b) : type (kInteger), intValue (b) {}
  47. inline FVariant (uint32 v) : type (kInteger), intValue (v) {}
  48. inline FVariant (int64 v) : type (kInteger), intValue (v) {}
  49. inline FVariant (double v) : type (kFloat), floatValue (v) {}
  50. inline FVariant (const char8* str) : type (kString8), string8 (str) {}
  51. inline FVariant (const char16* str) : type (kString16), string16 (str) {}
  52. inline FVariant (FUnknown* obj, bool owner = false) : type (kObject), object (obj)
  53. {
  54. setOwner (owner);
  55. }
  56. inline ~FVariant () { empty (); }
  57. //------------------------------------------------------------------------
  58. inline FVariant& operator= (const FVariant& variant);
  59. inline void set (bool b)
  60. {
  61. setInt (b);
  62. }
  63. inline void set (uint32 v)
  64. {
  65. setInt (v);
  66. }
  67. inline void set (int64 v)
  68. {
  69. setInt (v);
  70. }
  71. inline void set (double v)
  72. {
  73. setFloat (v);
  74. }
  75. inline void set (const char8* c)
  76. {
  77. setString8 (c);
  78. }
  79. inline void set (const char16* c)
  80. {
  81. setString16 (c);
  82. }
  83. inline void setInt (int64 v)
  84. {
  85. empty ();
  86. type = kInteger;
  87. intValue = v;
  88. }
  89. inline void setFloat (double v)
  90. {
  91. empty ();
  92. type = kFloat;
  93. floatValue = v;
  94. }
  95. inline void setString8 (const char8* v)
  96. {
  97. empty ();
  98. type = kString8;
  99. string8 = v;
  100. }
  101. inline void setString16 (const char16* v)
  102. {
  103. empty ();
  104. type = kString16;
  105. string16 = v;
  106. }
  107. inline void setObject (FUnknown* obj)
  108. {
  109. empty ();
  110. type = kObject;
  111. object = obj;
  112. }
  113. template <typename T>
  114. inline T get () const;
  115. inline int64 getInt () const { return (type & kInteger) ? intValue : 0; }
  116. inline double getFloat () const { return (type & kFloat) ? floatValue : 0.; }
  117. inline double getNumber () const
  118. {
  119. return (type & kInteger) ? static_cast<double> (intValue) : (type & kFloat) ? floatValue :
  120. 0.;
  121. }
  122. inline const char8* getString8 () const { return (type & kString8) ? string8 : nullptr; }
  123. inline const char16* getString16 () const { return (type & kString16) ? string16 : nullptr; }
  124. inline FUnknown* getObject () const { return (type & kObject) ? object : nullptr; }
  125. inline uint16 getType () const { return static_cast<uint16> (type & ~(kOwner)); }
  126. inline bool isEmpty () const { return getType () == kEmpty; }
  127. inline bool isOwner () const { return (type & kOwner) != 0; }
  128. inline bool isString () const { return (type & (kString8 | kString16)) != 0; }
  129. inline void setOwner (bool state)
  130. {
  131. if (state)
  132. type |= kOwner;
  133. else
  134. type &= ~kOwner;
  135. }
  136. void empty ();
  137. //------------------------------------------------------------------------
  138. uint16 type;
  139. union
  140. {
  141. int64 intValue;
  142. double floatValue;
  143. const char8* string8;
  144. const char16* string16;
  145. FUnknown* object;
  146. };
  147. };
  148. //------------------------------------------------------------------------
  149. inline bool operator== (const FVariant& v1, const FVariant& v2)
  150. {
  151. #if SMTG_PLATFORM_64
  152. return v1.type == v2.type && v1.intValue == v2.intValue;
  153. #else
  154. if (v1.type != v2.type)
  155. return false;
  156. if (v1.type & (FVariant::kString8 | FVariant::kString16 | FVariant::kObject))
  157. return v1.string8 == v2.string8; // pointer type comparisons
  158. return v1.intValue == v2.intValue; // intValue & double comparison
  159. #endif
  160. }
  161. template <>
  162. inline bool FVariant::get<bool> () const
  163. {
  164. return getInt () != 0;
  165. }
  166. template <>
  167. inline uint32 FVariant::get<uint32> () const
  168. {
  169. return static_cast<uint32> (getInt ());
  170. }
  171. template <>
  172. inline int32 FVariant::get<int32> () const
  173. {
  174. return static_cast<int32> (getInt ());
  175. }
  176. template <>
  177. inline int64 FVariant::get<int64> () const
  178. {
  179. return static_cast<int64> (getInt ());
  180. }
  181. template <>
  182. inline float FVariant::get<float> () const
  183. {
  184. return static_cast<float> (getFloat ());
  185. }
  186. template <>
  187. inline double FVariant::get<double> () const
  188. {
  189. return getFloat ();
  190. }
  191. template <>
  192. inline const char8* FVariant::get<const char8*> () const
  193. {
  194. return getString8 ();
  195. }
  196. template <>
  197. inline const char16* FVariant::get<const char16*> () const
  198. {
  199. return getString16 ();
  200. }
  201. template <>
  202. inline FUnknown* FVariant::get<FUnknown*> () const
  203. {
  204. return getObject ();
  205. }
  206. //------------------------------------------------------------------------
  207. inline bool operator!= (const FVariant& v1, const FVariant& v2) { return !(v1 == v2); }
  208. //------------------------------------------------------------------------
  209. inline FVariant::FVariant (const FVariant& variant) : type (kEmpty) { *this = variant; }
  210. //------------------------------------------------------------------------
  211. inline void FVariant::empty ()
  212. {
  213. if (type & kOwner)
  214. {
  215. if ((type & kString8) && string8)
  216. delete[] string8;
  217. else if ((type & kString16) && string16)
  218. delete[] string16;
  219. else if ((type & kObject) && object)
  220. object->release ();
  221. }
  222. memset (this, 0, sizeof (FVariant));
  223. }
  224. //------------------------------------------------------------------------
  225. inline FVariant& FVariant::operator= (const FVariant& variant)
  226. {
  227. empty ();
  228. type = variant.type;
  229. if ((type & kString8) && variant.string8)
  230. {
  231. string8 = new char8[strlen (variant.string8) + 1];
  232. strcpy (const_cast<char8*> (string8), variant.string8);
  233. type |= kOwner;
  234. }
  235. else if ((type & kString16) && variant.string16)
  236. {
  237. auto len = static_cast<size_t> (strlen16 (variant.string16));
  238. string16 = new char16[len + 1];
  239. char16* tmp = const_cast<char16*> (string16);
  240. memcpy (tmp, variant.string16, len * sizeof (char16));
  241. tmp[len] = 0;
  242. type |= kOwner;
  243. }
  244. else if ((type & kObject) && variant.object)
  245. {
  246. object = variant.object;
  247. object->addRef ();
  248. type |= kOwner;
  249. }
  250. else
  251. intValue = variant.intValue; // copy memory
  252. return *this;
  253. }
  254. //------------------------------------------------------------------------
  255. } // namespace Steinberg