summaryrefslogtreecommitdiff
path: root/src/modules/json/JSONNode.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/modules/json/JSONNode.h')
-rw-r--r--src/modules/json/JSONNode.h923
1 files changed, 923 insertions, 0 deletions
diff --git a/src/modules/json/JSONNode.h b/src/modules/json/JSONNode.h
new file mode 100644
index 0000000000..36ebcd6145
--- /dev/null
+++ b/src/modules/json/JSONNode.h
@@ -0,0 +1,923 @@
+#ifndef JSONNODE_H
+#define JSONNODE_H
+
+#include "JSONDefs.h" //for string type
+#include "internalJSONNode.h" //internal structure for json value
+#include <stdexcept>
+#include <cstdarg> //for the ... parameter
+
+#ifdef JSON_BINARY
+ #include "JSON_Base64.h"
+#endif
+
+#ifndef JSON_REF_COUNT
+ #define makeUniqueInternal() (void)0
+#endif
+
+#define JSON_CHECK_INTERNAL() JSON_ASSERT(internal, JSON_TEXT("no internal"))
+
+#ifdef JSON_MUTEX_CALLBACKS
+ #define JSON_MUTEX_COPY_DECL ,void * parentMutex
+ #define JSON_MUTEX_COPY_DECL2 ,void * parentMutex = 0
+#else
+ #define JSON_MUTEX_COPY_DECL
+ #define JSON_MUTEX_COPY_DECL2
+#endif
+
+#ifdef JSON_LIBRARY
+ #define JSON_PTR_LIB *
+ #define JSON_NEW(x) JSONNode::newJSONNode_Shallow(x)
+ #define DECLARE_FOR_ALL_TYPES(foo)\
+ foo(long);\
+ foo(json_number);\
+ foo(bool);\
+ foo(const json_string &);
+
+ #define DECLARE_FOR_ALL_TYPES_CONST(foo)\
+ foo(long) const;\
+ foo(json_number) const;\
+ foo(bool) const;\
+ foo(const json_string &) const;\
+ foo(const JSONNode &) const;
+
+ #define IMPLEMENT_FOR_ALL_NUMBERS(foo)\
+ foo(long)\
+ foo(json_number)
+
+
+#else
+ #define JSON_PTR_LIB
+ #define JSON_NEW(x) x
+ #define DECLARE_FOR_ALL_TYPES(foo)\
+ foo(char); foo(unsigned char);\
+ foo(short); foo(unsigned short);\
+ foo(int); foo(unsigned int);\
+ foo(long); foo(unsigned long);\
+ foo(float); foo(double);\
+ foo(bool);\
+ foo(const json_string &);\
+ foo(const json_char *);
+
+ #define DECLARE_FOR_ALL_TYPES_CONST(foo)\
+ foo(char) const; foo(unsigned char) const;\
+ foo(short) const; foo(unsigned short) const;\
+ foo(int) const; foo(unsigned int) const;\
+ foo(long) const; foo(unsigned long) const;\
+ foo(float) const; foo(double) const;\
+ foo(bool) const;\
+ foo(const json_string &) const;\
+ foo(const JSONNode &) const;\
+ foo(const json_char *) const;
+
+ #define IMPLEMENT_FOR_ALL_NUMBERS(foo)\
+ foo(char) foo(unsigned char)\
+ foo(short) foo(unsigned short)\
+ foo(int) foo(unsigned int)\
+ foo(long) foo(unsigned long)\
+ foo(float) foo(double)
+
+#endif
+
+#define IMPLEMENT_FOR_ALL_TYPES(foo)\
+ IMPLEMENT_FOR_ALL_NUMBERS(foo)\
+ foo(const json_string &)\
+ foo(bool)
+
+/*
+ This class is mostly just a wrapper class around internalJSONNode, this class keeps
+ the reference count and handles copy on write and such. This class is also responsible
+ for argument checking and throwing exceptions if needed.
+*/
+
+
+class JSONNode {
+public:
+ explicit JSONNode(char mytype = JSON_NODE);
+ #define DECLARE_CTOR(type) JSONNode(const json_string & name_t, type value_t)
+ DECLARE_FOR_ALL_TYPES(DECLARE_CTOR)
+
+ JSONNode(const JSONNode & orig);
+ ~JSONNode(void);
+
+ json_index_t size(void) const;
+ bool empty(void) const;
+ void clear(void);
+ unsigned char type(void) const;
+
+ json_string name(void) const;
+ void set_name(const json_string & newname);
+ #ifdef JSON_COMMENTS
+ void set_comment(const json_string & comment);
+ json_string get_comment(void) const;
+ #endif
+ #ifndef JSON_PREPARSE
+ void preparse(void);
+ #endif
+ #ifdef JSON_VALIDATE
+ #ifndef JSON_SAFE
+ #error JSON_VALIDATE also requires JSON_SAFE
+ #endif
+ bool validate(void);
+ #endif
+
+ json_string as_string(void) const;
+ long as_int(void) const;
+ json_number as_float(void) const;
+ bool as_bool(void) const;
+ JSONNode as_node(void) const;
+ JSONNode as_array(void) const;
+
+ #ifdef JSON_BINARY
+ std::string as_binary(void) const;
+ void set_binary(const unsigned char * bin, json_index_t bytes);
+ #endif
+
+ JSONNode & at(json_index_t pos);
+ const JSONNode & at(json_index_t pos) const;
+ JSONNode & operator[](json_index_t pos);
+ const JSONNode & operator[](json_index_t pos) const;
+
+ JSONNode & at(const json_string & name_t);
+ const JSONNode & at(const json_string & name_t) const;
+ #ifdef JSON_CASE_INSENSITIVE_FUNCTIONS
+ JSONNode & at_nocase(const json_string & name_t);
+ const JSONNode & at_nocase(const json_string & name_t) const;
+ #endif
+ JSONNode & operator[](const json_string & name_t);
+ const JSONNode & operator[](const json_string & name_t) const;
+
+ #ifdef JSON_LIBRARY
+ void push_back(JSONNode * node);
+ #else
+ void push_back(const JSONNode & node);
+ #endif
+ void reserve(json_index_t size);
+ JSONNode JSON_PTR_LIB pop_back(json_index_t pos);
+ JSONNode JSON_PTR_LIB pop_back(const json_string & name_t);
+ #ifdef JSON_CASE_INSENSITIVE_FUNCTIONS
+ JSONNode JSON_PTR_LIB pop_back_nocase(const json_string & name_t);
+ #endif
+
+ DECLARE_FOR_ALL_TYPES(JSONNode & operator =)
+ JSONNode & operator = (const JSONNode &);
+
+ DECLARE_FOR_ALL_TYPES_CONST(bool operator ==)
+ DECLARE_FOR_ALL_TYPES_CONST(bool operator !=)
+
+
+ void nullify(void);
+ void swap(JSONNode & other);
+ void merge(JSONNode & other);
+ void merge(unsigned int num, ...);
+ JSONNode duplicate(void) const;
+ void cast(char newtype);
+
+
+ //iterator
+ #ifdef JSON_ITERATORS
+ #ifndef JSON_LIBRARY
+ #define json_iterator_ptr(iter) iter.it
+ #define ptr_to_json_iterator(iter) json_iterator(iter)
+ struct iterator {
+ inline iterator& operator ++(void){ ++it; return *this; }
+ inline iterator& operator --(void){ --it; return *this; }
+ inline iterator& operator +=(long i){ it += i; return *this; }
+ inline iterator& operator -=(long i){ it -= i; return *this; }
+ inline iterator operator ++(int){
+ iterator result(*this);
+ ++it;
+ return result;
+ }
+ inline iterator operator --(int){
+ iterator result(*this);
+ --it;
+ return result;
+ }
+ inline iterator operator +(long i) const {
+ iterator result(*this);
+ result.it += i;
+ return result;
+ }
+ inline iterator operator -(long i) const {
+ iterator result(*this);
+ result.it -= i;
+ return result;
+ }
+ inline JSONNode& operator [](size_t pos) const { return *it[pos]; };
+ inline JSONNode& operator *(void) const { return *(*it); }
+ inline bool operator == (const iterator & other) const { return it == other.it; }
+ inline bool operator != (const iterator & other) const { return it != other.it; }
+ inline bool operator > (const iterator & other) const { return it > other.it; }
+ inline bool operator >= (const iterator & other) const { return it >= other.it; }
+ inline bool operator < (const iterator & other) const { return it < other.it; }
+ inline bool operator <= (const iterator & other) const { return it <= other.it; }
+ inline iterator & operator = (const iterator & orig){ it = orig.it; return *this; }
+ iterator (const iterator & orig) : it(orig.it) {}
+ private:
+ JSONNode ** it;
+ iterator(JSONNode ** starter) : it(starter) {}
+ friend class JSONNode;
+ };
+ typedef iterator json_iterator;
+
+ struct const_iterator {
+ inline const_iterator& operator ++(void){ ++it; return *this; }
+ inline const_iterator& operator --(void){ --it; return *this; }
+ inline const_iterator& operator +=(long i){ it += i; return *this; }
+ inline const_iterator& operator -=(long i){ it -= i; return *this; }
+ inline const_iterator operator ++(int){
+ const_iterator result(*this);
+ ++it;
+ return result;
+ }
+ inline const_iterator operator --(int){
+ const_iterator result(*this);
+ --it;
+ return result;
+ }
+ inline const_iterator operator +(long i) const {
+ const_iterator result(*this);
+ result.it += i;
+ return result;
+ }
+ inline const_iterator operator -(long i) const {
+ const_iterator result(*this);
+ result.it -= i;
+ return result;
+ }
+ inline const JSONNode& operator [](size_t pos) const { return const_cast<const JSONNode&>(*it[pos]); };
+ inline const JSONNode& operator *(void) const { return const_cast<const JSONNode&>(*(*it)); }
+ inline bool operator == (const const_iterator & other) const { return it == other.it; }
+ inline bool operator != (const const_iterator & other) const { return it != other.it; }
+ inline bool operator > (const const_iterator & other) const { return it > other.it; }
+ inline bool operator >= (const const_iterator & other) const { return it >= other.it; }
+ inline bool operator < (const const_iterator & other) const { return it < other.it; }
+ inline bool operator <= (const const_iterator & other) const { return it <= other.it; }
+ inline const_iterator & operator =(const const_iterator & orig){ it = orig.it; return *this; }
+ const_iterator (const const_iterator & orig) : it(orig.it) {}
+ private:
+ JSONNode ** it;
+ const_iterator(JSONNode ** starter) : it(starter) {}
+ friend class JSONNode;
+ };
+ const_iterator begin(void) const;
+ const_iterator end(void) const;
+
+ struct reverse_iterator {
+ inline reverse_iterator& operator ++(void){ --it; return *this; }
+ inline reverse_iterator& operator --(void){ ++it; return *this; }
+ inline reverse_iterator& operator +=(long i){ it -= i; return *this; }
+ inline reverse_iterator& operator -=(long i){ it += i; return *this; }
+ inline reverse_iterator operator ++(int){
+ reverse_iterator result(*this);
+ --it;
+ return result;
+ }
+ inline reverse_iterator operator --(int){
+ reverse_iterator result(*this);
+ ++it;
+ return result;
+ }
+ inline reverse_iterator operator +(long i) const {
+ reverse_iterator result(*this);
+ result.it -= i;
+ return result;
+ }
+ inline reverse_iterator operator -(long i) const {
+ reverse_iterator result(*this);
+ result.it += i;
+ return result;
+ }
+ inline JSONNode& operator [](size_t pos) const { return *it[pos]; };
+ inline JSONNode& operator *(void) const { return *(*it); }
+ inline bool operator == (const reverse_iterator & other) const { return it == other.it; }
+ inline bool operator != (const reverse_iterator & other) const { return it != other.it; }
+ inline bool operator < (const reverse_iterator & other) const { return it > other.it; }
+ inline bool operator <= (const reverse_iterator & other) const { return it >= other.it; }
+ inline bool operator > (const reverse_iterator & other) const { return it < other.it; }
+ inline bool operator >= (const reverse_iterator & other) const { return it <= other.it; }
+ inline reverse_iterator & operator = (const reverse_iterator & orig){ it = orig.it; return *this; }
+ reverse_iterator (const reverse_iterator & orig) : it(orig.it) {}
+ private:
+ JSONNode ** it;
+ reverse_iterator(JSONNode ** starter) : it(starter) {}
+ friend class JSONNode;
+ };
+ reverse_iterator rbegin(void);
+ reverse_iterator rend(void);
+
+ struct reverse_const_iterator {
+ inline reverse_const_iterator& operator ++(void){ --it; return *this; }
+ inline reverse_const_iterator& operator --(void){ ++it; return *this; }
+ inline reverse_const_iterator& operator +=(long i){ it -= i; return *this; }
+ inline reverse_const_iterator& operator -=(long i){ it += i; return *this; }
+ inline reverse_const_iterator operator ++(int){
+ reverse_const_iterator result(*this);
+ --it;
+ return result;
+ }
+ inline reverse_const_iterator operator --(int){
+ reverse_const_iterator result(*this);
+ ++it;
+ return result;
+ }
+ inline reverse_const_iterator operator +(long i) const {
+ reverse_const_iterator result(*this);
+ result.it -= i;
+ return result;
+ }
+ inline reverse_const_iterator operator -(long i) const {
+ reverse_const_iterator result(*this);
+ result.it += i;
+ return result;
+ }
+ inline const JSONNode& operator [](size_t pos) const { return const_cast<const JSONNode&>(*it[pos]); };
+ inline const JSONNode& operator *(void) const { return const_cast<const JSONNode&>(*(*it)); }
+ inline bool operator == (const reverse_const_iterator & other) const { return it == other.it; }
+ inline bool operator != (const reverse_const_iterator & other) const { return it != other.it; }
+ inline bool operator < (const reverse_const_iterator & other) const { return it > other.it; }
+ inline bool operator <= (const reverse_const_iterator & other) const { return it >= other.it; }
+ inline bool operator > (const reverse_const_iterator & other) const { return it < other.it; }
+ inline bool operator >= (const reverse_const_iterator & other) const { return it <= other.it; }
+ inline reverse_const_iterator & operator = (const reverse_const_iterator & orig){ it = orig.it; return *this; }
+ reverse_const_iterator (const reverse_const_iterator & orig) : it(orig.it) {}
+ private:
+ JSONNode ** it;
+ reverse_const_iterator(JSONNode ** starter) : it(starter) {}
+ friend class JSONNode;
+ };
+ reverse_const_iterator rbegin(void) const;
+ reverse_const_iterator rend(void) const;
+
+ const_iterator find(const json_string & name_t) const;
+ #ifdef JSON_CASE_INSENSITIVE_FUNCTIONS
+ const_iterator find_nocase(const json_string & name_t) const;
+ #endif
+
+ reverse_iterator erase(reverse_iterator pos);
+ reverse_iterator erase(reverse_iterator start, const reverse_iterator & end);
+
+ iterator insert(iterator pos, const JSONNode & x);
+ reverse_iterator insert(reverse_iterator pos, const JSONNode & x);
+ iterator insert(iterator pos, const reverse_iterator & _start, const reverse_iterator & _end);
+ reverse_iterator insert(reverse_iterator pos, const iterator & _start, const iterator & _end);
+ reverse_iterator insert(reverse_iterator pos, const reverse_iterator & _start, const reverse_iterator & _end);
+
+ json_iterator insert(json_iterator pos, const const_iterator & _start, const const_iterator & _end);
+ reverse_iterator insert(reverse_iterator pos, const const_iterator & _start, const const_iterator & _end);
+ json_iterator insert(json_iterator pos, const reverse_const_iterator & _start, const reverse_const_iterator & _end);
+ reverse_iterator insert(reverse_iterator pos, const reverse_const_iterator & _start, const reverse_const_iterator & _end);
+ #else
+ typedef JSONNode** json_iterator;
+ #define json_iterator_ptr(iter) iter
+ #define ptr_to_json_iterator(iter) iter
+ json_iterator insert(json_iterator pos, JSONNode * x);
+ #endif
+
+ json_iterator begin(void);
+ json_iterator end(void);
+
+ json_iterator find(const json_string & name_t);
+ #ifdef JSON_CASE_INSENSITIVE_FUNCTIONS
+ json_iterator find_nocase(const json_string & name_t);
+ #endif
+ json_iterator erase(json_iterator pos);
+ json_iterator erase(json_iterator start, const json_iterator & end);
+ json_iterator insert(json_iterator pos, const json_iterator & _start, const json_iterator & _end);
+ #endif
+
+
+ #ifdef JSON_MUTEX_CALLBACKS
+ static void register_mutex_callbacks(json_mutex_callback_t lock, json_mutex_callback_t unlock, void * manager_lock);
+ #ifdef JSON_MUTEX_MANAGE
+ static void register_mutex_destructor(json_mutex_callback_t destroy);
+ #endif
+ static void set_global_mutex(void * mutex);
+ void set_mutex(void * mutex);
+ void lock(int thread);
+ void unlock(int thread);
+ struct auto_lock {
+ public:
+ auto_lock(JSONNode & node, int thread) : mynode(&node), mythread(thread){
+ mynode -> lock(mythread);
+ }
+ auto_lock(JSONNode * node, int thread) : mynode(node), mythread(thread){
+ mynode -> lock(mythread);
+ }
+ ~auto_lock(void){
+ mynode -> unlock(mythread);
+ }
+ private:
+ auto_lock & operator = (const auto_lock &);
+ auto_lock(const auto_lock &);
+ JSONNode * mynode;
+ int mythread;
+ };
+ static void * getThisLock(JSONNode * pthis);
+ #endif
+
+ #ifdef JSON_UNIT_TEST
+ static int getNodeAllocationCount(void);
+ static int getNodeDeallocationCount(void);
+ static int getInternalAllocationCount(void);
+ static int getInternalDeallocationCount(void);
+ static void incAllocCount(void);
+ static void decAllocCount(void);
+ static void incinternalAllocCount(void);
+ static void decinternalAllocCount(void);
+ #endif
+
+ #ifdef JSON_WRITER
+ json_string write(void);
+ json_string write_formatted(void);
+ #endif
+
+ #ifdef JSON_DEBUG
+ #ifndef JSON_LIBRARY
+ JSONNode dump(void) const;
+ #endif
+ #endif
+ static void deleteJSONNode(JSONNode * ptr);
+ static JSONNode * newJSONNode_Shallow(const JSONNode & orig);
+JSON_PRIVATE
+ static JSONNode * newJSONNode(const JSONNode & orig JSON_MUTEX_COPY_DECL2);
+ static JSONNode * newJSONNode(internalJSONNode * internal_t);
+ //used by JSONWorker
+ JSONNode(const json_string & unparsed) : internal(internalJSONNode::newInternal(unparsed)) { //root, specialized because it can only be array or node
+ incAllocCount();
+ }
+ JSONNode(internalJSONNode * internal_t) : internal(internal_t){ //do not increment anything, this is only used in one case and it's already taken care of
+ incAllocCount();
+ }
+ JSONNode(bool, JSONNode & orig);
+
+ void decRef(void); //decrements internal's counter, deletes it if needed
+ #ifdef JSON_REF_COUNT
+ void makeUniqueInternal(void); //makes internal it's own
+ void merge(JSONNode * other);
+ #endif
+
+ #ifdef JSON_DEBUG
+ #ifndef JSON_LIBRARY
+ JSONNode dump(size_t & totalmemory);
+ #endif
+ #endif
+
+ #ifdef JSON_ITERATORS
+ #ifndef JSON_LIBRARY
+ json_iterator insertFRR(json_iterator pos, JSONNode ** const _start, JSONNode ** const _end);
+ reverse_iterator insertRRR(reverse_iterator pos, JSONNode ** const _start, JSONNode ** const _end);
+ reverse_iterator insertRFF(reverse_iterator pos, JSONNode ** const _start, JSONNode ** const _end);
+ #endif
+ json_iterator insertFFF(json_iterator pos, JSONNode ** const _start, JSONNode ** const _end);
+ #endif
+
+ mutable internalJSONNode * internal;
+ friend class JSONWorker;
+ friend class internalJSONNode;
+};
+
+
+
+/*
+ Implementations are here to keep the class declaration cleaner. They can't be placed in a different
+ file because they are inlined.
+*/
+
+inline JSONNode::JSONNode(char mytype) : internal(internalJSONNode::newInternal(mytype)) {
+ JSON_ASSERT((mytype == JSON_NULL) ||
+ (mytype == JSON_STRING) ||
+ (mytype == JSON_NUMBER) ||
+ (mytype == JSON_BOOL) ||
+ (mytype == JSON_ARRAY) ||
+ (mytype == JSON_NODE), JSON_TEXT("Not a proper JSON type"));
+ incAllocCount();
+}
+
+inline JSONNode::JSONNode(const JSONNode & orig): internal(orig.internal -> incRef()) {
+ incAllocCount();
+}
+
+//this allows a temp node to simply transfer its contents, even with ref counting off
+inline JSONNode::JSONNode(bool, JSONNode & orig): internal(orig.internal){
+ orig.internal = 0;
+ incAllocCount();
+}
+
+inline JSONNode::~JSONNode(void){
+ if (internal) decRef();
+ decAllocCount();
+}
+
+inline json_index_t JSONNode::size(void) const {
+ JSON_CHECK_INTERNAL();
+ return internal -> size();
+}
+
+inline bool JSONNode::empty(void) const {
+ JSON_CHECK_INTERNAL();
+ return internal -> empty();
+}
+
+inline void JSONNode::clear(void){
+ JSON_CHECK_INTERNAL();
+ if (!empty()) {
+ makeUniqueInternal();
+ internal -> Children.clear();
+ }
+}
+
+inline unsigned char JSONNode::type(void) const {
+ JSON_CHECK_INTERNAL();
+ return internal -> type();
+}
+
+inline json_string JSONNode::name(void) const {
+ JSON_CHECK_INTERNAL();
+ return internal -> name();
+}
+
+inline void JSONNode::set_name(const json_string & newname){
+ JSON_CHECK_INTERNAL();
+ makeUniqueInternal();
+ internal -> setname(newname);
+}
+
+#ifdef JSON_COMMENTS
+ inline void JSONNode::set_comment(const json_string & newname){
+ JSON_CHECK_INTERNAL();
+ makeUniqueInternal();
+ internal -> setcomment(newname);
+ }
+
+ inline json_string JSONNode::get_comment(void) const {
+ JSON_CHECK_INTERNAL();
+ return internal -> getcomment();
+ }
+#endif
+
+inline json_string JSONNode::as_string(void) const {
+ JSON_CHECK_INTERNAL();
+ return internal -> as_string();
+}
+
+inline long JSONNode::as_int(void) const {
+ JSON_CHECK_INTERNAL();
+ return internal -> as_int();
+}
+
+inline json_number JSONNode::as_float(void) const {
+ JSON_CHECK_INTERNAL();
+ return internal -> as_float();
+}
+
+inline bool JSONNode::as_bool(void) const {
+ JSON_CHECK_INTERNAL();
+ return internal -> as_bool();
+}
+
+#ifdef JSON_BINARY
+ inline void JSONNode::set_binary(const unsigned char * bin, json_index_t bytes){
+ JSON_CHECK_INTERNAL();
+ *this = JSONBase64::json_encode64(bin, bytes);
+ }
+
+ inline std::string JSONNode::as_binary(void) const {
+ JSON_ASSERT_SAFE(type() == JSON_STRING, JSON_TEXT("using as_binary for a non-string type"), return EMPTY_STRING2;);
+ JSON_CHECK_INTERNAL();
+ return JSONBase64::json_decode64(as_string());
+ }
+#endif
+
+inline JSONNode & JSONNode::operator[](const json_string & name_t){
+ JSON_CHECK_INTERNAL();
+ makeUniqueInternal();
+ return *(*(internal -> at(name_t)));
+}
+
+inline const JSONNode & JSONNode::operator[](const json_string & name_t) const {
+ JSON_CHECK_INTERNAL();
+ return *(*(internal -> at(name_t)));
+}
+
+#ifdef JSON_LIBRARY
+inline void JSONNode::push_back(JSONNode * child){
+#else
+inline void JSONNode::push_back(const JSONNode & child){
+#endif
+ JSON_CHECK_INTERNAL();
+ makeUniqueInternal();
+ internal -> push_back(child);
+}
+
+inline void JSONNode::reserve(json_index_t size){
+ makeUniqueInternal();
+ internal -> reserve(size);
+}
+
+inline JSONNode & JSONNode::operator = (const JSONNode & orig){
+ JSON_CHECK_INTERNAL();
+ #ifdef JSON_REF_COUNT
+ if (internal == orig.internal) return *this; //don't want it accidentally deleting itself
+ #endif
+ decRef(); //dereference my current one
+ internal = orig.internal -> incRef(); //increase reference of original
+ return *this;
+}
+
+#ifndef JSON_LIBRARY
+ inline JSONNode & JSONNode::operator = (const json_char * val){
+ JSON_CHECK_INTERNAL();
+ *this = json_string(val);
+ return *this;
+ }
+#endif
+
+#define NODE_SET_TYPED(type)\
+ inline JSONNode & JSONNode::operator = (type val){\
+ JSON_CHECK_INTERNAL();\
+ makeUniqueInternal();\
+ internal -> Set(val);\
+ return *this;\
+ }
+
+IMPLEMENT_FOR_ALL_TYPES(NODE_SET_TYPED)
+
+
+/*
+ This section is the equality operators
+*/
+
+#define NODE_CHECK_EQUALITY(type)\
+ inline bool JSONNode::operator == (type val) const {\
+ JSON_CHECK_INTERNAL();\
+ return internal -> IsEqualToNum<type>(val);\
+ }
+
+IMPLEMENT_FOR_ALL_NUMBERS(NODE_CHECK_EQUALITY)
+
+inline bool JSONNode::operator == (const json_string & val) const {
+ JSON_CHECK_INTERNAL();
+ return internal -> IsEqualTo(val);
+}
+
+#ifndef JSON_LIBRARY
+ inline bool JSONNode::operator == (const json_char * val) const {
+ JSON_CHECK_INTERNAL();
+ return *this == json_string(val);
+ }
+#endif
+
+inline bool JSONNode::operator == (bool val) const {
+ JSON_CHECK_INTERNAL();
+ return internal -> IsEqualTo(val);
+}
+inline bool JSONNode::operator == (const JSONNode & val) const {
+ JSON_CHECK_INTERNAL();
+ return internal -> IsEqualTo(val.internal);
+}
+
+
+/*
+ This section is the inequality operators
+*/
+
+
+#define NODE_CHECK_INEQUALITY(type)\
+ inline bool JSONNode::operator != (type val) const {\
+ JSON_CHECK_INTERNAL();\
+ return !(*this == val);\
+ }
+
+IMPLEMENT_FOR_ALL_TYPES(NODE_CHECK_INEQUALITY)
+NODE_CHECK_INEQUALITY(const JSONNode &)
+#ifndef JSON_LIBRARY
+ NODE_CHECK_INEQUALITY(const json_char * )
+#endif
+
+inline void JSONNode::nullify(void){
+ JSON_CHECK_INTERNAL();
+ makeUniqueInternal();
+ internal -> Nullify();
+}
+
+inline void JSONNode::swap(JSONNode & other){
+ JSON_CHECK_INTERNAL();
+ internalJSONNode * temp = other.internal;
+ other.internal = internal;
+ internal = temp;
+ JSON_CHECK_INTERNAL();
+}
+
+inline void JSONNode::decRef(void){ //decrements internal's counter, deletes it if needed
+ JSON_CHECK_INTERNAL();
+ #ifdef JSON_REF_COUNT
+ internal -> decRef();
+ if (internal -> hasNoReferences()) {
+ internalJSONNode::deleteInternal(internal);
+ }
+ #else
+ internalJSONNode::deleteInternal(internal);
+ #endif
+}
+
+#ifdef JSON_REF_COUNT
+ inline void JSONNode::makeUniqueInternal() { //makes internal it's own
+ JSON_CHECK_INTERNAL();
+ internal = internal -> makeUnique(); //might return itself or a new one that's exactly the same
+ }
+#endif
+
+#ifdef JSON_ITERATORS
+ inline JSONNode::json_iterator JSONNode::begin(void){
+ JSON_CHECK_INTERNAL();
+ JSON_ASSERT(type() == JSON_NODE || type() == JSON_ARRAY, JSON_TEXT("iterating a non-iteratable node"));
+ makeUniqueInternal();
+ return json_iterator(internal -> begin());
+ }
+
+ inline JSONNode::json_iterator JSONNode::end(void){
+ JSON_CHECK_INTERNAL();
+ JSON_ASSERT(type() == JSON_NODE || type() == JSON_ARRAY, JSON_TEXT("iterating a non-iteratable node"));
+ makeUniqueInternal();
+ return json_iterator(internal -> end());
+ }
+
+ #ifndef JSON_LIBRARY
+ inline JSONNode::const_iterator JSONNode::begin(void) const {
+ JSON_CHECK_INTERNAL();
+ JSON_ASSERT(type() == JSON_NODE || type() == JSON_ARRAY, JSON_TEXT("iterating a non-iteratable node"));
+ return JSONNode::const_iterator(internal -> begin());
+ }
+
+ inline JSONNode::const_iterator JSONNode::end(void) const {
+ JSON_CHECK_INTERNAL();
+ JSON_ASSERT(type() == JSON_NODE || type() == JSON_ARRAY, JSON_TEXT("iterating a non-iteratable node"));
+ return JSONNode::const_iterator(internal -> end());
+ }
+
+ inline JSONNode::reverse_iterator JSONNode::rbegin(void){
+ JSON_CHECK_INTERNAL();
+ JSON_ASSERT(type() == JSON_NODE || type() == JSON_ARRAY, JSON_TEXT("iterating a non-iteratable node"));
+ makeUniqueInternal();
+ return JSONNode::reverse_iterator(internal -> end() - 1);
+ }
+
+ inline JSONNode::reverse_iterator JSONNode::rend(void){
+ JSON_CHECK_INTERNAL();
+ JSON_ASSERT(type() == JSON_NODE || type() == JSON_ARRAY, JSON_TEXT("iterating a non-iteratable node"));
+ makeUniqueInternal();
+ return JSONNode::reverse_iterator(internal -> begin() - 1);
+ }
+
+ inline JSONNode::reverse_const_iterator JSONNode::rbegin(void) const {
+ JSON_CHECK_INTERNAL();
+ JSON_ASSERT(type() == JSON_NODE || type() == JSON_ARRAY, JSON_TEXT("iterating a non-iteratable node"));
+ return JSONNode::reverse_const_iterator(internal -> end() - 1);
+ }
+
+ inline JSONNode::reverse_const_iterator JSONNode::rend(void) const {
+ JSON_CHECK_INTERNAL();
+ JSON_ASSERT(type() == JSON_NODE || type() == JSON_ARRAY, JSON_TEXT("iterating a non-iteratable node"));
+ return JSONNode::reverse_const_iterator(internal -> begin() - 1);
+ }
+
+ inline JSONNode::iterator JSONNode::insert(json_iterator pos, const const_iterator & _start, const const_iterator & _end){
+ return insertFFF(pos, _start.it, _end.it);
+ }
+
+ inline JSONNode::reverse_iterator JSONNode::insert(reverse_iterator pos, const const_iterator & _start, const const_iterator & _end){
+ return insertRFF(pos, _start.it, _end.it);
+ }
+
+ inline JSONNode::reverse_iterator JSONNode::insert(reverse_iterator pos, const iterator & _start, const iterator & _end){
+ return insertRFF(pos, _start.it, _end.it);
+ }
+
+ inline JSONNode::reverse_iterator JSONNode::insert(reverse_iterator pos, const reverse_const_iterator & _start, const reverse_const_iterator & _end){
+ return insertRRR(pos, _start.it, _end.it);
+ }
+
+ inline JSONNode::reverse_iterator JSONNode::insert(reverse_iterator pos, const reverse_iterator & _start, const reverse_iterator & _end){
+ return insertRRR(pos, _start.it, _end.it);
+ }
+
+ inline JSONNode::iterator JSONNode::insert(json_iterator pos, const reverse_const_iterator & _start, const reverse_const_iterator & _end){
+ return insertFRR(pos, _start.it, _end.it);
+ }
+
+ inline JSONNode::iterator JSONNode::insert(iterator pos, const reverse_iterator & _start, const reverse_iterator & _end){
+ return insertFRR(pos, _start.it, _end.it);
+ }
+ #endif
+
+ inline JSONNode::json_iterator JSONNode::insert(json_iterator pos, const json_iterator & _start, const json_iterator & _end){
+ return insertFFF(pos, json_iterator_ptr(_start), json_iterator_ptr(_end));
+ }
+#endif
+
+#ifdef JSON_WRITER
+ inline json_string JSONNode::write(void){
+ JSON_CHECK_INTERNAL();
+ JSON_ASSERT_SAFE(type() == JSON_NODE || type() == JSON_ARRAY, JSON_TEXT("Writing a non-writable node"), return JSON_TEXT(""););
+ return internal -> Write(0xFFFFFFFF, true);
+ }
+
+ inline json_string JSONNode::write_formatted(void){
+ JSON_CHECK_INTERNAL();
+ JSON_ASSERT_SAFE(type() == JSON_NODE || type() == JSON_ARRAY, JSON_TEXT("Writing a non-writable node"), return JSON_TEXT(""););
+ return internal -> Write(0, true);
+ }
+
+#endif
+
+#ifndef JSON_PREPARSE
+ inline void JSONNode::preparse(void){
+ JSON_CHECK_INTERNAL();
+ internal -> preparse();
+ }
+#endif
+
+#ifdef JSON_VALIDATE
+ inline bool JSONNode::validate(void){
+ JSON_CHECK_INTERNAL();
+ if (type() == JSON_NULL) return false;
+ JSON_ASSERT_SAFE(type() == JSON_NODE || type() == JSON_ARRAY, JSON_TEXT("Validating non root node"), return false;);
+ #ifndef JSON_PREPARSE
+ internal -> Fetch(); //will nullify it if it's bad
+ #endif
+ if (type() == JSON_NULL) return false;
+ return internal -> validate();
+ }
+#endif
+
+#ifdef JSON_DEBUG
+ #ifndef JSON_LIBRARY
+ inline JSONNode JSONNode::dump(void) const {
+ JSON_CHECK_INTERNAL();
+ JSONNode dumpage(JSON_NODE);
+ dumpage.push_back(JSON_NEW(JSONNode(JSON_TEXT("this"), (long)this)));
+ size_t total = 0;
+ JSONNode node = internal -> Dump(total);
+ dumpage.push_back(JSON_NEW(JSONNode(JSON_TEXT("total bytes used"), total)));
+ dumpage.push_back(JSON_NEW(JSONNode(JSON_TEXT("bytes used"), sizeof(JSONNode))));
+ dumpage.push_back(JSON_NEW(node));
+ return dumpage;
+ }
+
+ inline JSONNode JSONNode::dump(size_t & totalmemory){
+ JSON_CHECK_INTERNAL();
+ JSONNode dumpage(JSON_NODE);
+ dumpage.push_back(JSON_NEW(JSONNode(JSON_TEXT("this"), (long)this)));
+ dumpage.push_back(JSON_NEW(JSONNode(JSON_TEXT("bytes used"), sizeof(JSONNode))));
+ dumpage.push_back(JSON_NEW(internal -> Dump(totalmemory)));
+ return dumpage;
+ }
+ #endif
+#endif
+
+
+inline void JSONNode::deleteJSONNode(JSONNode * ptr){
+ #ifdef JSON_MEMORY_CALLBACKS
+ ptr -> ~JSONNode();
+ libjson_free<JSONNode>(ptr);
+ #else
+ delete ptr;
+ #endif
+}
+
+inline JSONNode * _newJSONNode(const JSONNode & orig){
+ #ifdef JSON_MEMORY_CALLBACKS
+ return new(json_malloc<JSONNode>(1)) JSONNode(orig);
+ #else
+ return new JSONNode(orig);
+ #endif
+}
+
+inline JSONNode * JSONNode::newJSONNode(const JSONNode & orig JSON_MUTEX_COPY_DECL){
+ #ifdef JSON_MUTEX_CALLBACKS
+ if (parentMutex){
+ JSONNode * temp = _newJSONNode(orig);
+ temp -> set_mutex(parentMutex);
+ return temp;
+ }
+ #endif
+ return _newJSONNode(orig);
+}
+
+inline JSONNode * JSONNode::newJSONNode(internalJSONNode * internal_t){
+ #ifdef JSON_MEMORY_CALLBACKS
+ return new(json_malloc<JSONNode>(1)) JSONNode(internal_t);
+ #else
+ return new JSONNode(internal_t);
+ #endif
+}
+
+inline JSONNode * JSONNode::newJSONNode_Shallow(const JSONNode & orig){
+ #ifdef JSON_MEMORY_CALLBACKS
+ return new(json_malloc<JSONNode>(1)) JSONNode(true, const_cast<JSONNode &>(orig));
+ #else
+ return new JSONNode(true, const_cast<JSONNode &>(orig));
+ #endif
+}
+#endif