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.

710 lines
30KB

  1. /*
  2. ==============================================================================
  3. This file is part of the juce_core module of the JUCE library.
  4. Copyright (c) 2013 - Raw Material Software Ltd.
  5. Permission to use, copy, modify, and/or distribute this software for any purpose with
  6. or without fee is hereby granted, provided that the above copyright notice and this
  7. permission notice appear in all copies.
  8. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
  9. TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
  10. NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  11. DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
  12. IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  13. CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  14. ------------------------------------------------------------------------------
  15. NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
  16. All other JUCE modules are covered by a dual GPL/commercial license, so if you are
  17. using any other modules, be sure to check that you also comply with their license.
  18. For more details, visit www.juce.com
  19. ==============================================================================
  20. */
  21. enum VariantStreamMarkers
  22. {
  23. varMarker_Int = 1,
  24. varMarker_BoolTrue = 2,
  25. varMarker_BoolFalse = 3,
  26. varMarker_Double = 4,
  27. varMarker_String = 5,
  28. varMarker_Int64 = 6,
  29. varMarker_Array = 7,
  30. varMarker_Binary = 8
  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::empty; }
  42. virtual bool toBool (const ValueUnion&) const noexcept { return false; }
  43. virtual ReferenceCountedObject* toObject (const ValueUnion&) const noexcept { return nullptr; }
  44. virtual Array<var>* toArray (const ValueUnion&) const noexcept { return nullptr; }
  45. virtual MemoryBlock* toBinary (const ValueUnion&) const noexcept { return nullptr; }
  46. virtual bool isVoid() const noexcept { return false; }
  47. virtual bool isInt() const noexcept { return false; }
  48. virtual bool isInt64() const noexcept { return false; }
  49. virtual bool isBool() const noexcept { return false; }
  50. virtual bool isDouble() const noexcept { return false; }
  51. virtual bool isString() const noexcept { return false; }
  52. virtual bool isObject() const noexcept { return false; }
  53. virtual bool isArray() const noexcept { return false; }
  54. virtual bool isBinary() const noexcept { return false; }
  55. virtual bool isMethod() const noexcept { return false; }
  56. virtual void cleanUp (ValueUnion&) const noexcept {}
  57. virtual void createCopy (ValueUnion& dest, const ValueUnion& source) const { dest = source; }
  58. virtual bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept = 0;
  59. virtual void writeToStream (const ValueUnion& data, OutputStream& output) const = 0;
  60. };
  61. //==============================================================================
  62. class var::VariantType_Void : public var::VariantType
  63. {
  64. public:
  65. VariantType_Void() noexcept {}
  66. static const VariantType_Void instance;
  67. bool isVoid() const noexcept { return true; }
  68. bool equals (const ValueUnion&, const ValueUnion&, const VariantType& otherType) const noexcept { return otherType.isVoid(); }
  69. void writeToStream (const ValueUnion&, OutputStream& output) const { output.writeCompressedInt (0); }
  70. };
  71. //==============================================================================
  72. class var::VariantType_Int : public var::VariantType
  73. {
  74. public:
  75. VariantType_Int() noexcept {}
  76. static const VariantType_Int instance;
  77. int toInt (const ValueUnion& data) const noexcept { return data.intValue; };
  78. int64 toInt64 (const ValueUnion& data) const noexcept { return (int64) data.intValue; };
  79. double toDouble (const ValueUnion& data) const noexcept { return (double) data.intValue; }
  80. String toString (const ValueUnion& data) const { return String (data.intValue); }
  81. bool toBool (const ValueUnion& data) const noexcept { return data.intValue != 0; }
  82. bool isInt() const noexcept { return true; }
  83. bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept
  84. {
  85. return otherType.toInt (otherData) == data.intValue;
  86. }
  87. void writeToStream (const ValueUnion& data, OutputStream& output) const
  88. {
  89. output.writeCompressedInt (5);
  90. output.writeByte (varMarker_Int);
  91. output.writeInt (data.intValue);
  92. }
  93. };
  94. //==============================================================================
  95. class var::VariantType_Int64 : public var::VariantType
  96. {
  97. public:
  98. VariantType_Int64() noexcept {}
  99. static const VariantType_Int64 instance;
  100. int toInt (const ValueUnion& data) const noexcept { return (int) data.int64Value; };
  101. int64 toInt64 (const ValueUnion& data) const noexcept { return data.int64Value; };
  102. double toDouble (const ValueUnion& data) const noexcept { return (double) data.int64Value; }
  103. String toString (const ValueUnion& data) const { return String (data.int64Value); }
  104. bool toBool (const ValueUnion& data) const noexcept { return data.int64Value != 0; }
  105. bool isInt64() const noexcept { return true; }
  106. bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept
  107. {
  108. return otherType.toInt64 (otherData) == data.int64Value;
  109. }
  110. void writeToStream (const ValueUnion& data, OutputStream& output) const
  111. {
  112. output.writeCompressedInt (9);
  113. output.writeByte (varMarker_Int64);
  114. output.writeInt64 (data.int64Value);
  115. }
  116. };
  117. //==============================================================================
  118. class var::VariantType_Double : public var::VariantType
  119. {
  120. public:
  121. VariantType_Double() noexcept {}
  122. static const VariantType_Double instance;
  123. int toInt (const ValueUnion& data) const noexcept { return (int) data.doubleValue; };
  124. int64 toInt64 (const ValueUnion& data) const noexcept { return (int64) data.doubleValue; };
  125. double toDouble (const ValueUnion& data) const noexcept { return data.doubleValue; }
  126. String toString (const ValueUnion& data) const { return String (data.doubleValue); }
  127. bool toBool (const ValueUnion& data) const noexcept { return data.doubleValue != 0; }
  128. bool isDouble() const noexcept { return true; }
  129. bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept
  130. {
  131. return std::abs (otherType.toDouble (otherData) - data.doubleValue) < std::numeric_limits<double>::epsilon();
  132. }
  133. void writeToStream (const ValueUnion& data, OutputStream& output) const
  134. {
  135. output.writeCompressedInt (9);
  136. output.writeByte (varMarker_Double);
  137. output.writeDouble (data.doubleValue);
  138. }
  139. };
  140. //==============================================================================
  141. class var::VariantType_Bool : public var::VariantType
  142. {
  143. public:
  144. VariantType_Bool() noexcept {}
  145. static const VariantType_Bool instance;
  146. int toInt (const ValueUnion& data) const noexcept { return data.boolValue ? 1 : 0; };
  147. int64 toInt64 (const ValueUnion& data) const noexcept { return data.boolValue ? 1 : 0; };
  148. double toDouble (const ValueUnion& data) const noexcept { return data.boolValue ? 1.0 : 0.0; }
  149. String toString (const ValueUnion& data) const { return String::charToString (data.boolValue ? (juce_wchar) '1' : (juce_wchar) '0'); }
  150. bool toBool (const ValueUnion& data) const noexcept { return data.boolValue; }
  151. bool isBool() const noexcept { return true; }
  152. bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept
  153. {
  154. return otherType.toBool (otherData) == data.boolValue;
  155. }
  156. void writeToStream (const ValueUnion& data, OutputStream& output) const
  157. {
  158. output.writeCompressedInt (1);
  159. output.writeByte (data.boolValue ? (char) varMarker_BoolTrue : (char) varMarker_BoolFalse);
  160. }
  161. };
  162. //==============================================================================
  163. class var::VariantType_String : public var::VariantType
  164. {
  165. public:
  166. VariantType_String() noexcept {}
  167. static const VariantType_String instance;
  168. void cleanUp (ValueUnion& data) const noexcept { getString (data)-> ~String(); }
  169. void createCopy (ValueUnion& dest, const ValueUnion& source) const { new (dest.stringValue) String (*getString (source)); }
  170. bool isString() const noexcept { return true; }
  171. int toInt (const ValueUnion& data) const noexcept { return getString (data)->getIntValue(); };
  172. int64 toInt64 (const ValueUnion& data) const noexcept { return getString (data)->getLargeIntValue(); };
  173. double toDouble (const ValueUnion& data) const noexcept { return getString (data)->getDoubleValue(); }
  174. String toString (const ValueUnion& data) const { return *getString (data); }
  175. bool toBool (const ValueUnion& data) const noexcept { return getString (data)->getIntValue() != 0
  176. || getString (data)->trim().equalsIgnoreCase ("true")
  177. || getString (data)->trim().equalsIgnoreCase ("yes"); }
  178. bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept
  179. {
  180. return otherType.toString (otherData) == *getString (data);
  181. }
  182. void writeToStream (const ValueUnion& data, OutputStream& output) const
  183. {
  184. const String* const s = getString (data);
  185. const size_t len = s->getNumBytesAsUTF8() + 1;
  186. HeapBlock<char> temp (len);
  187. s->copyToUTF8 (temp, len);
  188. output.writeCompressedInt ((int) (len + 1));
  189. output.writeByte (varMarker_String);
  190. output.write (temp, len);
  191. }
  192. private:
  193. static inline const String* getString (const ValueUnion& data) noexcept { return reinterpret_cast <const String*> (data.stringValue); }
  194. static inline String* getString (ValueUnion& data) noexcept { return reinterpret_cast <String*> (data.stringValue); }
  195. };
  196. //==============================================================================
  197. class var::VariantType_Object : public var::VariantType
  198. {
  199. public:
  200. VariantType_Object() noexcept {}
  201. static const VariantType_Object instance;
  202. void cleanUp (ValueUnion& data) const noexcept { if (data.objectValue != nullptr) data.objectValue->decReferenceCount(); }
  203. void createCopy (ValueUnion& dest, const ValueUnion& source) const
  204. {
  205. dest.objectValue = source.objectValue;
  206. if (dest.objectValue != nullptr)
  207. dest.objectValue->incReferenceCount();
  208. }
  209. String toString (const ValueUnion& data) const { return "Object 0x" + String::toHexString ((int) (pointer_sized_int) data.objectValue); }
  210. bool toBool (const ValueUnion& data) const noexcept { return data.objectValue != 0; }
  211. ReferenceCountedObject* toObject (const ValueUnion& data) const noexcept { return data.objectValue; }
  212. bool isObject() const noexcept { return true; }
  213. bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept
  214. {
  215. return otherType.toObject (otherData) == data.objectValue;
  216. }
  217. void writeToStream (const ValueUnion&, OutputStream& output) const
  218. {
  219. jassertfalse; // Can't write an object to a stream!
  220. output.writeCompressedInt (0);
  221. }
  222. };
  223. //==============================================================================
  224. class var::VariantType_Array : public var::VariantType
  225. {
  226. public:
  227. VariantType_Array() noexcept {}
  228. static const VariantType_Array instance;
  229. void cleanUp (ValueUnion& data) const noexcept { delete data.arrayValue; }
  230. void createCopy (ValueUnion& dest, const ValueUnion& source) const { dest.arrayValue = new Array<var> (*(source.arrayValue)); }
  231. String toString (const ValueUnion&) const { return "[Array]"; }
  232. bool isArray() const noexcept { return true; }
  233. Array<var>* toArray (const ValueUnion& data) const noexcept { return data.arrayValue; }
  234. bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept
  235. {
  236. const Array<var>* const otherArray = otherType.toArray (otherData);
  237. return otherArray != nullptr && *otherArray == *(data.arrayValue);
  238. }
  239. void writeToStream (const ValueUnion& data, OutputStream& output) const
  240. {
  241. MemoryOutputStream buffer (512);
  242. const int numItems = data.arrayValue->size();
  243. buffer.writeCompressedInt (numItems);
  244. for (int i = 0; i < numItems; ++i)
  245. data.arrayValue->getReference(i).writeToStream (buffer);
  246. output.writeCompressedInt (1 + (int) buffer.getDataSize());
  247. output.writeByte (varMarker_Array);
  248. output << buffer;
  249. }
  250. };
  251. //==============================================================================
  252. class var::VariantType_Binary : public var::VariantType
  253. {
  254. public:
  255. VariantType_Binary() noexcept {}
  256. static const VariantType_Binary instance;
  257. void cleanUp (ValueUnion& data) const noexcept { delete data.binaryValue; }
  258. void createCopy (ValueUnion& dest, const ValueUnion& source) const { dest.binaryValue = new MemoryBlock (*source.binaryValue); }
  259. String toString (const ValueUnion& data) const { return data.binaryValue->toBase64Encoding(); }
  260. bool isBinary() const noexcept { return true; }
  261. MemoryBlock* toBinary (const ValueUnion& data) const noexcept { return data.binaryValue; }
  262. bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept
  263. {
  264. const MemoryBlock* const otherBlock = otherType.toBinary (otherData);
  265. return otherBlock != nullptr && *otherBlock == *data.binaryValue;
  266. }
  267. void writeToStream (const ValueUnion& data, OutputStream& output) const
  268. {
  269. output.writeCompressedInt (1 + (int) data.binaryValue->getSize());
  270. output.writeByte (varMarker_Binary);
  271. output << *data.binaryValue;
  272. }
  273. };
  274. //==============================================================================
  275. class var::VariantType_Method : public var::VariantType
  276. {
  277. public:
  278. VariantType_Method() noexcept {}
  279. static const VariantType_Method instance;
  280. String toString (const ValueUnion&) const { return "Method"; }
  281. bool toBool (const ValueUnion& data) const noexcept { return data.methodValue != nullptr; }
  282. bool isMethod() const noexcept { return true; }
  283. bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept
  284. {
  285. return otherType.isMethod() && otherData.methodValue == data.methodValue;
  286. }
  287. void writeToStream (const ValueUnion&, OutputStream& output) const
  288. {
  289. jassertfalse; // Can't write a method to a stream!
  290. output.writeCompressedInt (0);
  291. }
  292. };
  293. //==============================================================================
  294. const var::VariantType_Void var::VariantType_Void::instance;
  295. const var::VariantType_Int var::VariantType_Int::instance;
  296. const var::VariantType_Int64 var::VariantType_Int64::instance;
  297. const var::VariantType_Bool var::VariantType_Bool::instance;
  298. const var::VariantType_Double var::VariantType_Double::instance;
  299. const var::VariantType_String var::VariantType_String::instance;
  300. const var::VariantType_Object var::VariantType_Object::instance;
  301. const var::VariantType_Array var::VariantType_Array::instance;
  302. const var::VariantType_Binary var::VariantType_Binary::instance;
  303. const var::VariantType_Method var::VariantType_Method::instance;
  304. //==============================================================================
  305. var::var() noexcept : type (&VariantType_Void::instance)
  306. {
  307. }
  308. var::~var() noexcept
  309. {
  310. type->cleanUp (value);
  311. }
  312. const var var::null;
  313. //==============================================================================
  314. var::var (const var& valueToCopy) : type (valueToCopy.type)
  315. {
  316. type->createCopy (value, valueToCopy.value);
  317. }
  318. var::var (const int v) noexcept : type (&VariantType_Int::instance) { value.intValue = v; }
  319. var::var (const int64 v) noexcept : type (&VariantType_Int64::instance) { value.int64Value = v; }
  320. var::var (const bool v) noexcept : type (&VariantType_Bool::instance) { value.boolValue = v; }
  321. var::var (const double v) noexcept : type (&VariantType_Double::instance) { value.doubleValue = v; }
  322. var::var (MethodFunction m) noexcept : type (&VariantType_Method::instance) { value.methodValue = m; }
  323. var::var (const Array<var>& v) : type (&VariantType_Array::instance) { value.arrayValue = new Array<var> (v); }
  324. var::var (const String& v) : type (&VariantType_String::instance) { new (value.stringValue) String (v); }
  325. var::var (const char* const v) : type (&VariantType_String::instance) { new (value.stringValue) String (v); }
  326. var::var (const wchar_t* const v) : type (&VariantType_String::instance) { new (value.stringValue) String (v); }
  327. var::var (const void* v, size_t sz) : type (&VariantType_Binary::instance) { value.binaryValue = new MemoryBlock (v, sz); }
  328. var::var (const MemoryBlock& v) : type (&VariantType_Binary::instance) { value.binaryValue = new MemoryBlock (v); }
  329. var::var (ReferenceCountedObject* const object) : type (&VariantType_Object::instance)
  330. {
  331. value.objectValue = object;
  332. if (object != nullptr)
  333. object->incReferenceCount();
  334. }
  335. //==============================================================================
  336. bool var::isVoid() const noexcept { return type->isVoid(); }
  337. bool var::isInt() const noexcept { return type->isInt(); }
  338. bool var::isInt64() const noexcept { return type->isInt64(); }
  339. bool var::isBool() const noexcept { return type->isBool(); }
  340. bool var::isDouble() const noexcept { return type->isDouble(); }
  341. bool var::isString() const noexcept { return type->isString(); }
  342. bool var::isObject() const noexcept { return type->isObject(); }
  343. bool var::isArray() const noexcept { return type->isArray(); }
  344. bool var::isBinaryData() const noexcept { return type->isBinary(); }
  345. bool var::isMethod() const noexcept { return type->isMethod(); }
  346. var::operator int() const noexcept { return type->toInt (value); }
  347. var::operator int64() const noexcept { return type->toInt64 (value); }
  348. var::operator bool() const noexcept { return type->toBool (value); }
  349. var::operator float() const noexcept { return (float) type->toDouble (value); }
  350. var::operator double() const noexcept { return type->toDouble (value); }
  351. String var::toString() const { return type->toString (value); }
  352. var::operator String() const { return type->toString (value); }
  353. ReferenceCountedObject* var::getObject() const noexcept { return type->toObject (value); }
  354. Array<var>* var::getArray() const noexcept { return type->toArray (value); }
  355. MemoryBlock* var::getBinaryData() const noexcept { return type->toBinary (value); }
  356. DynamicObject* var::getDynamicObject() const noexcept { return dynamic_cast <DynamicObject*> (getObject()); }
  357. //==============================================================================
  358. void var::swapWith (var& other) noexcept
  359. {
  360. std::swap (type, other.type);
  361. std::swap (value, other.value);
  362. }
  363. var& var::operator= (const var& v) { type->cleanUp (value); type = v.type; type->createCopy (value, v.value); return *this; }
  364. var& var::operator= (const int v) { type->cleanUp (value); type = &VariantType_Int::instance; value.intValue = v; return *this; }
  365. var& var::operator= (const int64 v) { type->cleanUp (value); type = &VariantType_Int64::instance; value.int64Value = v; return *this; }
  366. var& var::operator= (const bool v) { type->cleanUp (value); type = &VariantType_Bool::instance; value.boolValue = v; return *this; }
  367. var& var::operator= (const double v) { type->cleanUp (value); type = &VariantType_Double::instance; value.doubleValue = v; return *this; }
  368. var& var::operator= (const char* const v) { type->cleanUp (value); type = &VariantType_String::instance; new (value.stringValue) String (v); return *this; }
  369. var& var::operator= (const wchar_t* const v) { type->cleanUp (value); type = &VariantType_String::instance; new (value.stringValue) String (v); return *this; }
  370. var& var::operator= (const String& v) { type->cleanUp (value); type = &VariantType_String::instance; new (value.stringValue) String (v); return *this; }
  371. var& var::operator= (const Array<var>& v) { var v2 (v); swapWith (v2); return *this; }
  372. var& var::operator= (ReferenceCountedObject* v) { var v2 (v); swapWith (v2); return *this; }
  373. var& var::operator= (MethodFunction v) { var v2 (v); swapWith (v2); return *this; }
  374. #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
  375. var::var (var&& other) noexcept
  376. : type (other.type),
  377. value (other.value)
  378. {
  379. other.type = &VariantType_Void::instance;
  380. }
  381. var& var::operator= (var&& other) noexcept
  382. {
  383. swapWith (other);
  384. return *this;
  385. }
  386. var::var (String&& v) : type (&VariantType_String::instance)
  387. {
  388. new (value.stringValue) String (static_cast<String&&> (v));
  389. }
  390. var::var (MemoryBlock&& v) : type (&VariantType_Binary::instance)
  391. {
  392. value.binaryValue = new MemoryBlock (static_cast<MemoryBlock&&> (v));
  393. }
  394. var& var::operator= (String&& v)
  395. {
  396. type->cleanUp (value);
  397. type = &VariantType_String::instance;
  398. new (value.stringValue) String (static_cast<String&&> (v));
  399. return *this;
  400. }
  401. #endif
  402. //==============================================================================
  403. bool var::equals (const var& other) const noexcept
  404. {
  405. return type->equals (value, other.value, *other.type);
  406. }
  407. bool var::equalsWithSameType (const var& other) const noexcept
  408. {
  409. return type == other.type && equals (other);
  410. }
  411. bool operator== (const var& v1, const var& v2) noexcept { return v1.equals (v2); }
  412. bool operator!= (const var& v1, const var& v2) noexcept { return ! v1.equals (v2); }
  413. bool operator== (const var& v1, const String& v2) { return v1.toString() == v2; }
  414. bool operator!= (const var& v1, const String& v2) { return v1.toString() != v2; }
  415. bool operator== (const var& v1, const char* const v2) { return v1.toString() == v2; }
  416. bool operator!= (const var& v1, const char* const v2) { return v1.toString() != v2; }
  417. //==============================================================================
  418. var var::operator[] (const Identifier propertyName) const
  419. {
  420. if (DynamicObject* const o = getDynamicObject())
  421. return o->getProperty (propertyName);
  422. return var::null;
  423. }
  424. var var::operator[] (const char* const propertyName) const
  425. {
  426. return operator[] (Identifier (propertyName));
  427. }
  428. var var::getProperty (const Identifier propertyName, const var& defaultReturnValue) const
  429. {
  430. if (DynamicObject* const o = getDynamicObject())
  431. return o->getProperties().getWithDefault (propertyName, defaultReturnValue);
  432. return defaultReturnValue;
  433. }
  434. var var::invoke (const Identifier method, const var* arguments, int numArguments) const
  435. {
  436. if (DynamicObject* const o = getDynamicObject())
  437. return o->invokeMethod (method, arguments, numArguments);
  438. return var::null;
  439. }
  440. var var::invokeMethod (DynamicObject* const target, const var* const arguments, const int numArguments) const
  441. {
  442. jassert (target != nullptr);
  443. if (isMethod())
  444. return (target->*(value.methodValue)) (arguments, numArguments);
  445. return var::null;
  446. }
  447. var var::call (const Identifier method) const
  448. {
  449. return invoke (method, nullptr, 0);
  450. }
  451. var var::call (const Identifier method, const var& arg1) const
  452. {
  453. return invoke (method, &arg1, 1);
  454. }
  455. var var::call (const Identifier method, const var& arg1, const var& arg2) const
  456. {
  457. var args[] = { arg1, arg2 };
  458. return invoke (method, args, 2);
  459. }
  460. var var::call (const Identifier method, const var& arg1, const var& arg2, const var& arg3)
  461. {
  462. var args[] = { arg1, arg2, arg3 };
  463. return invoke (method, args, 3);
  464. }
  465. var var::call (const Identifier method, const var& arg1, const var& arg2, const var& arg3, const var& arg4) const
  466. {
  467. var args[] = { arg1, arg2, arg3, arg4 };
  468. return invoke (method, args, 4);
  469. }
  470. var var::call (const Identifier method, const var& arg1, const var& arg2, const var& arg3, const var& arg4, const var& arg5) const
  471. {
  472. var args[] = { arg1, arg2, arg3, arg4, arg5 };
  473. return invoke (method, args, 5);
  474. }
  475. //==============================================================================
  476. int var::size() const
  477. {
  478. if (const Array<var>* const array = getArray())
  479. return array->size();
  480. return 0;
  481. }
  482. const var& var::operator[] (int arrayIndex) const
  483. {
  484. const Array<var>* const array = getArray();
  485. // When using this method, the var must actually be an array, and the index
  486. // must be in-range!
  487. jassert (array != nullptr && isPositiveAndBelow (arrayIndex, array->size()));
  488. return array->getReference (arrayIndex);
  489. }
  490. var& var::operator[] (int arrayIndex)
  491. {
  492. const Array<var>* const array = getArray();
  493. // When using this method, the var must actually be an array, and the index
  494. // must be in-range!
  495. jassert (array != nullptr && isPositiveAndBelow (arrayIndex, array->size()));
  496. return array->getReference (arrayIndex);
  497. }
  498. Array<var>* var::convertToArray()
  499. {
  500. Array<var>* array = getArray();
  501. if (array == nullptr)
  502. {
  503. const Array<var> tempVar;
  504. var v (tempVar);
  505. array = v.value.arrayValue;
  506. if (! isVoid())
  507. array->add (*this);
  508. swapWith (v);
  509. }
  510. return array;
  511. }
  512. void var::append (const var& n)
  513. {
  514. convertToArray()->add (n);
  515. }
  516. void var::remove (const int index)
  517. {
  518. if (Array<var>* const array = getArray())
  519. array->remove (index);
  520. }
  521. void var::insert (const int index, const var& n)
  522. {
  523. convertToArray()->insert (index, n);
  524. }
  525. void var::resize (const int numArrayElementsWanted)
  526. {
  527. convertToArray()->resize (numArrayElementsWanted);
  528. }
  529. int var::indexOf (const var& n) const
  530. {
  531. if (const Array<var>* const array = getArray())
  532. return array->indexOf (n);
  533. return -1;
  534. }
  535. //==============================================================================
  536. void var::writeToStream (OutputStream& output) const
  537. {
  538. type->writeToStream (value, output);
  539. }
  540. var var::readFromStream (InputStream& input)
  541. {
  542. const int numBytes = input.readCompressedInt();
  543. if (numBytes > 0)
  544. {
  545. switch (input.readByte())
  546. {
  547. case varMarker_Int: return var (input.readInt());
  548. case varMarker_Int64: return var (input.readInt64());
  549. case varMarker_BoolTrue: return var (true);
  550. case varMarker_BoolFalse: return var (false);
  551. case varMarker_Double: return var (input.readDouble());
  552. case varMarker_String:
  553. {
  554. MemoryOutputStream mo;
  555. mo.writeFromInputStream (input, numBytes - 1);
  556. return var (mo.toUTF8());
  557. }
  558. case varMarker_Binary:
  559. {
  560. MemoryBlock mb ((size_t) numBytes - 1);
  561. if (numBytes > 1)
  562. {
  563. const int numRead = input.read (mb.getData(), numBytes - 1);
  564. mb.setSize ((size_t) numRead);
  565. }
  566. return var (mb);
  567. }
  568. case varMarker_Array:
  569. {
  570. var v;
  571. Array<var>* const destArray = v.convertToArray();
  572. for (int i = input.readCompressedInt(); --i >= 0;)
  573. destArray->add (readFromStream (input));
  574. return v;
  575. }
  576. default:
  577. input.skipNextBytes (numBytes - 1); break;
  578. }
  579. }
  580. return var::null;
  581. }