26 enum VariantStreamMarkers
29 varMarker_BoolTrue = 2,
30 varMarker_BoolFalse = 3,
36 varMarker_Undefined = 9
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; }
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; }
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; }
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;
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(); }
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(); }
99 void writeToStream (
const ValueUnion&,
OutputStream& output)
const override
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; }
121 bool equals (
const ValueUnion& data,
const ValueUnion& otherData,
const VariantType& otherType)
const noexcept
override
123 if (otherType.isDouble() || otherType.isInt64() || otherType.isString())
124 return otherType.equals (otherData, data, *
this);
126 return otherType.toInt (otherData) == data.intValue;
129 void writeToStream (
const ValueUnion& data,
OutputStream& output)
const override
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; }
152 bool equals (
const ValueUnion& data,
const ValueUnion& otherData,
const VariantType& otherType)
const noexcept
override
154 if (otherType.isDouble() || otherType.isString())
155 return otherType.equals (otherData, data, *
this);
157 return otherType.toInt64 (otherData) == data.int64Value;
160 void writeToStream (
const ValueUnion& data,
OutputStream& output)
const override
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; }
183 bool equals (
const ValueUnion& data,
const ValueUnion& otherData,
const VariantType& otherType)
const noexcept
override
185 return std::abs (otherType.toDouble (otherData) - data.doubleValue) < std::numeric_limits<double>::epsilon();
188 void writeToStream (
const ValueUnion& data,
OutputStream& output)
const override
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; }
211 bool equals (
const ValueUnion& data,
const ValueUnion& otherData,
const VariantType& otherType)
const noexcept
override
213 return otherType.toBool (otherData) == data.boolValue;
216 void writeToStream (
const ValueUnion& data,
OutputStream& output)
const override
219 output.
writeByte (data.boolValue ? (
char) varMarker_BoolTrue : (
char) varMarker_BoolFalse);
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)); }
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
241 bool isComparable()
const noexcept
override {
return true; }
243 bool equals (
const ValueUnion& data,
const ValueUnion& otherData,
const VariantType& otherType)
const noexcept
override
245 return otherType.toString (otherData) == *getString (data);
248 void writeToStream (
const ValueUnion& data,
OutputStream& output)
const override
250 auto* s = getString (data);
251 const size_t len = s->getNumBytesAsUTF8() + 1;
253 s->copyToUTF8 (temp, len);
256 output.
write (temp, len);
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); }
271 void cleanUp (ValueUnion& data)
const noexcept
override {
if (data.objectValue !=
nullptr) data.objectValue->decReferenceCount(); }
273 void createCopy (ValueUnion& dest,
const ValueUnion& source)
const override
275 dest.objectValue = source.objectValue;
276 if (dest.objectValue !=
nullptr)
277 dest.objectValue->incReferenceCount();
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; }
285 bool equals (
const ValueUnion& data,
const ValueUnion& otherData,
const VariantType& otherType)
const noexcept
override
287 return otherType.toObject (otherData) == data.objectValue;
290 var clone (
const var& original)
const override
292 if (
auto* d = original.getDynamicObject())
293 return d->
clone().get();
299 void writeToStream (
const ValueUnion&,
OutputStream& output)
const override
313 String toString (
const ValueUnion&)
const override {
return "[Array]"; }
315 bool isArray()
const noexcept
override {
return true; }
317 Array<var>* toArray (
const ValueUnion& data)
const noexcept
override
325 bool equals (
const ValueUnion& data,
const ValueUnion& otherData,
const VariantType& otherType)
const noexcept
override
327 auto* thisArray = toArray (data);
328 auto* otherArray = otherType.toArray (otherData);
329 return thisArray == otherArray || (thisArray !=
nullptr && otherArray !=
nullptr && *otherArray == *thisArray);
332 var clone (
const var& original)
const override
336 if (
auto* array = toArray (original.value))
340 for (
auto& i : *array)
341 arrayCopy.
add (i.clone());
344 return var (arrayCopy);
347 void writeToStream (
const ValueUnion& data,
OutputStream& output)
const override
349 if (
auto* array = toArray (data))
354 for (
auto& i : *array)
355 i.writeToStream (buffer);
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); }
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; }
386 bool equals (
const ValueUnion& data,
const ValueUnion& otherData,
const VariantType& otherType)
const noexcept
override
388 const MemoryBlock*
const otherBlock = otherType.toBinary (otherData);
389 return otherBlock !=
nullptr && *otherBlock == *data.binaryValue;
392 void writeToStream (
const ValueUnion& data,
OutputStream& output)
const override
396 output << *data.binaryValue;
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); }
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; }
414 bool equals (
const ValueUnion& data,
const ValueUnion& otherData,
const VariantType& otherType)
const noexcept
override
416 return otherType.isMethod() && otherData.methodValue == data.methodValue;
419 void writeToStream (
const ValueUnion&,
OutputStream& output)
const override
442 var::var (
const VariantType& t) noexcept : type (&t) {}
445 JUCE_DECLARE_DEPRECATED_STATIC (
const var var::null;)
448 var::var (
const var& valueToCopy) : type (valueToCopy.type)
450 type->createCopy (value, valueToCopy.value);
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); }
465 var::var (
const StringArray& v) : type (&VariantType_Array::instance)
468 strings.ensureStorageAllocated (v.size());
471 strings.add (
var (i));
473 value.objectValue =
new VariantType_Array::RefCountedArray (strings);
476 var::var (ReferenceCountedObject*
const object) : type (&VariantType_Object::instance)
478 value.objectValue = object;
480 if (
object !=
nullptr)
481 object->incReferenceCount();
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(); }
499 var::operator int() const noexcept {
return type->toInt (value); }
500 var::operator int64() const noexcept {
return type->toInt64 (value); }
501 var::operator bool() const noexcept {
return type->toBool (value); }
502 var::operator float() const noexcept {
return (
float) type->toDouble (value); }
503 var::operator double() const noexcept {
return type->toDouble (value); }
504 String var::toString()
const {
return type->toString (value); }
505 var::operator String()
const {
return type->toString (value); }
506 ReferenceCountedObject* var::getObject() const noexcept {
return type->toObject (value); }
512 void var::swapWith (var& other) noexcept
514 std::swap (type, other.type);
515 std::swap (value, other.value);
518 var& var::operator= (
const var& v) { type->cleanUp (value); type = v.type; type->createCopy (value, v.value);
return *
this; }
519 var& var::operator= (
const int v) { type->cleanUp (value); type = &VariantType_Int::instance; value.intValue = v;
return *
this; }
520 var& var::operator= (
const int64 v) { type->cleanUp (value); type = &VariantType_Int64::instance; value.int64Value = v;
return *
this; }
521 var& var::operator= (
const bool v) { type->cleanUp (value); type = &VariantType_Bool::instance; value.boolValue = v;
return *
this; }
522 var& var::operator= (
const double v) { type->cleanUp (value); type = &VariantType_Double::instance; value.doubleValue = v;
return *
this; }
523 var& var::operator= (
const char*
const v) { type->cleanUp (value); type = &VariantType_String::instance;
new (value.stringValue) String (v);
return *
this; }
524 var& var::operator= (
const wchar_t*
const v) { type->cleanUp (value); type = &VariantType_String::instance;
new (value.stringValue) String (v);
return *
this; }
525 var& var::operator= (
const String& v) { type->cleanUp (value); type = &VariantType_String::instance;
new (value.stringValue) String (v);
return *
this; }
526 var& var::operator= (
const MemoryBlock& v) { type->cleanUp (value); type = &VariantType_Binary::instance; value.binaryValue =
new MemoryBlock (v);
return *
this; }
527 var& var::operator= (
const Array<var>& v) {
var v2 (v); swapWith (v2);
return *
this; }
528 var& var::operator= (ReferenceCountedObject* v) {
var v2 (v); swapWith (v2);
return *
this; }
529 var& var::operator= (NativeFunction v) {
var v2 (v); swapWith (v2);
return *
this; }
535 other.type = &VariantType_Void::instance;
538 var& var::operator= (var&& other) noexcept
544 var::var (String&& v) : type (&VariantType_String::instance)
546 new (value.stringValue) String (std::move (v));
549 var::var (MemoryBlock&& v) : type (&VariantType_Binary::instance)
551 value.binaryValue =
new MemoryBlock (std::move (v));
554 var::var (Array<var>&& v) : type (&VariantType_Array::instance)
556 value.objectValue =
new VariantType_Array::RefCountedArray (std::move (v));
559 var& var::operator= (String&& v)
561 type->cleanUp (value);
562 type = &VariantType_String::instance;
563 new (value.stringValue) String (std::move (v));
570 return type->equals (value, other.value, *other.type);
575 return hasSameTypeAs (other) && equals (other);
580 return type == other.type;
583 bool canCompare (
const var& v1,
const var& v2)
585 return v1.type->isComparable() && v2.type->isComparable();
588 static int compare (
const var& v1,
const var& v2)
590 if (v1.isString() && v2.isString())
591 return v1.toString().compare (v2.toString());
593 auto diff =
static_cast<double> (v1) -
static_cast<double> (v2);
594 return diff == 0 ? 0 : (diff < 0 ? -1 : 1);
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; }
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; }
612 return type->clone (*
this);
618 if (
auto* o = getDynamicObject())
621 return getNullVarRef();
631 if (
auto* o = getDynamicObject())
632 return o->getProperties().getWithDefault (propertyName, defaultReturnValue);
634 return defaultReturnValue;
639 if (
auto* o = getDynamicObject())
640 return o->hasProperty (propertyName);
647 return isMethod() && (value.methodValue !=
nullptr) ? *value.methodValue :
nullptr;
652 if (
auto* o = getDynamicObject())
660 return invoke (method,
nullptr, 0);
665 return invoke (method, &arg1, 1);
670 var args[] = { arg1, arg2 };
671 return invoke (method, args, 2);
676 var args[] = { arg1, arg2, arg3 };
677 return invoke (method, args, 3);
682 var args[] = { arg1, arg2, arg3, arg4 };
683 return invoke (method, args, 4);
688 var args[] = { arg1, arg2, arg3, arg4, arg5 };
689 return invoke (method, args, 5);
696 return array->size();
707 jassert (array !=
nullptr && isPositiveAndBelow (arrayIndex, array->size()));
709 return array->getReference (arrayIndex);
718 jassert (array !=
nullptr && isPositiveAndBelow (arrayIndex, array->size()));
720 return array->getReference (arrayIndex);
739 convertToArray()->add (n);
745 array->remove (index);
750 convertToArray()->insert (index, n);
755 convertToArray()->resize (numArrayElementsWanted);
761 return array->indexOf (n);
769 type->writeToStream (value, output);
780 case varMarker_Int:
return var (input.
readInt());
782 case varMarker_BoolTrue:
return var (
true);
783 case varMarker_BoolFalse:
return var (
false);
786 case varMarker_String:
793 case varMarker_Binary:
799 const int numRead = input.
read (mb.
getData(), numBytes - 1);
806 case varMarker_Array:
809 auto* destArray = v.convertToArray();
825 var::NativeFunctionArgs::NativeFunctionArgs (
const var& t,
const var* args,
int numArgs) noexcept
826 : thisObject (t), arguments (args), numArguments (numArgs)