OpenShot Audio Library | OpenShotAudio: juce_Variant.cpp Source File

OpenShot Audio Library | OpenShotAudio 0.4.0

Loading...
Searching...
No Matches
juce_Variant.cpp
1/*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
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//==============================================================================
40struct var::VariantType
41{
42 struct VoidTag {};
43 struct UndefinedTag {};
44 struct IntTag {};
45 struct Int64Tag {};
46 struct DoubleTag {};
47 struct BoolTag {};
48 struct StringTag {};
49 struct ObjectTag {};
50 struct ArrayTag {};
51 struct BinaryTag {};
52 struct MethodTag {};
53
54 // members =====================================================================
55 bool isVoid = false;
56 bool isUndefined = false;
57 bool isInt = false;
58 bool isInt64 = false;
59 bool isBool = false;
60 bool isDouble = false;
61 bool isString = false;
62 bool isObject = false;
63 bool isArray = false;
64 bool isBinary = false;
65 bool isMethod = false;
66 bool isComparable = false;
67
68 int (*toInt) (const ValueUnion&) = defaultToInt;
69 int64 (*toInt64) (const ValueUnion&) = defaultToInt64;
70 double (*toDouble) (const ValueUnion&) = defaultToDouble;
71 String (*toString) (const ValueUnion&) = defaultToString;
72 bool (*toBool) (const ValueUnion&) = defaultToBool;
73 ReferenceCountedObject* (*toObject) (const ValueUnion&) = defaultToObject;
74 Array<var>* (*toArray) (const ValueUnion&) = defaultToArray;
75 MemoryBlock* (*toBinary) (const ValueUnion&) = defaultToBinary;
76 var (*clone) (const var&) = defaultClone;
77 void (*cleanUp) (ValueUnion&) = defaultCleanUp;
78 void (*createCopy) (ValueUnion&, const ValueUnion&) = defaultCreateCopy;
79
80 bool (*equals) (const ValueUnion&, const ValueUnion&, const VariantType&) = nullptr;
81 void (*writeToStream) (const ValueUnion&, OutputStream&) = nullptr;
82
83 // defaults ====================================================================
84 static int defaultToInt (const ValueUnion&) { return 0; }
85 static int64 defaultToInt64 (const ValueUnion&) { return 0; }
86 static double defaultToDouble (const ValueUnion&) { return 0; }
87 static String defaultToString (const ValueUnion&) { return {}; }
88 static bool defaultToBool (const ValueUnion&) { return false; }
89 static ReferenceCountedObject* defaultToObject (const ValueUnion&) { return nullptr; }
90 static Array<var>* defaultToArray (const ValueUnion&) { return nullptr; }
91 static MemoryBlock* defaultToBinary (const ValueUnion&) { return nullptr; }
92 static var defaultClone (const var& other) { return other; }
93 static void defaultCleanUp (ValueUnion&) {}
94 static void defaultCreateCopy (ValueUnion& dest, const ValueUnion& source) { dest = source; }
95
96 // void ========================================================================
97 static bool voidEquals (const ValueUnion&, const ValueUnion&, const VariantType& otherType) noexcept
98 {
99 return otherType.isVoid || otherType.isUndefined;
100 }
101
102 static void voidWriteToStream (const ValueUnion&, OutputStream& output)
103 {
104 output.writeCompressedInt (0);
105 }
106
107 constexpr explicit VariantType (VoidTag) noexcept
108 : isVoid (true),
109 isComparable (true),
110 equals (voidEquals),
111 writeToStream (voidWriteToStream) {}
112
113 // undefined ===================================================================
114 static String undefinedToString (const ValueUnion&) { return "undefined"; }
115
116 static bool undefinedEquals (const ValueUnion&, const ValueUnion&, const VariantType& otherType) noexcept
117 {
118 return otherType.isVoid || otherType.isUndefined;
119 }
120
121 static void undefinedWriteToStream (const ValueUnion&, OutputStream& output)
122 {
123 output.writeCompressedInt (1);
124 output.writeByte (varMarker_Undefined);
125 }
126
127 constexpr explicit VariantType (UndefinedTag) noexcept
128 : isUndefined (true),
129 toString (undefinedToString),
130 equals (undefinedEquals),
131 writeToStream (undefinedWriteToStream) {}
132
133 // int =========================================================================
134 static int intToInt (const ValueUnion& data) noexcept { return data.intValue; }
135 static int64 intToInt64 (const ValueUnion& data) noexcept { return (int64) data.intValue; }
136 static double intToDouble (const ValueUnion& data) noexcept { return (double) data.intValue; }
137 static String intToString (const ValueUnion& data) { return String (data.intValue); }
138 static bool intToBool (const ValueUnion& data) noexcept { return data.intValue != 0; }
139
140 static bool intEquals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) noexcept
141 {
142 if (otherType.isDouble || otherType.isInt64 || otherType.isString)
143 return otherType.equals (otherData, data, VariantType { IntTag{} });
144
145 return otherType.toInt (otherData) == data.intValue;
146 }
147
148 static void intWriteToStream (const ValueUnion& data, OutputStream& output)
149 {
150 output.writeCompressedInt (5);
151 output.writeByte (varMarker_Int);
152 output.writeInt (data.intValue);
153 }
154
155 constexpr explicit VariantType (IntTag) noexcept
156 : isInt (true),
157 isComparable (true),
158 toInt (intToInt),
159 toInt64 (intToInt64),
160 toDouble (intToDouble),
161 toString (intToString),
162 toBool (intToBool),
163 equals (intEquals),
164 writeToStream (intWriteToStream) {}
165
166 // int64 =======================================================================
167 static int int64ToInt (const ValueUnion& data) noexcept { return (int) data.int64Value; }
168 static int64 int64ToInt64 (const ValueUnion& data) noexcept { return data.int64Value; }
169 static double int64ToDouble (const ValueUnion& data) noexcept { return (double) data.int64Value; }
170 static String int64ToString (const ValueUnion& data) { return String (data.int64Value); }
171 static bool int64ToBool (const ValueUnion& data) noexcept { return data.int64Value != 0; }
172
173 static bool int64Equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) noexcept
174 {
175 if (otherType.isDouble || otherType.isString)
176 return otherType.equals (otherData, data, VariantType { Int64Tag{} });
177
178 return otherType.toInt64 (otherData) == data.int64Value;
179 }
180
181 static void int64WriteToStream (const ValueUnion& data, OutputStream& output)
182 {
183 output.writeCompressedInt (9);
184 output.writeByte (varMarker_Int64);
185 output.writeInt64 (data.int64Value);
186 }
187
188 constexpr explicit VariantType (Int64Tag) noexcept
189 : isInt64 (true),
190 isComparable (true),
191 toInt (int64ToInt),
192 toInt64 (int64ToInt64),
193 toDouble (int64ToDouble),
194 toString (int64ToString),
195 toBool (int64ToBool),
196 equals (int64Equals),
197 writeToStream (int64WriteToStream) {}
198
199 // double ======================================================================
200 static int doubleToInt (const ValueUnion& data) noexcept { return (int) data.doubleValue; }
201 static int64 doubleToInt64 (const ValueUnion& data) noexcept { return (int64) data.doubleValue; }
202 static double doubleToDouble (const ValueUnion& data) noexcept { return data.doubleValue; }
203 static String doubleToString (const ValueUnion& data) { return serialiseDouble (data.doubleValue); }
204 static bool doubleToBool (const ValueUnion& data) noexcept { return ! exactlyEqual (data.doubleValue, 0.0); }
205
206 static bool doubleEquals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) noexcept
207 {
208 return std::abs (otherType.toDouble (otherData) - data.doubleValue) < std::numeric_limits<double>::epsilon();
209 }
210
211 static void doubleWriteToStream (const ValueUnion& data, OutputStream& output)
212 {
213 output.writeCompressedInt (9);
214 output.writeByte (varMarker_Double);
215 output.writeDouble (data.doubleValue);
216 }
217
218 constexpr explicit VariantType (DoubleTag) noexcept
219 : isDouble (true),
220 isComparable (true),
221 toInt (doubleToInt),
222 toInt64 (doubleToInt64),
223 toDouble (doubleToDouble),
224 toString (doubleToString),
225 toBool (doubleToBool),
226 equals (doubleEquals),
227 writeToStream (doubleWriteToStream) {}
228
229 // bool ========================================================================
230 static int boolToInt (const ValueUnion& data) noexcept { return data.boolValue ? 1 : 0; }
231 static int64 boolToInt64 (const ValueUnion& data) noexcept { return data.boolValue ? 1 : 0; }
232 static double boolToDouble (const ValueUnion& data) noexcept { return data.boolValue ? 1.0 : 0.0; }
233 static String boolToString (const ValueUnion& data) { return String::charToString (data.boolValue ? (juce_wchar) '1' : (juce_wchar) '0'); }
234 static bool boolToBool (const ValueUnion& data) noexcept { return data.boolValue; }
235
236 static bool boolEquals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) noexcept
237 {
238 return otherType.toBool (otherData) == data.boolValue;
239 }
240
241 static void boolWriteToStream (const ValueUnion& data, OutputStream& output)
242 {
243 output.writeCompressedInt (1);
244 output.writeByte (data.boolValue ? (char) varMarker_BoolTrue : (char) varMarker_BoolFalse);
245 }
246
247 constexpr explicit VariantType (BoolTag) noexcept
248 : isBool (true),
249 isComparable (true),
250 toInt (boolToInt),
251 toInt64 (boolToInt64),
252 toDouble (boolToDouble),
253 toString (boolToString),
254 toBool (boolToBool),
255 equals (boolEquals),
256 writeToStream (boolWriteToStream) {}
257
258 // string ======================================================================
259 static const String* getString (const ValueUnion& data) noexcept { return unalignedPointerCast<const String*> (data.stringValue); }
260 static String* getString ( ValueUnion& data) noexcept { return unalignedPointerCast<String*> (data.stringValue); }
261
262 static int stringToInt (const ValueUnion& data) noexcept { return getString (data)->getIntValue(); }
263 static int64 stringToInt64 (const ValueUnion& data) noexcept { return getString (data)->getLargeIntValue(); }
264 static double stringToDouble (const ValueUnion& data) noexcept { return getString (data)->getDoubleValue(); }
265 static String stringToString (const ValueUnion& data) { return *getString (data); }
266 static bool stringToBool (const ValueUnion& data) noexcept
267 {
268 return getString (data)->getIntValue() != 0
269 || getString (data)->trim().equalsIgnoreCase ("true")
270 || getString (data)->trim().equalsIgnoreCase ("yes");
271 }
272
273 static void stringCleanUp (ValueUnion& data) noexcept { getString (data)-> ~String(); }
274 static void stringCreateCopy (ValueUnion& dest, const ValueUnion& source) { new (dest.stringValue) String (*getString (source)); }
275
276 static bool stringEquals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) noexcept
277 {
278 return otherType.toString (otherData) == *getString (data);
279 }
280
281 static void stringWriteToStream (const ValueUnion& data, OutputStream& output)
282 {
283 auto* s = getString (data);
284 const size_t len = s->getNumBytesAsUTF8() + 1;
285 HeapBlock<char> temp (len);
286 s->copyToUTF8 (temp, len);
287 output.writeCompressedInt ((int) (len + 1));
288 output.writeByte (varMarker_String);
289 output.write (temp, len);
290 }
291
292 constexpr explicit VariantType (StringTag) noexcept
293 : isString (true),
294 isComparable (true),
295 toInt (stringToInt),
296 toInt64 (stringToInt64),
297 toDouble (stringToDouble),
298 toString (stringToString),
299 toBool (stringToBool),
300 cleanUp (stringCleanUp),
301 createCopy (stringCreateCopy),
302 equals (stringEquals),
303 writeToStream (stringWriteToStream) {}
304
305 // object ======================================================================
306 static String objectToString (const ValueUnion& data)
307 {
308 return "Object 0x" + String::toHexString ((int) (pointer_sized_int) data.objectValue);
309 }
310
311 static bool objectToBool (const ValueUnion& data) noexcept { return data.objectValue != nullptr; }
312 static ReferenceCountedObject* objectToObject (const ValueUnion& data) noexcept { return data.objectValue; }
313
314 static var objectClone (const var& original)
315 {
316 if (auto* d = original.getDynamicObject())
317 return d->clone().release();
318
319 jassertfalse; // can only clone DynamicObjects!
320 return {};
321 }
322
323 static void objectCleanUp (ValueUnion& data) noexcept { if (data.objectValue != nullptr) data.objectValue->decReferenceCount(); }
324
325 static void objectCreateCopy (ValueUnion& dest, const ValueUnion& source)
326 {
327 dest.objectValue = source.objectValue;
328 if (dest.objectValue != nullptr)
329 dest.objectValue->incReferenceCount();
330 }
331
332 static bool objectEquals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) noexcept
333 {
334 return otherType.toObject (otherData) == data.objectValue;
335 }
336
337 static void objectWriteToStream (const ValueUnion&, OutputStream& output)
338 {
339 jassertfalse; // Can't write an object to a stream!
340 output.writeCompressedInt (0);
341 }
342
343 constexpr explicit VariantType (ObjectTag) noexcept
344 : isObject (true),
345 toString (objectToString),
346 toBool (objectToBool),
347 toObject (objectToObject),
348 clone (objectClone),
349 cleanUp (objectCleanUp),
350 createCopy (objectCreateCopy),
351 equals (objectEquals),
352 writeToStream (objectWriteToStream) {}
353
354 // array =======================================================================
355 static String arrayToString (const ValueUnion&) { return "[Array]"; }
356 static ReferenceCountedObject* arrayToObject (const ValueUnion&) noexcept { return nullptr; }
357
358 static Array<var>* arrayToArray (const ValueUnion& data) noexcept
359 {
360 if (auto* a = dynamic_cast<RefCountedArray*> (data.objectValue))
361 return &(a->array);
362
363 return nullptr;
364 }
365
366 static bool arrayEquals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) noexcept
367 {
368 auto* thisArray = arrayToArray (data);
369 auto* otherArray = otherType.toArray (otherData);
370 return thisArray == otherArray || (thisArray != nullptr && otherArray != nullptr && *otherArray == *thisArray);
371 }
372
373 static var arrayClone (const var& original)
374 {
375 Array<var> arrayCopy;
376
377 if (auto* array = arrayToArray (original.value))
378 {
379 arrayCopy.ensureStorageAllocated (array->size());
380
381 for (auto& i : *array)
382 arrayCopy.add (i.clone());
383 }
384
385 return var (arrayCopy);
386 }
387
388 static void arrayWriteToStream (const ValueUnion& data, OutputStream& output)
389 {
390 if (auto* array = arrayToArray (data))
391 {
392 MemoryOutputStream buffer (512);
393 buffer.writeCompressedInt (array->size());
394
395 for (auto& i : *array)
396 i.writeToStream (buffer);
397
398 output.writeCompressedInt (1 + (int) buffer.getDataSize());
399 output.writeByte (varMarker_Array);
400 output << buffer;
401 }
402 }
403
404 struct RefCountedArray final : public ReferenceCountedObject
405 {
406 RefCountedArray (const Array<var>& a) : array (a) { incReferenceCount(); }
407 RefCountedArray (Array<var>&& a) : array (std::move (a)) { incReferenceCount(); }
408 Array<var> array;
409 };
410
411 constexpr explicit VariantType (ArrayTag) noexcept
412 : isObject (true),
413 isArray (true),
414 toString (arrayToString),
415 toBool (objectToBool),
416 toObject (arrayToObject),
417 toArray (arrayToArray),
418 clone (arrayClone),
419 cleanUp (objectCleanUp),
420 createCopy (objectCreateCopy),
421 equals (arrayEquals),
422 writeToStream (arrayWriteToStream) {}
423
424 // binary ======================================================================
425 static void binaryCleanUp (ValueUnion& data) noexcept { delete data.binaryValue; }
426 static void binaryCreateCopy (ValueUnion& dest, const ValueUnion& source) { dest.binaryValue = new MemoryBlock (*source.binaryValue); }
427
428 static String binaryToString (const ValueUnion& data) { return data.binaryValue->toBase64Encoding(); }
429 static MemoryBlock* binaryToBinary (const ValueUnion& data) noexcept { return data.binaryValue; }
430
431 static bool binaryEquals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) noexcept
432 {
433 const MemoryBlock* const otherBlock = otherType.toBinary (otherData);
434 return otherBlock != nullptr && *otherBlock == *data.binaryValue;
435 }
436
437 static void binaryWriteToStream (const ValueUnion& data, OutputStream& output)
438 {
439 output.writeCompressedInt (1 + (int) data.binaryValue->getSize());
440 output.writeByte (varMarker_Binary);
441 output << *data.binaryValue;
442 }
443
444 constexpr explicit VariantType (BinaryTag) noexcept
445 : isBinary (true),
446 toString (binaryToString),
447 toBinary (binaryToBinary),
448 cleanUp (binaryCleanUp),
449 createCopy (binaryCreateCopy),
450 equals (binaryEquals),
451 writeToStream (binaryWriteToStream) {}
452
453 // method ======================================================================
454 static void methodCleanUp (ValueUnion& data) noexcept { if (data.methodValue != nullptr ) delete data.methodValue; }
455 static void methodCreateCopy (ValueUnion& dest, const ValueUnion& source) { dest.methodValue = new NativeFunction (*source.methodValue); }
456
457 static String methodToString (const ValueUnion&) { return "Method"; }
458 static bool methodToBool (const ValueUnion& data) noexcept { return data.methodValue != nullptr; }
459
460 static bool methodEquals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) noexcept
461 {
462 return otherType.isMethod && otherData.methodValue == data.methodValue;
463 }
464
465 static void methodWriteToStream (const ValueUnion&, OutputStream& output)
466 {
467 jassertfalse; // Can't write a method to a stream!
468 output.writeCompressedInt (0);
469 }
470
471 constexpr explicit VariantType (MethodTag) noexcept
472 : isMethod (true),
473 toString (methodToString),
474 toBool (methodToBool),
475 cleanUp (methodCleanUp),
476 createCopy (methodCreateCopy),
477 equals (methodEquals),
478 writeToStream (methodWriteToStream) {}
479};
480
481struct var::Instance
482{
483 static constexpr VariantType attributesVoid { VariantType::VoidTag{} };
484 static constexpr VariantType attributesUndefined { VariantType::UndefinedTag{} };
485 static constexpr VariantType attributesInt { VariantType::IntTag{} };
486 static constexpr VariantType attributesInt64 { VariantType::Int64Tag{} };
487 static constexpr VariantType attributesBool { VariantType::BoolTag{} };
488 static constexpr VariantType attributesDouble { VariantType::DoubleTag{} };
489 static constexpr VariantType attributesMethod { VariantType::MethodTag{} };
490 static constexpr VariantType attributesArray { VariantType::ArrayTag{} };
491 static constexpr VariantType attributesString { VariantType::StringTag{} };
492 static constexpr VariantType attributesBinary { VariantType::BinaryTag{} };
493 static constexpr VariantType attributesObject { VariantType::ObjectTag{} };
494};
495
496//==============================================================================
497var::var() noexcept : type (&Instance::attributesVoid) {}
498 var::var (const VariantType& t) noexcept : type (&t) {}
499var::~var() noexcept { type->cleanUp (value); }
500
501//==============================================================================
502 var::var (const var& valueToCopy) : type (valueToCopy.type)
503{
504 type->createCopy (value, valueToCopy.value);
505}
506
507 var::var (const int v) noexcept : type (&Instance::attributesInt) { value.intValue = v; }
508 var::var (const int64 v) noexcept : type (&Instance::attributesInt64) { value.int64Value = v; }
509 var::var (const bool v) noexcept : type (&Instance::attributesBool) { value.boolValue = v; }
510 var::var (const double v) noexcept : type (&Instance::attributesDouble) { value.doubleValue = v; }
511 var::var (NativeFunction m) noexcept : type (&Instance::attributesMethod) { value.methodValue = new NativeFunction (m); }
512 var::var (const Array<var>& v) : type (&Instance::attributesArray) { value.objectValue = new VariantType::RefCountedArray (v); }
513 var::var (const String& v) : type (&Instance::attributesString) { new (value.stringValue) String (v); }
514 var::var (const char* const v) : type (&Instance::attributesString) { new (value.stringValue) String (v); }
515 var::var (const wchar_t* const v) : type (&Instance::attributesString) { new (value.stringValue) String (v); }
516 var::var (const void* v, size_t sz) : type (&Instance::attributesBinary) { value.binaryValue = new MemoryBlock (v, sz); }
517 var::var (const MemoryBlock& v) : type (&Instance::attributesBinary) { value.binaryValue = new MemoryBlock (v); }
518
519 var::var (const StringArray& v) : type (&Instance::attributesArray)
520{
521 Array<var> strings;
522 strings.ensureStorageAllocated (v.size());
523
524 for (auto& i : v)
525 strings.add (var (i));
526
527 value.objectValue = new VariantType::RefCountedArray (strings);
528}
529
530 var::var (ReferenceCountedObject* const object) : type (&Instance::attributesObject)
531{
532 value.objectValue = object;
533
534 if (object != nullptr)
535 object->incReferenceCount();
536}
537
538 var var::undefined() noexcept { return var (Instance::attributesUndefined); }
539
540//==============================================================================
541bool var::isVoid() const noexcept { return type->isVoid; }
542bool var::isUndefined() const noexcept { return type->isUndefined; }
543bool var::isInt() const noexcept { return type->isInt; }
544bool var::isInt64() const noexcept { return type->isInt64; }
545bool var::isBool() const noexcept { return type->isBool; }
546bool var::isDouble() const noexcept { return type->isDouble; }
547bool var::isString() const noexcept { return type->isString; }
548bool var::isObject() const noexcept { return type->isObject; }
549bool var::isArray() const noexcept { return type->isArray; }
550bool var::isBinaryData() const noexcept { return type->isBinary; }
551bool var::isMethod() const noexcept { return type->isMethod; }
552
553var::operator int() const noexcept { return type->toInt (value); }
554var::operator int64() const noexcept { return type->toInt64 (value); }
555var::operator bool() const noexcept { return type->toBool (value); }
556var::operator float() const noexcept { return (float) type->toDouble (value); }
557var::operator double() const noexcept { return type->toDouble (value); }
558String var::toString() const { return type->toString (value); }
559var::operator String() const { return type->toString (value); }
560ReferenceCountedObject* var::getObject() const noexcept { return type->toObject (value); }
561 Array<var>* var::getArray() const noexcept { return type->toArray (value); }
562 MemoryBlock* var::getBinaryData() const noexcept { return type->toBinary (value); }
563 DynamicObject* var::getDynamicObject() const noexcept { return dynamic_cast<DynamicObject*> (getObject()); }
564
565//==============================================================================
566void var::swapWith (var& other) noexcept
567{
568 std::swap (type, other.type);
569 std::swap (value, other.value);
570}
571
572var& var::operator= (const var& v) { type->cleanUp (value); type = v.type; type->createCopy (value, v.value); return *this; }
573var& var::operator= (const int v) { type->cleanUp (value); type = &Instance::attributesInt; value.intValue = v; return *this; }
574var& var::operator= (const int64 v) { type->cleanUp (value); type = &Instance::attributesInt64; value.int64Value = v; return *this; }
575var& var::operator= (const bool v) { type->cleanUp (value); type = &Instance::attributesBool; value.boolValue = v; return *this; }
576var& var::operator= (const double v) { type->cleanUp (value); type = &Instance::attributesDouble; value.doubleValue = v; return *this; }
577var& var::operator= (const char* const v) { type->cleanUp (value); type = &Instance::attributesString; new (value.stringValue) String (v); return *this; }
578var& var::operator= (const wchar_t* const v) { type->cleanUp (value); type = &Instance::attributesString; new (value.stringValue) String (v); return *this; }
579var& var::operator= (const String& v) { type->cleanUp (value); type = &Instance::attributesString; new (value.stringValue) String (v); return *this; }
580var& var::operator= (const MemoryBlock& v) { type->cleanUp (value); type = &Instance::attributesBinary; value.binaryValue = new MemoryBlock (v); return *this; }
581var& var::operator= (const Array<var>& v) { var v2 (v); swapWith (v2); return *this; }
582var& var::operator= (ReferenceCountedObject* v) { var v2 (v); swapWith (v2); return *this; }
583var& var::operator= (NativeFunction v) { var v2 (v); swapWith (v2); return *this; }
584
585 var::var (var&& other) noexcept
586 : type (other.type),
587 value (other.value)
588{
589 other.type = &Instance::attributesVoid;
590}
591
592var& var::operator= (var&& other) noexcept
593{
594 swapWith (other);
595 return *this;
596}
597
598 var::var (String&& v) : type (&Instance::attributesString)
599{
600 new (value.stringValue) String (std::move (v));
601}
602
603 var::var (MemoryBlock&& v) : type (&Instance::attributesBinary)
604{
605 value.binaryValue = new MemoryBlock (std::move (v));
606}
607
608 var::var (Array<var>&& v) : type (&Instance::attributesArray)
609{
610 value.objectValue = new VariantType::RefCountedArray (std::move (v));
611}
612
613var& var::operator= (String&& v)
614{
615 type->cleanUp (value);
616 type = &Instance::attributesString;
617 new (value.stringValue) String (std::move (v));
618 return *this;
619}
620
621//==============================================================================
622 bool var::equals (const var& other) const noexcept
623{
624 return type->equals (value, other.value, *other.type);
625}
626
627 bool var::equalsWithSameType (const var& other) const noexcept
628{
629 return hasSameTypeAs (other) && equals (other);
630}
631
632 bool var::hasSameTypeAs (const var& other) const noexcept
633{
634 return type == other.type;
635}
636
637bool canCompare (const var& v1, const var& v2)
638{
639 return v1.type->isComparable && v2.type->isComparable;
640}
641
642static int compare (const var& v1, const var& v2)
643{
644 if (v1.isString() && v2.isString())
645 return v1.toString().compare (v2.toString());
646
647 auto diff = static_cast<double> (v1) - static_cast<double> (v2);
648 return exactlyEqual (diff, 0.0) ? 0 : (diff < 0 ? -1 : 1);
649}
650
651bool operator== (const var& v1, const var& v2) { return v1.equals (v2); }
652bool operator!= (const var& v1, const var& v2) { return ! v1.equals (v2); }
653bool operator< (const var& v1, const var& v2) { return canCompare (v1, v2) && compare (v1, v2) < 0; }
654bool operator> (const var& v1, const var& v2) { return canCompare (v1, v2) && compare (v1, v2) > 0; }
655bool operator<= (const var& v1, const var& v2) { return canCompare (v1, v2) && compare (v1, v2) <= 0; }
656bool operator>= (const var& v1, const var& v2) { return canCompare (v1, v2) && compare (v1, v2) >= 0; }
657
658bool operator== (const var& v1, const String& v2) { return v1.toString() == v2; }
659bool operator!= (const var& v1, const String& v2) { return v1.toString() != v2; }
660bool operator== (const var& v1, const char* v2) { return v1.toString() == v2; }
661bool operator!= (const var& v1, const char* v2) { return v1.toString() != v2; }
662
663//==============================================================================
664 var var::clone() const noexcept
665{
666 return type->clone (*this);
667}
668
669//==============================================================================
670 const var& var::operator[] (const Identifier& propertyName) const
671{
672 if (auto* o = getDynamicObject())
673 return o->getProperty (propertyName);
674
675 return getNullVarRef();
676}
677
678 const var& var::operator[] (const char* const propertyName) const
679{
680 return operator[] (Identifier (propertyName));
681}
682
683 var var::getProperty (const Identifier& propertyName, const var& defaultReturnValue) const
684{
685 if (auto* o = getDynamicObject())
686 return o->getProperties().getWithDefault (propertyName, defaultReturnValue);
687
688 return defaultReturnValue;
689}
690
691 bool var::hasProperty (const Identifier& propertyName) const noexcept
692{
693 if (auto* o = getDynamicObject())
694 return o->hasProperty (propertyName);
695
696 return false;
697}
698
699var::NativeFunction var::getNativeFunction() const
700{
701 return isMethod() && (value.methodValue != nullptr) ? *value.methodValue : nullptr;
702}
703
704 var var::invoke (const Identifier& method, const var* arguments, int numArguments) const
705{
706 if (auto* o = getDynamicObject())
707 return o->invokeMethod (method, var::NativeFunctionArgs (*this, arguments, numArguments));
708
709 return {};
710}
711
712 var var::call (const Identifier& method) const
713{
714 return invoke (method, nullptr, 0);
715}
716
717 var var::call (const Identifier& method, const var& arg1) const
718{
719 return invoke (method, &arg1, 1);
720}
721
722 var var::call (const Identifier& method, const var& arg1, const var& arg2) const
723{
724 var args[] = { arg1, arg2 };
725 return invoke (method, args, 2);
726}
727
728 var var::call (const Identifier& method, const var& arg1, const var& arg2, const var& arg3)
729{
730 var args[] = { arg1, arg2, arg3 };
731 return invoke (method, args, 3);
732}
733
734 var var::call (const Identifier& method, const var& arg1, const var& arg2, const var& arg3, const var& arg4) const
735{
736 var args[] = { arg1, arg2, arg3, arg4 };
737 return invoke (method, args, 4);
738}
739
740 var var::call (const Identifier& method, const var& arg1, const var& arg2, const var& arg3, const var& arg4, const var& arg5) const
741{
742 var args[] = { arg1, arg2, arg3, arg4, arg5 };
743 return invoke (method, args, 5);
744}
745
746//==============================================================================
747 int var::size() const
748{
749 if (auto array = getArray())
750 return array->size();
751
752 return 0;
753}
754
755 const var& var::operator[] (int arrayIndex) const
756{
757 auto array = getArray();
758
759 // When using this method, the var must actually be an array, and the index
760 // must be in-range!
761 jassert (array != nullptr && isPositiveAndBelow (arrayIndex, array->size()));
762
763 return array->getReference (arrayIndex);
764}
765
766 var& var::operator[] (int arrayIndex)
767{
768 auto array = getArray();
769
770 // When using this method, the var must actually be an array, and the index
771 // must be in-range!
772 jassert (array != nullptr && isPositiveAndBelow (arrayIndex, array->size()));
773
774 return array->getReference (arrayIndex);
775}
776
777 Array<var>* var::convertToArray()
778{
779 if (auto array = getArray())
780 return array;
781
782 Array<var> tempVar;
783
784 if (! isVoid())
785 tempVar.add (*this);
786
787 *this = tempVar;
788 return getArray();
789}
790
791 void var::append (const var& n)
792{
793 convertToArray()->add (n);
794}
795
796 void var::remove (const int index)
797{
798 if (auto array = getArray())
799 array->remove (index);
800}
801
802 void var::insert (const int index, const var& n)
803{
804 convertToArray()->insert (index, n);
805}
806
807 void var::resize (const int numArrayElementsWanted)
808{
809 convertToArray()->resize (numArrayElementsWanted);
810}
811
812 int var::indexOf (const var& n) const
813{
814 if (auto array = getArray())
815 return array->indexOf (n);
816
817 return -1;
818}
819
820//==============================================================================
821 void var::writeToStream (OutputStream& output) const
822{
823 type->writeToStream (value, output);
824}
825
826 var var::readFromStream (InputStream& input)
827{
828 const int numBytes = input.readCompressedInt();
829
830 if (numBytes > 0)
831 {
832 switch (input.readByte())
833 {
834 case varMarker_Int: return var (input.readInt());
835 case varMarker_Int64: return var (input.readInt64());
836 case varMarker_BoolTrue: return var (true);
837 case varMarker_BoolFalse: return var (false);
838 case varMarker_Double: return var (input.readDouble());
839
840 case varMarker_String:
841 {
842 MemoryOutputStream mo;
843 mo.writeFromInputStream (input, numBytes - 1);
844 return var (mo.toUTF8());
845 }
846
847 case varMarker_Binary:
848 {
849 MemoryBlock mb ((size_t) numBytes - 1);
850
851 if (numBytes > 1)
852 {
853 const int numRead = input.read (mb.getData(), numBytes - 1);
854 mb.setSize ((size_t) numRead);
855 }
856
857 return var (mb);
858 }
859
860 case varMarker_Array:
861 {
862 var v;
863 auto* destArray = v.convertToArray();
864
865 for (int i = input.readCompressedInt(); --i >= 0;)
866 destArray->add (readFromStream (input));
867
868 return v;
869 }
870
871 default:
872 input.skipNextBytes (numBytes - 1); break;
873 }
874 }
875
876 return {};
877}
878
879var::NativeFunctionArgs::NativeFunctionArgs (const var& t, const var* args, int numArgs) noexcept
880 : thisObject (t), arguments (args), numArguments (numArgs)
881{
882}
883
884//==============================================================================
885#if JUCE_ALLOW_STATIC_NULL_VARIABLES
886
887JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wdeprecated-declarations")
888JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4996)
889
890const var var::null;
891
892JUCE_END_IGNORE_WARNINGS_GCC_LIKE
893JUCE_END_IGNORE_WARNINGS_MSVC
894
895#endif
896
897} // 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(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::equalsIgnoreCase
bool equalsIgnoreCase(const String &other) const noexcept
Definition juce_String.cpp:590
juce::String::trim
String trim() const
Definition juce_String.cpp:1656
juce::String::getDoubleValue
double getDoubleValue() const noexcept
Definition juce_String.cpp:1874
juce::String::toHexString
static String toHexString(IntegerType number)
Definition juce_String.h:1097
juce::String::charToString
static String charToString(juce_wchar character)
Definition juce_String.cpp:359
juce::String::getLargeIntValue
int64 getLargeIntValue() const noexcept
Definition juce_String.cpp:1872
juce::String::getIntValue
int getIntValue() const noexcept
Definition juce_String.cpp:1871
juce::var
Definition juce_Variant.h:42
juce::var::undefined
static var undefined() noexcept
Definition juce_Variant.cpp:538
juce::var::insert
void insert(int index, const var &value)
Definition juce_Variant.cpp:802
juce::var::size
int size() const
Definition juce_Variant.cpp:747
juce::var::invoke
var invoke(const Identifier &method, const var *arguments, int numArguments) const
Definition juce_Variant.cpp:704
juce::var::writeToStream
void writeToStream(OutputStream &output) const
Definition juce_Variant.cpp:821
juce::var::var
var() noexcept
Definition juce_Variant.cpp:497
juce::var::~var
~var() noexcept
Definition juce_Variant.cpp:499
juce::var::getArray
Array< var > * getArray() const noexcept
Definition juce_Variant.cpp:561
juce::var::indexOf
int indexOf(const var &value) const
Definition juce_Variant.cpp:812
juce::var::operator[]
const var & operator[](int arrayIndex) const
Definition juce_Variant.cpp:755
juce::var::getNativeFunction
NativeFunction getNativeFunction() const
Definition juce_Variant.cpp:699
juce::var::hasProperty
bool hasProperty(const Identifier &propertyName) const noexcept
Definition juce_Variant.cpp:691
juce::var::readFromStream
static var readFromStream(InputStream &input)
Definition juce_Variant.cpp:826
juce::var::append
void append(const var &valueToAppend)
Definition juce_Variant.cpp:791
juce::var::equals
bool equals(const var &other) const noexcept
Definition juce_Variant.cpp:622
juce::var::equalsWithSameType
bool equalsWithSameType(const var &other) const noexcept
Definition juce_Variant.cpp:627
juce::var::resize
void resize(int numArrayElementsWanted)
Definition juce_Variant.cpp:807
juce::var::getProperty
var getProperty(const Identifier &propertyName, const var &defaultReturnValue) const
Definition juce_Variant.cpp:683
juce::var::remove
void remove(int index)
Definition juce_Variant.cpp:796
juce::var::call
var call(const Identifier &method) const
Definition juce_Variant.cpp:712
juce::var::hasSameTypeAs
bool hasSameTypeAs(const var &other) const noexcept
Definition juce_Variant.cpp:632
juce::var::clone
var clone() const noexcept
Definition juce_Variant.cpp:664
juce::var::getBinaryData
MemoryBlock * getBinaryData() const noexcept
Definition juce_Variant.cpp:562
juce::var::NativeFunctionArgs
Definition juce_Variant.h:49