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