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.

653 lines
27KB

  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. BEGIN_JUCE_NAMESPACE
  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. };
  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 0; }
  42. virtual bool isVoid() const noexcept { return false; }
  43. virtual bool isInt() const noexcept { return false; }
  44. virtual bool isInt64() const noexcept { return false; }
  45. virtual bool isBool() const noexcept { return false; }
  46. virtual bool isDouble() const noexcept { return false; }
  47. virtual bool isString() const noexcept { return false; }
  48. virtual bool isObject() const noexcept { return false; }
  49. virtual bool isArray() const noexcept { return false; }
  50. virtual bool isMethod() const noexcept { return false; }
  51. virtual void cleanUp (ValueUnion&) const noexcept {}
  52. virtual void createCopy (ValueUnion& dest, const ValueUnion& source) const { dest = source; }
  53. virtual bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept = 0;
  54. virtual void writeToStream (const ValueUnion& data, OutputStream& output) const = 0;
  55. };
  56. //==============================================================================
  57. class var::VariantType_Void : public var::VariantType
  58. {
  59. public:
  60. VariantType_Void() noexcept {}
  61. static const VariantType_Void instance;
  62. bool isVoid() const noexcept { return true; }
  63. bool equals (const ValueUnion&, const ValueUnion&, const VariantType& otherType) const noexcept { return otherType.isVoid(); }
  64. void writeToStream (const ValueUnion&, OutputStream& output) const { output.writeCompressedInt (0); }
  65. };
  66. //==============================================================================
  67. class var::VariantType_Int : public var::VariantType
  68. {
  69. public:
  70. VariantType_Int() noexcept {}
  71. static const VariantType_Int instance;
  72. int toInt (const ValueUnion& data) const noexcept { return data.intValue; };
  73. int64 toInt64 (const ValueUnion& data) const noexcept { return (int64) data.intValue; };
  74. double toDouble (const ValueUnion& data) const noexcept { return (double) data.intValue; }
  75. String toString (const ValueUnion& data) const { return String (data.intValue); }
  76. bool toBool (const ValueUnion& data) const noexcept { return data.intValue != 0; }
  77. bool isInt() const noexcept { return true; }
  78. bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept
  79. {
  80. return otherType.toInt (otherData) == data.intValue;
  81. }
  82. void writeToStream (const ValueUnion& data, OutputStream& output) const
  83. {
  84. output.writeCompressedInt (5);
  85. output.writeByte (varMarker_Int);
  86. output.writeInt (data.intValue);
  87. }
  88. };
  89. //==============================================================================
  90. class var::VariantType_Int64 : public var::VariantType
  91. {
  92. public:
  93. VariantType_Int64() noexcept {}
  94. static const VariantType_Int64 instance;
  95. int toInt (const ValueUnion& data) const noexcept { return (int) data.int64Value; };
  96. int64 toInt64 (const ValueUnion& data) const noexcept { return data.int64Value; };
  97. double toDouble (const ValueUnion& data) const noexcept { return (double) data.int64Value; }
  98. String toString (const ValueUnion& data) const { return String (data.int64Value); }
  99. bool toBool (const ValueUnion& data) const noexcept { return data.int64Value != 0; }
  100. bool isInt64() const noexcept { return true; }
  101. bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept
  102. {
  103. return otherType.toInt64 (otherData) == data.int64Value;
  104. }
  105. void writeToStream (const ValueUnion& data, OutputStream& output) const
  106. {
  107. output.writeCompressedInt (9);
  108. output.writeByte (varMarker_Int64);
  109. output.writeInt64 (data.int64Value);
  110. }
  111. };
  112. //==============================================================================
  113. class var::VariantType_Double : public var::VariantType
  114. {
  115. public:
  116. VariantType_Double() noexcept {}
  117. static const VariantType_Double instance;
  118. int toInt (const ValueUnion& data) const noexcept { return (int) data.doubleValue; };
  119. int64 toInt64 (const ValueUnion& data) const noexcept { return (int64) data.doubleValue; };
  120. double toDouble (const ValueUnion& data) const noexcept { return data.doubleValue; }
  121. String toString (const ValueUnion& data) const { return String (data.doubleValue); }
  122. bool toBool (const ValueUnion& data) const noexcept { return data.doubleValue != 0; }
  123. bool isDouble() const noexcept { return true; }
  124. bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept
  125. {
  126. return otherType.toDouble (otherData) == data.doubleValue;
  127. }
  128. void writeToStream (const ValueUnion& data, OutputStream& output) const
  129. {
  130. output.writeCompressedInt (9);
  131. output.writeByte (varMarker_Double);
  132. output.writeDouble (data.doubleValue);
  133. }
  134. };
  135. //==============================================================================
  136. class var::VariantType_Bool : public var::VariantType
  137. {
  138. public:
  139. VariantType_Bool() noexcept {}
  140. static const VariantType_Bool instance;
  141. int toInt (const ValueUnion& data) const noexcept { return data.boolValue ? 1 : 0; };
  142. int64 toInt64 (const ValueUnion& data) const noexcept { return data.boolValue ? 1 : 0; };
  143. double toDouble (const ValueUnion& data) const noexcept { return data.boolValue ? 1.0 : 0.0; }
  144. String toString (const ValueUnion& data) const { return String::charToString (data.boolValue ? (juce_wchar) '1' : (juce_wchar) '0'); }
  145. bool toBool (const ValueUnion& data) const noexcept { return data.boolValue; }
  146. bool isBool() const noexcept { return true; }
  147. bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept
  148. {
  149. return otherType.toBool (otherData) == data.boolValue;
  150. }
  151. void writeToStream (const ValueUnion& data, OutputStream& output) const
  152. {
  153. output.writeCompressedInt (1);
  154. output.writeByte (data.boolValue ? (char) varMarker_BoolTrue : (char) varMarker_BoolFalse);
  155. }
  156. };
  157. //==============================================================================
  158. class var::VariantType_String : public var::VariantType
  159. {
  160. public:
  161. VariantType_String() noexcept {}
  162. static const VariantType_String instance;
  163. void cleanUp (ValueUnion& data) const noexcept { getString (data)-> ~String(); }
  164. void createCopy (ValueUnion& dest, const ValueUnion& source) const { new (dest.stringValue) String (*getString (source)); }
  165. bool isString() const noexcept { return true; }
  166. int toInt (const ValueUnion& data) const noexcept { return getString (data)->getIntValue(); };
  167. int64 toInt64 (const ValueUnion& data) const noexcept { return getString (data)->getLargeIntValue(); };
  168. double toDouble (const ValueUnion& data) const noexcept { return getString (data)->getDoubleValue(); }
  169. String toString (const ValueUnion& data) const { return *getString (data); }
  170. bool toBool (const ValueUnion& data) const noexcept { return getString (data)->getIntValue() != 0
  171. || getString (data)->trim().equalsIgnoreCase ("true")
  172. || getString (data)->trim().equalsIgnoreCase ("yes"); }
  173. bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept
  174. {
  175. return otherType.toString (otherData) == *getString (data);
  176. }
  177. void writeToStream (const ValueUnion& data, OutputStream& output) const
  178. {
  179. const String* const s = getString (data);
  180. const int len = s->getNumBytesAsUTF8() + 1;
  181. HeapBlock<char> temp ((size_t) len);
  182. s->copyToUTF8 (temp, len);
  183. output.writeCompressedInt (len + 1);
  184. output.writeByte (varMarker_String);
  185. output.write (temp, len);
  186. }
  187. private:
  188. static inline const String* getString (const ValueUnion& data) noexcept { return reinterpret_cast <const String*> (data.stringValue); }
  189. static inline String* getString (ValueUnion& data) noexcept { return reinterpret_cast <String*> (data.stringValue); }
  190. };
  191. //==============================================================================
  192. class var::VariantType_Object : public var::VariantType
  193. {
  194. public:
  195. VariantType_Object() noexcept {}
  196. static const VariantType_Object instance;
  197. void cleanUp (ValueUnion& data) const noexcept { if (data.objectValue != nullptr) data.objectValue->decReferenceCount(); }
  198. void createCopy (ValueUnion& dest, const ValueUnion& source) const
  199. {
  200. dest.objectValue = source.objectValue;
  201. if (dest.objectValue != nullptr)
  202. dest.objectValue->incReferenceCount();
  203. }
  204. String toString (const ValueUnion& data) const { return "Object 0x" + String::toHexString ((int) (pointer_sized_int) data.objectValue); }
  205. bool toBool (const ValueUnion& data) const noexcept { return data.objectValue != 0; }
  206. ReferenceCountedObject* toObject (const ValueUnion& data) const noexcept { return data.objectValue; }
  207. bool isObject() const noexcept { return true; }
  208. bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept
  209. {
  210. return otherType.toObject (otherData) == data.objectValue;
  211. }
  212. void writeToStream (const ValueUnion&, OutputStream& output) const
  213. {
  214. jassertfalse; // Can't write an object to a stream!
  215. output.writeCompressedInt (0);
  216. }
  217. };
  218. //==============================================================================
  219. class var::VariantType_Array : public var::VariantType
  220. {
  221. public:
  222. VariantType_Array() noexcept {}
  223. static const VariantType_Array instance;
  224. void cleanUp (ValueUnion& data) const noexcept { delete data.arrayValue; }
  225. void createCopy (ValueUnion& dest, const ValueUnion& source) const { dest.arrayValue = new Array<var> (*(source.arrayValue)); }
  226. String toString (const ValueUnion&) const { return "[Array]"; }
  227. bool isArray() const noexcept { return true; }
  228. Array<var>* toArray (const ValueUnion& data) const noexcept { return data.arrayValue; }
  229. bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept
  230. {
  231. const Array<var>* const otherArray = otherType.toArray (otherData);
  232. return otherArray != nullptr && *otherArray == *(data.arrayValue);
  233. }
  234. void writeToStream (const ValueUnion& data, OutputStream& output) const
  235. {
  236. MemoryOutputStream buffer (512);
  237. const int numItems = data.arrayValue->size();
  238. buffer.writeCompressedInt (numItems);
  239. for (int i = 0; i < numItems; ++i)
  240. data.arrayValue->getReference(i).writeToStream (buffer);
  241. output.writeCompressedInt (1 + (int) buffer.getDataSize());
  242. output.writeByte (varMarker_Array);
  243. output << buffer;
  244. }
  245. };
  246. //==============================================================================
  247. class var::VariantType_Method : public var::VariantType
  248. {
  249. public:
  250. VariantType_Method() noexcept {}
  251. static const VariantType_Method instance;
  252. String toString (const ValueUnion&) const { return "Method"; }
  253. bool toBool (const ValueUnion& data) const noexcept { return data.methodValue != 0; }
  254. bool isMethod() const noexcept { return true; }
  255. bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept
  256. {
  257. return otherType.isMethod() && otherData.methodValue == data.methodValue;
  258. }
  259. void writeToStream (const ValueUnion&, OutputStream& output) const
  260. {
  261. jassertfalse; // Can't write a method to a stream!
  262. output.writeCompressedInt (0);
  263. }
  264. };
  265. //==============================================================================
  266. const var::VariantType_Void var::VariantType_Void::instance;
  267. const var::VariantType_Int var::VariantType_Int::instance;
  268. const var::VariantType_Int64 var::VariantType_Int64::instance;
  269. const var::VariantType_Bool var::VariantType_Bool::instance;
  270. const var::VariantType_Double var::VariantType_Double::instance;
  271. const var::VariantType_String var::VariantType_String::instance;
  272. const var::VariantType_Object var::VariantType_Object::instance;
  273. const var::VariantType_Array var::VariantType_Array::instance;
  274. const var::VariantType_Method var::VariantType_Method::instance;
  275. //==============================================================================
  276. var::var() noexcept : type (&VariantType_Void::instance)
  277. {
  278. }
  279. var::~var() noexcept
  280. {
  281. type->cleanUp (value);
  282. }
  283. const var var::null;
  284. //==============================================================================
  285. var::var (const var& valueToCopy) : type (valueToCopy.type)
  286. {
  287. type->createCopy (value, valueToCopy.value);
  288. }
  289. var::var (const int value_) noexcept : type (&VariantType_Int::instance) { value.intValue = value_; }
  290. var::var (const int64 value_) noexcept : type (&VariantType_Int64::instance) { value.int64Value = value_; }
  291. var::var (const bool value_) noexcept : type (&VariantType_Bool::instance) { value.boolValue = value_; }
  292. var::var (const double value_) noexcept : type (&VariantType_Double::instance) { value.doubleValue = value_; }
  293. var::var (MethodFunction method_) noexcept : type (&VariantType_Method::instance) { value.methodValue = method_; }
  294. var::var (const String& value_) : type (&VariantType_String::instance) { new (value.stringValue) String (value_); }
  295. var::var (const char* const value_) : type (&VariantType_String::instance) { new (value.stringValue) String (value_); }
  296. var::var (const wchar_t* const value_) : type (&VariantType_String::instance) { new (value.stringValue) String (value_); }
  297. var::var (const Array<var>& value_) : type (&VariantType_Array::instance)
  298. {
  299. value.arrayValue = new Array<var> (value_);
  300. }
  301. var::var (ReferenceCountedObject* const object) : type (&VariantType_Object::instance)
  302. {
  303. value.objectValue = object;
  304. if (object != nullptr)
  305. object->incReferenceCount();
  306. }
  307. //==============================================================================
  308. bool var::isVoid() const noexcept { return type->isVoid(); }
  309. bool var::isInt() const noexcept { return type->isInt(); }
  310. bool var::isInt64() const noexcept { return type->isInt64(); }
  311. bool var::isBool() const noexcept { return type->isBool(); }
  312. bool var::isDouble() const noexcept { return type->isDouble(); }
  313. bool var::isString() const noexcept { return type->isString(); }
  314. bool var::isObject() const noexcept { return type->isObject(); }
  315. bool var::isArray() const noexcept { return type->isArray(); }
  316. bool var::isMethod() const noexcept { return type->isMethod(); }
  317. var::operator int() const noexcept { return type->toInt (value); }
  318. var::operator int64() const noexcept { return type->toInt64 (value); }
  319. var::operator bool() const noexcept { return type->toBool (value); }
  320. var::operator float() const noexcept { return (float) type->toDouble (value); }
  321. var::operator double() const noexcept { return type->toDouble (value); }
  322. String var::toString() const { return type->toString (value); }
  323. var::operator String() const { return type->toString (value); }
  324. ReferenceCountedObject* var::getObject() const noexcept { return type->toObject (value); }
  325. Array<var>* var::getArray() const noexcept { return type->toArray (value); }
  326. DynamicObject* var::getDynamicObject() const noexcept { return dynamic_cast <DynamicObject*> (getObject()); }
  327. //==============================================================================
  328. void var::swapWith (var& other) noexcept
  329. {
  330. std::swap (type, other.type);
  331. std::swap (value, other.value);
  332. }
  333. var& var::operator= (const var& v) { type->cleanUp (value); type = v.type; type->createCopy (value, v.value); return *this; }
  334. var& var::operator= (const int v) { type->cleanUp (value); type = &VariantType_Int::instance; value.intValue = v; return *this; }
  335. var& var::operator= (const int64 v) { type->cleanUp (value); type = &VariantType_Int64::instance; value.int64Value = v; return *this; }
  336. var& var::operator= (const bool v) { type->cleanUp (value); type = &VariantType_Bool::instance; value.boolValue = v; return *this; }
  337. var& var::operator= (const double v) { type->cleanUp (value); type = &VariantType_Double::instance; value.doubleValue = v; return *this; }
  338. var& var::operator= (const char* const v) { type->cleanUp (value); type = &VariantType_String::instance; new (value.stringValue) String (v); return *this; }
  339. var& var::operator= (const wchar_t* const v) { type->cleanUp (value); type = &VariantType_String::instance; new (value.stringValue) String (v); return *this; }
  340. var& var::operator= (const String& v) { type->cleanUp (value); type = &VariantType_String::instance; new (value.stringValue) String (v); return *this; }
  341. var& var::operator= (const Array<var>& v) { var v2 (v); swapWith (v2); return *this; }
  342. var& var::operator= (ReferenceCountedObject* v) { var v2 (v); swapWith (v2); return *this; }
  343. var& var::operator= (MethodFunction v) { var v2 (v); swapWith (v2); return *this; }
  344. #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
  345. var::var (var&& other) noexcept
  346. : type (other.type),
  347. value (other.value)
  348. {
  349. other.type = &VariantType_Void::instance;
  350. }
  351. var& var::operator= (var&& other) noexcept
  352. {
  353. swapWith (other);
  354. return *this;
  355. }
  356. var::var (String&& value_) : type (&VariantType_String::instance)
  357. {
  358. new (value.stringValue) String (static_cast<String&&> (value_));
  359. }
  360. var& var::operator= (String&& v)
  361. {
  362. type->cleanUp (value);
  363. type = &VariantType_String::instance;
  364. new (value.stringValue) String (static_cast<String&&> (v));
  365. return *this;
  366. }
  367. #endif
  368. //==============================================================================
  369. bool var::equals (const var& other) const noexcept
  370. {
  371. return type->equals (value, other.value, *other.type);
  372. }
  373. bool var::equalsWithSameType (const var& other) const noexcept
  374. {
  375. return type == other.type && equals (other);
  376. }
  377. bool operator== (const var& v1, const var& v2) noexcept { return v1.equals (v2); }
  378. bool operator!= (const var& v1, const var& v2) noexcept { return ! v1.equals (v2); }
  379. bool operator== (const var& v1, const String& v2) { return v1.toString() == v2; }
  380. bool operator!= (const var& v1, const String& v2) { return v1.toString() != v2; }
  381. bool operator== (const var& v1, const char* const v2) { return v1.toString() == v2; }
  382. bool operator!= (const var& v1, const char* const v2) { return v1.toString() != v2; }
  383. //==============================================================================
  384. var var::operator[] (const Identifier& propertyName) const
  385. {
  386. DynamicObject* const o = getDynamicObject();
  387. return o != nullptr ? o->getProperty (propertyName) : var::null;
  388. }
  389. var var::operator[] (const char* const propertyName) const
  390. {
  391. return operator[] (Identifier (propertyName));
  392. }
  393. var var::getProperty (const Identifier& propertyName, const var& defaultReturnValue) const
  394. {
  395. DynamicObject* const o = getDynamicObject();
  396. return o != nullptr ? o->getProperties().getWithDefault (propertyName, defaultReturnValue) : defaultReturnValue;
  397. }
  398. var var::invoke (const Identifier& method, const var* arguments, int numArguments) const
  399. {
  400. DynamicObject* const o = getDynamicObject();
  401. return o != nullptr ? o->invokeMethod (method, arguments, numArguments) : var::null;
  402. }
  403. var var::invokeMethod (DynamicObject* const target, const var* const arguments, const int numArguments) const
  404. {
  405. jassert (target != nullptr);
  406. if (isMethod())
  407. return (target->*(value.methodValue)) (arguments, numArguments);
  408. return var::null;
  409. }
  410. var var::call (const Identifier& method) const
  411. {
  412. return invoke (method, nullptr, 0);
  413. }
  414. var var::call (const Identifier& method, const var& arg1) const
  415. {
  416. return invoke (method, &arg1, 1);
  417. }
  418. var var::call (const Identifier& method, const var& arg1, const var& arg2) const
  419. {
  420. var args[] = { arg1, arg2 };
  421. return invoke (method, args, 2);
  422. }
  423. var var::call (const Identifier& method, const var& arg1, const var& arg2, const var& arg3)
  424. {
  425. var args[] = { arg1, arg2, arg3 };
  426. return invoke (method, args, 3);
  427. }
  428. var var::call (const Identifier& method, const var& arg1, const var& arg2, const var& arg3, const var& arg4) const
  429. {
  430. var args[] = { arg1, arg2, arg3, arg4 };
  431. return invoke (method, args, 4);
  432. }
  433. var var::call (const Identifier& method, const var& arg1, const var& arg2, const var& arg3, const var& arg4, const var& arg5) const
  434. {
  435. var args[] = { arg1, arg2, arg3, arg4, arg5 };
  436. return invoke (method, args, 5);
  437. }
  438. //==============================================================================
  439. int var::size() const
  440. {
  441. const Array<var>* const array = getArray();
  442. return array != nullptr ? array->size() : 0;
  443. }
  444. const var& var::operator[] (int arrayIndex) const
  445. {
  446. const Array<var>* const array = getArray();
  447. // When using this method, the var must actually be an array, and the index
  448. // must be in-range!
  449. jassert (array != nullptr && isPositiveAndBelow (arrayIndex, array->size()));
  450. return array->getReference (arrayIndex);
  451. }
  452. var& var::operator[] (int arrayIndex)
  453. {
  454. const Array<var>* const array = getArray();
  455. // When using this method, the var must actually be an array, and the index
  456. // must be in-range!
  457. jassert (array != nullptr && isPositiveAndBelow (arrayIndex, array->size()));
  458. return array->getReference (arrayIndex);
  459. }
  460. Array<var>* var::convertToArray()
  461. {
  462. Array<var>* array = getArray();
  463. if (array == nullptr)
  464. {
  465. const Array<var> tempVar;
  466. var v (tempVar);
  467. array = v.value.arrayValue;
  468. if (! isVoid())
  469. array->add (*this);
  470. swapWith (v);
  471. }
  472. return array;
  473. }
  474. void var::append (const var& n)
  475. {
  476. convertToArray()->add (n);
  477. }
  478. void var::remove (const int index)
  479. {
  480. Array<var>* const array = getArray();
  481. if (array != nullptr)
  482. array->remove (index);
  483. }
  484. void var::insert (const int index, const var& n)
  485. {
  486. convertToArray()->insert (index, n);
  487. }
  488. void var::resize (const int numArrayElementsWanted)
  489. {
  490. convertToArray()->resize (numArrayElementsWanted);
  491. }
  492. int var::indexOf (const var& n) const
  493. {
  494. const Array<var>* const array = getArray();
  495. return array != nullptr ? array->indexOf (n) : -1;
  496. }
  497. //==============================================================================
  498. void var::writeToStream (OutputStream& output) const
  499. {
  500. type->writeToStream (value, output);
  501. }
  502. var var::readFromStream (InputStream& input)
  503. {
  504. const int numBytes = input.readCompressedInt();
  505. if (numBytes > 0)
  506. {
  507. switch (input.readByte())
  508. {
  509. case varMarker_Int: return var (input.readInt());
  510. case varMarker_Int64: return var (input.readInt64());
  511. case varMarker_BoolTrue: return var (true);
  512. case varMarker_BoolFalse: return var (false);
  513. case varMarker_Double: return var (input.readDouble());
  514. case varMarker_String:
  515. {
  516. MemoryOutputStream mo;
  517. mo.writeFromInputStream (input, numBytes - 1);
  518. return var (mo.toUTF8());
  519. }
  520. case varMarker_Array:
  521. {
  522. var v;
  523. Array<var>* const destArray = v.convertToArray();
  524. for (int i = input.readCompressedInt(); --i >= 0;)
  525. destArray->add (readFromStream (input));
  526. return v;
  527. }
  528. default:
  529. input.skipNextBytes (numBytes - 1); break;
  530. }
  531. }
  532. return var::null;
  533. }
  534. END_JUCE_NAMESPACE