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
239 || getString (data)->trim().equalsIgnoreCase (
"true")
240 || getString (data)->trim().equalsIgnoreCase (
"yes"); }
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 319 if (
auto* a = dynamic_cast<RefCountedArray*> (data.objectValue))
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 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); }
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); }
478 value.objectValue = object;
480 if (
object !=
nullptr)
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); }
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; }
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
546 new (value.stringValue)
String (std::move (v));
551 value.binaryValue =
new MemoryBlock (std::move (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);
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)
void insert(int index, const var &value)
Inserts an element to the var, converting it to an array if it isn't already one. ...
var call(const Identifier &method) const
Invokes a named method call with no arguments.
var getProperty(const Identifier &propertyName, const var &defaultReturnValue) const
If this variant is an object, this returns one of its properties, or a default fallback value if the ...
virtual bool write(const void *dataToWrite, size_t numberOfBytes)=0
Writes a block of data to the stream.
virtual bool writeByte(char byte)
Writes a single byte to the stream.
Represents a string identifier, designed for accessing properties by name.
void writeToStream(OutputStream &output) const
Writes a binary representation of this value to a stream.
A variant class, that can be used to hold a range of primitive values.
void ensureStorageAllocated(int minNumElements)
Increases the array's internal storage to hold a minimum number of elements.
void add(const ElementType &newElement)
Appends a new element at the end of the array.
int64 writeFromInputStream(InputStream &, int64 maxNumBytesToWrite) override
Reads data from an input stream and writes it to this stream.
const var & operator[](int arrayIndex) const
If the var is an array, this can be used to return one of its elements.
int indexOf(const var &value) const
If the var is an array, this searches it for the first occurrence of the specified value...
var() noexcept
Creates a void variant.
A special array for holding a list of strings.
int size() const
If the var is an array, this returns the number of elements.
bool hasProperty(const Identifier &propertyName) const noexcept
Returns true if this variant is an object and if it has the given property.
Represents a dynamically implemented object.
void * getData() noexcept
Returns a void pointer to the data.
bool equals(const var &other) const noexcept
Returns true if this var has the same value as the one supplied.
void resize(int numArrayElementsWanted)
Treating the var as an array, this resizes it to contain the specified number of elements.
virtual bool writeInt64(int64 value)
Writes a 64-bit integer to the stream in a little-endian byte order.
static String toHexString(IntegerType number)
Returns a string representing this numeric value in hexadecimal.
var invoke(const Identifier &method, const var *arguments, int numArguments) const
Invokes a named method call with a list of arguments.
Array< var > * getArray() const noexcept
If this variant holds an array, this provides access to it.
void incReferenceCount() noexcept
Increments the object's reference count.
The base class for streams that write data to some kind of destination.
Holds a resizable array of primitive or copy-by-value objects.
void remove(int index)
If the var is an array, this removes one of its elements.
This structure is passed to a NativeFunction callback, and contains invocation details about the func...
MemoryBlock * getBinaryData() const noexcept
If this variant holds a memory block, this provides access to it.
size_t getDataSize() const noexcept
Returns the number of bytes of data that have been written to the stream.
bool equalsWithSameType(const var &other) const noexcept
Returns true if this var has the same value and type as the one supplied.
virtual bool writeDouble(double value)
Writes a 64-bit floating point value to the stream in a binary format.
void append(const var &valueToAppend)
Appends an element to the var, converting it to an array if it isn't already one. ...
~var() noexcept
Destructor.
int getIntValue() const noexcept
Reads the value of the string as a decimal number (up to 32 bits in size).
NativeFunction getNativeFunction() const
If this object is a method, this returns the function pointer.
static String charToString(juce_wchar character)
Creates a string from a single character.
int size() const noexcept
Returns the number of strings in the array.
static var undefined() noexcept
Returns a var object that can be used where you need the javascript "undefined" value.
virtual bool writeInt(int value)
Writes a 32-bit integer to the stream in a little-endian byte order.
String toUTF8() const
Returns a String created from the (UTF8) data that has been written to the stream.
A base class which provides methods for reference-counting.
virtual bool writeCompressedInt(int value)
Writes a condensed binary encoding of a 32-bit integer.
Writes data to an internal memory buffer, which grows as required.
int compare(const String &other) const noexcept
Case-sensitive comparison with another string.
bool hasSameTypeAs(const var &other) const noexcept
Returns true if this var has the same type as the one supplied.
A class to hold a resizable block of raw data.
static var readFromStream(InputStream &input)
Reads back a stored binary representation of a value.
void setSize(const size_t newSize, bool initialiseNewSpaceToZero=false)
Resizes the memory block.
var clone() const noexcept
Returns a deep copy of this object.