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
23namespace juce
24{
25
26enum 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//==============================================================================
40class var::VariantType
41{
42public:
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//==============================================================================
76class var::VariantType_Void : public var::VariantType
77{
78public:
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//==============================================================================
89class var::VariantType_Undefined : public var::VariantType
90{
91public:
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//==============================================================================
107class var::VariantType_Int : public var::VariantType
108{
109public:
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//==============================================================================
138class var::VariantType_Int64 : public var::VariantType
139{
140public:
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//==============================================================================
169class var::VariantType_Double : public var::VariantType
170{
171public:
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//==============================================================================
197class var::VariantType_Bool : public var::VariantType
198{
199public:
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//==============================================================================
224class var::VariantType_String : public var::VariantType
225{
226public:
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
259private:
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//==============================================================================
265class var::VariantType_Object : public var::VariantType
266{
267public:
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//==============================================================================
307class var::VariantType_Array : public var::VariantType_Object
308{
309public:
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//==============================================================================
372class var::VariantType_Binary : public var::VariantType
373{
374public:
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//==============================================================================
401class var::VariantType_Method : public var::VariantType
402{
403public:
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//==============================================================================
427const var::VariantType_Void var::VariantType_Void::instance;
428const var::VariantType_Undefined var::VariantType_Undefined::instance;
429const var::VariantType_Int var::VariantType_Int::instance;
430const var::VariantType_Int64 var::VariantType_Int64::instance;
431const var::VariantType_Bool var::VariantType_Bool::instance;
432const var::VariantType_Double var::VariantType_Double::instance;
433const var::VariantType_String var::VariantType_String::instance;
434const var::VariantType_Object var::VariantType_Object::instance;
435const var::VariantType_Array var::VariantType_Array::instance;
436const var::VariantType_Binary var::VariantType_Binary::instance;
437const var::VariantType_Method var::VariantType_Method::instance;
438
439
440//==============================================================================
441var::var() noexcept : type (&VariantType_Void::instance) {}
442var::var (const VariantType& t) noexcept : type (&t) {}
443var::~var() noexcept { type->cleanUp (value); }
444
445JUCE_DECLARE_DEPRECATED_STATIC (const var var::null;)
446
447//==============================================================================
448var::var (const var& valueToCopy) : type (valueToCopy.type)
449{
450 type->createCopy (value, valueToCopy.value);
451}
452
453var::var (const int v) noexcept : type (&VariantType_Int::instance) { value.intValue = v; }
454var::var (const int64 v) noexcept : type (&VariantType_Int64::instance) { value.int64Value = v; }
455var::var (const bool v) noexcept : type (&VariantType_Bool::instance) { value.boolValue = v; }
456var::var (const double v) noexcept : type (&VariantType_Double::instance) { value.doubleValue = v; }
457var::var (NativeFunction m) noexcept : type (&VariantType_Method::instance) { value.methodValue = new NativeFunction (m); }
458var::var (const Array<var>& v) : type (&VariantType_Array::instance) { value.objectValue = new VariantType_Array::RefCountedArray(v); }
459var::var (const String& v) : type (&VariantType_String::instance) { new (value.stringValue) String (v); }
460var::var (const char* const v) : type (&VariantType_String::instance) { new (value.stringValue) String (v); }
461var::var (const wchar_t* const v) : type (&VariantType_String::instance) { new (value.stringValue) String (v); }
462var::var (const void* v, size_t sz) : type (&VariantType_Binary::instance) { value.binaryValue = new MemoryBlock (v, sz); }
463var::var (const MemoryBlock& v) : type (&VariantType_Binary::instance) { value.binaryValue = new MemoryBlock (v); }
464
465var::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
476var::var (ReferenceCountedObject* const object) : type (&VariantType_Object::instance)
477{
478 value.objectValue = object;
479
480 if (object != nullptr)
481 object->incReferenceCount();
482}
483
484var var::undefined() noexcept { return var (VariantType_Undefined::instance); }
485
486//==============================================================================
487bool var::isVoid() const noexcept { return type->isVoid(); }
488bool var::isUndefined() const noexcept { return type->isUndefined(); }
489bool var::isInt() const noexcept { return type->isInt(); }
490bool var::isInt64() const noexcept { return type->isInt64(); }
491bool var::isBool() const noexcept { return type->isBool(); }
492bool var::isDouble() const noexcept { return type->isDouble(); }
493bool var::isString() const noexcept { return type->isString(); }
494bool var::isObject() const noexcept { return type->isObject(); }
495bool var::isArray() const noexcept { return type->isArray(); }
496bool var::isBinaryData() const noexcept { return type->isBinary(); }
497bool 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); }
507Array<var>* var::getArray() const noexcept { return type->toArray (value); }
508MemoryBlock* var::getBinaryData() const noexcept { return type->toBinary (value); }
509DynamicObject* var::getDynamicObject() const noexcept { return dynamic_cast<DynamicObject*> (getObject()); }
510
511//==============================================================================
512void 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
531var::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
544var::var (String&& v) : type (&VariantType_String::instance)
545{
546 new (value.stringValue) String (std::move (v));
547}
548
549var::var (MemoryBlock&& v) : type (&VariantType_Binary::instance)
550{
551 value.binaryValue = new MemoryBlock (std::move (v));
552}
553
554var::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//==============================================================================
568bool var::equals (const var& other) const noexcept
569{
570 return type->equals (value, other.value, *other.type);
571}
572
573bool var::equalsWithSameType (const var& other) const noexcept
574{
575 return hasSameTypeAs (other) && equals (other);
576}
577
578bool var::hasSameTypeAs (const var& other) const noexcept
579{
580 return type == other.type;
581}
582
583bool canCompare (const var& v1, const var& v2)
584{
585 return v1.type->isComparable() && v2.type->isComparable();
586}
587
588static 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
597bool operator== (const var& v1, const var& v2) { return v1.equals (v2); }
598bool operator!= (const var& v1, const var& v2) { return ! v1.equals (v2); }
599bool operator< (const var& v1, const var& v2) { return canCompare (v1, v2) && compare (v1, v2) < 0; }
600bool operator> (const var& v1, const var& v2) { return canCompare (v1, v2) && compare (v1, v2) > 0; }
601bool operator<= (const var& v1, const var& v2) { return canCompare (v1, v2) && compare (v1, v2) <= 0; }
602bool operator>= (const var& v1, const var& v2) { return canCompare (v1, v2) && compare (v1, v2) >= 0; }
603
604bool operator== (const var& v1, const String& v2) { return v1.toString() == v2; }
605bool operator!= (const var& v1, const String& v2) { return v1.toString() != v2; }
606bool operator== (const var& v1, const char* v2) { return v1.toString() == v2; }
607bool operator!= (const var& v1, const char* v2) { return v1.toString() != v2; }
608
609//==============================================================================
611{
612 return type->clone (*this);
613}
614
615//==============================================================================
617{
618 if (auto* o = getDynamicObject())
619 return o->getProperty (propertyName);
620
621 return getNullVarRef();
622}
623
624const var& var::operator[] (const char* const propertyName) const
625{
627}
628
630{
631 if (auto* o = getDynamicObject())
632 return o->getProperties().getWithDefault (propertyName, defaultReturnValue);
633
634 return defaultReturnValue;
635}
636
637bool 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
650var 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
659{
660 return invoke (method, nullptr, 0);
661}
662
663var var::call (const Identifier& method, const var& arg1) const
664{
665 return invoke (method, &arg1, 1);
666}
667
668var 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
674var 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
680var 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
686var 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//==============================================================================
693int var::size() const
694{
695 if (auto array = getArray())
696 return array->size();
697
698 return 0;
699}
700
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
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
723Array<var>* var::convertToArray()
724{
725 if (auto array = getArray())
726 return array;
727
729
730 if (! isVoid())
731 tempVar.add (*this);
732
733 *this = tempVar;
734 return getArray();
735}
736
737void var::append (const var& n)
738{
739 convertToArray()->add (n);
740}
741
742void var::remove (const int index)
743{
744 if (auto array = getArray())
745 array->remove (index);
746}
747
748void var::insert (const int index, const var& n)
749{
750 convertToArray()->insert (index, n);
751}
752
754{
755 convertToArray()->resize (numArrayElementsWanted);
756}
757
758int var::indexOf (const var& n) const
759{
760 if (auto array = getArray())
761 return array->indexOf (n);
762
763 return -1;
764}
765
766//==============================================================================
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
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
int size() const noexcept
Definition juce_Array.h:215
void remove(int indexToRemove)
Definition juce_Array.h:767
void insert(int indexToInsertAt, ParameterType newElement)
Definition juce_Array.h:462
int indexOf(ParameterType elementToLookFor) const
Definition juce_Array.h:382
void add(const ElementType &newElement)
Definition juce_Array.h:418
void resize(int targetNumItems)
Definition juce_Array.h:670
virtual int64 readInt64()
virtual int readCompressedInt()
virtual void skipNextBytes(int64 numBytesToSkip)
virtual int read(void *destBuffer, int maxBytesToRead)=0
virtual double readDouble()
virtual char readByte()
static String toHexString(IntegerType number)
static String charToString(juce_wchar character)
static var undefined() noexcept
void insert(int index, const var &value)
int size() const
var invoke(const Identifier &method, const var *arguments, int numArguments) const
void writeToStream(OutputStream &output) const
var() noexcept
~var() noexcept
Array< var > * getArray() const noexcept
int indexOf(const var &value) const
const var & operator[](int arrayIndex) const
NativeFunction getNativeFunction() const
bool hasProperty(const Identifier &propertyName) const noexcept
static var readFromStream(InputStream &input)
void append(const var &valueToAppend)
bool equals(const var &other) const noexcept
bool equalsWithSameType(const var &other) const noexcept
void resize(int numArrayElementsWanted)
var getProperty(const Identifier &propertyName, const var &defaultReturnValue) const
void remove(int index)
var call(const Identifier &method) const
bool hasSameTypeAs(const var &other) const noexcept
var clone() const noexcept
MemoryBlock * getBinaryData() const noexcept