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.

326 lines
16KB

  1. /*
  2. ==============================================================================
  3. This file is part of the Water library.
  4. Copyright (c) 2016 ROLI Ltd.
  5. Copyright (C) 2017 Filipe Coelho <falktx@falktx.com>
  6. Permission is granted to use this software under the terms of the ISC license
  7. http://www.isc.org/downloads/software-support-policy/isc-license/
  8. Permission to use, copy, modify, and/or distribute this software for any
  9. purpose with or without fee is hereby granted, provided that the above
  10. copyright notice and this permission notice appear in all copies.
  11. THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD
  12. TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  13. FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT,
  14. OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
  15. USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  16. TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
  17. OF THIS SOFTWARE.
  18. ==============================================================================
  19. */
  20. #include "Variant.h"
  21. namespace water {
  22. enum VariantStreamMarkers
  23. {
  24. varMarker_Int = 1,
  25. varMarker_BoolTrue = 2,
  26. varMarker_BoolFalse = 3,
  27. varMarker_Double = 4,
  28. varMarker_String = 5,
  29. varMarker_Int64 = 6,
  30. varMarker_Undefined = 9
  31. };
  32. //==============================================================================
  33. class var::VariantType
  34. {
  35. public:
  36. VariantType() noexcept {}
  37. virtual ~VariantType() noexcept {}
  38. virtual int toInt (const ValueUnion&) const noexcept { return 0; }
  39. virtual int64 toInt64 (const ValueUnion&) const noexcept { return 0; }
  40. virtual double toDouble (const ValueUnion&) const noexcept { return 0; }
  41. virtual String toString (const ValueUnion&) const { return String(); }
  42. virtual bool toBool (const ValueUnion&) const noexcept { return false; }
  43. virtual var clone (const var& original) const { return original; }
  44. virtual bool isVoid() const noexcept { return false; }
  45. virtual bool isUndefined() const noexcept { return false; }
  46. virtual bool isInt() const noexcept { return false; }
  47. virtual bool isInt64() const noexcept { return false; }
  48. virtual bool isBool() const noexcept { return false; }
  49. virtual bool isDouble() const noexcept { return false; }
  50. virtual bool isString() const noexcept { return false; }
  51. virtual void cleanUp (ValueUnion&) const noexcept {}
  52. virtual void createCopy (ValueUnion& dest, const ValueUnion& source) const { dest = source; }
  53. virtual bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept = 0;
  54. };
  55. //==============================================================================
  56. class var::VariantType_Void : public var::VariantType
  57. {
  58. public:
  59. VariantType_Void() noexcept {}
  60. static const VariantType_Void instance;
  61. bool isVoid() const noexcept override { return true; }
  62. bool equals (const ValueUnion&, const ValueUnion&, const VariantType& otherType) const noexcept override { return otherType.isVoid() || otherType.isUndefined(); }
  63. };
  64. //==============================================================================
  65. class var::VariantType_Undefined : public var::VariantType
  66. {
  67. public:
  68. VariantType_Undefined() noexcept {}
  69. static const VariantType_Undefined instance;
  70. bool isUndefined() const noexcept override { return true; }
  71. String toString (const ValueUnion&) const override { return "undefined"; }
  72. bool equals (const ValueUnion&, const ValueUnion&, const VariantType& otherType) const noexcept override { return otherType.isVoid() || otherType.isUndefined(); }
  73. };
  74. //==============================================================================
  75. class var::VariantType_Int : public var::VariantType
  76. {
  77. public:
  78. VariantType_Int() noexcept {}
  79. static const VariantType_Int instance;
  80. int toInt (const ValueUnion& data) const noexcept override { return data.intValue; };
  81. int64 toInt64 (const ValueUnion& data) const noexcept override { return (int64) data.intValue; };
  82. double toDouble (const ValueUnion& data) const noexcept override { return (double) data.intValue; }
  83. String toString (const ValueUnion& data) const override { return String (data.intValue); }
  84. bool toBool (const ValueUnion& data) const noexcept override { return data.intValue != 0; }
  85. bool isInt() const noexcept override { return true; }
  86. bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept override
  87. {
  88. if (otherType.isDouble() || otherType.isInt64() || otherType.isString())
  89. return otherType.equals (otherData, data, *this);
  90. return otherType.toInt (otherData) == data.intValue;
  91. }
  92. };
  93. //==============================================================================
  94. class var::VariantType_Int64 : public var::VariantType
  95. {
  96. public:
  97. VariantType_Int64() noexcept {}
  98. static const VariantType_Int64 instance;
  99. int toInt (const ValueUnion& data) const noexcept override { return (int) data.int64Value; };
  100. int64 toInt64 (const ValueUnion& data) const noexcept override { return data.int64Value; };
  101. double toDouble (const ValueUnion& data) const noexcept override { return (double) data.int64Value; }
  102. String toString (const ValueUnion& data) const override { return String (data.int64Value); }
  103. bool toBool (const ValueUnion& data) const noexcept override { return data.int64Value != 0; }
  104. bool isInt64() const noexcept override { return true; }
  105. bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept override
  106. {
  107. if (otherType.isDouble() || otherType.isString())
  108. return otherType.equals (otherData, data, *this);
  109. return otherType.toInt64 (otherData) == data.int64Value;
  110. }
  111. };
  112. //==============================================================================
  113. class var::VariantType_Double : public var::VariantType
  114. {
  115. public:
  116. VariantType_Double() noexcept {}
  117. static const VariantType_Double instance;
  118. int toInt (const ValueUnion& data) const noexcept override { return (int) data.doubleValue; };
  119. int64 toInt64 (const ValueUnion& data) const noexcept override { return (int64) data.doubleValue; };
  120. double toDouble (const ValueUnion& data) const noexcept override { return data.doubleValue; }
  121. String toString (const ValueUnion& data) const override { return String (data.doubleValue, 20); }
  122. bool toBool (const ValueUnion& data) const noexcept override { return data.doubleValue != 0; }
  123. bool isDouble() const noexcept override { return true; }
  124. bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept override
  125. {
  126. return std::abs (otherType.toDouble (otherData) - data.doubleValue) < std::numeric_limits<double>::epsilon();
  127. }
  128. };
  129. //==============================================================================
  130. class var::VariantType_Bool : public var::VariantType
  131. {
  132. public:
  133. VariantType_Bool() noexcept {}
  134. static const VariantType_Bool instance;
  135. int toInt (const ValueUnion& data) const noexcept override { return data.boolValue ? 1 : 0; };
  136. int64 toInt64 (const ValueUnion& data) const noexcept override { return data.boolValue ? 1 : 0; };
  137. double toDouble (const ValueUnion& data) const noexcept override { return data.boolValue ? 1.0 : 0.0; }
  138. String toString (const ValueUnion& data) const override { return String::charToString (data.boolValue ? (water_uchar) '1' : (water_uchar) '0'); }
  139. bool toBool (const ValueUnion& data) const noexcept override { return data.boolValue; }
  140. bool isBool() const noexcept override { return true; }
  141. bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept override
  142. {
  143. return otherType.toBool (otherData) == data.boolValue;
  144. }
  145. };
  146. //==============================================================================
  147. class var::VariantType_String : public var::VariantType
  148. {
  149. public:
  150. VariantType_String() noexcept {}
  151. static const VariantType_String instance;
  152. void cleanUp (ValueUnion& data) const noexcept override { getString (data)-> ~String(); }
  153. void createCopy (ValueUnion& dest, const ValueUnion& source) const override { new (dest.stringValue) String (*getString (source)); }
  154. bool isString() const noexcept override { return true; }
  155. int toInt (const ValueUnion& data) const noexcept override { return getString (data)->getIntValue(); };
  156. int64 toInt64 (const ValueUnion& data) const noexcept override { return getString (data)->getLargeIntValue(); };
  157. double toDouble (const ValueUnion& data) const noexcept override { return getString (data)->getDoubleValue(); }
  158. String toString (const ValueUnion& data) const override { return *getString (data); }
  159. bool toBool (const ValueUnion& data) const noexcept override { return getString (data)->getIntValue() != 0
  160. || getString (data)->trim().equalsIgnoreCase ("true")
  161. || getString (data)->trim().equalsIgnoreCase ("yes"); }
  162. bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept override
  163. {
  164. return otherType.toString (otherData) == *getString (data);
  165. }
  166. private:
  167. static inline const String* getString (const ValueUnion& data) noexcept { return reinterpret_cast<const String*> (data.stringValue); }
  168. static inline String* getString (ValueUnion& data) noexcept { return reinterpret_cast<String*> (data.stringValue); }
  169. };
  170. //==============================================================================
  171. const var::VariantType_Void var::VariantType_Void::instance;
  172. const var::VariantType_Undefined var::VariantType_Undefined::instance;
  173. const var::VariantType_Int var::VariantType_Int::instance;
  174. const var::VariantType_Int64 var::VariantType_Int64::instance;
  175. const var::VariantType_Bool var::VariantType_Bool::instance;
  176. const var::VariantType_Double var::VariantType_Double::instance;
  177. const var::VariantType_String var::VariantType_String::instance;
  178. //==============================================================================
  179. var::var() noexcept : type (&VariantType_Void::instance) {}
  180. var::var (const VariantType& t) noexcept : type (&t) {}
  181. var::~var() noexcept { type->cleanUp (value); }
  182. //==============================================================================
  183. var::var (const var& valueToCopy) : type (valueToCopy.type)
  184. {
  185. type->createCopy (value, valueToCopy.value);
  186. }
  187. var::var (const int v) noexcept : type (&VariantType_Int::instance) { value.intValue = v; }
  188. var::var (const int64 v) noexcept : type (&VariantType_Int64::instance) { value.int64Value = v; }
  189. var::var (const bool v) noexcept : type (&VariantType_Bool::instance) { value.boolValue = v; }
  190. var::var (const double v) noexcept : type (&VariantType_Double::instance) { value.doubleValue = v; }
  191. var::var (const String& v) : type (&VariantType_String::instance) { new (value.stringValue) String (v); }
  192. var::var (const char* const v) : type (&VariantType_String::instance) { new (value.stringValue) String (v); }
  193. var var::undefined() noexcept { return var (VariantType_Undefined::instance); }
  194. //==============================================================================
  195. bool var::isVoid() const noexcept { return type->isVoid(); }
  196. bool var::isUndefined() const noexcept { return type->isUndefined(); }
  197. bool var::isInt() const noexcept { return type->isInt(); }
  198. bool var::isInt64() const noexcept { return type->isInt64(); }
  199. bool var::isBool() const noexcept { return type->isBool(); }
  200. bool var::isDouble() const noexcept { return type->isDouble(); }
  201. bool var::isString() const noexcept { return type->isString(); }
  202. var::operator int() const noexcept { return type->toInt (value); }
  203. var::operator int64() const noexcept { return type->toInt64 (value); }
  204. var::operator bool() const noexcept { return type->toBool (value); }
  205. var::operator float() const noexcept { return (float) type->toDouble (value); }
  206. var::operator double() const noexcept { return type->toDouble (value); }
  207. String var::toString() const { return type->toString (value); }
  208. var::operator String() const { return type->toString (value); }
  209. //==============================================================================
  210. void var::swapWith (var& other) noexcept
  211. {
  212. std::swap (type, other.type);
  213. std::swap (value, other.value);
  214. }
  215. var& var::operator= (const var& v) { type->cleanUp (value); type = v.type; type->createCopy (value, v.value); return *this; }
  216. var& var::operator= (const int v) { type->cleanUp (value); type = &VariantType_Int::instance; value.intValue = v; return *this; }
  217. var& var::operator= (const int64 v) { type->cleanUp (value); type = &VariantType_Int64::instance; value.int64Value = v; return *this; }
  218. var& var::operator= (const bool v) { type->cleanUp (value); type = &VariantType_Bool::instance; value.boolValue = v; return *this; }
  219. var& var::operator= (const double v) { type->cleanUp (value); type = &VariantType_Double::instance; value.doubleValue = v; return *this; }
  220. var& var::operator= (const char* const v) { type->cleanUp (value); type = &VariantType_String::instance; new (value.stringValue) String (v); return *this; }
  221. var& var::operator= (const String& v) { type->cleanUp (value); type = &VariantType_String::instance; new (value.stringValue) String (v); return *this; }
  222. #if WATER_COMPILER_SUPPORTS_MOVE_SEMANTICS
  223. var::var (var&& other) noexcept
  224. : type (other.type),
  225. value (other.value)
  226. {
  227. other.type = &VariantType_Void::instance;
  228. }
  229. var& var::operator= (var&& other) noexcept
  230. {
  231. swapWith (other);
  232. return *this;
  233. }
  234. var::var (String&& v) : type (&VariantType_String::instance)
  235. {
  236. new (value.stringValue) String (static_cast<String&&> (v));
  237. }
  238. var& var::operator= (String&& v)
  239. {
  240. type->cleanUp (value);
  241. type = &VariantType_String::instance;
  242. new (value.stringValue) String (static_cast<String&&> (v));
  243. return *this;
  244. }
  245. #endif
  246. //==============================================================================
  247. bool var::equals (const var& other) const noexcept
  248. {
  249. return type->equals (value, other.value, *other.type);
  250. }
  251. bool var::equalsWithSameType (const var& other) const noexcept
  252. {
  253. return type == other.type && equals (other);
  254. }
  255. bool var::hasSameTypeAs (const var& other) const noexcept
  256. {
  257. return type == other.type;
  258. }
  259. bool operator== (const var& v1, const var& v2) noexcept { return v1.equals (v2); }
  260. bool operator!= (const var& v1, const var& v2) noexcept { return ! v1.equals (v2); }
  261. bool operator== (const var& v1, const String& v2) { return v1.toString() == v2; }
  262. bool operator!= (const var& v1, const String& v2) { return v1.toString() != v2; }
  263. bool operator== (const var& v1, const char* const v2) { return v1.toString() == v2; }
  264. bool operator!= (const var& v1, const char* const v2) { return v1.toString() != v2; }
  265. //==============================================================================
  266. var var::clone() const noexcept
  267. {
  268. return type->clone (*this);
  269. }
  270. }