Blame | Last modification | View Log | Download | RSS feed
#ifndef INTERNAL_JSONNODE_H#define INTERNAL_JSONNODE_H#include "JSONDebug.h"#include "JSONChildren.h"#include "JSONMemory.h"#include "JSONGlobals.h"#ifdef JSON_DEBUG#include <climits> //to check int value#endif#include "JSONSharedString.h"#ifdef JSON_LESS_MEMORY#ifdef __GNUC__#pragma pack(push, 1)#elif _MSC_VER#pragma pack(push, internalJSONNode_pack, 1)#endif#endif/*This class is the work horse of libjson, it handles all of thefunctinality of JSONNode. This object is reference counted forspeed and memory reasons.If JSON_REF_COUNT is not on, this internal structure still has an importantpurpose, 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) json_nothrow json_write_priority; void Set(unsigned type) json_nothrow json_write_priority;#define DECL_CAST_OP(type) operator type() const json_nothrow; operator unsigned type() const json_nothrow;#endif#ifdef JSON_MUTEX_CALLBACKS#define initializeMutex(x) ,mylock(x)#else#define initializeMutex(x)#endif#if defined(JSON_PREPARSE) || !defined(JSON_READ_PRIORITY)#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#ifdef JSON_LESS_MEMORY#define CHILDREN _value.Children#define DELETE_CHILDREN()\if (isContainer()){\jsonChildren::deleteChildren(CHILDREN);\}#define CHILDREN_TO_NULL() (void)0#define initializeChildren(x)#else#define CHILDREN Children#define DELETE_CHILDREN()\if (CHILDREN != 0) jsonChildren::deleteChildren(CHILDREN);#define CHILDREN_TO_NULL() CHILDREN = 0#define makeNotContainer() (void)0#define makeContainer() if (!CHILDREN) CHILDREN = jsonChildren::newChildren()#define initializeChildren(x) ,CHILDREN(x)#endifclass internalJSONNode {public:LIBJSON_OBJECT(internalJSONNode)internalJSONNode(char mytype = JSON_NULL) json_nothrow json_hot;#ifdef JSON_READ_PRIORITYinternalJSONNode(const json_string & unparsed) json_nothrow json_hot;internalJSONNode(const json_string & name_t, const json_string & value_t) json_nothrow json_read_priority;#endifinternalJSONNode(const internalJSONNode & orig) json_nothrow json_hot;internalJSONNode & operator = (const internalJSONNode &) json_nothrow json_hot;~internalJSONNode(void) json_nothrow json_hot;static internalJSONNode * newInternal(char mytype = JSON_NULL) json_hot;#ifdef JSON_READ_PRIORITYstatic internalJSONNode * newInternal(const json_string & unparsed) json_hot;static internalJSONNode * newInternal(const json_string & name_t, const json_string & value_t) json_hot;#endifstatic internalJSONNode * newInternal(const internalJSONNode & orig) json_hot; //not copyable, only by this classstatic void deleteInternal(internalJSONNode * ptr) json_nothrow json_hot;json_index_t size(void) const json_nothrow json_read_priority;bool empty(void) const json_nothrow;unsigned char type(void) const json_nothrow json_read_priority;json_string name(void) const json_nothrow json_read_priority;void setname(const json_string & newname) json_nothrow json_write_priority;#ifdef JSON_COMMENTSvoid setcomment(const json_string & comment) json_nothrow;json_string getcomment(void) const json_nothrow;#endif#if !defined(JSON_PREPARSE) && defined(JSON_READ_PRIORITY)void preparse(void) json_nothrow;#endif#ifdef JSON_LIBRARYvoid push_back(JSONNode * node) json_nothrow;#elsevoid push_back(const JSONNode & node) json_nothrow;#endifvoid reserve(json_index_t siz) json_nothrow;void push_front(const JSONNode & node) json_nothrow;JSONNode * pop_back(json_index_t pos) json_nothrow;JSONNode * pop_back(const json_string & name_t) json_nothrow;#ifdef JSON_CASE_INSENSITIVE_FUNCTIONSJSONNode * pop_back_nocase(const json_string & name_t) json_nothrow;#endifJSONNode * at(json_index_t pos) json_nothrow;//These return ** because pop_back needs themJSONNode ** at(const json_string & name_t) json_nothrow;#ifdef JSON_CASE_INSENSITIVE_FUNCTIONSJSONNode ** at_nocase(const json_string & name_t) json_nothrow;#endifvoid Set(const json_string & val) json_nothrow json_write_priority;#ifdef JSON_LIBRARYvoid Set(json_number val) json_nothrow json_write_priority;void Set(json_int_t val) json_nothrow json_write_priority;operator json_int_t() const json_nothrow;operator json_number() const json_nothrow;#elseDECL_SET_INTEGER(char)DECL_SET_INTEGER(short)DECL_SET_INTEGER(int)DECL_SET_INTEGER(long)#ifndef JSON_ISO_STRICTDECL_SET_INTEGER(long long)void Set(long double val) json_nothrow json_write_priority;#endifvoid Set(float val) json_nothrow json_write_priority;void Set(double val) json_nothrow json_write_priority;DECL_CAST_OP(char)DECL_CAST_OP(short)DECL_CAST_OP(int)DECL_CAST_OP(long)#ifndef JSON_ISO_STRICTDECL_CAST_OP(long long)operator long double() const json_nothrow;#endifoperator float() const json_nothrow;operator double() const json_nothrow;#endifoperator json_string()const json_nothrow;operator bool() const json_nothrow;void Set(bool val) json_nothrow;bool IsEqualTo(const json_string & val) const json_nothrow;bool IsEqualTo(bool val) const json_nothrow;bool IsEqualTo(const internalJSONNode * val) const json_nothrow;template<typename T>bool IsEqualToNum(T val) const json_nothrow;internalJSONNode * incRef(void) json_nothrow;#ifdef JSON_REF_COUNTvoid decRef(void) json_nothrow json_hot;bool hasNoReferences(void) json_nothrow json_hot;#endifinternalJSONNode * makeUnique(void) json_nothrow json_hot;JSONNode ** begin(void) const json_nothrow;JSONNode ** end(void) const json_nothrow;bool Fetched(void) const json_nothrow json_hot;#ifdef JSON_MUTEX_CALLBACKSvoid _set_mutex(void * mutex, bool unset = true) json_nothrow json_cold;void _unset_mutex(void) json_nothrow json_cold;#endif#ifdef JSON_WRITE_PRIORITYvoid DumpRawString(json_string & output) const json_nothrow json_write_priority;void WriteName(bool formatted, bool arrayChild, json_string & output) const json_nothrow json_write_priority;#ifdef JSON_ARRAY_SIZE_ON_ONE_LINEvoid WriteChildrenOneLine(unsigned int indent, json_string & output) const json_nothrow json_write_priority;#endifvoid WriteChildren(unsigned int indent, json_string & output) const json_nothrow json_write_priority;void WriteComment(unsigned int indent, json_string & output) const json_nothrow json_write_priority;void Write(unsigned int indent, bool arrayChild, json_string & output) const json_nothrow json_write_priority;#endifinline bool isContainer(void) const json_nothrow {return (_type == JSON_NODE || _type == JSON_ARRAY);}inline bool isNotContainer(void) const json_nothrow {return (_type != JSON_NODE && _type != JSON_ARRAY);}#ifdef JSON_LESS_MEMORYinline void makeNotContainer(void){if (isContainer()){jsonChildren::deleteChildren(CHILDREN);}}inline void makeContainer(void){if (isNotContainer()){CHILDREN = jsonChildren::newChildren();}}#endifvoid Nullify(void) const json_nothrow;#if !defined(JSON_PREPARSE) && defined(JSON_READ_PRIORITY)void SetFetched(bool val) const json_nothrow json_hot;void Fetch(void) const json_nothrow json_hot; //it's const because it doesn't change the VALUE of the function#endif#ifdef JSON_READ_PRIORITYvoid FetchString(void) const json_nothrow json_read_priority;void FetchNode(void) const json_nothrow json_read_priority;void FetchArray(void) const json_nothrow json_read_priority;#endifvoid FetchNumber(void) const json_nothrow json_read_priority;#ifdef JSON_CASE_INSENSITIVE_FUNCTIONSstatic bool AreEqualNoCase(const json_char * ch_one, const json_char * ch_two) json_nothrow json_read_priority;#endifinline void clearname(void) json_nothrow {clearString(_name);}#ifdef JSON_DEBUG#ifndef JSON_LIBRARYJSONNode Dump(size_t & totalmemory) const json_nothrow;JSONNode DumpMutex(void) const json_nothrow;#endif#endifmutable unsigned char _type BITS(3);json_string _name;mutable bool _name_encoded BITS(1);mutable json_string _string; //these are both mutable because the string can change when it's fetchedmutable bool _string_encoded BITS(1);//the value of the jsonunion value_union_t {bool _bool BITS(1);json_number _number;#ifdef JSON_LESS_MEMORYjsonChildren * Children;#endif};mutable value_union_t _value; //internal structure changes depending on type#ifdef JSON_MUTEX_CALLBACKSvoid * mylock;#endif#ifdef JSON_REF_COUNTsize_t refcount PACKED(20);#endif#if !defined(JSON_PREPARSE) && defined(JSON_READ_PRIORITY)mutable bool fetched BITS(1);#endif#ifdef JSON_COMMENTSjson_string _comment;#endif#ifndef JSON_LESS_MEMORYjsonChildren * CHILDREN;#endif};inline internalJSONNode::internalJSONNode(char mytype) json_nothrow : _type(mytype), _name(), _name_encoded(), _string(), _string_encoded(), _value()initializeMutex(0)initializeRefCount(1)initializeFetch(true)initializeComment(json_global(EMPTY_JSON_STRING))initializeChildren((_type == JSON_NODE || _type == JSON_ARRAY) ? jsonChildren::newChildren() : 0){LIBJSON_CTOR;#ifdef JSON_LESS_MEMORY//if not less memory, its in the initialization listif (isContainer()){CHILDREN = jsonChildren::newChildren();}#endif}inline internalJSONNode * internalJSONNode::incRef(void) json_nothrow {#ifdef JSON_REF_COUNT++refcount;return this;#elsereturn makeUnique();#endif}inline json_index_t internalJSONNode::size(void) const json_nothrow {if (isNotContainer()) return 0;Fetch();return CHILDREN -> size();}inline bool internalJSONNode::empty(void) const json_nothrow {if (isNotContainer()) return true;Fetch();return CHILDREN -> empty();}inline unsigned char internalJSONNode::type(void) const json_nothrow {return _type;}inline json_string internalJSONNode::name(void) const json_nothrow {return _name;}inline void internalJSONNode::setname(const json_string & newname) json_nothrow {#ifdef JSON_LESS_MEMORYJSON_ASSERT(newname.capacity() == newname.length(), JSON_TEXT("name object too large"));#endif_name = newname;_name_encoded = true;}#ifdef JSON_COMMENTSinline void internalJSONNode::setcomment(const json_string & comment) json_nothrow {_comment = comment;}inline json_string internalJSONNode::getcomment(void) const json_nothrow {return _comment;}#endifinline bool internalJSONNode::IsEqualTo(const json_string & val) const json_nothrow {if (type() != JSON_STRING) return false;Fetch();return _string == val;}inline bool internalJSONNode::IsEqualTo(bool val) const json_nothrow {if (type() != JSON_BOOL) return false;Fetch();return val == _value._bool;}template<typename T>inline bool internalJSONNode::IsEqualToNum(T val) const json_nothrow {if (type() != JSON_NUMBER) return false;Fetch();return (json_number)val == _value._number;}#ifdef JSON_REF_COUNTinline void internalJSONNode::decRef(void) json_nothrow {JSON_ASSERT(refcount != 0, JSON_TEXT("decRef on a 0 refcount internal"));--refcount;}inline bool internalJSONNode::hasNoReferences(void) json_nothrow {return refcount == 0;}#endifinline internalJSONNode * internalJSONNode::makeUnique(void) json_nothrow {#ifdef JSON_REF_COUNTif (refcount > 1){decRef();return newInternal(*this);}JSON_ASSERT(refcount == 1, JSON_TEXT("makeUnique on a 0 refcount internal"));return this;#elsereturn newInternal(*this);#endif}#if !defined(JSON_PREPARSE) && defined(JSON_READ_PRIORITY)inline void internalJSONNode::SetFetched(bool val) const json_nothrow {fetched = val;}#endifinline bool internalJSONNode::Fetched(void) const json_nothrow {#if !defined(JSON_PREPARSE) && defined(JSON_READ_PRIORITY)return fetched;#elsereturn true;#endif}inline JSONNode ** internalJSONNode::begin(void) const json_nothrow {JSON_ASSERT_SAFE(isContainer(), json_global(ERROR_NON_CONTAINER) + JSON_TEXT("begin"), return 0;);Fetch();return CHILDREN -> begin();}inline JSONNode ** internalJSONNode::end(void) const json_nothrow {JSON_ASSERT_SAFE(isContainer(), json_global(ERROR_NON_CONTAINER) + JSON_TEXT("end"), return 0;);Fetch();return CHILDREN -> end();}inline JSONNode * internalJSONNode::at(json_index_t pos) json_nothrow {JSON_ASSERT_SAFE(isContainer(), JSON_TEXT("calling at on non-container type"), return 0;);Fetch();return (*CHILDREN)[pos];}#if defined(JSON_LESS_MEMORY) && defined(__GNUC__)inline void internalJSONNode::reserve(json_index_t __attribute__((unused)) siz) json_nothrow#elseinline void internalJSONNode::reserve(json_index_t siz) json_nothrow#endif{JSON_ASSERT_SAFE(isContainer(), json_global(ERROR_NON_CONTAINER) + JSON_TEXT("reserve"), return;);Fetch();jsonChildren::reserve2(CHILDREN, siz);}/*cast operators*/#ifndef JSON_LIBRARY#ifdef JSON_ISO_STRICT#define BASE_CONVERT_TYPE long#else#define BASE_CONVERT_TYPE long long#endif#define IMP_SMALLER_INT_CAST_OP(_type, type_max, type_min)\inline internalJSONNode::operator _type() const json_nothrow {\JSON_ASSERT(_value._number > type_min, _string + json_global(ERROR_LOWER_RANGE) + JSON_TEXT(#_type));\JSON_ASSERT(_value._number < type_max, _string + json_global(ERROR_UPPER_RANGE) + JSON_TEXT(#_type));\JSON_ASSERT(_value._number == (json_number)((_type)(_value._number)), json_string(JSON_TEXT("(")) + json_string(JSON_TEXT(#_type)) + json_string(JSON_TEXT(") will truncate ")) + _string);\return (_type)static_cast<BASE_CONVERT_TYPE>(*this);\}IMP_SMALLER_INT_CAST_OP(char, CHAR_MAX, CHAR_MIN)IMP_SMALLER_INT_CAST_OP(unsigned char, UCHAR_MAX, 0)IMP_SMALLER_INT_CAST_OP(short, SHRT_MAX, SHRT_MIN)IMP_SMALLER_INT_CAST_OP(unsigned short, USHRT_MAX, 0)IMP_SMALLER_INT_CAST_OP(int, INT_MAX, INT_MIN)IMP_SMALLER_INT_CAST_OP(unsigned int, UINT_MAX, 0)#ifndef JSON_ISO_STRICTIMP_SMALLER_INT_CAST_OP(long, LONG_MAX, LONG_MIN)IMP_SMALLER_INT_CAST_OP(unsigned long, ULONG_MAX, 0)#endif#endifinline internalJSONNode::operator json_string() const json_nothrow {Fetch();return _string;}#ifndef JSON_LIBRARY#ifndef JSON_ISO_STRICTinline internalJSONNode::operator float() const json_nothrow {return static_cast<float>(static_cast<long double>(*this));}inline internalJSONNode::operator double() const json_nothrow {return static_cast<double>(static_cast<long double>(*this));}#elseinline internalJSONNode::operator float() const json_nothrow {return static_cast<float>(static_cast<double>(*this));}#endif#endif#ifdef JSON_LESS_MEMORY#ifdef __GNUC__#pragma pack(pop)#elif _MSC_VER#pragma pack(pop, internalJSONNode_pack,)#endif#endif#endif