From dde56bab6a9a80482435dac2d3d3f12c9b4b2c29 Mon Sep 17 00:00:00 2001 From: jules Date: Tue, 9 Apr 2013 12:11:06 +0100 Subject: [PATCH] Added a binary data type to the var class. --- modules/juce_core/containers/juce_Variant.cpp | 75 ++++++++++++++++--- modules/juce_core/containers/juce_Variant.h | 7 ++ modules/juce_core/json/juce_JSON.cpp | 17 +++-- 3 files changed, 79 insertions(+), 20 deletions(-) diff --git a/modules/juce_core/containers/juce_Variant.cpp b/modules/juce_core/containers/juce_Variant.cpp index 23d016aef8..701c8432e6 100644 --- a/modules/juce_core/containers/juce_Variant.cpp +++ b/modules/juce_core/containers/juce_Variant.cpp @@ -31,7 +31,8 @@ enum VariantStreamMarkers varMarker_Double = 4, varMarker_String = 5, varMarker_Int64 = 6, - varMarker_Array = 7 + varMarker_Array = 7, + varMarker_Binary = 8 }; //============================================================================== @@ -47,7 +48,8 @@ public: virtual String toString (const ValueUnion&) const { return String::empty; } virtual bool toBool (const ValueUnion&) const noexcept { return false; } virtual ReferenceCountedObject* toObject (const ValueUnion&) const noexcept { return nullptr; } - virtual Array* toArray (const ValueUnion&) const noexcept { return 0; } + virtual Array* toArray (const ValueUnion&) const noexcept { return nullptr; } + virtual MemoryBlock* toBinary (const ValueUnion&) const noexcept { return nullptr; } virtual bool isVoid() const noexcept { return false; } virtual bool isInt() const noexcept { return false; } @@ -57,6 +59,7 @@ public: 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 void cleanUp (ValueUnion&) const noexcept {} @@ -292,6 +295,35 @@ public: } }; +//============================================================================== +class var::VariantType_Binary : public var::VariantType +{ +public: + VariantType_Binary() noexcept {} + + static const VariantType_Binary instance; + + void cleanUp (ValueUnion& data) const noexcept { delete data.binaryValue; } + void createCopy (ValueUnion& dest, const ValueUnion& source) const { dest.binaryValue = new MemoryBlock (*source.binaryValue); } + + String toString (const ValueUnion& data) const { return data.binaryValue->toBase64Encoding(); } + bool isBinary() const noexcept { return true; } + MemoryBlock* toBinary (const ValueUnion& data) const noexcept { return data.binaryValue; } + + bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept + { + const MemoryBlock* const otherBlock = otherType.toBinary (otherData); + return otherBlock != nullptr && *otherBlock == *data.binaryValue; + } + + void writeToStream (const ValueUnion& data, OutputStream& output) const + { + output.writeCompressedInt (1 + data.binaryValue->getSize()); + output.writeByte (varMarker_Binary); + output << *data.binaryValue; + } +}; + //============================================================================== class var::VariantType_Method : public var::VariantType { @@ -300,7 +332,7 @@ public: static const VariantType_Method instance; String toString (const ValueUnion&) const { return "Method"; } - bool toBool (const ValueUnion& data) const noexcept { return data.methodValue != 0; } + bool toBool (const ValueUnion& data) const noexcept { return data.methodValue != nullptr; } bool isMethod() const noexcept { return true; } bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept @@ -324,6 +356,7 @@ 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; @@ -354,6 +387,8 @@ var::var (const Array& v) : type (&VariantType_Array::instance) { 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 (ReferenceCountedObject* const object) : type (&VariantType_Object::instance) { @@ -363,16 +398,18 @@ var::var (ReferenceCountedObject* const object) : type (&VariantType_Object::in object->incReferenceCount(); } + //============================================================================== -bool var::isVoid() const noexcept { return type->isVoid(); } -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::isMethod() const noexcept { return type->isMethod(); } +bool var::isVoid() const noexcept { return type->isVoid(); } +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); } @@ -383,6 +420,7 @@ String var::toString() const { return type->toString var::operator String() const { return type->toString (value); } ReferenceCountedObject* var::getObject() const noexcept { return type->toObject (value); } Array* var::getArray() const noexcept { return type->toArray (value); } +MemoryBlock* var::getBinaryData() const noexcept { return type->toBinary (value); } DynamicObject* var::getDynamicObject() const noexcept { return dynamic_cast (getObject()); } //============================================================================== @@ -423,6 +461,11 @@ var::var (String&& v) : type (&VariantType_String::instance) new (value.stringValue) String (static_cast (v)); } +var::var (MemoryBlock&& v) : type (&VariantType_Binary::instance) +{ + value.binaryValue = new MemoryBlock (static_cast (v)); +} + var& var::operator= (String&& v) { type->cleanUp (value); @@ -630,6 +673,14 @@ var var::readFromStream (InputStream& input) return var (mo.toUTF8()); } + case varMarker_Binary: + { + MemoryBlock mb (numBytes - 1); + const int numRead = input.read (mb.getData(), numBytes - 1); + mb.setSize (numRead); + return var (mb); + } + case varMarker_Array: { var v; diff --git a/modules/juce_core/containers/juce_Variant.h b/modules/juce_core/containers/juce_Variant.h index 107bc111f6..6bdc0b25c6 100644 --- a/modules/juce_core/containers/juce_Variant.h +++ b/modules/juce_core/containers/juce_Variant.h @@ -77,6 +77,8 @@ public: var (const Array& value); var (ReferenceCountedObject* object); var (MethodFunction method) noexcept; + var (const void* binaryData, size_t dataSize); + var (const MemoryBlock& binaryData); var& operator= (const var& valueToCopy); var& operator= (int value); @@ -93,6 +95,7 @@ public: #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS var (var&& other) noexcept; var (String&& value); + var (MemoryBlock&& binaryData); var& operator= (var&& other) noexcept; var& operator= (String&& value); #endif @@ -107,6 +110,7 @@ public: operator String() const; String toString() const; Array* getArray() const noexcept; + MemoryBlock* getBinaryData() const noexcept; ReferenceCountedObject* getObject() const noexcept; DynamicObject* getDynamicObject() const noexcept; @@ -118,6 +122,7 @@ public: 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. @@ -245,6 +250,7 @@ private: class VariantType_String; friend class VariantType_String; class VariantType_Object; friend class VariantType_Object; class VariantType_Array; friend class VariantType_Array; + class VariantType_Binary; friend class VariantType_Binary; class VariantType_Method; friend class VariantType_Method; union ValueUnion @@ -256,6 +262,7 @@ private: char stringValue [sizeof (String)]; ReferenceCountedObject* objectValue; Array* arrayValue; + MemoryBlock* binaryValue; MethodFunction methodValue; }; diff --git a/modules/juce_core/json/juce_JSON.cpp b/modules/juce_core/json/juce_JSON.cpp index e03df74d1a..bad08e738e 100644 --- a/modules/juce_core/json/juce_JSON.cpp +++ b/modules/juce_core/json/juce_JSON.cpp @@ -194,7 +194,8 @@ private: if (nextChar == ',') continue; - else if (nextChar == '}') + + if (nextChar == '}') break; } } @@ -237,7 +238,8 @@ private: if (nextChar == ',') continue; - else if (nextChar == ']') + + if (nextChar == ']') break; return createFail ("Expected object array item, but found", &oldT); @@ -248,8 +250,7 @@ private: static Result parseString (String::CharPointerType& t, var& result) { - Array buffer; - buffer.ensureStorageAllocated (256); + MemoryOutputStream buffer (256); for (;;) { @@ -295,11 +296,10 @@ private: if (c == 0) return createFail ("Unexpected end-of-input in string constant"); - buffer.add (c); + buffer.appendUTF8Char (c); } - buffer.add (0); - result = String (CharPointer_UTF32 (buffer.getRawDataPointer())); + result = buffer.toString(); return Result::ok(); } }; @@ -336,7 +336,8 @@ public: } else { - jassert (! v.isMethod()); // Can't convert an object with methods to JSON! + // Can't convert these other types of object to JSON! + jassert (! (v.isMethod() || v.isBinaryData())); out << v.toString(); }