1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365
|
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2020 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
The code included in this file is provided under the terms of the ISC license
http://www.isc.org/downloads/software-support-policy/isc-license. Permission
To use, copy, modify, and/or distribute this software for any purpose with or
without fee is hereby granted provided that the above copyright notice and
this permission notice appear in all copies.
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
/**
A variant class, that can be used to hold a range of primitive values.
A var object can hold a range of simple primitive values, strings, or
any kind of ReferenceCountedObject. The var class is intended to act like
the kind of values used in dynamic scripting languages.
You can save/load var objects either in a small, proprietary binary format
using writeToStream()/readFromStream(), or as JSON by using the JSON class.
@see JSON, DynamicObject
@tags{Core}
*/
class JUCE_API var
{
public:
//==============================================================================
/** This structure is passed to a NativeFunction callback, and contains invocation
details about the function's arguments and context.
*/
struct JUCE_API NativeFunctionArgs
{
NativeFunctionArgs (const var& thisObject, const var* args, int numArgs) noexcept;
const var& thisObject;
const var* arguments;
int numArguments;
};
using NativeFunction = std::function<var (const NativeFunctionArgs&)>;
//==============================================================================
/** Creates a void variant. */
var() noexcept;
/** Destructor. */
~var() noexcept;
var (const var& valueToCopy);
var (int value) noexcept;
var (int64 value) noexcept;
var (bool value) noexcept;
var (double value) noexcept;
var (const char* value);
var (const wchar_t* value);
var (const String& value);
var (const Array<var>& value);
var (const StringArray& value);
var (ReferenceCountedObject* object);
var (NativeFunction method) noexcept;
var (const void* binaryData, size_t dataSize);
var (const MemoryBlock& binaryData);
var& operator= (const var& valueToCopy);
var& operator= (int value);
var& operator= (int64 value);
var& operator= (bool value);
var& operator= (double value);
var& operator= (const char* value);
var& operator= (const wchar_t* value);
var& operator= (const String& value);
var& operator= (const MemoryBlock& value);
var& operator= (const Array<var>& value);
var& operator= (ReferenceCountedObject* object);
var& operator= (NativeFunction method);
var (var&&) noexcept;
var (String&&);
var (MemoryBlock&&);
var (Array<var>&&);
var& operator= (var&&) noexcept;
var& operator= (String&&);
void swapWith (var& other) noexcept;
/** Returns a var object that can be used where you need the javascript "undefined" value. */
static var undefined() noexcept;
//==============================================================================
operator int() const noexcept;
operator int64() const noexcept;
operator bool() const noexcept;
operator float() const noexcept;
operator double() const noexcept;
operator String() const;
String toString() const;
/** If this variant holds an array, this provides access to it.
NOTE: Beware when you use this - the array pointer is only valid for the lifetime
of the variant that returned it, so be very careful not to call this method on temporary
var objects that are the return-value of a function, and which may go out of scope before
you use the array!
*/
Array<var>* getArray() const noexcept;
/** If this variant holds a memory block, this provides access to it.
NOTE: Beware when you use this - the MemoryBlock pointer is only valid for the lifetime
of the variant that returned it, so be very careful not to call this method on temporary
var objects that are the return-value of a function, and which may go out of scope before
you use the MemoryBlock!
*/
MemoryBlock* getBinaryData() const noexcept;
ReferenceCountedObject* getObject() const noexcept;
DynamicObject* getDynamicObject() const noexcept;
//==============================================================================
bool isVoid() const noexcept;
bool isUndefined() const noexcept;
bool isInt() const noexcept;
bool isInt64() const noexcept;
bool isBool() const noexcept;
bool isDouble() const noexcept;
bool isString() const noexcept;
bool isObject() const noexcept;
bool isArray() const noexcept;
bool isBinaryData() const noexcept;
bool isMethod() const noexcept;
/** Returns true if this var has the same value as the one supplied.
Note that this ignores the type, so a string var "123" and an integer var with the
value 123 are considered to be equal.
Note that equality checking depends on the "wrapped" type of the object on which
equals() is called. That means the following code will convert the right-hand-side
argument to a string and compare the string values, because the object on the
left-hand-side was initialised from a string:
@code var ("123").equals (var (123)) @endcode
However, the following code will convert the right-hand-side argument to a double
and compare the values as doubles, because the object on the left-hand-side was
initialised from a double:
@code var (45.6).equals ("45.6000") @endcode
@see equalsWithSameType
*/
bool equals (const var& other) const noexcept;
/** Returns true if this var has the same value and type as the one supplied.
This differs from equals() because e.g. "123" and 123 will be considered different.
@see equals
*/
bool equalsWithSameType (const var& other) const noexcept;
/** Returns true if this var has the same type as the one supplied. */
bool hasSameTypeAs (const var& other) const noexcept;
/** Returns a deep copy of this object.
For simple types this just returns a copy, but if the object contains any arrays
or DynamicObjects, they will be cloned (recursively).
*/
var clone() const noexcept;
//==============================================================================
/** If the var is an array, this returns the number of elements.
If the var isn't actually an array, this will return 0.
*/
int size() const;
/** If the var is an array, this can be used to return one of its elements.
To call this method, you must make sure that the var is actually an array, and
that the index is a valid number. If these conditions aren't met, behaviour is
undefined.
For more control over the array's contents, you can call getArray() and manipulate
it directly as an Array\<var\>.
*/
const var& operator[] (int arrayIndex) const;
/** If the var is an array, this can be used to return one of its elements.
To call this method, you must make sure that the var is actually an array, and
that the index is a valid number. If these conditions aren't met, behaviour is
undefined.
For more control over the array's contents, you can call getArray() and manipulate
it directly as an Array\<var\>.
*/
var& operator[] (int arrayIndex);
/** Appends an element to the var, converting it to an array if it isn't already one.
If the var isn't an array, it will be converted to one, and if its value was non-void,
this value will be kept as the first element of the new array. The parameter value
will then be appended to it.
For more control over the array's contents, you can call getArray() and manipulate
it directly as an Array\<var\>.
*/
void append (const var& valueToAppend);
/** Inserts an element to the var, converting it to an array if it isn't already one.
If the var isn't an array, it will be converted to one, and if its value was non-void,
this value will be kept as the first element of the new array. The parameter value
will then be inserted into it.
For more control over the array's contents, you can call getArray() and manipulate
it directly as an Array\<var\>.
*/
void insert (int index, const var& value);
/** If the var is an array, this removes one of its elements.
If the index is out-of-range or the var isn't an array, nothing will be done.
For more control over the array's contents, you can call getArray() and manipulate
it directly as an Array\<var\>.
*/
void remove (int index);
/** Treating the var as an array, this resizes it to contain the specified number of elements.
If the var isn't an array, it will be converted to one, and if its value was non-void,
this value will be kept as the first element of the new array before resizing.
For more control over the array's contents, you can call getArray() and manipulate
it directly as an Array\<var\>.
*/
void resize (int numArrayElementsWanted);
/** If the var is an array, this searches it for the first occurrence of the specified value,
and returns its index.
If the var isn't an array, or if the value isn't found, this returns -1.
*/
int indexOf (const var& value) const;
//==============================================================================
/** If this variant is an object, this returns one of its properties. */
const var& operator[] (const Identifier& propertyName) const;
/** If this variant is an object, this returns one of its properties. */
const var& operator[] (const char* propertyName) const;
/** If this variant is an object, this returns one of its properties, or a default
fallback value if the property is not set. */
var getProperty (const Identifier& propertyName, const var& defaultReturnValue) const;
/** Returns true if this variant is an object and if it has the given property. */
bool hasProperty (const Identifier& propertyName) const noexcept;
/** Invokes a named method call with no arguments. */
var call (const Identifier& method) const;
/** Invokes a named method call with one argument. */
var call (const Identifier& method, const var& arg1) const;
/** Invokes a named method call with 2 arguments. */
var call (const Identifier& method, const var& arg1, const var& arg2) const;
/** Invokes a named method call with 3 arguments. */
var call (const Identifier& method, const var& arg1, const var& arg2, const var& arg3);
/** Invokes a named method call with 4 arguments. */
var call (const Identifier& method, const var& arg1, const var& arg2, const var& arg3, const var& arg4) const;
/** Invokes a named method call with 5 arguments. */
var call (const Identifier& method, const var& arg1, const var& arg2, const var& arg3, const var& arg4, const var& arg5) const;
/** Invokes a named method call with a list of arguments. */
var invoke (const Identifier& method, const var* arguments, int numArguments) const;
/** If this object is a method, this returns the function pointer. */
NativeFunction getNativeFunction() const;
//==============================================================================
/** Writes a binary representation of this value to a stream.
The data can be read back later using readFromStream().
@see JSON
*/
void writeToStream (OutputStream& output) const;
/** Reads back a stored binary representation of a value.
The data in the stream must have been written using writeToStream(), or this
will have unpredictable results.
@see JSON
*/
static var readFromStream (InputStream& input);
//==============================================================================
#if JUCE_ALLOW_STATIC_NULL_VARIABLES && ! defined (DOXYGEN)
[[deprecated ("This was a static empty var object, but is now deprecated as it's too easy to accidentally "
"use it indirectly during a static constructor leading to hard-to-find order-of-initialisation "
"problems. Use var() or {} instead. For returning an empty var from a function by reference, "
"use a function-local static var and return that.")]]
static const var null;
#endif
private:
//==============================================================================
struct VariantType;
struct Instance;
union ValueUnion
{
int intValue;
int64 int64Value;
bool boolValue;
double doubleValue;
char stringValue[sizeof (String)];
ReferenceCountedObject* objectValue;
MemoryBlock* binaryValue;
NativeFunction* methodValue;
};
friend bool canCompare (const var&, const var&);
const VariantType* type;
ValueUnion value;
Array<var>* convertToArray();
var (const VariantType&) noexcept;
// This is needed to prevent the wrong constructor/operator being called
var (const ReferenceCountedObject*) = delete;
var& operator= (const ReferenceCountedObject*) = delete;
var (const void*) = delete;
var& operator= (const void*) = delete;
};
/** Compares the values of two var objects, using the var::equals() comparison. */
JUCE_API bool operator== (const var&, const var&);
/** Compares the values of two var objects, using the var::equals() comparison. */
JUCE_API bool operator!= (const var&, const var&);
/** Compares the values of two var objects, using the var::equals() comparison. */
JUCE_API bool operator< (const var&, const var&);
/** Compares the values of two var objects, using the var::equals() comparison. */
JUCE_API bool operator<= (const var&, const var&);
/** Compares the values of two var objects, using the var::equals() comparison. */
JUCE_API bool operator> (const var&, const var&);
/** Compares the values of two var objects, using the var::equals() comparison. */
JUCE_API bool operator>= (const var&, const var&);
JUCE_API bool operator== (const var&, const String&);
JUCE_API bool operator!= (const var&, const String&);
JUCE_API bool operator== (const var&, const char*);
JUCE_API bool operator!= (const var&, const char*);
//==============================================================================
/** This template-overloaded class can be used to convert between var and custom types.
@tags{Core}
*/
template <typename Type>
struct VariantConverter
{
static Type fromVar (const var& v) { return static_cast<Type> (v); }
static var toVar (const Type& t) { return t; }
};
#ifndef DOXYGEN
template <>
struct VariantConverter<String>
{
static String fromVar (const var& v) { return v.toString(); }
static var toVar (const String& s) { return s; }
};
#endif
} // namespace juce
|