diff options
author | George Hazan <george.hazan@gmail.com> | 2012-06-23 17:15:01 +0000 |
---|---|---|
committer | George Hazan <george.hazan@gmail.com> | 2012-06-23 17:15:01 +0000 |
commit | 240b769d44fe6c50cabbf311f8e9fb1fae7cd80e (patch) | |
tree | fb464ca81e54b3133a475b19fd4cdf811b789fad /src/modules/json/internalJSONNode.h | |
parent | 7a0f39abf558c7dde715a87d9356d92275d5d34e (diff) |
libjson interface added to the core
git-svn-id: http://svn.miranda-ng.org/main/trunk@573 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'src/modules/json/internalJSONNode.h')
-rw-r--r-- | src/modules/json/internalJSONNode.h | 453 |
1 files changed, 453 insertions, 0 deletions
diff --git a/src/modules/json/internalJSONNode.h b/src/modules/json/internalJSONNode.h new file mode 100644 index 0000000000..9e9f9de983 --- /dev/null +++ b/src/modules/json/internalJSONNode.h @@ -0,0 +1,453 @@ +#ifndef INTERNAL_JSONNODE_H +#define INTERNAL_JSONNODE_H + +#include "JSONDebug.h" +#include "JSONChildren.h" +#include "JSONMemory.h" +#ifdef JSON_DEBUG + #include <climits> //to check int value +#endif + +/* + This class is the work horse of libJSON, it handles all of the + functinality of JSONNode. This object is reference counted for + speed and memory reasons. + + If JSON_REF_COUNT is not on, this internal structure still has an important + purpose, as it can be passed around by JSONNoders that are flagged as temporary +*/ + +class JSONNode; //forward declaration + +#ifndef JSON_LIBRARY + #define DECL_SET_INTEGER(type) void Set(type); void Set(unsigned type); +#endif + +#ifdef JSON_MUTEX_CALLBACKS + #define initializeMutex(x) ,mylock(x) +#else + #define initializeMutex(x) +#endif + +#ifdef JSON_PREPARSE + #define SetFetched(b) (void)0 + #define Fetch() (void)0 + #define initializeFetch(x) +#else + #define initializeFetch(x) ,fetched(x) +#endif + +#ifdef JSON_REF_COUNT + #define initializeRefCount(x) ,refcount(x) +#else + #define initializeRefCount(x) +#endif + +#ifdef JSON_COMMENTS + #define initializeComment(x) ,_comment(x) +#else + #define initializeComment(x) +#endif + +#ifndef JSON_UNIT_TEST + #define incAllocCount() (void)0 + #define decAllocCount() (void)0 + #define incinternalAllocCount() (void)0 + #define decinternalAllocCount() (void)0 +#endif + +#ifdef JSON_VALIDATE + #define initializeValid(x) ,isValid(x) +#else + #define initializeValid(x) +#endif + +class internalJSONNode { +public: + internalJSONNode(char mytype = JSON_NULL); + internalJSONNode(const json_string & unparsed); + internalJSONNode(const json_string & name_t, const json_string & value_t); + internalJSONNode(const internalJSONNode & orig); + internalJSONNode & operator = (const internalJSONNode &); + ~internalJSONNode(void); + + static internalJSONNode * newInternal(char mytype = JSON_NULL); + static internalJSONNode * newInternal(const json_string & unparsed); + static internalJSONNode * newInternal(const json_string & name_t, const json_string & value_t); + static internalJSONNode * newInternal(const internalJSONNode & orig); //not copyable, only by this class + static void deleteInternal(internalJSONNode * ptr); + + json_index_t size(void) const; + bool empty(void) const; + unsigned char type(void) const; + + json_string name(void) const; + void setname(const json_string & newname); + #ifdef JSON_COMMENTS + void setcomment(const json_string & comment); + json_string getcomment(void) const; + #endif + json_string as_string(void) const; + long as_int(void) const; + json_number as_float(void) const; + bool as_bool(void) const; + + #ifndef JSON_PREPARSE + void preparse(void); + #endif + + #ifdef JSON_LIBRARY + void push_back(JSONNode * node); + #else + void push_back(const JSONNode & node); + #endif + void reserve(json_index_t size); + void push_front(const JSONNode & node); + JSONNode * pop_back(json_index_t pos); + JSONNode * pop_back(const json_string & name_t); + #ifdef JSON_CASE_INSENSITIVE_FUNCTIONS + JSONNode * pop_back_nocase(const json_string & name_t); + #endif + + JSONNode * at(json_index_t pos); + //These return ** because pop_back needs them + JSONNode ** at(const json_string & name_t); + #ifdef JSON_CASE_INSENSITIVE_FUNCTIONS + JSONNode ** at_nocase(const json_string & name_t); + #endif + + void Set(const json_string & val); + #ifdef JSON_LIBRARY + void Set(json_number val); + void Set(long val); + #else + DECL_SET_INTEGER(char) + DECL_SET_INTEGER(short) + DECL_SET_INTEGER(int) + DECL_SET_INTEGER(long) + #ifndef JSON_ISO_STRICT + DECL_SET_INTEGER(long long) + #endif + + void Set(float val); + void Set(double val); + #endif + void Set(bool val); + + bool IsEqualTo(const json_string & val)const ; + bool IsEqualTo(bool val) const; + bool IsEqualTo(const internalJSONNode * val) const; + + template<typename T> + bool IsEqualToNum(T val) const; + + internalJSONNode * incRef(void); + #ifdef JSON_REF_COUNT + void decRef(void); + bool hasNoReferences(void); + #endif + internalJSONNode * makeUnique(void); + + JSONNode ** begin(void) const; + JSONNode ** end(void) const; + #ifdef JSON_REF_COUNT + size_t refcount BITS(20); + #endif + bool Fetched(void) const; + #ifdef JSON_MUTEX_CALLBACKS + void * mylock; + void _set_mutex(void * mutex, bool unset = true); + void _unset_mutex(void); + #endif + #ifdef JSON_UNIT_TEST + static void incinternalAllocCount(void); + static void decinternalAllocCount(void); + #endif + + #ifdef JSON_WRITER + json_string WriteName(bool formatted, bool arrayChild) const; + json_string WriteChildren(unsigned int indent); + json_string WriteComment(unsigned int indent) const; + json_string Write(unsigned int indent, bool arrayChild); + #endif + #ifdef JSON_DEBUG + #ifndef JSON_LIBRARY + JSONNode Dump(size_t & totalmemory) const; + JSONNode DumpMutex(void) const; + #endif + #endif + + //json parts + mutable unsigned char _type BITS(3); + mutable bool _name_encoded BITS(1); //must be above name due to initialization list order + json_string _name; + + mutable json_string _string; //these are both mutable because the string can change when it's fetched + mutable bool _string_encoded BITS(1); + + //the value of the json + union value_union_t { + bool _bool; + json_number _number; + }; + mutable value_union_t _value; //internal structure changes depending on type + + jsonChildren Children; //container that holds all of my children + + #ifdef JSON_VALIDATE + mutable bool isValid BITS(1); //this does not need to be initialized, it's only used if it's null + void Nullify(bool validation = true) const; + bool validate(void); + #else + void Nullify(void) const; + #endif + + //Fetching and such + #ifndef JSON_PREPARSE + mutable bool fetched BITS(1); + void SetFetched(bool val) const; + void Fetch(void) const; //it's const because it doesn't change the VALUE of the function + #endif + + #ifdef JSON_COMMENTS + json_string _comment; + #endif + + void FetchString(void) const; + void FetchNode(void) const; + void FetchArray(void) const; + void FetchNumber(void) const; + #ifdef JSON_CASE_INSENSITIVE_FUNCTIONS + static bool AreEqualNoCase(const json_char * ch_one, const json_char * ch_two); + #endif +}; + +inline internalJSONNode::internalJSONNode(char mytype) : _type(mytype), Children(), _name(), _name_encoded(), _string(), _string_encoded(), _value() + initializeMutex(0) + initializeRefCount(1) + initializeFetch(true) + initializeComment(0) + initializeValid(true){ + + incinternalAllocCount(); +} + +inline internalJSONNode * internalJSONNode::incRef(void){ + #ifdef JSON_REF_COUNT + ++refcount; + return this; + #else + return makeUnique(); + #endif +} + +inline json_index_t internalJSONNode::size(void) const { + Fetch(); + return Children.size(); +} + +inline bool internalJSONNode::empty(void) const { + if (type() != JSON_NODE && type() != JSON_ARRAY) return true; + Fetch(); + return Children.empty(); +} + +inline unsigned char internalJSONNode::type(void) const { + #ifdef JSON_LESS_MEMORY + return _type & 0xF; + #else + return _type; + #endif +} + +inline json_string internalJSONNode::name(void) const { + return _name; +} + +inline void internalJSONNode::setname(const json_string & newname){ + _name = newname; + #ifdef JSON_LESS_MEMORY + _type |= 0x10; + #else + _name_encoded = true; + #endif +} + +#ifdef JSON_COMMENTS + inline void internalJSONNode::setcomment(const json_string & comment){ + _comment = comment; + } + + inline json_string internalJSONNode::getcomment(void) const { + return _comment; + } +#endif + +inline json_string internalJSONNode::as_string(void) const { + Fetch(); + return _string; +} + +inline long internalJSONNode::as_int(void) const { + Fetch(); + switch(type()) { + case JSON_NULL: + return 0; + case JSON_BOOL: + return _value._bool ? 1 : 0; + } + JSON_ASSERT(type() == JSON_NUMBER, JSON_TEXT("as_int returning undefined results")); + JSON_ASSERT(_value._number > LONG_MIN, _string + JSON_TEXT(" is outside the lower range of long")); + JSON_ASSERT(_value._number < LONG_MAX, _string + JSON_TEXT(" is outside the upper range of long")); + JSON_ASSERT(_value._number == (json_number)((int)_value._number), json_string(JSON_TEXT("as_int will truncate ")) + _string); + return (int)_value._number; +} + +inline json_number internalJSONNode::as_float(void) const { + Fetch(); + switch(type()) { + case JSON_NULL: + return (json_number)0.0; + case JSON_BOOL: + return (json_number)(_value._bool ? 1.0 : 0.0); + } + JSON_ASSERT(type() == JSON_NUMBER, JSON_TEXT("as_float returning undefined results")); + return _value._number; +} + +inline bool internalJSONNode::as_bool(void) const { + Fetch(); + switch(type()) { + case JSON_NUMBER: + return _value._number != 0.0f; + case JSON_NULL: + return false; + } + JSON_ASSERT(type() == JSON_BOOL, JSON_TEXT("as_bool returning undefined results")); + return _value._bool; +} + +inline bool internalJSONNode::IsEqualTo(const json_string & val) const { + if (type() != JSON_STRING) return false; + Fetch(); + return val == _string; +} + +inline bool internalJSONNode::IsEqualTo(bool val) const { + if (type() != JSON_BOOL) return false; + Fetch(); + return val == _value._bool; +} + +template<typename T> +inline bool internalJSONNode::IsEqualToNum(T val) const { + if (type() != JSON_NUMBER) return false; + Fetch(); + return (json_number)val == _value._number; +} + +#ifdef JSON_REF_COUNT + inline void internalJSONNode::decRef(void){ + JSON_ASSERT(refcount != 0, JSON_TEXT("decRef on a 0 refcount internal")); + --refcount; + } + + inline bool internalJSONNode::hasNoReferences(void){ + return refcount == 0; + } +#endif + +inline internalJSONNode * internalJSONNode::makeUnique(void){ + #ifdef JSON_REF_COUNT + if (refcount > 1){ + decRef(); + return newInternal(*this); + } + JSON_ASSERT(refcount == 1, JSON_TEXT("makeUnique on a 0 refcount internal")); + return this; + #else + return newInternal(*this); + #endif +} + +#ifndef JSON_PREPARSE + inline void internalJSONNode::SetFetched(bool val) const { + fetched = val; + } +#endif + +inline bool internalJSONNode::Fetched(void) const { + #ifndef JSON_PREPARSE + return fetched; + #else + return true; + #endif +} + +inline JSONNode ** internalJSONNode::begin(void) const { + Fetch(); + return Children.begin(); +} + +inline JSONNode ** internalJSONNode::end(void) const { + Fetch(); + return Children.end(); +} + +inline JSONNode * internalJSONNode::at(json_index_t pos){ + Fetch(); + return Children[pos]; +} + +inline void internalJSONNode::reserve(json_index_t size){ + Fetch(); + Children.reserve2(size); +} + +/* + These functions are to allow allocation to be completely controlled by the callbacks +*/ + +inline void internalJSONNode::deleteInternal(internalJSONNode * ptr){ + #ifdef JSON_MEMORY_CALLBACKS + ptr -> ~internalJSONNode(); + libjson_free<internalJSONNode>(ptr); + #else + delete ptr; + #endif +} + +inline internalJSONNode * internalJSONNode::newInternal(char mytype){ + #ifdef JSON_MEMORY_CALLBACKS + return new(json_malloc<internalJSONNode>(1)) internalJSONNode(mytype); + #else + return new internalJSONNode(mytype); + #endif +} + +inline internalJSONNode * internalJSONNode::newInternal(const json_string & unparsed){ + #ifdef JSON_MEMORY_CALLBACKS + return new(json_malloc<internalJSONNode>(1)) internalJSONNode(unparsed); + #else + return new internalJSONNode(unparsed); + #endif +} + +inline internalJSONNode * internalJSONNode::newInternal(const json_string & name_t, const json_string & value_t){ + #ifdef JSON_MEMORY_CALLBACKS + return new(json_malloc<internalJSONNode>(1)) internalJSONNode(name_t, value_t); + #else + return new internalJSONNode(name_t, value_t); + #endif +} + +inline internalJSONNode * internalJSONNode::newInternal(const internalJSONNode & orig){ + #ifdef JSON_MEMORY_CALLBACKS + return new(json_malloc<internalJSONNode>(1)) internalJSONNode(orig); + #else + return new internalJSONNode(orig); + #endif +} + + +#endif |