jvar
JS inspired Variant and Json
var.h
00001 // Copyright (c) 2014 Yasser Asmi
00002 // Released under the MIT License (http://opensource.org/licenses/MIT)
00003 
00004 #ifndef _VAR_H
00005 #define _VAR_H
00006 
00007 #include "util.h"
00008 #include "arr.h"
00009 #include "str.h"
00010 #include <math.h>
00011 
00012 #define VNULL Variant::vNull
00013 #define VEMPTY Variant::vEmpty
00014 
00015 #define VAR_PATH_DELIM     "."
00016 
00017 namespace jvar
00018 {
00019 
00020 class VarFuncObj;
00021 
00027 class Variant
00028 {
00029 public:
00030     typedef int (*Compare)(const Variant*, const Variant*);
00031 
00032     enum Type
00033     {
00034         V_EMPTY,
00035         V_NULL,
00036         V_INT,
00037         V_BOOL,
00038         V_DOUBLE,
00039         V_STRING,
00040         V_ARRAY,
00041         V_OBJECT,
00042         V_FUNCTION,
00043         V_POINTER
00044     };
00045 
00046 public:
00047 
00051     inline Variant()
00052     {
00053         mData.type = V_EMPTY;
00054         mData.flags = 0;
00055     }
00056 
00060     inline Variant(longint i)
00061     {
00062         mData.type = V_INT;
00063         mData.intData = i;
00064     }
00065 
00069     inline Variant(int i)
00070     {
00071         mData.type = V_INT;
00072         mData.intData = (longint)i;
00073     }
00074 
00078     inline Variant(double d)
00079     {
00080         mData.type = V_DOUBLE;
00081         mData.dblData = d;
00082     }
00083 
00087     inline Variant(std::string s)
00088     {
00089         mData.type = V_STRING;
00090 
00091         // Inplace new a std::string object with the source string passed to
00092         // the constructor.
00093 
00094         new (&mData.strMemData) std::string(s);
00095     }
00096 
00100     inline Variant(const char* s)
00101     {
00102         mData.type = V_STRING;
00103 
00104         // Inplace new a std::string object with the source string passed to
00105         // the constructor.
00106 
00107         new (&mData.strMemData) std::string(s);
00108     }
00109 
00113     inline Variant(Variant const& src)
00114     {
00115         mData.type = V_EMPTY;
00116         *this = src;
00117     }
00118 
00122     inline ~Variant()
00123     {
00124         (void)deleteData();
00125     }
00126 
00130     inline Variant& operator=(const Variant& src)
00131     {
00132         copyFrom(&src);
00133         return *this;
00134     }
00135 
00139     inline Variant& operator=(const Variant* src)
00140     {
00141         copyFrom(src);
00142         return *this;
00143     }
00144 
00148     inline Variant& operator=(const char* src)
00149     {
00150         assignStr(src);
00151         return *this;
00152     }
00153 
00157     inline Variant& operator=(const std::string& src)
00158     {
00159         assignStr(src);
00160         return *this;
00161     }
00162 
00166     inline Variant& operator=(bool src)
00167     {
00168         assignBool(src);
00169         return *this;
00170     }
00171 
00175     inline Variant& operator=(longint src)
00176     {
00177         assignInt(src);
00178         return *this;
00179     }
00180 
00184     inline Variant& operator=(int src)
00185     {
00186         assignInt((longint)src);
00187         return *this;
00188     }
00189 
00193     inline Variant& operator=(double src)
00194     {
00195         assignDbl(src);
00196         return *this;
00197     }
00198 
00202     inline Variant& operator=(float src)
00203     {
00204         assignDbl((double)src);
00205         return *this;
00206     }
00207 
00220     inline Variant& operator+=(const Variant& rhs)
00221     {
00222         internalAdd(*this, rhs);
00223         return *this;
00224     }
00225 
00229     inline Variant& operator+=(longint rhs)
00230     {
00231         Variant r(rhs);
00232         internalAdd(*this, r);
00233         return *this;
00234     }
00235 
00239     inline Variant& operator+=(int rhs)
00240     {
00241         Variant r((longint)rhs);
00242         internalAdd(*this, r);
00243         return *this;
00244     }
00245 
00249     inline Variant& operator+=(const char* rhs)
00250     {
00251         Variant r(rhs);
00252         internalAdd(*this, r);
00253         return *this;
00254     }
00255 
00259     inline Variant& operator+=(const std::string& rhs)
00260     {
00261         Variant r(rhs);
00262         internalAdd(*this, r);
00263         return *this;
00264     }
00265 
00269     inline Variant& operator+=(double rhs)
00270     {
00271         Variant r(rhs);
00272         internalAdd(*this, r);
00273         return *this;
00274     }
00275 
00280     inline Variant& operator++()
00281     {
00282         Variant r(1);
00283         internalAdd(*this, r);
00284         return *this;
00285     }
00286 
00291     inline Variant operator++(int)
00292     {
00293         Variant r(1);
00294         internalAdd(*this, r);
00295         return *this;
00296     }
00297 
00301     inline longint toInt() const
00302     {
00303         return makeInt();
00304     }
00305 
00309     inline double toDouble() const
00310     {
00311         return makeDbl();
00312     }
00313 
00317     inline bool toBool() const
00318     {
00319         return makeBool();
00320     }
00321 
00325     inline operator longint() const
00326     {
00327         return makeInt();
00328     }
00329 
00333     inline operator double() const
00334     {
00335         return makeDbl();
00336     }
00337 
00341     inline operator bool() const
00342     {
00343         return makeBool();
00344     }
00345 
00349     inline operator const char*()
00350     {
00351         return c_str();
00352     }
00353 
00357     inline const char* c_str() const
00358     {
00359         if (mData.type == V_STRING)
00360         {
00361             return mData.strData()->c_str();
00362         }
00363         return NULL;
00364     }
00365 
00375     std::string& s();
00376 
00383     std::string toString() const;
00384 
00393     std::string toFixed(int digs = 0) const;
00394 
00400     std::string toJsonString() const;
00401 
00409     bool parseJson(const char* jsontxt);
00410 
00414     void format(const char* fmt, ...);
00415 
00421     inline Type type() const
00422     {
00423         return (Type)(mData.type);
00424     }
00425 
00431     const char* typeName() const;
00432 
00433     inline bool isNull() const
00434     {
00435         return (mData.type == V_NULL);
00436     }
00437     inline bool isEmpty() const
00438     {
00439         return (mData.type == V_EMPTY);
00440     }
00441     inline bool isObject() const
00442     {
00443         return (mData.type == V_OBJECT);
00444     }
00445     inline bool isArray() const
00446     {
00447         return (mData.type == V_ARRAY);
00448     }
00449     inline bool isPointer() const
00450     {
00451         return (mData.type == V_POINTER);
00452     }
00453     inline bool isNaN()
00454     {
00455         if (mData.type == V_DOUBLE)
00456         {
00457             return isnan(mData.dblData);
00458         }
00459         else if (mData.type == V_INT)
00460         {
00461             return false;
00462         }
00463         return true;
00464     }
00465 
00470     int length() const;
00471 
00475     Variant& operator[](int i);
00476 
00480     const Variant& operator[](int i) const;
00481 
00485     Variant& operator[](const char* key);
00486 
00490     const Variant& operator[](const char* key) const;
00491 
00500     Variant& path(const char* pathkey);
00501 
00510     inline Variant& path(const std::string& pathkey)
00511     {
00512         return path(pathkey.c_str());
00513     }
00514 
00520     void createArray(const char* initvalue = NULL);
00521 
00529     Variant* append(const Variant& elem = VEMPTY);
00530 
00534     inline void push(const Variant& elem)
00535     {
00536         (void)append(elem);
00537     }
00538 
00544     Variant pop();
00545 
00551     Variant shift();
00552 
00558     void sort(Compare comp);
00559 
00565     void createObject(const char* initvalue = NULL);
00566 
00575     Variant& addProperty(const char* key, const Variant& value = vEmpty);
00576 
00584     bool hasProperty(const char* key);
00585 
00593     const char* getKey(int n);
00594 
00600     void createFunction(Variant (*func)(Variant& env, Variant& arg));
00601 
00610     bool addEnv(const char* varname, const Variant& value = vEmpty);
00611     Variant operator() ();
00612     Variant operator() (const Variant& value1);
00613     Variant operator() (const Variant& value1, const Variant& value2);
00614     Variant operator() (const Variant& value1, const Variant& value2, const Variant& value3);
00615     Variant operator() (const Variant& value1, const Variant& value2, const Variant& value3, const Variant& value4);
00616 
00624     inline bool forEach(Iter<Variant>& iter)
00625     {
00626         if (mData.type == V_ARRAY)
00627         {
00628             return mData.arrayData->forEach(iter);
00629         }
00630         else if (mData.type == V_OBJECT)
00631         {
00632             return mData.objectData->forEach(iter);
00633         }
00634         return false;
00635     }
00636 
00640     inline void clear()
00641     {
00642         (void)deleteData();
00643     }
00644 
00648     inline void setModified()
00649     {
00650         setFlag(mData.flags, VF_MODIFIED);
00651     }
00652 
00656     inline void clearModified()
00657     {
00658         clearFlag(mData.flags, VF_MODIFIED);
00659     }
00660 
00664     inline bool isModified()
00665     {
00666         return isFlagSet(mData.flags, VF_MODIFIED);
00667     }
00668 
00669 private:
00670 
00671     enum Flags
00672     {
00673         VF_MODIFIED = 0x1
00674     };
00675 
00676     #pragma pack(push, 4)
00677     struct VarData
00678     {
00679         ushortint type;
00680         shortint flags;
00681         union
00682         {
00683             longint intData;
00684             double dblData;
00685             bool boolData;
00686             char strMemData[sizeof(std::string)];
00687             ObjArray<Variant>* arrayData;
00688             PropArray<Variant>* objectData;
00689             VarFuncObj* funcData;
00690             Variant* vptrData;
00691         };
00692 
00693         std::string* strData() const
00694         {
00695             return (std::string*)&strMemData;
00696         }
00697     };
00698     #pragma pack(pop)
00699 
00700     VarData mData;
00701 
00702 private:
00703 
00704     bool deleteData();
00705     void copyFrom(const Variant* src);
00706 
00707     void assignInt(longint src);
00708     void assignDbl(double src);
00709     void assignBool(bool src);
00710     void assignStr(const char* src);
00711     void assignStr(const std::string& src);
00712 
00713     longint makeInt() const;
00714     double makeDbl() const;
00715     inline bool makeBool() const
00716     {
00717         return makeInt() == 0 ? false : true;
00718     }
00719     void makeString(std::string& s, int level, bool json);
00720 
00721     void jsonifyStr(std::string& s);
00722     inline void appendQuote(std::string& s, Type type)
00723     {
00724         if (type == V_STRING)
00725         {
00726             s += '"';
00727         }
00728     }
00729     inline void appendNewline(std::string& s, int level, bool json)
00730     {
00731         if (json)
00732         {
00733             s += '\n';
00734             s += std::string(level, '\t');
00735         }
00736     }
00737 
00738     static const KeywordArray::Entry sTypeNames[];
00739 
00740 public:
00741     static Variant vEmpty;
00742     static Variant vNull;
00743 
00744 public:
00747     Variant(Type type)
00748     {
00749         mData.type = type;
00750     }
00751 
00752     void internalAdd(const Variant& lhs, const Variant& rhs);
00753     void internalSetPtr(const Variant* v);
00754 
00756 };
00757 
00759 class VarFuncObj
00760 {
00761 public:
00762     VarFuncObj() :
00763         mFunc(NULL)
00764     {
00765     }
00766 
00767     Variant mEnv;
00768     Variant (*mFunc)(Variant& env, Variant& arg);
00769 };
00777 inline Variant operator+(const Variant& lhs, const Variant& rhs)
00778 {
00779     Variant res;
00780     res.internalAdd(lhs, rhs);
00781     return res;
00782 }
00783 
00789 inline Variant operator+(const Variant& lhs, const char* rhs)
00790 {
00791     Variant res;
00792     Variant r(rhs);
00793     res.internalAdd(lhs, r);
00794     return res;
00795 }
00796 
00802 inline Variant operator+(const char* lhs, const Variant& rhs)
00803 {
00804     Variant res;
00805     Variant l(lhs);
00806     res.internalAdd(l, rhs);
00807     return res;
00808 }
00809 
00815 inline Variant operator+(const std::string& lhs, const Variant& rhs)
00816 {
00817     Variant res;
00818     Variant l(lhs);
00819     res.internalAdd(l, rhs);
00820     return res;
00821 }
00822 
00828 inline Variant operator+(const Variant& lhs, const std::string& rhs)
00829 {
00830     Variant res;
00831     Variant r(rhs);
00832     res.internalAdd(lhs, r);
00833     return res;
00834 }
00835 
00841 inline Variant operator+(const Variant& lhs, longint rhs)
00842 {
00843     Variant res;
00844     Variant r(rhs);
00845     res.internalAdd(lhs, r);
00846     return res;
00847 }
00848 
00854 inline Variant operator+(const Variant& lhs, int rhs)
00855 {
00856     return operator+(lhs, (longint)rhs);
00857 }
00858 
00864 inline Variant operator+(const Variant& lhs, double rhs)
00865 {
00866     Variant res;
00867     Variant r(rhs);
00868     res.internalAdd(lhs, r);
00869     return res;
00870 }
00871 
00877 inline Variant operator+(double lhs, const Variant& rhs)
00878 {
00879     Variant res;
00880     Variant l(lhs);
00881     res.internalAdd(l, rhs);
00882     return res;
00883 }
00884 
00885 } // jvar
00886 
00887 #endif // _VAR_H
 All Classes Functions Variables Enumerator