Browse Source

Variant refactoring. Uses less memory, added nested VariantVector & VariantMap support.

Lasse Öörni 15 years ago
parent
commit
c7175d4820

+ 14 - 4
Engine/Common/Deserializer.cpp

@@ -242,17 +242,27 @@ Variant Deserializer::readVariant()
     return ret;
 }
 
+VariantVector Deserializer::readVariantVector()
+{
+    VariantVector ret;
+    
+    unsigned num = readVLE();
+    ret.resize(num);
+    for (unsigned i = 0; i < num; ++i)
+        ret[i].read(*this);
+    
+    return ret;
+}
+
 VariantMap Deserializer::readVariantMap()
 {
     VariantMap ret;
     
     unsigned num = readVLE();
-    while (num)
+    for (unsigned i = 0; i < num; ++i)
     {
         ShortStringHash key = readShortStringHash();
-        Variant value = readVariant();
-        ret[key] = value;
-        --num;
+        ret[key].read(*this);
     }
     
     return ret;

+ 2 - 0
Engine/Common/Deserializer.h

@@ -108,6 +108,8 @@ public:
     ShortStringHash readShortStringHash();
     //! Read a Variant
     Variant readVariant();
+    //! Read a vector of Variants
+    VariantVector readVariantVector();
     //! Read a map of Variants
     VariantMap readVariantMap();
     //! Read a variable-length encoded unsigned integer, which can use 29 bits maximum

+ 8 - 0
Engine/Common/Serializer.cpp

@@ -165,6 +165,14 @@ void Serializer::writeVariant(const Variant& value)
     value.write(*this);
 }
 
+void Serializer::writeVariantVector(const VariantVector& value)
+{
+    writeVLE(value.size());
+    
+    for (VariantVector::const_iterator i = value.begin(); i != value.end(); ++i)
+        writeVariant(*i);
+}
+
 void Serializer::writeVariantMap(const VariantMap& value)
 {
     writeVLE(value.size());

+ 5 - 1
Engine/Common/Serializer.h

@@ -27,6 +27,7 @@
 #include "StringHash.h"
 
 #include <map>
+#include <vector>
 
 class Color;
 class IntRect;
@@ -38,6 +39,7 @@ class Vector2;
 class Vector3;
 class Vector4;
 
+typedef std::vector<Variant> VariantVector;
 typedef std::map<ShortStringHash, Variant> VariantMap;
 
 //! An abstract stream for writing
@@ -96,7 +98,9 @@ public:
     void writeShortStringHash(const ShortStringHash& value);
     //! Write a Variant
     void writeVariant(const Variant& value);
-    //! Write a map of Variants
+    //! Write a variant vector
+    void writeVariantVector(const VariantVector& value);
+    //! Write a variant map
     void writeVariantMap(const VariantMap& value);
     //! Write a variable-length encoded unsigned integer, which can use 29 bits maximum
     void writeVLE(unsigned value);

+ 282 - 43
Engine/Common/Variant.cpp

@@ -32,12 +32,92 @@
 
 #include "DebugNew.h"
 
+Variant& Variant::operator = (const Variant& rhs)
+{
+    setType(rhs.getType());
+    
+    switch (mType)
+    {
+    case VAR_STRING:
+        *(reinterpret_cast<std::string*>(mValue.mPtr)) = *(reinterpret_cast<const std::string*>(rhs.mValue.mPtr));
+        break;
+        
+    case VAR_BUFFER:
+        *(reinterpret_cast<std::vector<unsigned char>*>(mValue.mPtr)) = *(reinterpret_cast<const std::vector<unsigned char>*>(rhs.mValue.mPtr));
+        break;
+    
+    case VAR_VARIANTVECTOR:
+        *(reinterpret_cast<VariantVector*>(mValue.mPtr)) = *(reinterpret_cast<VariantVector*>(rhs.mValue.mPtr));
+        break;
+        
+    case VAR_VARIANTMAP:
+        *(reinterpret_cast<VariantMap*>(mValue.mPtr)) = *(reinterpret_cast<VariantMap*>(rhs.mValue.mPtr));
+        break;
+        
+    default:
+        mValue = rhs.mValue;
+        break;
+    }
+    
+    return *this;
+}
+
+bool Variant::operator == (const Variant& rhs) const
+{
+    if (mType != rhs.mType)
+        return false;
+    
+    switch (mType)
+    {
+    case VAR_INT:
+        return mValue.mInt == rhs.mValue.mInt;
+        
+    case VAR_BOOL:
+        return mValue.mBool == rhs.mValue.mBool;
+        
+    case VAR_FLOAT:
+        return mValue.mFloat == rhs.mValue.mFloat;
+        
+    case VAR_VECTOR2:
+        return *(reinterpret_cast<const Vector2*>(&mValue)) == *(reinterpret_cast<const Vector2*>(&rhs.mValue));
+        
+    case VAR_VECTOR3:
+        return *(reinterpret_cast<const Vector3*>(&mValue)) == *(reinterpret_cast<const Vector3*>(&rhs.mValue));
+        
+    case VAR_VECTOR4:
+        return *(reinterpret_cast<const Vector4*>(&mValue)) == *(reinterpret_cast<const Vector4*>(&rhs.mValue));
+        
+    case VAR_QUATERNION:
+        return *(reinterpret_cast<const Quaternion*>(&mValue)) == *(reinterpret_cast<const Quaternion*>(&rhs.mValue));
+        
+    case VAR_COLOR:
+        return *(reinterpret_cast<const Color*>(&mValue)) == *(reinterpret_cast<const Color*>(&rhs.mValue));
+        
+    case VAR_STRING:
+        return *(reinterpret_cast<const std::string*>(mValue.mPtr)) == *(reinterpret_cast<const std::string*>(rhs.mValue.mPtr));
+        
+    case VAR_BUFFER:
+        return *(reinterpret_cast<const std::vector<unsigned char>*>(mValue.mPtr)) == *(reinterpret_cast<const std::vector<unsigned char>*>(rhs.mValue.mPtr));
+        
+    case VAR_PTR:
+        return mValue.mPtr == rhs.mValue.mPtr;
+        
+    case VAR_VARIANTVECTOR:
+        return *(reinterpret_cast<const VariantVector*>(mValue.mPtr)) == *(reinterpret_cast<const VariantVector*>(rhs.mValue.mPtr));
+        
+    case VAR_VARIANTMAP:
+        return *(reinterpret_cast<const VariantMap*>(mValue.mPtr)) == *(reinterpret_cast<const VariantMap*>(rhs.mValue.mPtr));
+    }
+    
+    return true;
+}
+
 void Variant::fromString(const std::string& type, const std::string& value)
 {
     std::string typeLower = toLower(type);
     
     if (typeLower == "none")
-        mType = VAR_NONE;
+        setType(VAR_NONE);
     else if (typeLower == "int")
         *this = toInt(value);
     else if (typeLower == "bool")
@@ -58,19 +138,38 @@ void Variant::fromString(const std::string& type, const std::string& value)
         *this = value;
     else if (typeLower == "buffer")
     {
+        setType(VAR_BUFFER);
+        std::vector<unsigned char>& buffer = *(reinterpret_cast<std::vector<unsigned char>*>(mValue.mPtr));
         std::vector<std::string> values = split(value, ' ');
-        std::vector<unsigned char> buffer;
-        for (std::vector<std::string>::const_iterator i = values.begin(); i != values.end(); ++i)
-            buffer.push_back(toInt(*i));
-        *this = buffer;
+        buffer.resize(values.size());
+        for (unsigned i = 0; i < values.size(); ++i)
+            buffer[i] = toInt(values[i]);
     }
     else if (typeLower == "pointer")
     {
         LOGWARNING("Deserialized pointer Variant set to null");
         *this = (void*)0;
     }
+    else if (typeLower == "variantvector")
+    {
+        setType(VAR_VARIANTVECTOR);
+        VariantVector& dest = *(reinterpret_cast<VariantVector*>(mValue.mPtr));
+        std::vector<std::string> values = split(value, '#');
+        dest.resize(values.size() >> 1);
+        for (unsigned i = 0; i < values.size() - 1; i += 2)
+            dest[i >> 1].fromString(values[i], values[i + 1]);
+    }
+    else if (typeLower == "variantmap")
+    {
+        setType(VAR_VARIANTMAP);
+        VariantMap& dest = *(reinterpret_cast<VariantMap*>(mValue.mPtr));
+        dest.clear();
+        std::vector<std::string> values = split(value, '#');
+        for (unsigned i = 0; i < values.size() - 2; i += 3)
+            dest[ShortStringHash(values[i])].fromString(values[i + 1], values[i + 2]);
+    }
     else
-        clear();
+        setType(VAR_NONE);
 }
 
 void Variant::write(Serializer& dest) const
@@ -95,97 +194,144 @@ void Variant::write(Serializer& dest) const
         break;
         
     case VAR_VECTOR2:
-        dest.writeVector2(*(reinterpret_cast<const Vector2*>(&mValue.mVector4)));
+        dest.writeVector2(*(reinterpret_cast<const Vector2*>(&mValue)));
         break;
         
     case VAR_VECTOR3:
-        dest.writeVector3(*(reinterpret_cast<const Vector3*>(&mValue.mVector4)));
+        dest.writeVector3(*(reinterpret_cast<const Vector3*>(&mValue)));
         break;
         
     case VAR_VECTOR4:
-        dest.writeVector4(mValue.mVector4);
+        dest.writeVector4(*(reinterpret_cast<const Vector4*>(&mValue)));
         break;
         
     case VAR_QUATERNION:
-        dest.writeQuaternion(*(reinterpret_cast<const Quaternion*>(&mValue.mVector4)));
+        dest.writeQuaternion(*(reinterpret_cast<const Quaternion*>(&mValue)));
         break;
         
     case VAR_COLOR:
-        dest.writeColor(*(reinterpret_cast<const Color*>(&mValue.mVector4)));
+        dest.writeColor(*(reinterpret_cast<const Color*>(&mValue)));
         break;
         
     case VAR_STRING:
-        dest.writeString(mValue.mString);
+        dest.writeString(*(reinterpret_cast<const std::string*>(mValue.mPtr)));
         break;
         
     case VAR_BUFFER:
-        dest.writeVLE(mValue.mBuffer.size());
-        if (mValue.mBuffer.size())
-            dest.write(&mValue.mBuffer[0], mValue.mBuffer.size());
+        {
+            const std::vector<unsigned char>& buffer = *(reinterpret_cast<const std::vector<unsigned char>*>(mValue.mPtr));
+            dest.writeVLE(buffer.size());
+            if (buffer.size())
+                dest.write(&buffer[0], buffer.size());
+        }
         break;
         
     case VAR_PTR:
         LOGWARNING("Serialized pointer Variant set to null");
         dest.writeUInt(0);
         break;
+        
+    case VAR_VARIANTVECTOR:
+        {
+            const VariantVector& src = *(reinterpret_cast<VariantVector*>(mValue.mPtr));
+            dest.writeVariantVector(src);
+        }
+        break;
+        
+    case VAR_VARIANTMAP:
+        {
+            const VariantMap& src = *(reinterpret_cast<VariantMap*>(mValue.mPtr));
+            dest.writeVariantMap(src);
+        }
+        break;
     }
 }
 
 void Variant::read(Deserializer& source)
 {
-    mType = (VariantType)source.readUByte();
+    VariantType type = (VariantType)source.readUByte();
     
-    switch (mType)
+    switch (type)
     {
     case VAR_NONE:
+        setType(VAR_NONE);
         break;
         
     case VAR_INT:
-        mValue.mInt = source.readInt();
+        *this = source.readInt();
         break;
         
     case VAR_BOOL:
-        mValue.mBool = source.readBool();
+        *this = source.readBool();
         break;
         
     case VAR_FLOAT:
-        mValue.mFloat = source.readFloat();
+        *this = source.readFloat();
         break;
         
     case VAR_VECTOR2:
-        *(reinterpret_cast<Vector2*>(&mValue.mVector4)) = source.readVector2();
+        *this = source.readVector2();
         break;
         
     case VAR_VECTOR3:
-        *(reinterpret_cast<Vector3*>(&mValue.mVector4)) = source.readVector3();
+        *this = source.readVector3();
         break;
         
     case VAR_VECTOR4:
-        mValue.mVector4 = source.readVector4();
+        *this = source.readVector4();
         break;
         
     case VAR_QUATERNION:
-        *(reinterpret_cast<Quaternion*>(&mValue.mVector4)) = source.readQuaternion();
+        *this = source.readQuaternion();
         break;
         
     case VAR_COLOR:
-        *(reinterpret_cast<Color*>(&mValue.mVector4)) = source.readColor();
+        *this = source.readColor();
         break;
         
     case VAR_STRING:
-        mValue.mString = source.readString();
+        *this = source.readString();
         break;
         
     case VAR_BUFFER:
-        mValue.mBuffer.resize(source.readVLE());
-        if (mValue.mBuffer.size())
-            source.read(&mValue.mBuffer[0], mValue.mBuffer.size());
+        {
+            setType(VAR_BUFFER);
+            std::vector<unsigned char>& buffer = *(reinterpret_cast<std::vector<unsigned char>*>(mValue.mPtr));
+            buffer.resize(source.readVLE());
+            if (buffer.size())
+                source.read(&buffer[0], buffer.size());
+        }
         break;
         
     case VAR_PTR:
         LOGWARNING("Deserialized pointer Variant set to null");
         source.readUInt();
-        mValue.mPtr = 0;
+        *this = (void*)0;
+        break;
+        
+    case VAR_VARIANTVECTOR:
+        {
+            setType(VAR_VARIANTVECTOR);
+            VariantVector& dest = *(reinterpret_cast<VariantVector*>(mValue.mPtr));
+            unsigned num = source.readVLE();
+            dest.resize(num);
+            for (unsigned i = 0; i < num; ++i)
+                dest[i].read(source);
+        }
+        break;
+        
+    case VAR_VARIANTMAP:
+        {
+            setType(VAR_VARIANTMAP);
+            VariantMap& dest = *(reinterpret_cast<VariantMap*>(mValue.mPtr));
+            dest.clear();
+            unsigned num = source.readVLE();
+            for (unsigned i = 0; i < num; ++i)
+            {
+                ShortStringHash key = source.readShortStringHash();
+                dest[key].read(source);
+            }
+        }
         break;
         
     default:
@@ -198,10 +344,11 @@ void Variant::setBuffer(const void* data, unsigned size)
     if ((size) && (!data))
         SAFE_EXCEPTION("Null Variant buffer source");
     
-    mType = VAR_BUFFER;
-    mValue.mBuffer.resize(size);
-    if (size)
-        memcpy(&mValue.mBuffer[0], data, size);
+    setType(VAR_BUFFER);
+    std::vector<unsigned char>& buffer = *(reinterpret_cast<std::vector<unsigned char>*>(mValue.mPtr));
+    buffer.resize(size);
+    if (buffer.size())
+        memcpy(&buffer[0], data, size);
 }
 
 const std::string& Variant::getTypeName() const
@@ -219,7 +366,9 @@ const std::string& Variant::getTypeName() const
         "Color",
         "String",
         "Buffer",
-        "Pointer"
+        "Pointer",
+        "VariantVector",
+        "VariantMap"
     };
     
     return typeNames[mType];
@@ -231,33 +380,123 @@ std::string Variant::toString() const
     {
     case VAR_INT:
         return ::toString(mValue.mInt);
+        
     case VAR_BOOL:
         return ::toString(mValue.mBool);
+        
     case VAR_FLOAT:
         return ::toString(mValue.mFloat);
+        
     case VAR_VECTOR2:
-        return ::toString(*(reinterpret_cast<const Vector2*>(&mValue.mVector4)));
+        return ::toString(*(reinterpret_cast<const Vector2*>(&mValue)));
+        
     case VAR_VECTOR3:
-        return ::toString(*(reinterpret_cast<const Vector3*>(&mValue.mVector4)));
+        return ::toString(*(reinterpret_cast<const Vector3*>(&mValue)));
+        
     case VAR_VECTOR4:
-        return ::toString(mValue.mVector4);
+        return ::toString(*(reinterpret_cast<const Vector4*>(&mValue)));
+        
     case VAR_QUATERNION:
-        return ::toString(*(reinterpret_cast<const Quaternion*>(&mValue.mVector4)));
+        return ::toString(*(reinterpret_cast<const Quaternion*>(&mValue)));
+        
     case VAR_COLOR:
-        return ::toString(*(reinterpret_cast<const Color*>(&mValue.mVector4)));
+        return ::toString(*(reinterpret_cast<const Color*>(&mValue)));
+        
     case VAR_STRING:
-        return mValue.mString;
+        return *(reinterpret_cast<const std::string*>(mValue.mPtr));
+        
     case VAR_BUFFER:
         {
+            const std::vector<unsigned char>& buffer = *(reinterpret_cast<const std::vector<unsigned char>*>(mValue.mPtr));
             std::string ret;
-            for (std::vector<unsigned char>::const_iterator i = mValue.mBuffer.begin(); i != mValue.mBuffer.end(); ++i)
-                ret += ::toString(*i) + " ";
+            for (std::vector<unsigned char>::const_iterator i = buffer.begin(); i != buffer.end(); ++i)
+            {
+                if (i != buffer.begin())
+                    ret += " ";
+                ret += ::toString(*i);
+            }
             return ret;
         }
+        
     case VAR_PTR:
         LOGWARNING("Serialized pointer Variant set to null");
         return ::toString((unsigned)0);
+        
+    case VAR_VARIANTVECTOR:
+        {
+            const VariantVector& src = *(reinterpret_cast<const VariantVector*>(mValue.mPtr));
+            std::string ret;
+            for (VariantVector::const_iterator i = src.begin(); i != src.end(); ++i)
+            {
+                if (i != src.begin())
+                    ret += "#";
+                ret += i->getTypeName() + "#";
+                ret += i->toString();
+            }
+            return ret;
+        }
+        
+    case VAR_VARIANTMAP:
+        {
+            const VariantMap& src = *(reinterpret_cast<const VariantMap*>(mValue.mPtr));
+            std::string ret;
+            for (VariantMap::const_iterator i = src.begin(); i != src.end(); ++i)
+            {
+                if (i != src.begin())
+                    ret += "#";
+                ret += ::toString(i->first.mData) + "#";
+                ret += i->second.getTypeName() + "#";
+                ret += i->second.toString();
+            }
+            return ret;
+        }
     }
     
     return std::string();
 }
+
+void Variant::setType(VariantType newType)
+{
+    if (mType == newType)
+        return;
+    
+    switch (mType)
+    {
+    case VAR_STRING:
+        delete reinterpret_cast<std::string*>(mValue.mPtr);
+        break;
+        
+    case VAR_BUFFER:
+        delete reinterpret_cast<std::vector<unsigned char>*>(mValue.mPtr);
+        break;
+        
+    case VAR_VARIANTVECTOR:
+        delete reinterpret_cast<VariantVector*>(mValue.mPtr);
+        break;
+        
+    case VAR_VARIANTMAP:
+        delete reinterpret_cast<VariantMap*>(mValue.mPtr);
+        break;
+    }
+    
+    mType = newType;
+    
+    switch (mType)
+    {
+    case VAR_STRING:
+        *reinterpret_cast<std::string**>(&mValue.mPtr) = new std::string();
+        break;
+        
+    case VAR_BUFFER:
+        *reinterpret_cast<std::vector<unsigned char>**>(&mValue.mPtr) = new std::vector<unsigned char>();
+        break;
+        
+    case VAR_VARIANTVECTOR:
+        *reinterpret_cast<VariantVector**>(&mValue.mPtr) = new VariantVector();
+        break;
+        
+    case VAR_VARIANTMAP:
+        *reinterpret_cast<VariantMap**>(&mValue.mPtr) = new VariantMap();
+        break;
+    }
+}

+ 159 - 92
Engine/Common/Variant.h

@@ -46,7 +46,9 @@ enum VariantType
     VAR_COLOR,
     VAR_STRING,
     VAR_BUFFER,
-    VAR_PTR
+    VAR_PTR,
+    VAR_VARIANTVECTOR,
+    VAR_VARIANTMAP
 };
 
 //! Union for holding all the possible Variant values
@@ -60,13 +62,19 @@ struct VariantValue
         void* mPtr;
     };
     
-    Vector4 mVector4;
-    std::string mString;
-    std::vector<unsigned char> mBuffer;
+    float mY;
+    float mZ;
+    float mW;
 };
 
 class Deserializer;
 class Serializer;
+class Variant;
+
+//! Vector of variants
+typedef std::vector<Variant> VariantVector;
+//! Map of variants
+typedef std::map<ShortStringHash, Variant> VariantMap;
 
 //! A varying type with support for a fixed set of types
 class Variant
@@ -79,95 +87,137 @@ public:
     }
     
     //! Construct from integer
-    Variant(int value)
+    Variant(int value) :
+        mType(VAR_NONE)
     {
         *this = value;
     }
     
     //! Construct from unsigned integer
-    Variant(unsigned value)
+    Variant(unsigned value) :
+        mType(VAR_NONE)
     {
         *this = (int)value;
     }
     
     //! Construct from a StringHash (convert to integer)
-    Variant(const StringHash& value)
+    Variant(const StringHash& value) :
+        mType(VAR_NONE)
     {
         *this = (int)value.mData;
     }
     
     //! Construct from a ShortStringHash (convert to integer)
-    Variant(const ShortStringHash& value)
+    Variant(const ShortStringHash& value) :
+        mType(VAR_NONE)
     {
         *this = (int)value.mData;
     }
     
     //! Construct from a bool
-    Variant(bool value)
+    Variant(bool value) :
+        mType(VAR_NONE)
     {
         *this = value;
     }
     
     //! Construct from a float
-    Variant(float value)
+    Variant(float value) :
+        mType(VAR_NONE)
     {
         *this = value;
     }
     
     //! Construct from a Vector2
-    Variant(const Vector2& value)
+    Variant(const Vector2& value) :
+        mType(VAR_NONE)
     {
         *this = value;
     }
     
     //! Construct from a Vector3
-    Variant(const Vector3& value)
+    Variant(const Vector3& value) :
+        mType(VAR_NONE)
     {
         *this = value;
     }
     
     //! Construct from a Vector4
-    Variant(const Vector4& value)
+    Variant(const Vector4& value) :
+        mType(VAR_NONE)
     {
         *this = value;
     }
     
     //! Construct from a Quaternion
-    Variant(const Quaternion& value)
+    Variant(const Quaternion& value) :
+        mType(VAR_NONE)
     {
         *this = value;
     }
     
     //! Construct from a Color
-    Variant(const Color& value)
+    Variant(const Color& value) :
+        mType(VAR_NONE)
     {
         *this = value;
     }
     
     //! Construct from a string
-    Variant(const std::string& value)
+    Variant(const std::string& value) :
+        mType(VAR_NONE)
     {
         *this = value;
     }
     
     //! Construct from a buffer
-    Variant(const std::vector<unsigned char>& value)
+    Variant(const std::vector<unsigned char>& value) :
+        mType(VAR_NONE)
     {
         *this = value;
     }
     
     //! Construct from a pointer
-    Variant(void* value)
+    Variant(void* value) :
+        mType(VAR_NONE)
     {
         *this = value;
     }
     
+    //! Construct from a variant vector
+    Variant(const VariantVector& value) :
+        mType(VAR_NONE)
+    {
+        *this = value;
+    }
+    
+    //! Construct from a variant vector
+    Variant(const VariantMap& value) :
+        mType(VAR_NONE)
+    {
+        *this = value;
+    }
+    
+    //! Construct from type and value
+    Variant(const std::string& type, const std::string& value) :
+        mType(VAR_NONE)
+    {
+        fromString(type, value);
+    }
+    
     //! Copy-construct from another variant
-    Variant(const Variant& value)
+    Variant(const Variant& value) :
+        mType(VAR_NONE)
     {
         *this = value;
     }
     
+    //! Destruct
+    ~Variant()
+    {
+        setType(VAR_NONE);
+    }
+    
     //! Reset to none type
     void clear()
     {
@@ -175,12 +225,7 @@ public:
     }
     
     //! Assign from another variant
-    Variant& operator = (const Variant& rhs)
-    {
-        setType(rhs.mType);
-        mValue = rhs.mValue;
-        return *this;
-    }
+    Variant& operator = (const Variant& rhs);
     
     //! Assign from an integer
     Variant& operator = (int rhs)
@@ -234,7 +279,7 @@ public:
     Variant& operator = (const Vector2& rhs)
     {
         setType(VAR_VECTOR2);
-        *(reinterpret_cast<Vector2*>(&mValue.mVector4)) = rhs;
+        *(reinterpret_cast<Vector2*>(&mValue)) = rhs;
         return *this;
     }
     
@@ -242,7 +287,7 @@ public:
     Variant& operator = (const Vector3& rhs)
     {
         setType(VAR_VECTOR3);
-        *(reinterpret_cast<Vector3*>(&mValue.mVector4)) = rhs;
+        *(reinterpret_cast<Vector3*>(&mValue)) = rhs;
         return *this;
     }
     
@@ -250,7 +295,7 @@ public:
     Variant& operator = (const Vector4& rhs)
     {
         setType(VAR_VECTOR4);
-        mValue.mVector4 = rhs;
+        *(reinterpret_cast<Vector4*>(&mValue)) = rhs;
         return *this;
     }
     
@@ -258,7 +303,7 @@ public:
     Variant& operator = (const Quaternion& rhs)
     {
         setType(VAR_QUATERNION);
-        *(reinterpret_cast<Quaternion*>(&mValue.mVector4)) = rhs;
+        *(reinterpret_cast<Quaternion*>(&mValue)) = rhs;
         return *this;
     }
     
@@ -266,7 +311,7 @@ public:
     Variant& operator = (const Color& rhs)
     {
         setType(VAR_COLOR);
-        *(reinterpret_cast<Color*>(&mValue.mVector4)) = rhs;
+        *(reinterpret_cast<Color*>(&mValue)) = rhs;
         return *this;
     }
     
@@ -274,7 +319,7 @@ public:
     Variant& operator = (const std::string& rhs)
     {
         setType(VAR_STRING);
-        mValue.mString = rhs;
+        *(reinterpret_cast<std::string*>(mValue.mPtr)) = rhs;
         return *this;
     }
     
@@ -282,7 +327,7 @@ public:
     Variant& operator = (const std::vector<unsigned char>& rhs)
     {
         setType(VAR_BUFFER);
-        mValue.mBuffer = rhs;
+        *(reinterpret_cast<std::vector<unsigned char>*>(mValue.mPtr)) = rhs;
         return *this;
     }
     
@@ -294,41 +339,25 @@ public:
         return *this;
     }
     
-    //! Test for equality with another variant
-    bool operator == (const Variant& rhs) const
+    //! Assign from a variant vector
+    Variant& operator = (const VariantVector& rhs)
     {
-        if (mType != rhs.mType)
-            return false;
-        
-        switch (mType)
-        {
-        case VAR_INT:
-            return mValue.mInt == rhs.mValue.mInt;
-        case VAR_BOOL:
-            return mValue.mBool == rhs.mValue.mBool;
-        case VAR_FLOAT:
-            return mValue.mFloat == rhs.mValue.mFloat;
-        case VAR_VECTOR2:
-            return *(reinterpret_cast<const Vector2*>(&mValue.mVector4)) == *(reinterpret_cast<const Vector2*>(&rhs.mValue.mVector4));
-        case VAR_VECTOR3:
-            return *(reinterpret_cast<const Vector3*>(&mValue.mVector4)) == *(reinterpret_cast<const Vector3*>(&rhs.mValue.mVector4));
-        case VAR_VECTOR4:
-            return mValue.mVector4 == rhs.mValue.mVector4;
-        case VAR_QUATERNION:
-            return *(reinterpret_cast<const Quaternion*>(&mValue.mVector4)) == *(reinterpret_cast<const Quaternion*>(&rhs.mValue.mVector4));
-        case VAR_COLOR:
-            return *(reinterpret_cast<const Color*>(&mValue.mVector4)) == *(reinterpret_cast<const Color*>(&rhs.mValue.mVector4));
-        case VAR_STRING:
-            return mValue.mString == rhs.mValue.mString;
-        case VAR_BUFFER:
-            return mValue.mBuffer == rhs.mValue.mBuffer;
-        case VAR_PTR:
-            return mValue.mPtr == rhs.mValue.mPtr;
-        }
-        
-        return true;
+        setType(VAR_VARIANTVECTOR);
+        *(reinterpret_cast<VariantVector*>(mValue.mPtr)) = rhs;
+        return *this;
+    }
+    
+    //! Assign from a variant map
+    Variant& operator = (const VariantMap& rhs)
+    {
+        setType(VAR_VARIANTMAP);
+        *(reinterpret_cast<VariantMap*>(mValue.mPtr)) = rhs;
+        return *this;
     }
     
+    //! Test for equality with another variant
+    bool operator == (const Variant& rhs) const;
+    
     //! Test for inequality with another variant
     bool operator != (const Variant& rhs) const
     {
@@ -375,7 +404,7 @@ public:
     bool operator == (const Vector2& rhs) const
     {
         if (mType == VAR_VECTOR2)
-            return *(reinterpret_cast<const Vector2*>(&mValue.mVector4)) == rhs;
+            return *(reinterpret_cast<const Vector2*>(&mValue)) == rhs;
         else
             return false;
     }
@@ -384,7 +413,7 @@ public:
     bool operator == (const Vector3& rhs) const
     {
         if (mType == VAR_VECTOR3)
-            return *(reinterpret_cast<const Vector3*>(&mValue.mVector4)) == rhs;
+            return *(reinterpret_cast<const Vector3*>(&mValue)) == rhs;
         else
             return false;
     }
@@ -393,7 +422,7 @@ public:
     bool operator == (const Vector4& rhs) const
     {
         if (mType == VAR_VECTOR4)
-            return mValue.mVector4 == rhs;
+            return *(reinterpret_cast<const Vector4*>(&mValue)) == rhs;
         else
             return false;
     }
@@ -402,7 +431,7 @@ public:
     bool operator == (const Quaternion& rhs) const
     {
         if (mType == VAR_QUATERNION)
-            return *(reinterpret_cast<const Quaternion*>(&mValue.mVector4)) == rhs;
+            return *(reinterpret_cast<const Quaternion*>(&mValue)) == rhs;
         else
             return false;
     }
@@ -411,7 +440,7 @@ public:
     bool operator == (const Color& rhs) const
     {
         if (mType == VAR_COLOR)
-            return *(reinterpret_cast<const Color*>(&mValue.mVector4)) == rhs;
+            return *(reinterpret_cast<const Color*>(&mValue)) == rhs;
         else
             return false;
     }
@@ -420,7 +449,7 @@ public:
     bool operator == (const std::string& rhs) const
     {
         if (mType == VAR_STRING)
-            return mValue.mString == rhs;
+            return *(reinterpret_cast<const std::string*>(mValue.mPtr)) == rhs;
         else
             return false;
     }
@@ -429,7 +458,7 @@ public:
     bool operator == (const std::vector<unsigned char>& rhs) const
     {
         if (mType == VAR_BUFFER)
-            return mValue.mBuffer == rhs;
+            return *(reinterpret_cast<const std::vector<unsigned char>*>(mValue.mPtr)) == rhs;
         else
             return false;
     }
@@ -443,6 +472,24 @@ public:
             return false;
     }
     
+    //! Test for equality with a variant vector. To return true, both the type and value must match
+    bool operator == (const VariantVector& rhs) const
+    {
+        if (mType == VAR_VARIANTVECTOR)
+            return *(reinterpret_cast<VariantVector*>(mValue.mPtr)) == rhs;
+        else
+            return false;
+    }
+    
+    //! Test for equality with a variant map. To return true, both the type and value must match
+    bool operator == (const VariantMap& rhs) const
+    {
+        if (mType == VAR_VARIANTMAP)
+            return *(reinterpret_cast<VariantMap*>(mValue.mPtr)) == rhs;
+        else
+            return false;
+    }
+    
     //! Test for equality with a StringHash. To return true, both the type and value must match
     bool operator == (const StringHash& rhs) const
     {
@@ -521,6 +568,18 @@ public:
         return !(*this == rhs);
     }
     
+    //! Test for inequality with a variant vector
+    bool operator != (const VariantVector& rhs) const
+    {
+        return !(*this == rhs);
+    }
+    
+    //! Test for inequality with a variant map
+    bool operator != (const VariantMap& rhs) const
+    {
+        return !(*this == rhs);
+    }
+    
     //! Test for inequality with a StringHash
     bool operator != (const StringHash& rhs) const
     {
@@ -594,7 +653,7 @@ public:
     {
         if (mType != VAR_VECTOR2)
             return Vector2::sZero;
-        return *reinterpret_cast<const Vector2*>(&mValue.mVector4);
+        return *reinterpret_cast<const Vector2*>(&mValue);
     }
     
     //! Return a Vector3, zero vector if type mismatch
@@ -602,7 +661,7 @@ public:
     {
         if (mType != VAR_VECTOR3)
             return Vector3::sZero;
-        return *reinterpret_cast<const Vector3*>(&mValue.mVector4);
+        return *reinterpret_cast<const Vector3*>(&mValue);
     }
     
     //! Return a Vector4, zero vector if type mismatch
@@ -610,7 +669,7 @@ public:
     {
         if (mType != VAR_VECTOR4)
             return Vector4::sZero;
-        return mValue.mVector4;
+        return *reinterpret_cast<const Vector4*>(&mValue);
     }
     
     //! Return a Quaternion, identity if type mismatch
@@ -618,7 +677,7 @@ public:
     {
         if (mType != VAR_QUATERNION)
             return Quaternion::sIdentity;
-        return *reinterpret_cast<const Quaternion*>(&mValue.mVector4);
+        return *reinterpret_cast<const Quaternion*>(&mValue);
     }
     
     //! Return a Color, default if type mismatch
@@ -628,7 +687,7 @@ public:
         
         if (mType != VAR_COLOR)
             return noColor;
-        return *reinterpret_cast<const Color*>(&mValue.mVector4);
+        return *reinterpret_cast<const Color*>(&mValue);
     }
     
     //! Return a string, empty if type mismatch
@@ -638,7 +697,7 @@ public:
         
         if (mType != VAR_STRING)
             return noString;
-        return mValue.mString;
+        return *reinterpret_cast<const std::string*>(mValue.mPtr);
     }
     
     //! Return a buffer, empty if type mismatch
@@ -648,7 +707,27 @@ public:
         
         if (mType != VAR_BUFFER)
             return noBuffer;
-        return mValue.mBuffer;
+        return *reinterpret_cast<const std::vector<unsigned char>*>(mValue.mPtr);
+    }
+    
+    //! Return a variant vector, empty if type mismatch
+    const VariantVector& getVariantVector() const
+    {
+        static const VariantVector noVector;
+        
+        if (mType != VAR_VARIANTVECTOR)
+            return noVector;
+        return *reinterpret_cast<VariantVector*>(mValue.mPtr);
+    }
+    
+    //! Return a variant map, empty if type mismatch
+    const VariantMap& getVariantMap() const
+    {
+        static const VariantMap noMap;
+        
+        if (mType != VAR_VARIANTMAP)
+            return noMap;
+        return *reinterpret_cast<VariantMap*>(mValue.mPtr);
     }
     
     //! Return a pointer, null if type mismatch
@@ -676,17 +755,8 @@ public:
     std::string toString() const;
     
 private:
-    //! Set type and clean up if necessary
-    void setType(VariantType newType)
-    {
-        // Clean up the space-consuming storage if no longer needed
-        if ((mType == VAR_STRING) && (newType != VAR_STRING) && (mValue.mString.length()))
-            mValue.mString = std::string();
-        if ((mType == VAR_BUFFER) && (newType != VAR_BUFFER) && (mValue.mBuffer.size()))
-            mValue.mBuffer = std::vector<unsigned char>();
-        
-        mType = newType;
-    }
+    //! Set new type and allocate/deallocate memory as necessary
+    void Variant::setType(VariantType newType);
     
     //! Variant type
     VariantType mType;
@@ -694,7 +764,4 @@ private:
     VariantValue mValue;
 };
 
-//! Map of variants
-typedef std::map<ShortStringHash, Variant> VariantMap;
-
 #endif // COMMON_VARIANT_H