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.

707 lines
29KB

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