OpenShot Audio Library | OpenShotAudio 0.3.2

Loading...
Searching...
No Matches
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
445JUCE_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
499var::operator int() const noexcept { return type->toInt (value); }
500var::operator int64() const noexcept { return type->toInt64 (value); }
501var::operator bool() const noexcept { return type->toBool (value); }
502var::operator float() const noexcept { return (float) type->toDouble (value); }
503var::operator double() const noexcept { return type->toDouble (value); }
504String var::toString() const { return type->toString (value); }
505var::operator String() const { return type->toString (value); }
506ReferenceCountedObject* 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
518var& var::operator= (const var& v) { type->cleanUp (value); type = v.type; type->createCopy (value, v.value); return *this; }
519var& var::operator= (const int v) { type->cleanUp (value); type = &VariantType_Int::instance; value.intValue = v; return *this; }
520var& var::operator= (const int64 v) { type->cleanUp (value); type = &VariantType_Int64::instance; value.int64Value = v; return *this; }
521var& var::operator= (const bool v) { type->cleanUp (value); type = &VariantType_Bool::instance; value.boolValue = v; return *this; }
522var& var::operator= (const double v) { type->cleanUp (value); type = &VariantType_Double::instance; value.doubleValue = v; return *this; }
523var& var::operator= (const char* const v) { type->cleanUp (value); type = &VariantType_String::instance; new (value.stringValue) String (v); return *this; }
524var& var::operator= (const wchar_t* const v) { type->cleanUp (value); type = &VariantType_String::instance; new (value.stringValue) String (v); return *this; }
525var& var::operator= (const String& v) { type->cleanUp (value); type = &VariantType_String::instance; new (value.stringValue) String (v); return *this; }
526var& var::operator= (const MemoryBlock& v) { type->cleanUp (value); type = &VariantType_Binary::instance; value.binaryValue = new MemoryBlock (v); return *this; }
527var& var::operator= (const Array<var>& v) { var v2 (v); swapWith (v2); return *this; }
528var& var::operator= (ReferenceCountedObject* v) { var v2 (v); swapWith (v2); return *this; }
529var& 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
538var& 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
559var& 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
645var::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
772 var var::readFromStream (InputStream& input)
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 {
788 MemoryOutputStream mo;
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
825var::NativeFunctionArgs::NativeFunctionArgs (const var& t, const var* args, int numArgs) noexcept
826 : thisObject (t), arguments (args), numArguments (numArgs)
827{
828}
829
830} // namespace juce
juce::Array
Definition: juce_Array.h:56
juce::Array::add
void add(const ElementType &newElement)
Definition: juce_Array.h:418
juce::DynamicObject
Definition: juce_DynamicObject.h:40
juce::Identifier
Definition: juce_Identifier.h:39
juce::InputStream
Definition: juce_InputStream.h:37
juce::InputStream::readInt64
virtual int64 readInt64()
Definition: juce_InputStream.cpp:133
juce::InputStream::readCompressedInt
virtual int readCompressedInt()
Definition: juce_InputStream.cpp:108
juce::InputStream::skipNextBytes
virtual void skipNextBytes(int64 numBytesToSkip)
Definition: juce_InputStream.cpp:237
juce::InputStream::read
virtual int read(void *destBuffer, int maxBytesToRead)=0
juce::InputStream::readInt
virtual int readInt()
Definition: juce_InputStream.cpp:88
juce::InputStream::readDouble
virtual double readDouble()
Definition: juce_InputStream.cpp:168
juce::InputStream::readByte
virtual char readByte()
Definition: juce_InputStream.cpp:56
juce::MemoryBlock
Definition: juce_MemoryBlock.h:33
juce::MemoryBlock::getData
void * getData() noexcept
Definition: juce_MemoryBlock.h:91
juce::MemoryBlock::setSize
void setSize(const size_t newSize, bool initialiseNewSpaceToZero=false)
Definition: juce_MemoryBlock.cpp:115
juce::MemoryOutputStream
Definition: juce_MemoryOutputStream.h:36
juce::MemoryOutputStream::toUTF8
String toUTF8() const
Definition: juce_MemoryOutputStream.cpp:189
juce::MemoryOutputStream::writeFromInputStream
int64 writeFromInputStream(InputStream &, int64 maxNumBytesToWrite) override
Definition: juce_MemoryOutputStream.cpp:172
juce::OutputStream
Definition: juce_OutputStream.h:38
juce::ReferenceCountedObject::incReferenceCount
void incReferenceCount() noexcept
Definition: juce_ReferenceCountedObject.h:74
juce::String::toHexString
static String toHexString(IntegerType number)
Definition: juce_String.h:1053
juce::String::charToString
static String charToString(juce_wchar character)
Definition: juce_String.cpp:371
juce::var
Definition: juce_Variant.h:42
juce::var::undefined
static var undefined() noexcept
Definition: juce_Variant.cpp:484
juce::var::insert
void insert(int index, const var &value)
Definition: juce_Variant.cpp:748
juce::var::size
int size() const
Definition: juce_Variant.cpp:693
juce::var::invoke
var invoke(const Identifier &method, const var *arguments, int numArguments) const
Definition: juce_Variant.cpp:650
juce::var::writeToStream
void writeToStream(OutputStream &output) const
Definition: juce_Variant.cpp:767
juce::var::var
var() noexcept
Definition: juce_Variant.cpp:441
juce::var::~var
~var() noexcept
Definition: juce_Variant.cpp:443
juce::var::getArray
Array< var > * getArray() const noexcept
Definition: juce_Variant.cpp:507
juce::var::indexOf
int indexOf(const var &value) const
Definition: juce_Variant.cpp:758
juce::var::operator[]
const var & operator[](int arrayIndex) const
Definition: juce_Variant.cpp:701
juce::var::getNativeFunction
NativeFunction getNativeFunction() const
Definition: juce_Variant.cpp:645
juce::var::hasProperty
bool hasProperty(const Identifier &propertyName) const noexcept
Definition: juce_Variant.cpp:637
juce::var::readFromStream
static var readFromStream(InputStream &input)
Definition: juce_Variant.cpp:772
juce::var::append
void append(const var &valueToAppend)
Definition: juce_Variant.cpp:737
juce::var::equals
bool equals(const var &other) const noexcept
Definition: juce_Variant.cpp:568
juce::var::equalsWithSameType
bool equalsWithSameType(const var &other) const noexcept
Definition: juce_Variant.cpp:573
juce::var::resize
void resize(int numArrayElementsWanted)
Definition: juce_Variant.cpp:753
juce::var::getProperty
var getProperty(const Identifier &propertyName, const var &defaultReturnValue) const
Definition: juce_Variant.cpp:629
juce::var::remove
void remove(int index)
Definition: juce_Variant.cpp:742
juce::var::call
var call(const Identifier &method) const
Definition: juce_Variant.cpp:658
juce::var::hasSameTypeAs
bool hasSameTypeAs(const var &other) const noexcept
Definition: juce_Variant.cpp:578
juce::var::clone
var clone() const noexcept
Definition: juce_Variant.cpp:610
juce::var::getBinaryData
MemoryBlock * getBinaryData() const noexcept
Definition: juce_Variant.cpp:508
juce::var::NativeFunctionArgs
Definition: juce_Variant.h:49