| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504 |
- #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 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) 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)
- #endif
- class internalJSONNode {
- public:
- LIBJSON_OBJECT(internalJSONNode);
- internalJSONNode(char mytype = JSON_NULL) json_nothrow json_hot;
- #ifdef JSON_READ_PRIORITY
- internalJSONNode(const json_string & unparsed) json_nothrow json_hot;
- internalJSONNode(const json_string & name_t, const json_string & value_t) json_nothrow json_read_priority;
- #endif
- internalJSONNode(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_PRIORITY
- static internalJSONNode * newInternal(const json_string & unparsed) json_hot;
- static internalJSONNode * newInternal(const json_string & name_t, const json_string & value_t) json_hot;
- #endif
- static internalJSONNode * newInternal(const internalJSONNode & orig) json_hot; //not copyable, only by this class
- static 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_COMMENTS
- void 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_LIBRARY
- void push_back(JSONNode * node) json_nothrow;
- #else
- void push_back(const JSONNode & node) json_nothrow;
- #endif
- void 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_FUNCTIONS
- JSONNode * pop_back_nocase(const json_string & name_t) json_nothrow;
- #endif
- JSONNode * at(json_index_t pos) json_nothrow;
- //These return ** because pop_back needs them
- JSONNode ** at(const json_string & name_t) json_nothrow;
- #ifdef JSON_CASE_INSENSITIVE_FUNCTIONS
- JSONNode ** at_nocase(const json_string & name_t) json_nothrow;
- #endif
- void Set(const json_string & val) json_nothrow json_write_priority;
- #ifdef JSON_LIBRARY
- void 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;
- #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)
- void Set(long double val) json_nothrow json_write_priority;
- #endif
- void 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_STRICT
- DECL_CAST_OP(long long)
- operator long double() const json_nothrow;
- #endif
- operator float() const json_nothrow;
- operator double() const json_nothrow;
- #endif
- operator 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_COUNT
- void decRef(void) json_nothrow json_hot;
- bool hasNoReferences(void) json_nothrow json_hot;
- #endif
- internalJSONNode * 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_CALLBACKS
- void _set_mutex(void * mutex, bool unset = true) json_nothrow json_cold;
- void _unset_mutex(void) json_nothrow json_cold;
- #endif
- #ifdef JSON_WRITE_PRIORITY
- void 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_LINE
- void WriteChildrenOneLine(unsigned int indent, json_string & output) const json_nothrow json_write_priority;
- #endif
- void 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;
- #endif
- inline 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_MEMORY
- inline void makeNotContainer(void){
- if (isContainer()){
- jsonChildren::deleteChildren(CHILDREN);
- }
- }
- inline void makeContainer(void){
- if (isNotContainer()){
- CHILDREN = jsonChildren::newChildren();
- }
- }
- #endif
- void 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_PRIORITY
- void 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;
- #endif
- void FetchNumber(void) const json_nothrow json_read_priority;
- #ifdef JSON_CASE_INSENSITIVE_FUNCTIONS
- static bool AreEqualNoCase(const json_char * ch_one, const json_char * ch_two) json_nothrow json_read_priority;
- #endif
- inline void clearname(void) json_nothrow {
- clearString(_name);
- }
- #ifdef JSON_DEBUG
- #ifndef JSON_LIBRARY
- JSONNode Dump(size_t & totalmemory) const json_nothrow;
- JSONNode DumpMutex(void) const json_nothrow;
- #endif
- #endif
- mutable unsigned char _type BITS(3);
- json_string _name;
- mutable bool _name_encoded BITS(1); //must be above name due to initialization list order
- 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 BITS(1);
- json_number _number;
- #ifdef JSON_LESS_MEMORY
- jsonChildren * Children;
- #endif
- };
- mutable value_union_t _value; //internal structure changes depending on type
- #ifdef JSON_MUTEX_CALLBACKS
- void * mylock;
- #endif
- #ifdef JSON_REF_COUNT
- size_t refcount PACKED(20);
- #endif
- #if !defined(JSON_PREPARSE) && defined(JSON_READ_PRIORITY)
- mutable bool fetched BITS(1);
- #endif
- #ifdef JSON_COMMENTS
- json_string _comment;
- #endif
- #ifndef JSON_LESS_MEMORY
- jsonChildren * 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 list
- if (isContainer()){
- CHILDREN = jsonChildren::newChildren();
- }
- #endif
- }
- inline internalJSONNode * internalJSONNode::incRef(void) json_nothrow {
- #ifdef JSON_REF_COUNT
- ++refcount;
- return this;
- #else
- return 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_MEMORY
- JSON_ASSERT(newname.capacity() == newname.length(), JSON_TEXT("name object too large"));
- #endif
- _name = newname;
- _name_encoded = true;
- }
- #ifdef JSON_COMMENTS
- inline void internalJSONNode::setcomment(const json_string & comment) json_nothrow {
- _comment = comment;
- }
- inline json_string internalJSONNode::getcomment(void) const json_nothrow {
- return _comment;
- }
- #endif
- inline 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_COUNT
- inline 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;
- }
- #endif
- inline internalJSONNode * internalJSONNode::makeUnique(void) json_nothrow {
- #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
- }
- #if !defined(JSON_PREPARSE) && defined(JSON_READ_PRIORITY)
- inline void internalJSONNode::SetFetched(bool val) const json_nothrow {
- fetched = val;
- }
- #endif
- inline bool internalJSONNode::Fetched(void) const json_nothrow {
- #if !defined(JSON_PREPARSE) && defined(JSON_READ_PRIORITY)
- return fetched;
- #else
- return 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
- #else
- inline 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_STRICT
- IMP_SMALLER_INT_CAST_OP(long, LONG_MAX, LONG_MIN)
- IMP_SMALLER_INT_CAST_OP(unsigned long, ULONG_MAX, 0)
- #endif
- #endif
- inline internalJSONNode::operator json_string() const json_nothrow {
- Fetch();
- return _string;
- }
- #ifndef JSON_LIBRARY
- #ifndef JSON_ISO_STRICT
- inline 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));
- }
- #else
- inline 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
|