Browse Source

var: Make it safe to create var instances with static storage duration

tags/2021-05-28
reuk 4 years ago
parent
commit
ae1076d01f
No known key found for this signature in database GPG Key ID: 9ADCD339CFC98A11
2 changed files with 356 additions and 298 deletions
  1. +354
    -286
      modules/juce_core/containers/juce_Variant.cpp
  2. +2
    -12
      modules/juce_core/containers/juce_Variant.h

+ 354
- 286
modules/juce_core/containers/juce_Variant.cpp View File

@@ -37,215 +37,248 @@ enum VariantStreamMarkers
};
//==============================================================================
class var::VariantType
{
public:
VariantType() noexcept {}
virtual ~VariantType() noexcept {}
virtual int toInt (const ValueUnion&) const noexcept { return 0; }
virtual int64 toInt64 (const ValueUnion&) const noexcept { return 0; }
virtual double toDouble (const ValueUnion&) const noexcept { return 0; }
virtual String toString (const ValueUnion&) const { return {}; }
virtual bool toBool (const ValueUnion&) const noexcept { return false; }
virtual ReferenceCountedObject* toObject (const ValueUnion&) const noexcept { return nullptr; }
virtual Array<var>* toArray (const ValueUnion&) const noexcept { return nullptr; }
virtual MemoryBlock* toBinary (const ValueUnion&) const noexcept { return nullptr; }
virtual var clone (const var& original) const { return original; }
virtual bool isVoid() const noexcept { return false; }
virtual bool isUndefined() const noexcept { return false; }
virtual bool isInt() const noexcept { return false; }
virtual bool isInt64() const noexcept { return false; }
virtual bool isBool() const noexcept { return false; }
virtual bool isDouble() const noexcept { return false; }
virtual bool isString() const noexcept { return false; }
virtual bool isObject() const noexcept { return false; }
virtual bool isArray() const noexcept { return false; }
virtual bool isBinary() const noexcept { return false; }
virtual bool isMethod() const noexcept { return false; }
virtual bool isComparable() const noexcept { return false; }
virtual void cleanUp (ValueUnion&) const noexcept {}
virtual void createCopy (ValueUnion& dest, const ValueUnion& source) const { dest = source; }
virtual bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept = 0;
virtual void writeToStream (const ValueUnion& data, OutputStream& output) const = 0;
};
struct var::VariantType
{
struct VoidTag {};
struct UndefinedTag {};
struct IntTag {};
struct Int64Tag {};
struct DoubleTag {};
struct BoolTag {};
struct StringTag {};
struct ObjectTag {};
struct ArrayTag {};
struct BinaryTag {};
struct MethodTag {};
// members =====================================================================
bool isVoid = false;
bool isUndefined = false;
bool isInt = false;
bool isInt64 = false;
bool isBool = false;
bool isDouble = false;
bool isString = false;
bool isObject = false;
bool isArray = false;
bool isBinary = false;
bool isMethod = false;
bool isComparable = false;
int (*toInt) (const ValueUnion&) = defaultToInt;
int64 (*toInt64) (const ValueUnion&) = defaultToInt64;
double (*toDouble) (const ValueUnion&) = defaultToDouble;
String (*toString) (const ValueUnion&) = defaultToString;
bool (*toBool) (const ValueUnion&) = defaultToBool;
ReferenceCountedObject* (*toObject) (const ValueUnion&) = defaultToObject;
Array<var>* (*toArray) (const ValueUnion&) = defaultToArray;
MemoryBlock* (*toBinary) (const ValueUnion&) = defaultToBinary;
var (*clone) (const var&) = defaultClone;
void (*cleanUp) (ValueUnion&) = defaultCleanUp;
void (*createCopy) (ValueUnion&, const ValueUnion&) = defaultCreateCopy;
bool (*equals) (const ValueUnion&, const ValueUnion&, const VariantType&) = nullptr;
void (*writeToStream) (const ValueUnion&, OutputStream&) = nullptr;
// defaults ====================================================================
static int defaultToInt (const ValueUnion&) { return 0; }
static int64 defaultToInt64 (const ValueUnion&) { return 0; }
static double defaultToDouble (const ValueUnion&) { return 0; }
static String defaultToString (const ValueUnion&) { return {}; }
static bool defaultToBool (const ValueUnion&) { return false; }
static ReferenceCountedObject* defaultToObject (const ValueUnion&) { return nullptr; }
static Array<var>* defaultToArray (const ValueUnion&) { return nullptr; }
static MemoryBlock* defaultToBinary (const ValueUnion&) { return nullptr; }
static var defaultClone (const var& other) { return other; }
static void defaultCleanUp (ValueUnion&) {}
static void defaultCreateCopy (ValueUnion& dest, const ValueUnion& source) { dest = source; }
// void ========================================================================
static bool voidEquals (const ValueUnion&, const ValueUnion&, const VariantType& otherType) noexcept
{
return otherType.isVoid || otherType.isUndefined;
}
//==============================================================================
class var::VariantType_Void : public var::VariantType
{
public:
VariantType_Void() noexcept {}
static const VariantType_Void instance;
static void voidWriteToStream (const ValueUnion&, OutputStream& output)
{
output.writeCompressedInt (0);
}
bool isVoid() const noexcept override { return true; }
bool isComparable() const noexcept override { return true; }
bool equals (const ValueUnion&, const ValueUnion&, const VariantType& otherType) const noexcept override { return otherType.isVoid() || otherType.isUndefined(); }
void writeToStream (const ValueUnion&, OutputStream& output) const override { output.writeCompressedInt (0); }
};
constexpr explicit VariantType (VoidTag) noexcept
: isVoid (true),
isComparable (true),
equals (voidEquals),
writeToStream (voidWriteToStream) {}
//==============================================================================
class var::VariantType_Undefined : public var::VariantType
{
public:
VariantType_Undefined() noexcept {}
static const VariantType_Undefined instance;
// undefined ===================================================================
static String undefinedToString (const ValueUnion&) { return "undefined"; }
bool isUndefined() const noexcept override { return true; }
String toString (const ValueUnion&) const override { return "undefined"; }
bool equals (const ValueUnion&, const ValueUnion&, const VariantType& otherType) const noexcept override { return otherType.isVoid() || otherType.isUndefined(); }
static bool undefinedEquals (const ValueUnion&, const ValueUnion&, const VariantType& otherType) noexcept
{
return otherType.isVoid || otherType.isUndefined;
}
void writeToStream (const ValueUnion&, OutputStream& output) const override
static void undefinedWriteToStream (const ValueUnion&, OutputStream& output)
{
output.writeCompressedInt (1);
output.writeByte (varMarker_Undefined);
}
};
//==============================================================================
class var::VariantType_Int : public var::VariantType
{
public:
VariantType_Int() noexcept {}
static const VariantType_Int instance;
constexpr explicit VariantType (UndefinedTag) noexcept
: isUndefined (true),
toString (undefinedToString),
equals (undefinedEquals),
writeToStream (undefinedWriteToStream) {}
int toInt (const ValueUnion& data) const noexcept override { return data.intValue; }
int64 toInt64 (const ValueUnion& data) const noexcept override { return (int64) data.intValue; }
double toDouble (const ValueUnion& data) const noexcept override { return (double) data.intValue; }
String toString (const ValueUnion& data) const override { return String (data.intValue); }
bool toBool (const ValueUnion& data) const noexcept override { return data.intValue != 0; }
bool isInt() const noexcept override { return true; }
bool isComparable() const noexcept override { return true; }
// int =========================================================================
static int intToInt (const ValueUnion& data) noexcept { return data.intValue; }
static int64 intToInt64 (const ValueUnion& data) noexcept { return (int64) data.intValue; }
static double intToDouble (const ValueUnion& data) noexcept { return (double) data.intValue; }
static String intToString (const ValueUnion& data) { return String (data.intValue); }
static bool intToBool (const ValueUnion& data) noexcept { return data.intValue != 0; }
bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept override
static bool intEquals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) noexcept
{
if (otherType.isDouble() || otherType.isInt64() || otherType.isString())
return otherType.equals (otherData, data, *this);
if (otherType.isDouble || otherType.isInt64 || otherType.isString)
return otherType.equals (otherData, data, VariantType { IntTag{} });
return otherType.toInt (otherData) == data.intValue;
}
void writeToStream (const ValueUnion& data, OutputStream& output) const override
static void intWriteToStream (const ValueUnion& data, OutputStream& output)
{
output.writeCompressedInt (5);
output.writeByte (varMarker_Int);
output.writeInt (data.intValue);
}
};
//==============================================================================
class var::VariantType_Int64 : public var::VariantType
{
public:
VariantType_Int64() noexcept {}
static const VariantType_Int64 instance;
int toInt (const ValueUnion& data) const noexcept override { return (int) data.int64Value; }
int64 toInt64 (const ValueUnion& data) const noexcept override { return data.int64Value; }
double toDouble (const ValueUnion& data) const noexcept override { return (double) data.int64Value; }
String toString (const ValueUnion& data) const override { return String (data.int64Value); }
bool toBool (const ValueUnion& data) const noexcept override { return data.int64Value != 0; }
bool isInt64() const noexcept override { return true; }
bool isComparable() const noexcept override { return true; }
bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept override
constexpr explicit VariantType (IntTag) noexcept
: isInt (true),
isComparable (true),
toInt (intToInt),
toInt64 (intToInt64),
toDouble (intToDouble),
toString (intToString),
toBool (intToBool),
equals (intEquals),
writeToStream (intWriteToStream) {}
// int64 =======================================================================
static int int64ToInt (const ValueUnion& data) noexcept { return (int) data.int64Value; }
static int64 int64ToInt64 (const ValueUnion& data) noexcept { return data.int64Value; }
static double int64ToDouble (const ValueUnion& data) noexcept { return (double) data.int64Value; }
static String int64ToString (const ValueUnion& data) { return String (data.int64Value); }
static bool int64ToBool (const ValueUnion& data) noexcept { return data.int64Value != 0; }
static bool int64Equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) noexcept
{
if (otherType.isDouble() || otherType.isString())
return otherType.equals (otherData, data, *this);
if (otherType.isDouble || otherType.isString)
return otherType.equals (otherData, data, VariantType { Int64Tag{} });
return otherType.toInt64 (otherData) == data.int64Value;
}
void writeToStream (const ValueUnion& data, OutputStream& output) const override
static void int64WriteToStream (const ValueUnion& data, OutputStream& output)
{
output.writeCompressedInt (9);
output.writeByte (varMarker_Int64);
output.writeInt64 (data.int64Value);
}
};
//==============================================================================
class var::VariantType_Double : public var::VariantType
{
public:
VariantType_Double() noexcept {}
static const VariantType_Double instance;
int toInt (const ValueUnion& data) const noexcept override { return (int) data.doubleValue; }
int64 toInt64 (const ValueUnion& data) const noexcept override { return (int64) data.doubleValue; }
double toDouble (const ValueUnion& data) const noexcept override { return data.doubleValue; }
String toString (const ValueUnion& data) const override { return serialiseDouble (data.doubleValue); }
bool toBool (const ValueUnion& data) const noexcept override { return data.doubleValue != 0.0; }
bool isDouble() const noexcept override { return true; }
bool isComparable() const noexcept override { return true; }
bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept override
constexpr explicit VariantType (Int64Tag) noexcept
: isInt64 (true),
isComparable (true),
toInt (int64ToInt),
toInt64 (int64ToInt64),
toDouble (int64ToDouble),
toString (int64ToString),
toBool (int64ToBool),
equals (int64Equals),
writeToStream (int64WriteToStream) {}
// double ======================================================================
static int doubleToInt (const ValueUnion& data) noexcept { return (int) data.doubleValue; }
static int64 doubleToInt64 (const ValueUnion& data) noexcept { return (int64) data.doubleValue; }
static double doubleToDouble (const ValueUnion& data) noexcept { return data.doubleValue; }
static String doubleToString (const ValueUnion& data) { return serialiseDouble (data.doubleValue); }
static bool doubleToBool (const ValueUnion& data) noexcept { return data.doubleValue != 0.0; }
static bool doubleEquals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) noexcept
{
return std::abs (otherType.toDouble (otherData) - data.doubleValue) < std::numeric_limits<double>::epsilon();
}
void writeToStream (const ValueUnion& data, OutputStream& output) const override
static void doubleWriteToStream (const ValueUnion& data, OutputStream& output)
{
output.writeCompressedInt (9);
output.writeByte (varMarker_Double);
output.writeDouble (data.doubleValue);
}
};
//==============================================================================
class var::VariantType_Bool : public var::VariantType
{
public:
VariantType_Bool() noexcept {}
static const VariantType_Bool instance;
int toInt (const ValueUnion& data) const noexcept override { return data.boolValue ? 1 : 0; }
int64 toInt64 (const ValueUnion& data) const noexcept override { return data.boolValue ? 1 : 0; }
double toDouble (const ValueUnion& data) const noexcept override { return data.boolValue ? 1.0 : 0.0; }
String toString (const ValueUnion& data) const override { return String::charToString (data.boolValue ? (juce_wchar) '1' : (juce_wchar) '0'); }
bool toBool (const ValueUnion& data) const noexcept override { return data.boolValue; }
bool isBool() const noexcept override { return true; }
bool isComparable() const noexcept override { return true; }
bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept override
constexpr explicit VariantType (DoubleTag) noexcept
: isDouble (true),
isComparable (true),
toInt (doubleToInt),
toInt64 (doubleToInt64),
toDouble (doubleToDouble),
toString (doubleToString),
toBool (doubleToBool),
equals (doubleEquals),
writeToStream (doubleWriteToStream) {}
// bool ========================================================================
static int boolToInt (const ValueUnion& data) noexcept { return data.boolValue ? 1 : 0; }
static int64 boolToInt64 (const ValueUnion& data) noexcept { return data.boolValue ? 1 : 0; }
static double boolToDouble (const ValueUnion& data) noexcept { return data.boolValue ? 1.0 : 0.0; }
static String boolToString (const ValueUnion& data) { return String::charToString (data.boolValue ? (juce_wchar) '1' : (juce_wchar) '0'); }
static bool boolToBool (const ValueUnion& data) noexcept { return data.boolValue; }
static bool boolEquals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) noexcept
{
return otherType.toBool (otherData) == data.boolValue;
}
void writeToStream (const ValueUnion& data, OutputStream& output) const override
static void boolWriteToStream (const ValueUnion& data, OutputStream& output)
{
output.writeCompressedInt (1);
output.writeByte (data.boolValue ? (char) varMarker_BoolTrue : (char) varMarker_BoolFalse);
}
};
//==============================================================================
class var::VariantType_String : public var::VariantType
{
public:
VariantType_String() noexcept {}
static const VariantType_String instance;
void cleanUp (ValueUnion& data) const noexcept override { getString (data)-> ~String(); }
void createCopy (ValueUnion& dest, const ValueUnion& source) const override { new (dest.stringValue) String (*getString (source)); }
bool isString() const noexcept override { return true; }
int toInt (const ValueUnion& data) const noexcept override { return getString (data)->getIntValue(); }
int64 toInt64 (const ValueUnion& data) const noexcept override { return getString (data)->getLargeIntValue(); }
double toDouble (const ValueUnion& data) const noexcept override { return getString (data)->getDoubleValue(); }
String toString (const ValueUnion& data) const override { return *getString (data); }
bool toBool (const ValueUnion& data) const noexcept override { return getString (data)->getIntValue() != 0
|| getString (data)->trim().equalsIgnoreCase ("true")
|| getString (data)->trim().equalsIgnoreCase ("yes"); }
bool isComparable() const noexcept override { return true; }
bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept override
constexpr explicit VariantType (BoolTag) noexcept
: isBool (true),
isComparable (true),
toInt (boolToInt),
toInt64 (boolToInt64),
toDouble (boolToDouble),
toString (boolToString),
toBool (boolToBool),
equals (boolEquals),
writeToStream (boolWriteToStream) {}
// string ======================================================================
static const String* getString (const ValueUnion& data) noexcept { return unalignedPointerCast<const String*> (data.stringValue); }
static String* getString ( ValueUnion& data) noexcept { return unalignedPointerCast<String*> (data.stringValue); }
static int stringToInt (const ValueUnion& data) noexcept { return getString (data)->getIntValue(); }
static int64 stringToInt64 (const ValueUnion& data) noexcept { return getString (data)->getLargeIntValue(); }
static double stringToDouble (const ValueUnion& data) noexcept { return getString (data)->getDoubleValue(); }
static String stringToString (const ValueUnion& data) { return *getString (data); }
static bool stringToBool (const ValueUnion& data) noexcept
{
return getString (data)->getIntValue() != 0
|| getString (data)->trim().equalsIgnoreCase ("true")
|| getString (data)->trim().equalsIgnoreCase ("yes");
}
static void stringCleanUp (ValueUnion& data) noexcept { getString (data)-> ~String(); }
static void stringCreateCopy (ValueUnion& dest, const ValueUnion& source) { new (dest.stringValue) String (*getString (source)); }
static bool stringEquals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) noexcept
{
return otherType.toString (otherData) == *getString (data);
}
void writeToStream (const ValueUnion& data, OutputStream& output) const override
static void stringWriteToStream (const ValueUnion& data, OutputStream& output)
{
auto* s = getString (data);
const size_t len = s->getNumBytesAsUTF8() + 1;
@@ -256,65 +289,73 @@ public:
output.write (temp, len);
}
private:
static const String* getString (const ValueUnion& data) noexcept { return unalignedPointerCast<const String*> (data.stringValue); }
static String* getString (ValueUnion& data) noexcept { return unalignedPointerCast<String*> (data.stringValue); }
};
constexpr explicit VariantType (StringTag) noexcept
: isString (true),
isComparable (true),
toInt (stringToInt),
toInt64 (stringToInt64),
toDouble (stringToDouble),
toString (stringToString),
toBool (stringToBool),
cleanUp (stringCleanUp),
createCopy (stringCreateCopy),
equals (stringEquals),
writeToStream (stringWriteToStream) {}
// object ======================================================================
static String objectToString (const ValueUnion& data)
{
return "Object 0x" + String::toHexString ((int) (pointer_sized_int) data.objectValue);
}
//==============================================================================
class var::VariantType_Object : public var::VariantType
{
public:
VariantType_Object() noexcept {}
static const VariantType_Object instance;
static bool objectToBool (const ValueUnion& data) noexcept { return data.objectValue != nullptr; }
static ReferenceCountedObject* objectToObject (const ValueUnion& data) noexcept { return data.objectValue; }
static var objectClone (const var& original)
{
if (auto* d = original.getDynamicObject())
return d->clone().get();
void cleanUp (ValueUnion& data) const noexcept override { if (data.objectValue != nullptr) data.objectValue->decReferenceCount(); }
jassertfalse; // can only clone DynamicObjects!
return {};
}
void createCopy (ValueUnion& dest, const ValueUnion& source) const override
static void objectCleanUp (ValueUnion& data) noexcept { if (data.objectValue != nullptr) data.objectValue->decReferenceCount(); }
static void objectCreateCopy (ValueUnion& dest, const ValueUnion& source)
{
dest.objectValue = source.objectValue;
if (dest.objectValue != nullptr)
dest.objectValue->incReferenceCount();
}
String toString (const ValueUnion& data) const override { return "Object 0x" + String::toHexString ((int) (pointer_sized_int) data.objectValue); }
bool toBool (const ValueUnion& data) const noexcept override { return data.objectValue != nullptr; }
ReferenceCountedObject* toObject (const ValueUnion& data) const noexcept override { return data.objectValue; }
bool isObject() const noexcept override { return true; }
bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept override
static bool objectEquals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) noexcept
{
return otherType.toObject (otherData) == data.objectValue;
}
var clone (const var& original) const override
{
if (auto* d = original.getDynamicObject())
return d->clone().get();
jassertfalse; // can only clone DynamicObjects!
return {};
}
void writeToStream (const ValueUnion&, OutputStream& output) const override
static void objectWriteToStream (const ValueUnion&, OutputStream& output)
{
jassertfalse; // Can't write an object to a stream!
output.writeCompressedInt (0);
}
};
//==============================================================================
class var::VariantType_Array : public var::VariantType_Object
{
public:
VariantType_Array() noexcept {}
static const VariantType_Array instance;
String toString (const ValueUnion&) const override { return "[Array]"; }
ReferenceCountedObject* toObject (const ValueUnion&) const noexcept override { return nullptr; }
bool isArray() const noexcept override { return true; }
Array<var>* toArray (const ValueUnion& data) const noexcept override
constexpr explicit VariantType (ObjectTag) noexcept
: isObject (true),
toString (objectToString),
toBool (objectToBool),
toObject (objectToObject),
clone (objectClone),
cleanUp (objectCleanUp),
createCopy (objectCreateCopy),
equals (objectEquals),
writeToStream (objectWriteToStream) {}
// array =======================================================================
static String arrayToString (const ValueUnion&) { return "[Array]"; }
static ReferenceCountedObject* arrayToObject (const ValueUnion&) noexcept { return nullptr; }
static Array<var>* arrayToArray (const ValueUnion& data) noexcept
{
if (auto* a = dynamic_cast<RefCountedArray*> (data.objectValue))
return &(a->array);
@@ -322,18 +363,18 @@ public:
return nullptr;
}
bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept override
static bool arrayEquals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) noexcept
{
auto* thisArray = toArray (data);
auto* thisArray = arrayToArray (data);
auto* otherArray = otherType.toArray (otherData);
return thisArray == otherArray || (thisArray != nullptr && otherArray != nullptr && *otherArray == *thisArray);
}
var clone (const var& original) const override
static var arrayClone (const var& original)
{
Array<var> arrayCopy;
if (auto* array = toArray (original.value))
if (auto* array = arrayToArray (original.value))
{
arrayCopy.ensureStorageAllocated (array->size());
@@ -344,9 +385,9 @@ public:
return var (arrayCopy);
}
void writeToStream (const ValueUnion& data, OutputStream& output) const override
static void arrayWriteToStream (const ValueUnion& data, OutputStream& output)
{
if (auto* array = toArray (data))
if (auto* array = arrayToArray (data))
{
MemoryOutputStream buffer (512);
buffer.writeCompressedInt (array->size());
@@ -366,79 +407,106 @@ public:
RefCountedArray (Array<var>&& a) : array (std::move (a)) { incReferenceCount(); }
Array<var> array;
};
};
//==============================================================================
class var::VariantType_Binary : public var::VariantType
{
public:
VariantType_Binary() noexcept {}
static const VariantType_Binary instance;
void cleanUp (ValueUnion& data) const noexcept override { delete data.binaryValue; }
void createCopy (ValueUnion& dest, const ValueUnion& source) const override { dest.binaryValue = new MemoryBlock (*source.binaryValue); }
String toString (const ValueUnion& data) const override { return data.binaryValue->toBase64Encoding(); }
bool isBinary() const noexcept override { return true; }
MemoryBlock* toBinary (const ValueUnion& data) const noexcept override { return data.binaryValue; }
bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept override
constexpr explicit VariantType (ArrayTag) noexcept
: isObject (true),
isArray (true),
toString (arrayToString),
toBool (objectToBool),
toObject (arrayToObject),
toArray (arrayToArray),
clone (arrayClone),
cleanUp (objectCleanUp),
createCopy (objectCreateCopy),
equals (arrayEquals),
writeToStream (arrayWriteToStream) {}
// binary ======================================================================
static void binaryCleanUp (ValueUnion& data) noexcept { delete data.binaryValue; }
static void binaryCreateCopy (ValueUnion& dest, const ValueUnion& source) { dest.binaryValue = new MemoryBlock (*source.binaryValue); }
static String binaryToString (const ValueUnion& data) { return data.binaryValue->toBase64Encoding(); }
static MemoryBlock* binaryToBinary (const ValueUnion& data) noexcept { return data.binaryValue; }
static bool binaryEquals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) noexcept
{
const MemoryBlock* const otherBlock = otherType.toBinary (otherData);
return otherBlock != nullptr && *otherBlock == *data.binaryValue;
}
void writeToStream (const ValueUnion& data, OutputStream& output) const override
static void binaryWriteToStream (const ValueUnion& data, OutputStream& output)
{
output.writeCompressedInt (1 + (int) data.binaryValue->getSize());
output.writeByte (varMarker_Binary);
output << *data.binaryValue;
}
};
//==============================================================================
class var::VariantType_Method : public var::VariantType
{
public:
VariantType_Method() noexcept {}
static const VariantType_Method instance;
constexpr explicit VariantType (BinaryTag) noexcept
: isBinary (true),
toString (binaryToString),
toBinary (binaryToBinary),
cleanUp (binaryCleanUp),
createCopy (binaryCreateCopy),
equals (binaryEquals),
writeToStream (binaryWriteToStream) {}
void cleanUp (ValueUnion& data) const noexcept override { if (data.methodValue != nullptr ) delete data.methodValue; }
void createCopy (ValueUnion& dest, const ValueUnion& source) const override { dest.methodValue = new NativeFunction (*source.methodValue); }
// method ======================================================================
static void methodCleanUp (ValueUnion& data) noexcept { if (data.methodValue != nullptr ) delete data.methodValue; }
static void methodCreateCopy (ValueUnion& dest, const ValueUnion& source) { dest.methodValue = new NativeFunction (*source.methodValue); }
String toString (const ValueUnion&) const override { return "Method"; }
bool toBool (const ValueUnion& data) const noexcept override { return data.methodValue != nullptr; }
bool isMethod() const noexcept override { return true; }
static String methodToString (const ValueUnion&) { return "Method"; }
static bool methodToBool (const ValueUnion& data) noexcept { return data.methodValue != nullptr; }
bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept override
static bool methodEquals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) noexcept
{
return otherType.isMethod() && otherData.methodValue == data.methodValue;
return otherType.isMethod && otherData.methodValue == data.methodValue;
}
void writeToStream (const ValueUnion&, OutputStream& output) const override
static void methodWriteToStream (const ValueUnion&, OutputStream& output)
{
jassertfalse; // Can't write a method to a stream!
output.writeCompressedInt (0);
}
constexpr explicit VariantType (MethodTag) noexcept
: isMethod (true),
toString (methodToString),
toBool (methodToBool),
cleanUp (methodCleanUp),
createCopy (methodCreateCopy),
equals (methodEquals),
writeToStream (methodWriteToStream) {}
};
//==============================================================================
const var::VariantType_Void var::VariantType_Void::instance;
const var::VariantType_Undefined var::VariantType_Undefined::instance;
const var::VariantType_Int var::VariantType_Int::instance;
const var::VariantType_Int64 var::VariantType_Int64::instance;
const var::VariantType_Bool var::VariantType_Bool::instance;
const var::VariantType_Double var::VariantType_Double::instance;
const var::VariantType_String var::VariantType_String::instance;
const var::VariantType_Object var::VariantType_Object::instance;
const var::VariantType_Array var::VariantType_Array::instance;
const var::VariantType_Binary var::VariantType_Binary::instance;
const var::VariantType_Method var::VariantType_Method::instance;
struct var::Instance
{
static constexpr VariantType attributesVoid { VariantType::VoidTag{} };
static constexpr VariantType attributesUndefined { VariantType::UndefinedTag{} };
static constexpr VariantType attributesInt { VariantType::IntTag{} };
static constexpr VariantType attributesInt64 { VariantType::Int64Tag{} };
static constexpr VariantType attributesBool { VariantType::BoolTag{} };
static constexpr VariantType attributesDouble { VariantType::DoubleTag{} };
static constexpr VariantType attributesMethod { VariantType::MethodTag{} };
static constexpr VariantType attributesArray { VariantType::ArrayTag{} };
static constexpr VariantType attributesString { VariantType::StringTag{} };
static constexpr VariantType attributesBinary { VariantType::BinaryTag{} };
static constexpr VariantType attributesObject { VariantType::ObjectTag{} };
};
constexpr var::VariantType var::Instance::attributesVoid;
constexpr var::VariantType var::Instance::attributesUndefined;
constexpr var::VariantType var::Instance::attributesInt;
constexpr var::VariantType var::Instance::attributesInt64;
constexpr var::VariantType var::Instance::attributesBool;
constexpr var::VariantType var::Instance::attributesDouble;
constexpr var::VariantType var::Instance::attributesMethod;
constexpr var::VariantType var::Instance::attributesArray;
constexpr var::VariantType var::Instance::attributesString;
constexpr var::VariantType var::Instance::attributesBinary;
constexpr var::VariantType var::Instance::attributesObject;
//==============================================================================
var::var() noexcept : type (&VariantType_Void::instance) {}
var::var() noexcept : type (&Instance::attributesVoid) {}
var::var (const VariantType& t) noexcept : type (&t) {}
var::~var() noexcept { type->cleanUp (value); }
@@ -450,19 +518,19 @@ var::var (const var& valueToCopy) : type (valueToCopy.type)
type->createCopy (value, valueToCopy.value);
}
var::var (const int v) noexcept : type (&VariantType_Int::instance) { value.intValue = v; }
var::var (const int64 v) noexcept : type (&VariantType_Int64::instance) { value.int64Value = v; }
var::var (const bool v) noexcept : type (&VariantType_Bool::instance) { value.boolValue = v; }
var::var (const double v) noexcept : type (&VariantType_Double::instance) { value.doubleValue = v; }
var::var (NativeFunction m) noexcept : type (&VariantType_Method::instance) { value.methodValue = new NativeFunction (m); }
var::var (const Array<var>& v) : type (&VariantType_Array::instance) { value.objectValue = new VariantType_Array::RefCountedArray(v); }
var::var (const String& v) : type (&VariantType_String::instance) { new (value.stringValue) String (v); }
var::var (const char* const v) : type (&VariantType_String::instance) { new (value.stringValue) String (v); }
var::var (const wchar_t* const v) : type (&VariantType_String::instance) { new (value.stringValue) String (v); }
var::var (const void* v, size_t sz) : type (&VariantType_Binary::instance) { value.binaryValue = new MemoryBlock (v, sz); }
var::var (const MemoryBlock& v) : type (&VariantType_Binary::instance) { value.binaryValue = new MemoryBlock (v); }
var::var (const int v) noexcept : type (&Instance::attributesInt) { value.intValue = v; }
var::var (const int64 v) noexcept : type (&Instance::attributesInt64) { value.int64Value = v; }
var::var (const bool v) noexcept : type (&Instance::attributesBool) { value.boolValue = v; }
var::var (const double v) noexcept : type (&Instance::attributesDouble) { value.doubleValue = v; }
var::var (NativeFunction m) noexcept : type (&Instance::attributesMethod) { value.methodValue = new NativeFunction (m); }
var::var (const Array<var>& v) : type (&Instance::attributesArray) { value.objectValue = new VariantType::RefCountedArray (v); }
var::var (const String& v) : type (&Instance::attributesString) { new (value.stringValue) String (v); }
var::var (const char* const v) : type (&Instance::attributesString) { new (value.stringValue) String (v); }
var::var (const wchar_t* const v) : type (&Instance::attributesString) { new (value.stringValue) String (v); }
var::var (const void* v, size_t sz) : type (&Instance::attributesBinary) { value.binaryValue = new MemoryBlock (v, sz); }
var::var (const MemoryBlock& v) : type (&Instance::attributesBinary) { value.binaryValue = new MemoryBlock (v); }
var::var (const StringArray& v) : type (&VariantType_Array::instance)
var::var (const StringArray& v) : type (&Instance::attributesArray)
{
Array<var> strings;
strings.ensureStorageAllocated (v.size());
@@ -470,10 +538,10 @@ var::var (const StringArray& v) : type (&VariantType_Array::instance)
for (auto& i : v)
strings.add (var (i));
value.objectValue = new VariantType_Array::RefCountedArray (strings);
value.objectValue = new VariantType::RefCountedArray (strings);
}
var::var (ReferenceCountedObject* const object) : type (&VariantType_Object::instance)
var::var (ReferenceCountedObject* const object) : type (&Instance::attributesObject)
{
value.objectValue = object;
@@ -481,20 +549,20 @@ var::var (ReferenceCountedObject* const object) : type (&VariantType_Object::in
object->incReferenceCount();
}
var var::undefined() noexcept { return var (VariantType_Undefined::instance); }
var var::undefined() noexcept { return var (Instance::attributesUndefined); }
//==============================================================================
bool var::isVoid() const noexcept { return type->isVoid(); }
bool var::isUndefined() const noexcept { return type->isUndefined(); }
bool var::isInt() const noexcept { return type->isInt(); }
bool var::isInt64() const noexcept { return type->isInt64(); }
bool var::isBool() const noexcept { return type->isBool(); }
bool var::isDouble() const noexcept { return type->isDouble(); }
bool var::isString() const noexcept { return type->isString(); }
bool var::isObject() const noexcept { return type->isObject(); }
bool var::isArray() const noexcept { return type->isArray(); }
bool var::isBinaryData() const noexcept { return type->isBinary(); }
bool var::isMethod() const noexcept { return type->isMethod(); }
bool var::isVoid() const noexcept { return type->isVoid; }
bool var::isUndefined() const noexcept { return type->isUndefined; }
bool var::isInt() const noexcept { return type->isInt; }
bool var::isInt64() const noexcept { return type->isInt64; }
bool var::isBool() const noexcept { return type->isBool; }
bool var::isDouble() const noexcept { return type->isDouble; }
bool var::isString() const noexcept { return type->isString; }
bool var::isObject() const noexcept { return type->isObject; }
bool var::isArray() const noexcept { return type->isArray; }
bool var::isBinaryData() const noexcept { return type->isBinary; }
bool var::isMethod() const noexcept { return type->isMethod; }
var::operator int() const noexcept { return type->toInt (value); }
var::operator int64() const noexcept { return type->toInt64 (value); }
@@ -516,14 +584,14 @@ void var::swapWith (var& other) noexcept
}
var& var::operator= (const var& v) { type->cleanUp (value); type = v.type; type->createCopy (value, v.value); return *this; }
var& var::operator= (const int v) { type->cleanUp (value); type = &VariantType_Int::instance; value.intValue = v; return *this; }
var& var::operator= (const int64 v) { type->cleanUp (value); type = &VariantType_Int64::instance; value.int64Value = v; return *this; }
var& var::operator= (const bool v) { type->cleanUp (value); type = &VariantType_Bool::instance; value.boolValue = v; return *this; }
var& var::operator= (const double v) { type->cleanUp (value); type = &VariantType_Double::instance; value.doubleValue = v; return *this; }
var& var::operator= (const char* const v) { type->cleanUp (value); type = &VariantType_String::instance; new (value.stringValue) String (v); return *this; }
var& var::operator= (const wchar_t* const v) { type->cleanUp (value); type = &VariantType_String::instance; new (value.stringValue) String (v); return *this; }
var& var::operator= (const String& v) { type->cleanUp (value); type = &VariantType_String::instance; new (value.stringValue) String (v); return *this; }
var& var::operator= (const MemoryBlock& v) { type->cleanUp (value); type = &VariantType_Binary::instance; value.binaryValue = new MemoryBlock (v); return *this; }
var& var::operator= (const int v) { type->cleanUp (value); type = &Instance::attributesInt; value.intValue = v; return *this; }
var& var::operator= (const int64 v) { type->cleanUp (value); type = &Instance::attributesInt64; value.int64Value = v; return *this; }
var& var::operator= (const bool v) { type->cleanUp (value); type = &Instance::attributesBool; value.boolValue = v; return *this; }
var& var::operator= (const double v) { type->cleanUp (value); type = &Instance::attributesDouble; value.doubleValue = v; return *this; }
var& var::operator= (const char* const v) { type->cleanUp (value); type = &Instance::attributesString; new (value.stringValue) String (v); return *this; }
var& var::operator= (const wchar_t* const v) { type->cleanUp (value); type = &Instance::attributesString; new (value.stringValue) String (v); return *this; }
var& var::operator= (const String& v) { type->cleanUp (value); type = &Instance::attributesString; new (value.stringValue) String (v); return *this; }
var& var::operator= (const MemoryBlock& v) { type->cleanUp (value); type = &Instance::attributesBinary; value.binaryValue = new MemoryBlock (v); return *this; }
var& var::operator= (const Array<var>& v) { var v2 (v); swapWith (v2); return *this; }
var& var::operator= (ReferenceCountedObject* v) { var v2 (v); swapWith (v2); return *this; }
var& var::operator= (NativeFunction v) { var v2 (v); swapWith (v2); return *this; }
@@ -532,7 +600,7 @@ var::var (var&& other) noexcept
: type (other.type),
value (other.value)
{
other.type = &VariantType_Void::instance;
other.type = &Instance::attributesVoid;
}
var& var::operator= (var&& other) noexcept
@@ -541,25 +609,25 @@ var& var::operator= (var&& other) noexcept
return *this;
}
var::var (String&& v) : type (&VariantType_String::instance)
var::var (String&& v) : type (&Instance::attributesString)
{
new (value.stringValue) String (std::move (v));
}
var::var (MemoryBlock&& v) : type (&VariantType_Binary::instance)
var::var (MemoryBlock&& v) : type (&Instance::attributesBinary)
{
value.binaryValue = new MemoryBlock (std::move (v));
}
var::var (Array<var>&& v) : type (&VariantType_Array::instance)
var::var (Array<var>&& v) : type (&Instance::attributesArray)
{
value.objectValue = new VariantType_Array::RefCountedArray (std::move (v));
value.objectValue = new VariantType::RefCountedArray (std::move (v));
}
var& var::operator= (String&& v)
{
type->cleanUp (value);
type = &VariantType_String::instance;
type = &Instance::attributesString;
new (value.stringValue) String (std::move (v));
return *this;
}
@@ -582,7 +650,7 @@ bool var::hasSameTypeAs (const var& other) const noexcept
bool canCompare (const var& v1, const var& v2)
{
return v1.type->isComparable() && v2.type->isComparable();
return v1.type->isComparable && v2.type->isComparable;
}
static int compare (const var& v1, const var& v2)


+ 2
- 12
modules/juce_core/containers/juce_Variant.h View File

@@ -283,18 +283,8 @@ public:
private:
//==============================================================================
class VariantType;
class VariantType_Void;
class VariantType_Undefined;
class VariantType_Int;
class VariantType_Int64;
class VariantType_Double;
class VariantType_Bool;
class VariantType_String;
class VariantType_Object;
class VariantType_Array;
class VariantType_Binary;
class VariantType_Method;
struct VariantType;
struct Instance;
union ValueUnion
{


Loading…
Cancel
Save