The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
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.

831 lines
35KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2020 - Raw Material Software Limited
  5. JUCE is an open source library subject to commercial or open-source
  6. licensing.
  7. The code included in this file is provided under the terms of the ISC license
  8. http://www.isc.org/downloads/software-support-policy/isc-license. Permission
  9. To use, copy, modify, and/or distribute this software for any purpose with or
  10. without fee is hereby granted provided that the above copyright notice and
  11. this permission notice appear in all copies.
  12. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  13. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  14. DISCLAIMED.
  15. ==============================================================================
  16. */
  17. namespace juce
  18. {
  19. enum VariantStreamMarkers
  20. {
  21. varMarker_Int = 1,
  22. varMarker_BoolTrue = 2,
  23. varMarker_BoolFalse = 3,
  24. varMarker_Double = 4,
  25. varMarker_String = 5,
  26. varMarker_Int64 = 6,
  27. varMarker_Array = 7,
  28. varMarker_Binary = 8,
  29. varMarker_Undefined = 9
  30. };
  31. //==============================================================================
  32. class var::VariantType
  33. {
  34. public:
  35. VariantType() noexcept {}
  36. virtual ~VariantType() noexcept {}
  37. virtual int toInt (const ValueUnion&) const noexcept { return 0; }
  38. virtual int64 toInt64 (const ValueUnion&) const noexcept { return 0; }
  39. virtual double toDouble (const ValueUnion&) const noexcept { return 0; }
  40. virtual String toString (const ValueUnion&) const { return {}; }
  41. virtual bool toBool (const ValueUnion&) const noexcept { return false; }
  42. virtual ReferenceCountedObject* toObject (const ValueUnion&) const noexcept { return nullptr; }
  43. virtual Array<var>* toArray (const ValueUnion&) const noexcept { return nullptr; }
  44. virtual MemoryBlock* toBinary (const ValueUnion&) const noexcept { return nullptr; }
  45. virtual var clone (const var& original) const { return original; }
  46. virtual bool isVoid() const noexcept { return false; }
  47. virtual bool isUndefined() const noexcept { return false; }
  48. virtual bool isInt() const noexcept { return false; }
  49. virtual bool isInt64() const noexcept { return false; }
  50. virtual bool isBool() const noexcept { return false; }
  51. virtual bool isDouble() const noexcept { return false; }
  52. virtual bool isString() const noexcept { return false; }
  53. virtual bool isObject() const noexcept { return false; }
  54. virtual bool isArray() const noexcept { return false; }
  55. virtual bool isBinary() const noexcept { return false; }
  56. virtual bool isMethod() const noexcept { return false; }
  57. virtual bool isComparable() const noexcept { return false; }
  58. virtual void cleanUp (ValueUnion&) const noexcept {}
  59. virtual void createCopy (ValueUnion& dest, const ValueUnion& source) const { dest = source; }
  60. virtual bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept = 0;
  61. virtual void writeToStream (const ValueUnion& data, OutputStream& output) const = 0;
  62. };
  63. //==============================================================================
  64. class var::VariantType_Void : public var::VariantType
  65. {
  66. public:
  67. VariantType_Void() noexcept {}
  68. static const VariantType_Void instance;
  69. bool isVoid() const noexcept override { return true; }
  70. bool isComparable() const noexcept override { return true; }
  71. bool equals (const ValueUnion&, const ValueUnion&, const VariantType& otherType) const noexcept override { return otherType.isVoid() || otherType.isUndefined(); }
  72. void writeToStream (const ValueUnion&, OutputStream& output) const override { output.writeCompressedInt (0); }
  73. };
  74. //==============================================================================
  75. class var::VariantType_Undefined : public var::VariantType
  76. {
  77. public:
  78. VariantType_Undefined() noexcept {}
  79. static const VariantType_Undefined instance;
  80. bool isUndefined() const noexcept override { return true; }
  81. String toString (const ValueUnion&) const override { return "undefined"; }
  82. bool equals (const ValueUnion&, const ValueUnion&, const VariantType& otherType) const noexcept override { return otherType.isVoid() || otherType.isUndefined(); }
  83. void writeToStream (const ValueUnion&, OutputStream& output) const override
  84. {
  85. output.writeCompressedInt (1);
  86. output.writeByte (varMarker_Undefined);
  87. }
  88. };
  89. //==============================================================================
  90. class var::VariantType_Int : public var::VariantType
  91. {
  92. public:
  93. VariantType_Int() noexcept {}
  94. static const VariantType_Int instance;
  95. int toInt (const ValueUnion& data) const noexcept override { return data.intValue; }
  96. int64 toInt64 (const ValueUnion& data) const noexcept override { return (int64) data.intValue; }
  97. double toDouble (const ValueUnion& data) const noexcept override { return (double) data.intValue; }
  98. String toString (const ValueUnion& data) const override { return String (data.intValue); }
  99. bool toBool (const ValueUnion& data) const noexcept override { return data.intValue != 0; }
  100. bool isInt() const noexcept override { return true; }
  101. bool isComparable() const noexcept override { return true; }
  102. bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept override
  103. {
  104. if (otherType.isDouble() || otherType.isInt64() || otherType.isString())
  105. return otherType.equals (otherData, data, *this);
  106. return otherType.toInt (otherData) == data.intValue;
  107. }
  108. void writeToStream (const ValueUnion& data, OutputStream& output) const override
  109. {
  110. output.writeCompressedInt (5);
  111. output.writeByte (varMarker_Int);
  112. output.writeInt (data.intValue);
  113. }
  114. };
  115. //==============================================================================
  116. class var::VariantType_Int64 : public var::VariantType
  117. {
  118. public:
  119. VariantType_Int64() noexcept {}
  120. static const VariantType_Int64 instance;
  121. int toInt (const ValueUnion& data) const noexcept override { return (int) data.int64Value; }
  122. int64 toInt64 (const ValueUnion& data) const noexcept override { return data.int64Value; }
  123. double toDouble (const ValueUnion& data) const noexcept override { return (double) data.int64Value; }
  124. String toString (const ValueUnion& data) const override { return String (data.int64Value); }
  125. bool toBool (const ValueUnion& data) const noexcept override { return data.int64Value != 0; }
  126. bool isInt64() const noexcept override { return true; }
  127. bool isComparable() const noexcept override { return true; }
  128. bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept override
  129. {
  130. if (otherType.isDouble() || otherType.isString())
  131. return otherType.equals (otherData, data, *this);
  132. return otherType.toInt64 (otherData) == data.int64Value;
  133. }
  134. void writeToStream (const ValueUnion& data, OutputStream& output) const override
  135. {
  136. output.writeCompressedInt (9);
  137. output.writeByte (varMarker_Int64);
  138. output.writeInt64 (data.int64Value);
  139. }
  140. };
  141. //==============================================================================
  142. class var::VariantType_Double : public var::VariantType
  143. {
  144. public:
  145. VariantType_Double() noexcept {}
  146. static const VariantType_Double instance;
  147. int toInt (const ValueUnion& data) const noexcept override { return (int) data.doubleValue; }
  148. int64 toInt64 (const ValueUnion& data) const noexcept override { return (int64) data.doubleValue; }
  149. double toDouble (const ValueUnion& data) const noexcept override { return data.doubleValue; }
  150. String toString (const ValueUnion& data) const override { return serialiseDouble (data.doubleValue); }
  151. bool toBool (const ValueUnion& data) const noexcept override { return data.doubleValue != 0.0; }
  152. bool isDouble() const noexcept override { return true; }
  153. bool isComparable() const noexcept override { return true; }
  154. bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept override
  155. {
  156. return std::abs (otherType.toDouble (otherData) - data.doubleValue) < std::numeric_limits<double>::epsilon();
  157. }
  158. void writeToStream (const ValueUnion& data, OutputStream& output) const override
  159. {
  160. output.writeCompressedInt (9);
  161. output.writeByte (varMarker_Double);
  162. output.writeDouble (data.doubleValue);
  163. }
  164. };
  165. //==============================================================================
  166. class var::VariantType_Bool : public var::VariantType
  167. {
  168. public:
  169. VariantType_Bool() noexcept {}
  170. static const VariantType_Bool instance;
  171. int toInt (const ValueUnion& data) const noexcept override { return data.boolValue ? 1 : 0; }
  172. int64 toInt64 (const ValueUnion& data) const noexcept override { return data.boolValue ? 1 : 0; }
  173. double toDouble (const ValueUnion& data) const noexcept override { return data.boolValue ? 1.0 : 0.0; }
  174. String toString (const ValueUnion& data) const override { return String::charToString (data.boolValue ? (juce_wchar) '1' : (juce_wchar) '0'); }
  175. bool toBool (const ValueUnion& data) const noexcept override { return data.boolValue; }
  176. bool isBool() const noexcept override { return true; }
  177. bool isComparable() const noexcept override { return true; }
  178. bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept override
  179. {
  180. return otherType.toBool (otherData) == data.boolValue;
  181. }
  182. void writeToStream (const ValueUnion& data, OutputStream& output) const override
  183. {
  184. output.writeCompressedInt (1);
  185. output.writeByte (data.boolValue ? (char) varMarker_BoolTrue : (char) varMarker_BoolFalse);
  186. }
  187. };
  188. //==============================================================================
  189. class var::VariantType_String : public var::VariantType
  190. {
  191. public:
  192. VariantType_String() noexcept {}
  193. static const VariantType_String instance;
  194. void cleanUp (ValueUnion& data) const noexcept override { getString (data)-> ~String(); }
  195. void createCopy (ValueUnion& dest, const ValueUnion& source) const override { new (dest.stringValue) String (*getString (source)); }
  196. bool isString() const noexcept override { return true; }
  197. int toInt (const ValueUnion& data) const noexcept override { return getString (data)->getIntValue(); }
  198. int64 toInt64 (const ValueUnion& data) const noexcept override { return getString (data)->getLargeIntValue(); }
  199. double toDouble (const ValueUnion& data) const noexcept override { return getString (data)->getDoubleValue(); }
  200. String toString (const ValueUnion& data) const override { return *getString (data); }
  201. bool toBool (const ValueUnion& data) const noexcept override { return getString (data)->getIntValue() != 0
  202. || getString (data)->trim().equalsIgnoreCase ("true")
  203. || getString (data)->trim().equalsIgnoreCase ("yes"); }
  204. bool isComparable() const noexcept override { return true; }
  205. bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept override
  206. {
  207. return otherType.toString (otherData) == *getString (data);
  208. }
  209. void writeToStream (const ValueUnion& data, OutputStream& output) const override
  210. {
  211. auto* s = getString (data);
  212. const size_t len = s->getNumBytesAsUTF8() + 1;
  213. HeapBlock<char> temp (len);
  214. s->copyToUTF8 (temp, len);
  215. output.writeCompressedInt ((int) (len + 1));
  216. output.writeByte (varMarker_String);
  217. output.write (temp, len);
  218. }
  219. private:
  220. static const String* getString (const ValueUnion& data) noexcept { return unalignedPointerCast<const String*> (data.stringValue); }
  221. static String* getString (ValueUnion& data) noexcept { return unalignedPointerCast<String*> (data.stringValue); }
  222. };
  223. //==============================================================================
  224. class var::VariantType_Object : public var::VariantType
  225. {
  226. public:
  227. VariantType_Object() noexcept {}
  228. static const VariantType_Object instance;
  229. void cleanUp (ValueUnion& data) const noexcept override { if (data.objectValue != nullptr) data.objectValue->decReferenceCount(); }
  230. void createCopy (ValueUnion& dest, const ValueUnion& source) const override
  231. {
  232. dest.objectValue = source.objectValue;
  233. if (dest.objectValue != nullptr)
  234. dest.objectValue->incReferenceCount();
  235. }
  236. String toString (const ValueUnion& data) const override { return "Object 0x" + String::toHexString ((int) (pointer_sized_int) data.objectValue); }
  237. bool toBool (const ValueUnion& data) const noexcept override { return data.objectValue != nullptr; }
  238. ReferenceCountedObject* toObject (const ValueUnion& data) const noexcept override { return data.objectValue; }
  239. bool isObject() const noexcept override { return true; }
  240. bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept override
  241. {
  242. return otherType.toObject (otherData) == data.objectValue;
  243. }
  244. var clone (const var& original) const override
  245. {
  246. if (auto* d = original.getDynamicObject())
  247. return d->clone().get();
  248. jassertfalse; // can only clone DynamicObjects!
  249. return {};
  250. }
  251. void writeToStream (const ValueUnion&, OutputStream& output) const override
  252. {
  253. jassertfalse; // Can't write an object to a stream!
  254. output.writeCompressedInt (0);
  255. }
  256. };
  257. //==============================================================================
  258. class var::VariantType_Array : public var::VariantType_Object
  259. {
  260. public:
  261. VariantType_Array() noexcept {}
  262. static const VariantType_Array instance;
  263. String toString (const ValueUnion&) const override { return "[Array]"; }
  264. ReferenceCountedObject* toObject (const ValueUnion&) const noexcept override { return nullptr; }
  265. bool isArray() const noexcept override { return true; }
  266. Array<var>* toArray (const ValueUnion& data) const noexcept override
  267. {
  268. if (auto* a = dynamic_cast<RefCountedArray*> (data.objectValue))
  269. return &(a->array);
  270. return nullptr;
  271. }
  272. bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept override
  273. {
  274. auto* thisArray = toArray (data);
  275. auto* otherArray = otherType.toArray (otherData);
  276. return thisArray == otherArray || (thisArray != nullptr && otherArray != nullptr && *otherArray == *thisArray);
  277. }
  278. var clone (const var& original) const override
  279. {
  280. Array<var> arrayCopy;
  281. if (auto* array = toArray (original.value))
  282. {
  283. arrayCopy.ensureStorageAllocated (array->size());
  284. for (auto& i : *array)
  285. arrayCopy.add (i.clone());
  286. }
  287. return var (arrayCopy);
  288. }
  289. void writeToStream (const ValueUnion& data, OutputStream& output) const override
  290. {
  291. if (auto* array = toArray (data))
  292. {
  293. MemoryOutputStream buffer (512);
  294. buffer.writeCompressedInt (array->size());
  295. for (auto& i : *array)
  296. i.writeToStream (buffer);
  297. output.writeCompressedInt (1 + (int) buffer.getDataSize());
  298. output.writeByte (varMarker_Array);
  299. output << buffer;
  300. }
  301. }
  302. struct RefCountedArray : public ReferenceCountedObject
  303. {
  304. RefCountedArray (const Array<var>& a) : array (a) { incReferenceCount(); }
  305. RefCountedArray (Array<var>&& a) : array (std::move (a)) { incReferenceCount(); }
  306. Array<var> array;
  307. };
  308. };
  309. //==============================================================================
  310. class var::VariantType_Binary : public var::VariantType
  311. {
  312. public:
  313. VariantType_Binary() noexcept {}
  314. static const VariantType_Binary instance;
  315. void cleanUp (ValueUnion& data) const noexcept override { delete data.binaryValue; }
  316. void createCopy (ValueUnion& dest, const ValueUnion& source) const override { dest.binaryValue = new MemoryBlock (*source.binaryValue); }
  317. String toString (const ValueUnion& data) const override { return data.binaryValue->toBase64Encoding(); }
  318. bool isBinary() const noexcept override { return true; }
  319. MemoryBlock* toBinary (const ValueUnion& data) const noexcept override { return data.binaryValue; }
  320. bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept override
  321. {
  322. const MemoryBlock* const otherBlock = otherType.toBinary (otherData);
  323. return otherBlock != nullptr && *otherBlock == *data.binaryValue;
  324. }
  325. void writeToStream (const ValueUnion& data, OutputStream& output) const override
  326. {
  327. output.writeCompressedInt (1 + (int) data.binaryValue->getSize());
  328. output.writeByte (varMarker_Binary);
  329. output << *data.binaryValue;
  330. }
  331. };
  332. //==============================================================================
  333. class var::VariantType_Method : public var::VariantType
  334. {
  335. public:
  336. VariantType_Method() noexcept {}
  337. static const VariantType_Method instance;
  338. void cleanUp (ValueUnion& data) const noexcept override { if (data.methodValue != nullptr ) delete data.methodValue; }
  339. void createCopy (ValueUnion& dest, const ValueUnion& source) const override { dest.methodValue = new NativeFunction (*source.methodValue); }
  340. String toString (const ValueUnion&) const override { return "Method"; }
  341. bool toBool (const ValueUnion& data) const noexcept override { return data.methodValue != nullptr; }
  342. bool isMethod() const noexcept override { return true; }
  343. bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept override
  344. {
  345. return otherType.isMethod() && otherData.methodValue == data.methodValue;
  346. }
  347. void writeToStream (const ValueUnion&, OutputStream& output) const override
  348. {
  349. jassertfalse; // Can't write a method to a stream!
  350. output.writeCompressedInt (0);
  351. }
  352. };
  353. //==============================================================================
  354. const var::VariantType_Void var::VariantType_Void::instance;
  355. const var::VariantType_Undefined var::VariantType_Undefined::instance;
  356. const var::VariantType_Int var::VariantType_Int::instance;
  357. const var::VariantType_Int64 var::VariantType_Int64::instance;
  358. const var::VariantType_Bool var::VariantType_Bool::instance;
  359. const var::VariantType_Double var::VariantType_Double::instance;
  360. const var::VariantType_String var::VariantType_String::instance;
  361. const var::VariantType_Object var::VariantType_Object::instance;
  362. const var::VariantType_Array var::VariantType_Array::instance;
  363. const var::VariantType_Binary var::VariantType_Binary::instance;
  364. const var::VariantType_Method var::VariantType_Method::instance;
  365. //==============================================================================
  366. var::var() noexcept : type (&VariantType_Void::instance) {}
  367. var::var (const VariantType& t) noexcept : type (&t) {}
  368. var::~var() noexcept { type->cleanUp (value); }
  369. JUCE_DECLARE_DEPRECATED_STATIC (const var var::null;)
  370. //==============================================================================
  371. var::var (const var& valueToCopy) : type (valueToCopy.type)
  372. {
  373. type->createCopy (value, valueToCopy.value);
  374. }
  375. var::var (const int v) noexcept : type (&VariantType_Int::instance) { value.intValue = v; }
  376. var::var (const int64 v) noexcept : type (&VariantType_Int64::instance) { value.int64Value = v; }
  377. var::var (const bool v) noexcept : type (&VariantType_Bool::instance) { value.boolValue = v; }
  378. var::var (const double v) noexcept : type (&VariantType_Double::instance) { value.doubleValue = v; }
  379. var::var (NativeFunction m) noexcept : type (&VariantType_Method::instance) { value.methodValue = new NativeFunction (m); }
  380. var::var (const Array<var>& v) : type (&VariantType_Array::instance) { value.objectValue = new VariantType_Array::RefCountedArray(v); }
  381. var::var (const String& v) : type (&VariantType_String::instance) { new (value.stringValue) String (v); }
  382. var::var (const char* const v) : type (&VariantType_String::instance) { new (value.stringValue) String (v); }
  383. var::var (const wchar_t* const v) : type (&VariantType_String::instance) { new (value.stringValue) String (v); }
  384. var::var (const void* v, size_t sz) : type (&VariantType_Binary::instance) { value.binaryValue = new MemoryBlock (v, sz); }
  385. var::var (const MemoryBlock& v) : type (&VariantType_Binary::instance) { value.binaryValue = new MemoryBlock (v); }
  386. var::var (const StringArray& v) : type (&VariantType_Array::instance)
  387. {
  388. Array<var> strings;
  389. strings.ensureStorageAllocated (v.size());
  390. for (auto& i : v)
  391. strings.add (var (i));
  392. value.objectValue = new VariantType_Array::RefCountedArray (strings);
  393. }
  394. var::var (ReferenceCountedObject* const object) : type (&VariantType_Object::instance)
  395. {
  396. value.objectValue = object;
  397. if (object != nullptr)
  398. object->incReferenceCount();
  399. }
  400. var var::undefined() noexcept { return var (VariantType_Undefined::instance); }
  401. //==============================================================================
  402. bool var::isVoid() const noexcept { return type->isVoid(); }
  403. bool var::isUndefined() const noexcept { return type->isUndefined(); }
  404. bool var::isInt() const noexcept { return type->isInt(); }
  405. bool var::isInt64() const noexcept { return type->isInt64(); }
  406. bool var::isBool() const noexcept { return type->isBool(); }
  407. bool var::isDouble() const noexcept { return type->isDouble(); }
  408. bool var::isString() const noexcept { return type->isString(); }
  409. bool var::isObject() const noexcept { return type->isObject(); }
  410. bool var::isArray() const noexcept { return type->isArray(); }
  411. bool var::isBinaryData() const noexcept { return type->isBinary(); }
  412. bool var::isMethod() const noexcept { return type->isMethod(); }
  413. var::operator int() const noexcept { return type->toInt (value); }
  414. var::operator int64() const noexcept { return type->toInt64 (value); }
  415. var::operator bool() const noexcept { return type->toBool (value); }
  416. var::operator float() const noexcept { return (float) type->toDouble (value); }
  417. var::operator double() const noexcept { return type->toDouble (value); }
  418. String var::toString() const { return type->toString (value); }
  419. var::operator String() const { return type->toString (value); }
  420. ReferenceCountedObject* var::getObject() const noexcept { return type->toObject (value); }
  421. Array<var>* var::getArray() const noexcept { return type->toArray (value); }
  422. MemoryBlock* var::getBinaryData() const noexcept { return type->toBinary (value); }
  423. DynamicObject* var::getDynamicObject() const noexcept { return dynamic_cast<DynamicObject*> (getObject()); }
  424. //==============================================================================
  425. void var::swapWith (var& other) noexcept
  426. {
  427. std::swap (type, other.type);
  428. std::swap (value, other.value);
  429. }
  430. var& var::operator= (const var& v) { type->cleanUp (value); type = v.type; type->createCopy (value, v.value); return *this; }
  431. var& var::operator= (const int v) { type->cleanUp (value); type = &VariantType_Int::instance; value.intValue = v; return *this; }
  432. var& var::operator= (const int64 v) { type->cleanUp (value); type = &VariantType_Int64::instance; value.int64Value = v; return *this; }
  433. var& var::operator= (const bool v) { type->cleanUp (value); type = &VariantType_Bool::instance; value.boolValue = v; return *this; }
  434. var& var::operator= (const double v) { type->cleanUp (value); type = &VariantType_Double::instance; value.doubleValue = v; return *this; }
  435. var& var::operator= (const char* const v) { type->cleanUp (value); type = &VariantType_String::instance; new (value.stringValue) String (v); return *this; }
  436. var& var::operator= (const wchar_t* const v) { type->cleanUp (value); type = &VariantType_String::instance; new (value.stringValue) String (v); return *this; }
  437. var& var::operator= (const String& v) { type->cleanUp (value); type = &VariantType_String::instance; new (value.stringValue) String (v); return *this; }
  438. var& var::operator= (const MemoryBlock& v) { type->cleanUp (value); type = &VariantType_Binary::instance; value.binaryValue = new MemoryBlock (v); return *this; }
  439. var& var::operator= (const Array<var>& v) { var v2 (v); swapWith (v2); return *this; }
  440. var& var::operator= (ReferenceCountedObject* v) { var v2 (v); swapWith (v2); return *this; }
  441. var& var::operator= (NativeFunction v) { var v2 (v); swapWith (v2); return *this; }
  442. var::var (var&& other) noexcept
  443. : type (other.type),
  444. value (other.value)
  445. {
  446. other.type = &VariantType_Void::instance;
  447. }
  448. var& var::operator= (var&& other) noexcept
  449. {
  450. swapWith (other);
  451. return *this;
  452. }
  453. var::var (String&& v) : type (&VariantType_String::instance)
  454. {
  455. new (value.stringValue) String (std::move (v));
  456. }
  457. var::var (MemoryBlock&& v) : type (&VariantType_Binary::instance)
  458. {
  459. value.binaryValue = new MemoryBlock (std::move (v));
  460. }
  461. var::var (Array<var>&& v) : type (&VariantType_Array::instance)
  462. {
  463. value.objectValue = new VariantType_Array::RefCountedArray (std::move (v));
  464. }
  465. var& var::operator= (String&& v)
  466. {
  467. type->cleanUp (value);
  468. type = &VariantType_String::instance;
  469. new (value.stringValue) String (std::move (v));
  470. return *this;
  471. }
  472. //==============================================================================
  473. bool var::equals (const var& other) const noexcept
  474. {
  475. return type->equals (value, other.value, *other.type);
  476. }
  477. bool var::equalsWithSameType (const var& other) const noexcept
  478. {
  479. return hasSameTypeAs (other) && equals (other);
  480. }
  481. bool var::hasSameTypeAs (const var& other) const noexcept
  482. {
  483. return type == other.type;
  484. }
  485. bool canCompare (const var& v1, const var& v2)
  486. {
  487. return v1.type->isComparable() && v2.type->isComparable();
  488. }
  489. static int compare (const var& v1, const var& v2)
  490. {
  491. if (v1.isString() && v2.isString())
  492. return v1.toString().compare (v2.toString());
  493. auto diff = static_cast<double> (v1) - static_cast<double> (v2);
  494. return diff == 0 ? 0 : (diff < 0 ? -1 : 1);
  495. }
  496. bool operator== (const var& v1, const var& v2) { return v1.equals (v2); }
  497. bool operator!= (const var& v1, const var& v2) { return ! v1.equals (v2); }
  498. bool operator< (const var& v1, const var& v2) { return canCompare (v1, v2) && compare (v1, v2) < 0; }
  499. bool operator> (const var& v1, const var& v2) { return canCompare (v1, v2) && compare (v1, v2) > 0; }
  500. bool operator<= (const var& v1, const var& v2) { return canCompare (v1, v2) && compare (v1, v2) <= 0; }
  501. bool operator>= (const var& v1, const var& v2) { return canCompare (v1, v2) && compare (v1, v2) >= 0; }
  502. bool operator== (const var& v1, const String& v2) { return v1.toString() == v2; }
  503. bool operator!= (const var& v1, const String& v2) { return v1.toString() != v2; }
  504. bool operator== (const var& v1, const char* v2) { return v1.toString() == v2; }
  505. bool operator!= (const var& v1, const char* v2) { return v1.toString() != v2; }
  506. //==============================================================================
  507. var var::clone() const noexcept
  508. {
  509. return type->clone (*this);
  510. }
  511. //==============================================================================
  512. const var& var::operator[] (const Identifier& propertyName) const
  513. {
  514. if (auto* o = getDynamicObject())
  515. return o->getProperty (propertyName);
  516. return getNullVarRef();
  517. }
  518. const var& var::operator[] (const char* const propertyName) const
  519. {
  520. return operator[] (Identifier (propertyName));
  521. }
  522. var var::getProperty (const Identifier& propertyName, const var& defaultReturnValue) const
  523. {
  524. if (auto* o = getDynamicObject())
  525. return o->getProperties().getWithDefault (propertyName, defaultReturnValue);
  526. return defaultReturnValue;
  527. }
  528. bool var::hasProperty (const Identifier& propertyName) const noexcept
  529. {
  530. if (auto* o = getDynamicObject())
  531. return o->hasProperty (propertyName);
  532. return false;
  533. }
  534. var::NativeFunction var::getNativeFunction() const
  535. {
  536. return isMethod() && (value.methodValue != nullptr) ? *value.methodValue : nullptr;
  537. }
  538. var var::invoke (const Identifier& method, const var* arguments, int numArguments) const
  539. {
  540. if (auto* o = getDynamicObject())
  541. return o->invokeMethod (method, var::NativeFunctionArgs (*this, arguments, numArguments));
  542. return {};
  543. }
  544. var var::call (const Identifier& method) const
  545. {
  546. return invoke (method, nullptr, 0);
  547. }
  548. var var::call (const Identifier& method, const var& arg1) const
  549. {
  550. return invoke (method, &arg1, 1);
  551. }
  552. var var::call (const Identifier& method, const var& arg1, const var& arg2) const
  553. {
  554. var args[] = { arg1, arg2 };
  555. return invoke (method, args, 2);
  556. }
  557. var var::call (const Identifier& method, const var& arg1, const var& arg2, const var& arg3)
  558. {
  559. var args[] = { arg1, arg2, arg3 };
  560. return invoke (method, args, 3);
  561. }
  562. var var::call (const Identifier& method, const var& arg1, const var& arg2, const var& arg3, const var& arg4) const
  563. {
  564. var args[] = { arg1, arg2, arg3, arg4 };
  565. return invoke (method, args, 4);
  566. }
  567. var var::call (const Identifier& method, const var& arg1, const var& arg2, const var& arg3, const var& arg4, const var& arg5) const
  568. {
  569. var args[] = { arg1, arg2, arg3, arg4, arg5 };
  570. return invoke (method, args, 5);
  571. }
  572. //==============================================================================
  573. int var::size() const
  574. {
  575. if (auto array = getArray())
  576. return array->size();
  577. return 0;
  578. }
  579. const var& var::operator[] (int arrayIndex) const
  580. {
  581. auto array = getArray();
  582. // When using this method, the var must actually be an array, and the index
  583. // must be in-range!
  584. jassert (array != nullptr && isPositiveAndBelow (arrayIndex, array->size()));
  585. return array->getReference (arrayIndex);
  586. }
  587. var& var::operator[] (int arrayIndex)
  588. {
  589. auto array = getArray();
  590. // When using this method, the var must actually be an array, and the index
  591. // must be in-range!
  592. jassert (array != nullptr && isPositiveAndBelow (arrayIndex, array->size()));
  593. return array->getReference (arrayIndex);
  594. }
  595. Array<var>* var::convertToArray()
  596. {
  597. if (auto array = getArray())
  598. return array;
  599. Array<var> tempVar;
  600. if (! isVoid())
  601. tempVar.add (*this);
  602. *this = tempVar;
  603. return getArray();
  604. }
  605. void var::append (const var& n)
  606. {
  607. convertToArray()->add (n);
  608. }
  609. void var::remove (const int index)
  610. {
  611. if (auto array = getArray())
  612. array->remove (index);
  613. }
  614. void var::insert (const int index, const var& n)
  615. {
  616. convertToArray()->insert (index, n);
  617. }
  618. void var::resize (const int numArrayElementsWanted)
  619. {
  620. convertToArray()->resize (numArrayElementsWanted);
  621. }
  622. int var::indexOf (const var& n) const
  623. {
  624. if (auto array = getArray())
  625. return array->indexOf (n);
  626. return -1;
  627. }
  628. //==============================================================================
  629. void var::writeToStream (OutputStream& output) const
  630. {
  631. type->writeToStream (value, output);
  632. }
  633. var var::readFromStream (InputStream& input)
  634. {
  635. const int numBytes = input.readCompressedInt();
  636. if (numBytes > 0)
  637. {
  638. switch (input.readByte())
  639. {
  640. case varMarker_Int: return var (input.readInt());
  641. case varMarker_Int64: return var (input.readInt64());
  642. case varMarker_BoolTrue: return var (true);
  643. case varMarker_BoolFalse: return var (false);
  644. case varMarker_Double: return var (input.readDouble());
  645. case varMarker_String:
  646. {
  647. MemoryOutputStream mo;
  648. mo.writeFromInputStream (input, numBytes - 1);
  649. return var (mo.toUTF8());
  650. }
  651. case varMarker_Binary:
  652. {
  653. MemoryBlock mb ((size_t) numBytes - 1);
  654. if (numBytes > 1)
  655. {
  656. const int numRead = input.read (mb.getData(), numBytes - 1);
  657. mb.setSize ((size_t) numRead);
  658. }
  659. return var (mb);
  660. }
  661. case varMarker_Array:
  662. {
  663. var v;
  664. auto* destArray = v.convertToArray();
  665. for (int i = input.readCompressedInt(); --i >= 0;)
  666. destArray->add (readFromStream (input));
  667. return v;
  668. }
  669. default:
  670. input.skipNextBytes (numBytes - 1); break;
  671. }
  672. }
  673. return {};
  674. }
  675. var::NativeFunctionArgs::NativeFunctionArgs (const var& t, const var* args, int numArgs) noexcept
  676. : thisObject (t), arguments (args), numArguments (numArgs)
  677. {
  678. }
  679. } // namespace juce