summaryrefslogtreecommitdiff
path: root/src/modules/json
diff options
context:
space:
mode:
authorKirill Volinsky <mataes2007@gmail.com>2012-12-17 14:19:09 +0000
committerKirill Volinsky <mataes2007@gmail.com>2012-12-17 14:19:09 +0000
commitd3a54e309c8c6335a5d6384d3e239bd7bc9390f6 (patch)
treed45e6ca446392d9ce9acf5b4b20e75dd5d85af4f /src/modules/json
parent375155f8dcd69863f1b9a220c5f890596844e99d (diff)
cleanup
git-svn-id: http://svn.miranda-ng.org/main/trunk@2757 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'src/modules/json')
-rw-r--r--src/modules/json/JSONNode.h1502
-rw-r--r--src/modules/json/JSONNode_Mutex.cpp431
-rw-r--r--src/modules/json/JSONOptions.h404
-rw-r--r--src/modules/json/JSONWorker.cpp1398
-rw-r--r--src/modules/json/JSONWorker.h92
-rw-r--r--src/modules/json/JSONWriter.cpp346
-rw-r--r--src/modules/json/NumberToString.h208
-rw-r--r--src/modules/json/libJSON.cpp1011
-rw-r--r--src/modules/json/libJSON.h423
9 files changed, 2857 insertions, 2958 deletions
diff --git a/src/modules/json/JSONNode.h b/src/modules/json/JSONNode.h
index 051475e704..2d36c5232b 100644
--- a/src/modules/json/JSONNode.h
+++ b/src/modules/json/JSONNode.h
@@ -7,917 +7,847 @@
#include <cstdarg> //for the ... parameter
#ifdef JSON_BINARY
- #include "JSON_Base64.h"
+ #include "JSON_Base64.h"
#endif
#ifndef JSON_REF_COUNT
- #define makeUniqueInternal() (void)0
+ #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
+ #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
+ #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)
-
+ #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)
-
+ #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)
-
+ 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.
+ 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);
+ 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;
+ 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.
+ 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();
+ 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();
+ 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();
+ orig.internal = 0;
+ incAllocCount();
}
-
inline JSONNode::~JSONNode(void){
- if (internal) decRef();
- decAllocCount();
+ if (internal) decRef();
+ decAllocCount();
}
-
inline json_index_t JSONNode::size(void) const {
- JSON_CHECK_INTERNAL();
- return internal -> size();
+ JSON_CHECK_INTERNAL();
+ return internal -> size();
}
-
inline bool JSONNode::empty(void) const {
- JSON_CHECK_INTERNAL();
- return internal -> empty();
+ JSON_CHECK_INTERNAL();
+ return internal -> empty();
}
-
inline void JSONNode::clear(void){
- JSON_CHECK_INTERNAL();
- if (!empty()) {
- makeUniqueInternal();
- internal -> Children.clear();
- }
+ JSON_CHECK_INTERNAL();
+ if (!empty()) {
+ makeUniqueInternal();
+ internal -> Children.clear();
+ }
}
-
inline unsigned char JSONNode::type(void) const {
- JSON_CHECK_INTERNAL();
- return internal -> type();
+ JSON_CHECK_INTERNAL();
+ return internal -> type();
}
-
inline json_string JSONNode::name(void) const {
- JSON_CHECK_INTERNAL();
- return internal -> name();
+ JSON_CHECK_INTERNAL();
+ return internal -> name();
}
-
inline void JSONNode::set_name(const json_string & newname){
- JSON_CHECK_INTERNAL();
- makeUniqueInternal();
- internal -> setname(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();
- }
+ 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();
+ JSON_CHECK_INTERNAL();
+ return internal -> as_string();
}
-
inline long JSONNode::as_int(void) const {
- JSON_CHECK_INTERNAL();
- return internal -> as_int();
+ JSON_CHECK_INTERNAL();
+ return internal -> as_int();
}
-
inline json_number JSONNode::as_float(void) const {
- JSON_CHECK_INTERNAL();
- return internal -> as_float();
+ JSON_CHECK_INTERNAL();
+ return internal -> as_float();
}
-
inline bool JSONNode::as_bool(void) const {
- JSON_CHECK_INTERNAL();
- return internal -> as_bool();
+ 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());
- }
+ 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)));
+ 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)));
+ 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);
+ JSON_CHECK_INTERNAL();
+ makeUniqueInternal();
+ internal -> push_back(child);
}
-
+
inline void JSONNode::reserve(json_index_t size){
- makeUniqueInternal();
- internal -> reserve(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;
+ 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;
- }
+ 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;\
- }
+#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
+ 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);\
- }
-
+ 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);
+ 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);
- }
+ 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);
+ JSON_CHECK_INTERNAL();
+ return internal -> IsEqualTo(val);
}
inline bool JSONNode::operator == (const JSONNode & val) const {
- JSON_CHECK_INTERNAL();
- return internal -> IsEqualTo(val.internal);
+ JSON_CHECK_INTERNAL();
+ return internal -> IsEqualTo(val.internal);
}
-
/*
- This section is the inequality operators
+ This section is the inequality operators
*/
-
#define NODE_CHECK_INEQUALITY(type)\
- inline bool JSONNode::operator != (type val) const {\
- JSON_CHECK_INTERNAL();\
- return !(*this == val);\
- }
-
+ 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 * )
+ NODE_CHECK_INEQUALITY(const json_char * )
#endif
-
+
inline void JSONNode::nullify(void){
- JSON_CHECK_INTERNAL();
- makeUniqueInternal();
- internal -> Nullify();
+ 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();
+ 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
+ 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
- }
+ 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));
- }
+ 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);
- }
-
+ 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();
- }
+ 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();
- }
+ 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
+ #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
+ #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
+ #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(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
+ #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
+ #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
diff --git a/src/modules/json/JSONNode_Mutex.cpp b/src/modules/json/JSONNode_Mutex.cpp
index 2adb694ca8..77a9e90697 100644
--- a/src/modules/json/JSONNode_Mutex.cpp
+++ b/src/modules/json/JSONNode_Mutex.cpp
@@ -1,216 +1,215 @@
-/*
-
-Miranda IM: the free IM client for Microsoft* Windows*
-
-Copyright 2000-2009 Miranda ICQ/IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#include "..\..\core\commonheaders.h"
-#include <m_json.h>
-
-#include "libJSON.h"
-
-#ifdef JSON_MUTEX_CALLBACKS
-
-json_mutex_callback_t json_lock_callback = 0;
-json_mutex_callback_t json_unlock_callback = 0;
-void * global_mutex = 0;
-void * manager_mutex = 0;
-
-struct AutoLock {
- AutoLock(void){
- json_lock_callback(manager_mutex);
- }
- ~AutoLock(void){
- json_unlock_callback(manager_mutex);
- }
-};
-
-#include <map>
-#ifdef JSON_MUTEX_MANAGE
- json_mutex_callback_t json_destroy = 0;
- std::map<void *, unsigned int> mutex_manager;
-
- //make sure that the global mutex is taken care of too
- struct auto_global {
- auto_global(void){}
- ~auto_global(void){
- if (global_mutex){
- JSON_ASSERT_SAFE(json_destroy, JSON_TEXT("No json_destroy in mutex managed mode"), return;);
- json_destroy(global_mutex);
- }
- }
- };
- auto_global cleanupGlobal;
-#endif
-
-void JSONNode::register_mutex_callbacks(json_mutex_callback_t lock, json_mutex_callback_t unlock, void * manager_lock){
- json_lock_callback = lock;
- json_unlock_callback = unlock;
- manager_mutex = manager_lock;
-}
-
-void JSONNode::set_global_mutex(void * mutex){
- global_mutex = mutex;
-}
-
-void JSONNode::set_mutex(void * mutex){
- makeUniqueInternal();
- internal -> _set_mutex(mutex);
-}
-
-std::map<int, std::map<void *, unsigned int> > threadlocks;
-
-void * JSONNode::getThisLock(JSONNode * pthis){
- if (pthis -> internal -> mylock){
- return pthis -> internal -> mylock;
- }
- JSON_ASSERT_SAFE(global_mutex, JSON_TEXT("No global_mutex"), return 0;);
- return global_mutex;
-}
-
-void JSONNode::lock(int thread){
- JSON_ASSERT_SAFE(json_lock_callback, JSON_TEXT("No locking callback"), return;);
-
- AutoLock lockControl;
-
- //first, figure out what needs to be locked
- void * thislock = getThisLock(this);
- #ifdef JSON_SAFE
- if (!thislock) return;
- #endif
-
- //make sure that the same thread isn't locking it more than once (possible due to complex ref counting)
- std::map<int, std::map<void *, unsigned int> >::iterator it = threadlocks.find(thread);
- if (it == threadlocks.end()) {
- std::map<void *, unsigned int> newthread;
- newthread[thislock] = 1;
- threadlocks.insert(std::pair<int, std::map<void *, unsigned int> >(thread, newthread));
- } else { //this thread already has some things locked, check if the current mutex is
- std::map<void *, unsigned int> & newthread = it -> second;
- std::map<void *, unsigned int>::iterator locker = newthread.find(thislock);
- if (locker == newthread.end()) { //current mutex is not locked, set it to locked
- newthread.insert(std::pair<void *, unsigned int>(thislock, 1));
- } else { //it's already locked, don't relock it
- ++(locker -> second);
- return; //don't try to relock, it will deadlock the program
- }
- }
-
- //if I need to, lock it
- json_lock_callback(thislock);
-}
-
-void JSONNode::unlock(int thread){
- JSON_ASSERT_SAFE(json_unlock_callback, JSON_TEXT("No unlocking callback"), return;);
-
- AutoLock lockControl;
-
- //first, figure out what needs to be locked
- void * thislock = getThisLock(this);
- #ifdef JSON_SAFE
- if (!thislock) return;
- #endif
-
- //get it out of the map
- std::map<int, std::map<void *, unsigned int> >::iterator it = threadlocks.find(thread);
- JSON_ASSERT_SAFE(it != threadlocks.end(), JSON_TEXT("thread unlocking something it didn't lock"), return;);
-
- //get the mutex out of the thread
- std::map<void *, unsigned int> & newthread = it -> second;
- std::map<void *, unsigned int>::iterator locker = newthread.find(thislock);
- JSON_ASSERT_SAFE(locker != newthread.end(), JSON_TEXT("thread unlocking mutex it didn't lock"), return;);
-
- //unlock it
- if (--(locker -> second)) return; //other nodes is this same thread still have a lock on it
-
- //if I need to, unlock it
- newthread.erase(locker);
- json_unlock_callback(thislock);
-}
-
-#ifdef JSON_MUTEX_MANAGE
- void JSONNode::register_mutex_destructor(json_mutex_callback_t destroy){
- json_destroy = destroy;
- }
-#endif
-
-
-void internalJSONNode::_set_mutex(void * mutex, bool unset){
- if (unset) _unset_mutex(); //for reference counting
- mylock = mutex;
- if (mutex){
- #ifdef JSON_MUTEX_MANAGE
- std::map<void *, unsigned int>::iterator it = mutex_manager.find(mutex);
- if (it == mutex_manager.end()) {
- mutex_manager.insert(std::pair<void *, unsigned int>(mutex, 1));
- } else {
- ++it -> second;
- }
- #endif
- json_foreach(Children, myrunner){
- (*myrunner) -> set_mutex(mutex);
- }
- }
-}
-
-void internalJSONNode::_unset_mutex(void){
- #ifdef JSON_MUTEX_MANAGE
- if (mylock){
- std::map<void *, unsigned int>::iterator it = mutex_manager.find(mylock);
- JSON_ASSERT_SAFE(it != mutex_manager.end(), JSON_TEXT("Mutex not managed"), return;);
- --it -> second;
- if (it -> second == 0){
- JSON_ASSERT_SAFE(json_destroy, JSON_TEXT("You didn't register a destructor for mutexes"), return;);
- mutex_manager.erase(it);
- }
- }
- #endif
-}
-
-#ifdef JSON_DEBUG
- #ifndef JSON_LIBRARY
- JSONNode internalJSONNode::DumpMutex(void) const {
- JSONNode mut(JSON_NODE);
- mut.set_name(JSON_TEXT("mylock"));
- #ifdef JSON_MUTEX_MANAGE
- if (mylock){
- mut.push_back(JSON_NEW(JSONNode(JSON_TEXT("this"), (long)mylock)));
- std::map<void *, unsigned int>::iterator it = mutex_manager.find(mylock);
- if (it == mutex_manager.end()) {
- mut.push_back(JSON_NEW(JSONNode(JSON_TEXT("references"), JSON_TEXT("error"))));
- } else {
- mut.push_back(JSON_NEW(JSONNode(JSON_TEXT("references"), it -> second)));
- }
- } else {
- mut = (long)mylock;
- }
- #else
- mut = (long)mylock;
- #endif
- return mut;
- }
- #endif
-#endif
-
-#else
- #ifdef JSON_MUTEX_MANAGE
- #error You can not have JSON_MUTEX_MANAGE on without JSON_MUTEX_CALLBACKS
- #endif
-#endif
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2009 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "..\..\core\commonheaders.h"
+#include <m_json.h>
+
+#include "libJSON.h"
+
+#ifdef JSON_MUTEX_CALLBACKS
+
+json_mutex_callback_t json_lock_callback = 0;
+json_mutex_callback_t json_unlock_callback = 0;
+void * global_mutex = 0;
+void * manager_mutex = 0;
+
+struct AutoLock {
+ AutoLock(void){
+ json_lock_callback(manager_mutex);
+ }
+ ~AutoLock(void){
+ json_unlock_callback(manager_mutex);
+ }
+};
+
+#include <map>
+#ifdef JSON_MUTEX_MANAGE
+ json_mutex_callback_t json_destroy = 0;
+ std::map<void *, unsigned int> mutex_manager;
+
+ //make sure that the global mutex is taken care of too
+ struct auto_global {
+ auto_global(void){}
+ ~auto_global(void){
+ if (global_mutex){
+ JSON_ASSERT_SAFE(json_destroy, JSON_TEXT("No json_destroy in mutex managed mode"), return;);
+ json_destroy(global_mutex);
+ }
+ }
+ };
+ auto_global cleanupGlobal;
+#endif
+
+void JSONNode::register_mutex_callbacks(json_mutex_callback_t lock, json_mutex_callback_t unlock, void * manager_lock){
+ json_lock_callback = lock;
+ json_unlock_callback = unlock;
+ manager_mutex = manager_lock;
+}
+
+void JSONNode::set_global_mutex(void * mutex){
+ global_mutex = mutex;
+}
+
+void JSONNode::set_mutex(void * mutex){
+ makeUniqueInternal();
+ internal -> _set_mutex(mutex);
+}
+
+std::map<int, std::map<void *, unsigned int> > threadlocks;
+
+void * JSONNode::getThisLock(JSONNode * pthis){
+ if (pthis -> internal -> mylock){
+ return pthis -> internal -> mylock;
+ }
+ JSON_ASSERT_SAFE(global_mutex, JSON_TEXT("No global_mutex"), return 0;);
+ return global_mutex;
+}
+
+void JSONNode::lock(int thread){
+ JSON_ASSERT_SAFE(json_lock_callback, JSON_TEXT("No locking callback"), return;);
+
+ AutoLock lockControl;
+
+ //first, figure out what needs to be locked
+ void * thislock = getThisLock(this);
+ #ifdef JSON_SAFE
+ if (!thislock) return;
+ #endif
+
+ //make sure that the same thread isn't locking it more than once (possible due to complex ref counting)
+ std::map<int, std::map<void *, unsigned int> >::iterator it = threadlocks.find(thread);
+ if (it == threadlocks.end()) {
+ std::map<void *, unsigned int> newthread;
+ newthread[thislock] = 1;
+ threadlocks.insert(std::pair<int, std::map<void *, unsigned int> >(thread, newthread));
+ } else { //this thread already has some things locked, check if the current mutex is
+ std::map<void *, unsigned int> & newthread = it -> second;
+ std::map<void *, unsigned int>::iterator locker = newthread.find(thislock);
+ if (locker == newthread.end()) { //current mutex is not locked, set it to locked
+ newthread.insert(std::pair<void *, unsigned int>(thislock, 1));
+ } else { //it's already locked, don't relock it
+ ++(locker -> second);
+ return; //don't try to relock, it will deadlock the program
+ }
+ }
+
+ //if I need to, lock it
+ json_lock_callback(thislock);
+}
+
+void JSONNode::unlock(int thread){
+ JSON_ASSERT_SAFE(json_unlock_callback, JSON_TEXT("No unlocking callback"), return;);
+
+ AutoLock lockControl;
+
+ //first, figure out what needs to be locked
+ void * thislock = getThisLock(this);
+ #ifdef JSON_SAFE
+ if (!thislock) return;
+ #endif
+
+ //get it out of the map
+ std::map<int, std::map<void *, unsigned int> >::iterator it = threadlocks.find(thread);
+ JSON_ASSERT_SAFE(it != threadlocks.end(), JSON_TEXT("thread unlocking something it didn't lock"), return;);
+
+ //get the mutex out of the thread
+ std::map<void *, unsigned int> & newthread = it -> second;
+ std::map<void *, unsigned int>::iterator locker = newthread.find(thislock);
+ JSON_ASSERT_SAFE(locker != newthread.end(), JSON_TEXT("thread unlocking mutex it didn't lock"), return;);
+
+ //unlock it
+ if (--(locker -> second)) return; //other nodes is this same thread still have a lock on it
+
+ //if I need to, unlock it
+ newthread.erase(locker);
+ json_unlock_callback(thislock);
+}
+
+#ifdef JSON_MUTEX_MANAGE
+ void JSONNode::register_mutex_destructor(json_mutex_callback_t destroy){
+ json_destroy = destroy;
+ }
+#endif
+
+void internalJSONNode::_set_mutex(void * mutex, bool unset){
+ if (unset) _unset_mutex(); //for reference counting
+ mylock = mutex;
+ if (mutex){
+ #ifdef JSON_MUTEX_MANAGE
+ std::map<void *, unsigned int>::iterator it = mutex_manager.find(mutex);
+ if (it == mutex_manager.end()) {
+ mutex_manager.insert(std::pair<void *, unsigned int>(mutex, 1));
+ } else {
+ ++it -> second;
+ }
+ #endif
+ json_foreach(Children, myrunner){
+ (*myrunner) -> set_mutex(mutex);
+ }
+ }
+}
+
+void internalJSONNode::_unset_mutex(void){
+ #ifdef JSON_MUTEX_MANAGE
+ if (mylock){
+ std::map<void *, unsigned int>::iterator it = mutex_manager.find(mylock);
+ JSON_ASSERT_SAFE(it != mutex_manager.end(), JSON_TEXT("Mutex not managed"), return;);
+ --it -> second;
+ if (it -> second == 0){
+ JSON_ASSERT_SAFE(json_destroy, JSON_TEXT("You didn't register a destructor for mutexes"), return;);
+ mutex_manager.erase(it);
+ }
+ }
+ #endif
+}
+
+#ifdef JSON_DEBUG
+ #ifndef JSON_LIBRARY
+ JSONNode internalJSONNode::DumpMutex(void) const {
+ JSONNode mut(JSON_NODE);
+ mut.set_name(JSON_TEXT("mylock"));
+ #ifdef JSON_MUTEX_MANAGE
+ if (mylock){
+ mut.push_back(JSON_NEW(JSONNode(JSON_TEXT("this"), (long)mylock)));
+ std::map<void *, unsigned int>::iterator it = mutex_manager.find(mylock);
+ if (it == mutex_manager.end()) {
+ mut.push_back(JSON_NEW(JSONNode(JSON_TEXT("references"), JSON_TEXT("error"))));
+ } else {
+ mut.push_back(JSON_NEW(JSONNode(JSON_TEXT("references"), it -> second)));
+ }
+ } else {
+ mut = (long)mylock;
+ }
+ #else
+ mut = (long)mylock;
+ #endif
+ return mut;
+ }
+ #endif
+#endif
+
+#else
+ #ifdef JSON_MUTEX_MANAGE
+ #error You can not have JSON_MUTEX_MANAGE on without JSON_MUTEX_CALLBACKS
+ #endif
+#endif
diff --git a/src/modules/json/JSONOptions.h b/src/modules/json/JSONOptions.h
index 3c5bb8168f..29d588113a 100644
--- a/src/modules/json/JSONOptions.h
+++ b/src/modules/json/JSONOptions.h
@@ -1,214 +1,190 @@
-#ifndef JSON_OPTIONS_H
-#define JSON_OPTIONS_H
-
-#define snprintf _snprintf
-
-/**
- * This file holds all of the compiling options for easy access and so
- * that you don't have to remember them, or look them up all the time
- */
-
-
-/*
- * JSON_LIBRARY must be declared if libjson is compiled as a static or dynamic
- * library. This exposes a C-style interface, but none of the inner workings of libjson
- */
-#define JSON_LIBRARY
-
-
-/*
- * JSON_DEBUG is used to perform extra error checking. Because libjson usually
- * does on the fly parsing, validation is impossible, so this option will allow
- * you to register an error callback so that you can record what is going wrong
- * before the library crashes. This option does not protect from these errors,
- * it simply tells you about them, which is nice for debugging, but not preferable
- * for release candidates
- */
-//#define JSON_DEBUG
-
-
-/*
- * JSON_SAFE performs similarly to JSON_DEBUG, except this option does protect
- * from the errors that it encounters. This option is recommended for those who
- * feel it's possible for their program to encounter invalid json.
- */
-#define JSON_SAFE
-
-
-/*
- * JSON_STDERROR routes error messages to cerr instead of a callback, this
- * option hides the callback registering function. This will usually display
- * messages in the console
- */
-//#define JSON_STDERROR
-
-
-/*
- * JSON_PREPARSE causes all parsing to be done immediately. By default, libjson
- * parses nodes on the fly as they are needed, this makes parsing much faster if
- * your program gets a lot of information that it doesn't need. An example of
- * this would be a client application communicating with a server if the server
- * returns things like last modified date and other things that you don't use.
- */
-//#define JSON_PREPARSE
-
-
-/*
- * JSON_LESS_MEMORY will force libjson to let go of memory as quickly as it can
- * this is recommended for software that has to run on less than optimal machines.
- * It will cut libjson's memory usage by about 20%, but also run slightly slower.
- * It's recommended that you also compile using the -Os option, as this will also
- * reduce the size of the library
- */
-//#define JSON_LESS_MEMORY
-
-
-/*
- * JSON_UNICODE tells libjson to use wstrings instead of regular strings, this
- * means that libjson supports the full array of unicode characters, but also takes
- * much more memory and processing power.
- */
-//#define JSON_UNICODE
-
-
-/*
- * JSON_REF_COUNT causes libjson to reference count JSONNodes, which makes copying
- * and passing them around much faster. It is recommended that this stay on for
- * most uses
- */
-#define JSON_REF_COUNT
-
-
-/*
- * JSON_BINARY is used to support binary, which is base64 encoded and decoded by libjson,
- * if this option is not turned on, no base64 support is included
- */
-//#define JSON_BINARY
-
-
-/*
- * JSON_MEMORY_CALLBACKS exposes functions to register callbacks for allocating, resizing,
- * and freeing memory. Because libjson is designed for costomizability, it is feasible
- * that some users would like to further add speed by having the library utilize a memory
- * pool. With this option turned on, the default behavior is still done internally unless
- * a callback is registered. So you can have this option on and mot use it.
- */
-#define JSON_MEMORY_CALLBACKS
-
-/*
- * JSON_MEMORY_MANAGE is used to create functionality to automatically track and clean
- * up memory that has been allocated by the user. This includes strings, binary data, and
- * nodes. It also exposes bulk delete functions.
- */
-//#define JSON_MEMORY_MANAGE
-
-
-/*
- * JSON_MUTEX_CALLBACKS exposes functions to register callbacks to lock and unlock
- * mutexs and functions to lock and unlock JSONNodes and all of it's children. This
- * does not prevent other threads from accessing the node, but will prevent them from
- * locking it. It is much easier for the end programmer to allow libjson to manage
- * your mutexs because of reference counting and manipulating trees, libjson automatically
- * tracks mutex controls for you, so you only ever lock what you need to
- */
-//#define JSON_MUTEX_CALLBACKS
-
-
-/*
- * JSON_MUTEX_MANAGE lets you set mutexes and forget them, libjson will not only keep
- * track of the mutex, but also keep a count of how many nodes are using it, and delete
- * it when there are no more references
- */
-//#define JSON_MUTEX_MANAGE
-
-
-/*
- * JSON_ISO_STRICT turns off all code that uses non-standard C++. This removes all
- * references to long long and long double as well as a few others
- */
-//#define JSON_ISO_STRICT
-
-/*
- * JSON_ITERATORS turns on all of libjson's iterating functionality. This would usually
- * only be turned off while compiling for use with C
- */
-//#define JSON_ITERATORS
-
-
-/*
- * JSON_WRITER turns on libjson's writing capabilties. Without this libjson can only
- * read and parse json, this allows it to write back out
- */
-#define JSON_WRITER
-
-
-/*
- * JSON_NEWLINE affects how libjson writes. If this option is turned on, libjson
- * will use whatever it's defined as for the newline signifier, otherwise, it will use
- * standard unix \n.
- */
-//#define JSON_NEWLINE "\r\n" //\r\n is standard for most windows and dos programs
-
-
-/*
- * JSON_COMMENTS tells libjson to store and write comments. libjson always supports
- * parsing json that has comments in it as it simply ignores them, but with this option
- * it keeps the comments and allows you to insert further comments
- */
-//#define JSON_COMMENTS
-
-
-/*
- * JSON_INDENT affects how libjson writes. If this option is turned on, libjson
- * will use \t to indent formatted json, otherwise it will use the number of characters
- * that you specify. If this is not turned on, then it will use the tab (\t) character
- */
-//#define JSON_INDENT " "
-
-
-/*
- * JSON_WRITE_BASH_COMMENTS will cause libjson to write all comments in bash (#) style
- * if this option is not turned on, then it will use C-style comments. Bash comments are
- * all single line
- */
-//#define JSON_WRITE_BASH_COMMENTS
-
-
-/*
- * JSON_WRITE_SINGLE_LINE_COMMENTS will cause libjson to write all comments in using //
- * notation, or (#) if that option is on. Some parsers do not support multiline C comments
- * although, this option is not needed for bash comments, as they are all single line anyway
- */
-//#define JSON_WRITE_SINGLE_LINE_COMMENTS
-
-
-/*
- * JSON_VALIDATE turns on validation features of libjson. This option requires JSON_SAFE
- */
-//#define JSON_VALIDATE
-
-
-/*
- * JSON_CASE_INSENSITIVE_FUNCTIONS turns on funtions for finding child nodes in a case-
- * insenititve way
- */
-//#define JSON_CASE_INSENSITIVE_FUNCTIONS
-
-
-/*
- * JSON_UNIT_TEST is used to maintain and debug the libjson. It makes all private
- * members and functions public so that tests can do checks of the inner workings
- * of libjson. This should not be turned on by end users.
- */
-//#define JSON_UNIT_TEST
-
-
-/*
- * JSON_INDEX_TYPE allows you th change the size type for the children functions. If this
- * option is not used then unsigned int is used. This option is useful for cutting down
- * on memory, or using huge numbers of child nodes (over 4 billion)
- */
-//#define JSON_INDEX_TYPE unsigned int
-
-#endif
-
+#ifndef JSON_OPTIONS_H
+#define JSON_OPTIONS_H
+
+#define snprintf _snprintf
+
+/**
+ * This file holds all of the compiling options for easy access and so
+ * that you don't have to remember them, or look them up all the time
+ */
+
+/*
+ * JSON_LIBRARY must be declared if libjson is compiled as a static or dynamic
+ * library. This exposes a C-style interface, but none of the inner workings of libjson
+ */
+#define JSON_LIBRARY
+
+/*
+ * JSON_DEBUG is used to perform extra error checking. Because libjson usually
+ * does on the fly parsing, validation is impossible, so this option will allow
+ * you to register an error callback so that you can record what is going wrong
+ * before the library crashes. This option does not protect from these errors,
+ * it simply tells you about them, which is nice for debugging, but not preferable
+ * for release candidates
+ */
+//#define JSON_DEBUG
+
+/*
+ * JSON_SAFE performs similarly to JSON_DEBUG, except this option does protect
+ * from the errors that it encounters. This option is recommended for those who
+ * feel it's possible for their program to encounter invalid json.
+ */
+#define JSON_SAFE
+
+/*
+ * JSON_STDERROR routes error messages to cerr instead of a callback, this
+ * option hides the callback registering function. This will usually display
+ * messages in the console
+ */
+//#define JSON_STDERROR
+
+/*
+ * JSON_PREPARSE causes all parsing to be done immediately. By default, libjson
+ * parses nodes on the fly as they are needed, this makes parsing much faster if
+ * your program gets a lot of information that it doesn't need. An example of
+ * this would be a client application communicating with a server if the server
+ * returns things like last modified date and other things that you don't use.
+ */
+//#define JSON_PREPARSE
+
+/*
+ * JSON_LESS_MEMORY will force libjson to let go of memory as quickly as it can
+ * this is recommended for software that has to run on less than optimal machines.
+ * It will cut libjson's memory usage by about 20%, but also run slightly slower.
+ * It's recommended that you also compile using the -Os option, as this will also
+ * reduce the size of the library
+ */
+//#define JSON_LESS_MEMORY
+
+/*
+ * JSON_UNICODE tells libjson to use wstrings instead of regular strings, this
+ * means that libjson supports the full array of unicode characters, but also takes
+ * much more memory and processing power.
+ */
+//#define JSON_UNICODE
+
+/*
+ * JSON_REF_COUNT causes libjson to reference count JSONNodes, which makes copying
+ * and passing them around much faster. It is recommended that this stay on for
+ * most uses
+ */
+#define JSON_REF_COUNT
+
+/*
+ * JSON_BINARY is used to support binary, which is base64 encoded and decoded by libjson,
+ * if this option is not turned on, no base64 support is included
+ */
+//#define JSON_BINARY
+
+/*
+ * JSON_MEMORY_CALLBACKS exposes functions to register callbacks for allocating, resizing,
+ * and freeing memory. Because libjson is designed for costomizability, it is feasible
+ * that some users would like to further add speed by having the library utilize a memory
+ * pool. With this option turned on, the default behavior is still done internally unless
+ * a callback is registered. So you can have this option on and mot use it.
+ */
+#define JSON_MEMORY_CALLBACKS
+
+/*
+ * JSON_MEMORY_MANAGE is used to create functionality to automatically track and clean
+ * up memory that has been allocated by the user. This includes strings, binary data, and
+ * nodes. It also exposes bulk delete functions.
+ */
+//#define JSON_MEMORY_MANAGE
+
+/*
+ * JSON_MUTEX_CALLBACKS exposes functions to register callbacks to lock and unlock
+ * mutexs and functions to lock and unlock JSONNodes and all of it's children. This
+ * does not prevent other threads from accessing the node, but will prevent them from
+ * locking it. It is much easier for the end programmer to allow libjson to manage
+ * your mutexs because of reference counting and manipulating trees, libjson automatically
+ * tracks mutex controls for you, so you only ever lock what you need to
+ */
+//#define JSON_MUTEX_CALLBACKS
+
+/*
+ * JSON_MUTEX_MANAGE lets you set mutexes and forget them, libjson will not only keep
+ * track of the mutex, but also keep a count of how many nodes are using it, and delete
+ * it when there are no more references
+ */
+//#define JSON_MUTEX_MANAGE
+
+/*
+ * JSON_ISO_STRICT turns off all code that uses non-standard C++. This removes all
+ * references to long long and long double as well as a few others
+ */
+//#define JSON_ISO_STRICT
+
+/*
+ * JSON_ITERATORS turns on all of libjson's iterating functionality. This would usually
+ * only be turned off while compiling for use with C
+ */
+//#define JSON_ITERATORS
+
+/*
+ * JSON_WRITER turns on libjson's writing capabilties. Without this libjson can only
+ * read and parse json, this allows it to write back out
+ */
+#define JSON_WRITER
+
+/*
+ * JSON_NEWLINE affects how libjson writes. If this option is turned on, libjson
+ * will use whatever it's defined as for the newline signifier, otherwise, it will use
+ * standard unix \n.
+ */
+//#define JSON_NEWLINE "\r\n" //\r\n is standard for most windows and dos programs
+
+/*
+ * JSON_COMMENTS tells libjson to store and write comments. libjson always supports
+ * parsing json that has comments in it as it simply ignores them, but with this option
+ * it keeps the comments and allows you to insert further comments
+ */
+//#define JSON_COMMENTS
+
+/*
+ * JSON_INDENT affects how libjson writes. If this option is turned on, libjson
+ * will use \t to indent formatted json, otherwise it will use the number of characters
+ * that you specify. If this is not turned on, then it will use the tab (\t) character
+ */
+//#define JSON_INDENT " "
+
+/*
+ * JSON_WRITE_BASH_COMMENTS will cause libjson to write all comments in bash (#) style
+ * if this option is not turned on, then it will use C-style comments. Bash comments are
+ * all single line
+ */
+//#define JSON_WRITE_BASH_COMMENTS
+
+/*
+ * JSON_WRITE_SINGLE_LINE_COMMENTS will cause libjson to write all comments in using //
+ * notation, or (#) if that option is on. Some parsers do not support multiline C comments
+ * although, this option is not needed for bash comments, as they are all single line anyway
+ */
+//#define JSON_WRITE_SINGLE_LINE_COMMENTS
+
+/*
+ * JSON_VALIDATE turns on validation features of libjson. This option requires JSON_SAFE
+ */
+//#define JSON_VALIDATE
+
+/*
+ * JSON_CASE_INSENSITIVE_FUNCTIONS turns on funtions for finding child nodes in a case-
+ * insenititve way
+ */
+//#define JSON_CASE_INSENSITIVE_FUNCTIONS
+
+/*
+ * JSON_UNIT_TEST is used to maintain and debug the libjson. It makes all private
+ * members and functions public so that tests can do checks of the inner workings
+ * of libjson. This should not be turned on by end users.
+ */
+//#define JSON_UNIT_TEST
+
+/*
+ * JSON_INDEX_TYPE allows you th change the size type for the children functions. If this
+ * option is not used then unsigned int is used. This option is useful for cutting down
+ * on memory, or using huge numbers of child nodes (over 4 billion)
+ */
+//#define JSON_INDEX_TYPE unsigned int
+
+#endif
diff --git a/src/modules/json/JSONWorker.cpp b/src/modules/json/JSONWorker.cpp
index 488089345f..83ab246ee1 100644
--- a/src/modules/json/JSONWorker.cpp
+++ b/src/modules/json/JSONWorker.cpp
@@ -1,701 +1,697 @@
-/*
-
-Miranda IM: the free IM client for Microsoft* Windows*
-
-Copyright 2000-2009 Miranda ICQ/IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#include "..\..\core\commonheaders.h"
-
-#include "JSONWorker.h"
-
-#ifdef JSON_VALIDATE
-JSONNode JSONWorker::validate(const json_string & json){
- JSONNode res = parse(json);
- if (!res.validate()) {
- throw std::invalid_argument(EMPTY_STRING2);
- }
- return JSONNode(true, res); //forces it to simply return the original interal, even with ref counting off
-}
-#endif
-
-JSONNode JSONWorker::parse(const json_string & json){
- json_auto<json_char> s;
- #if defined JSON_DEBUG || defined JSON_SAFE
- json_char lastchar;
- s.set(RemoveWhiteSpace(json, lastchar));
- #else
- s.set(RemoveWhiteSpace(json));
- #endif
-
- #ifdef JSON_COMMENTS
- json_char firstchar = s.ptr[0];
- json_string _comment;
- json_char * runner = s.ptr;
- if (firstchar == '\5') { //multiple comments will be consolidated into one
- newcomment:
- while(*(++runner) != '\5') {
- JSON_ASSERT(*runner, JSON_TEXT("Removing white space failed"));
- _comment += *runner;
- }
- firstchar = *(++runner); //step past the trailing tag
- if (firstchar == '\5') {
- _comment += '\n';
- goto newcomment;
- }
- }
- #else
- const json_char firstchar = s.ptr[0];
- #endif
-
- switch (firstchar){
- case '{':
- case '[':
- #if defined JSON_DEBUG || defined JSON_SAFE
- if (firstchar == '[') {
- if (lastchar != ']') {
- JSON_FAIL(JSON_TEXT("Missing final ]"));
- break;
- }
- } else {
- if (lastchar != '}') {
- JSON_FAIL(JSON_TEXT("Missing final }"));
- break;
- }
- }
- #endif
- #ifdef JSON_COMMENTS
- JSONNode foo(runner);
- foo.set_comment(_comment);
- return JSONNode(true, foo); //forces it to simply return the original interal, even with ref counting off
- #else
- return JSONNode(s.ptr);
- #endif
- }
-
- JSON_FAIL(JSON_TEXT("Not JSON!"));
- throw std::invalid_argument(EMPTY_STRING2);
-}
-
-#define QUOTECASE()\
- case JSON_TEXT('\"'):\
- while (*(++p) != JSON_TEXT('\"')) {\
- JSON_ASSERT_SAFE(*p, JSON_TEXT("Null terminator inside of a quotation"), return json_string::npos;);\
- }\
- break;
-
-#ifdef JSON_DEBUG
- #define NULLCASE(error)\
- case JSON_TEXT('\0'):\
- JSON_FAIL_SAFE(error, return json_string::npos;);\
- break;
-#else
- #define NULLCASE(error)
-#endif
-
-#define BRACKET(left, right)\
- case left: {\
- size_t brac = 1;\
- while (brac){\
- switch (*(++p)) {\
- case right:\
- --brac;\
- break;\
- case left:\
- ++brac;\
- break;\
- QUOTECASE()\
- NULLCASE(JSON_TEXT("Null terminator inside of a bracket"))\
- }\
- }\
- break;}\
- case right:\
- return json_string::npos;
-
-size_t JSONWorker::FindNextRelevant(json_char ch, const json_string & value_t, const size_t pos){
- const json_char * start = value_t.c_str();
- const json_char * p = start + pos; //start at the correct offset
- do {
- if (*p == ch) return p - start;
- switch (*p){
- BRACKET(JSON_TEXT('['), JSON_TEXT(']'))
- BRACKET(JSON_TEXT('{'), JSON_TEXT('}'))
- QUOTECASE()
- }
- } while(*(++p));
- return json_string::npos;
-}
-
-#ifdef JSON_COMMENTS
- #define COMMENT_DELIMITER() *runner++='\5'
- #define AND_RUNNER ,runner
- inline void SingleLineComment(const json_char * & p, json_char * & runner){
- COMMENT_DELIMITER();
- while((*(++p)) && (*p != JSON_TEXT('\n'))) {
- *runner++=*p;
- }
- COMMENT_DELIMITER();
- }
-#else
- #define COMMENT_DELIMITER() (void)0
- #define AND_RUNNER
-#endif
-
-inline void SingleLineComment(const json_char * & p){
- while((*(++p)) && (*p != JSON_TEXT('\n')));
-}
-
-
-#if defined JSON_DEBUG || defined JSON_SAFE
- json_char * JSONWorker::RemoveWhiteSpace(const json_string & value_t, json_char & last){
-#else
- json_char * JSONWorker::RemoveWhiteSpace(const json_string & value_t){
-#endif
- json_char * result;
- json_char * runner = result = json_malloc<json_char>(value_t.length() + 1); //dealing with raw memory is faster than adding to a json_string
- JSON_ASSERT(result, JSON_TEXT("Out of memory"));
- const json_char * p = value_t.c_str();
- while(*p){
- switch(*p){
- case JSON_TEXT(' '): //defined as white space
- case JSON_TEXT('\t'): //defined as white space
- case JSON_TEXT('\n'): //defined as white space
- case JSON_TEXT('\r'): //defined as white space
- break;
- case JSON_TEXT('/'): //a C comment
- if (*(++p) == JSON_TEXT('*')) { //a multiline comment
- COMMENT_DELIMITER();
- while ((*(++p) != JSON_TEXT('*')) || (*(p + 1) != JSON_TEXT('/'))) {
- JSON_ASSERT_SAFE(*p, JSON_TEXT("Null terminator inside of a multiline quote"), COMMENT_DELIMITER(); goto endofloop;);
- *runner++=*p;
- }
- ++p;
- COMMENT_DELIMITER();
- break;
- }
- //Should be a single line C comment, so let it fall through to use the bash comment stripper
- JSON_ASSERT_SAFE(*p == JSON_TEXT('/'), JSON_TEXT("stray / character, not quoted, or a comment"), goto endofloop;);
- case JSON_TEXT('#'): //a bash comment
- SingleLineComment(p AND_RUNNER);
- break;
- case JSON_TEXT('\"'): //a quote
- *runner++=JSON_TEXT('\"');
- while(*(++p) != JSON_TEXT('\"')) { //find the end of the quotation, as white space is preserved within it
- JSON_ASSERT_SAFE(*p, JSON_TEXT("Null terminator inside of a quotation"), goto endofloop;);
- switch(*p){
- case JSON_TEXT('\\'):
- *runner++=JSON_TEXT('\\');
- *runner++=(*++p == JSON_TEXT('\"')) ? JSON_TEXT('\1') : *p; //an escaped quote will reak havoc will all of my searching functions, so change it into an illegal character in JSON for convertion later on
- break;
- default:
- *runner++=*p;
- break;
- }
- }
- //no break, let it fall through so that the trailing quote gets added
- default:
- JSON_ASSERT_SAFE((json_uchar)*p >= 32, JSON_TEXT("Invalid JSON character detected (lo)"), goto endofloop;);
- JSON_ASSERT_SAFE((json_uchar)*p <= 126, JSON_TEXT("Invalid JSON character detected (hi)"), goto endofloop;);
- *runner++=*p;
- break;
- }
- ++p;
- }
- #ifdef JSON_SAFE
- endofloop:
- #endif
- #if defined JSON_DEBUG || defined JSON_SAFE
- last = *(runner - 1);
- #endif
- *runner = JSON_TEXT('\0');
- return result;
- }
-
-json_string JSONWorker::RemoveWhiteSpaceAndComments(const json_string & value_t){
- json_string result;
- result.reserve(value_t.length());
- const json_char * p = value_t.c_str();
- while(*p){
- switch(*p){
- case JSON_TEXT(' '): //defined as white space
- case JSON_TEXT('\t'): //defined as white space
- case JSON_TEXT('\n'): //defined as white space
- case JSON_TEXT('\r'): //defined as white space
- break;
- case JSON_TEXT('/'): //a C comment
- if (*(++p) == JSON_TEXT('*')) { //a multiline comment
- while ((*(++p) != JSON_TEXT('*')) || (*(p + 1) != JSON_TEXT('/'))) {
- JSON_ASSERT_SAFE(*p, JSON_TEXT("Null terminator inside of a multiline quote"), goto endofloop;);
- }
- ++p;
- break;
- }
- //Should be a single line C comment, so let it fall through to use the bash comment stripper
- JSON_ASSERT_SAFE(*p == JSON_TEXT('/'), JSON_TEXT("stray / character, not quoted, or a comment"), goto endofloop;);
- case JSON_TEXT('#'): //a bash comment
- SingleLineComment(p);
- break;
- case JSON_TEXT('\"'): //a quote
- result += JSON_TEXT('\"');
- while(*(++p) != JSON_TEXT('\"')) { //find the end of the quotation, as white space is preserved within it
- JSON_ASSERT(*p, JSON_TEXT("Null terminator inside of a quotation"));
- switch(*p){
- case JSON_TEXT('\\'):
- result += JSON_TEXT('\\');
- result += (*++p == JSON_TEXT('\"')) ? JSON_TEXT('\1') : *p; //an escaped quote will reak havoc will all of my searching functions, so change it into an illegal character in JSON for convertion later on
- break;
- default:
- result += *p;
- break;
- }
- }
- //no break, let it fall through so that the trailing quote gets added
- default:
- JSON_ASSERT_SAFE((json_uchar)*p >= 32, JSON_TEXT("Invalid JSON character detected (lo)"), goto endofloop;);
- JSON_ASSERT_SAFE((json_uchar)*p <= 126, JSON_TEXT("Invalid JSON character detected (hi)"), goto endofloop;);
- result += *p;
- break;
- }
- ++p;
- }
- #ifdef JSON_SAFE
- endofloop:
- #endif
- return result;
-}
-
-/*
- These three functions analyze json_string literals and convert them into std::strings
- This includes dealing with special characters and utf characters
- */
-#ifdef JSON_UNICODE
- inline json_uchar SurrogatePair(const json_uchar hi, const json_uchar lo){
- JSON_ASSERT(sizeof(unsigned int) == 4, JSON_TEXT("size of unsigned int is not 32-bit"));
- JSON_ASSERT(sizeof(json_uchar) == 4, JSON_TEXT("size of json_char is not 32-bit"));
- return (((hi << 10) & 0x1FFC00) + 0x10000) | lo & 0x3FF;
- }
-
- json_string JSONWorker::UTF(const json_char * & pos){
- json_string result;
- json_uchar first = UTF8(pos);
- if ((*(pos + 1) == '\\') && (*(pos + 2) == 'u')) {
- pos += 2;
- json_uchar second = UTF8(pos);
- //surrogate pair, not two characters
- if ((first > 0xD800) && (first < 0xDBFF) && (second > 0xDC00) && (second < 0xDFFF)) {
- result += SurrogatePair(first, second);
- } else {
- result += first;
- result += second;
- }
- } else {
- result += first;
- }
- JSON_ASSERT(!result.empty(), JSON_TEXT("missing case, somehow UTF returned empty"));
- return result;
- }
-#endif
-
-json_uchar JSONWorker::UTF8(const json_char * & pos){
- #ifdef JSON_UNICODE
- ++pos;
- json_uchar temp = Hex(pos) << 8;
- ++pos;
- return temp | Hex(pos);
- #else
- JSON_ASSERT(*(pos + 1) == JSON_TEXT('0'), JSON_TEXT("wide utf character (hihi)"));
- JSON_ASSERT(*(pos + 2) == JSON_TEXT('0'), JSON_TEXT("wide utf character (hilo)"));
- pos += 3;
- return Hex(pos);
- #endif
-}
-
-static json_char szU8Buffer[10];
-
-json_char* JSONWorker::UTF8_2(const json_char * & pos){
- #ifdef JSON_UNICODE
- ++pos;
- json_uchar temp = Hex(pos) << 8;
- ++pos;
- *szU8Buffer = temp | Hex(pos);
- szU8Buffer[1] = 0;
- return szU8Buffer;
- #else
- union {
- unsigned short uChar;
- unsigned char uByte[2];
- };
- pos++;
- strncpy(szU8Buffer+5,pos,4);
- szU8Buffer[9] = 0;
- uChar = strtoul(szU8Buffer+5,NULL,16);
- if (uChar<0x80) {
- szU8Buffer[0] = uChar;
- szU8Buffer[1] = 0;
- } else if (uChar<0x7ff) {
- szU8Buffer[0] = 0xc0+(uByte[1]<<2)+(uByte[0]>>6);
- szU8Buffer[1] = 0x80+(uByte[0]&0x3f);
- szU8Buffer[2] = 0;
- } else {
- szU8Buffer[0] = 0xe0+(uByte[1]>>4);
- szU8Buffer[1] = 0x80+((uByte[1]&0x0f)<<2)+(uByte[0]>>6);
- szU8Buffer[2] = 0x80+(uByte[0]&0x3f);
- szU8Buffer[3] = 0;
- }
-
- pos += 3;
- return szU8Buffer;
- #endif
-}
-
-
-json_char JSONWorker::Hex(const json_char * & pos){
- /*
- takes the numeric value of the next two characters and convert them
- \u0058 becomes 0x58
-
- In case of \u, it's SpecialChar's responsibility to move past the first two chars
- as this method is also used for \x
- */
- //First character
- json_uchar hi = *pos++ - 48;
- if (hi > 48){ //A-F don't immediately follow 0-9, so have to pull them down a little
- hi -= 39;
- } else if (hi > 9){ //neither do a-f
- hi -= 7;
- }
- //second character
- json_uchar lo = *pos - 48;
- if (lo > 48){ //A-F don't immediately follow 0-9, so have to pull them down a little
- lo -= 39;
- } else if (lo > 9){ //neither do a-f
- lo -= 7;
- }
- //combine them
- return (json_char)((hi << 4) | lo);
-}
-
-inline json_char FromOctal(const json_char * & str){
- JSON_ASSERT(json_strlen(str) > 3, JSON_TEXT("Octal will go out of bounds"));
- const json_uchar top = ((json_uchar)(*(str++) - 48));
- const json_uchar middle = (json_uchar)(*(str++) - 48);
- const json_uchar bottom = (json_uchar)(*str - 48);
- return (json_char)((top << 6) | (middle << 3) | bottom);
-}
-
-void JSONWorker::SpecialChar(const json_char * & pos, json_string & res){
- /*
- Since JSON uses forward slash escaping for special characters within strings, I have to
- convert these escaped characters into C characters
- */
- switch(*pos){
- case JSON_TEXT('\1'): //quote character (altered by RemoveWhiteSpace)
- res += JSON_TEXT('\"');
- break;
- case JSON_TEXT('t'): //tab character
- res += JSON_TEXT('\t');
- break;
- case JSON_TEXT('n'): //newline character
- res += JSON_TEXT('\n');
- break;
- case JSON_TEXT('r'): //return character
- res += JSON_TEXT('\r');
- break;
- case JSON_TEXT('\\'): //backslash
- res += JSON_TEXT('\\');
- break;
- case JSON_TEXT('/'): //forward slash
- res += JSON_TEXT('/');
- break;
- case JSON_TEXT('b'): //backspace
- res += JSON_TEXT('\b');
- break;
- case JSON_TEXT('f'): //formfeed
- res += JSON_TEXT('\f');
- break;
- case JSON_TEXT('v'): //vertical tab
- res += JSON_TEXT('\v');
- break;
- case JSON_TEXT('\''): //apostrophe
- res += JSON_TEXT('\'');
- break;
- case JSON_TEXT('x'): //hexidecimal ascii code
- res += Hex(++pos);
- break;
- case JSON_TEXT('u'): //utf character
- #ifdef JSON_UNICODE
- res += UTF(pos);
- #else
- //res += UTF8(pos);
- res.append(UTF8_2(pos));
- #endif
- break;
-
- //octal encoding
- case JSON_TEXT('1'):
- case JSON_TEXT('2'):
- case JSON_TEXT('3'):
- case JSON_TEXT('4'):
- case JSON_TEXT('5'):
- case JSON_TEXT('6'):
- case JSON_TEXT('7'):
- case JSON_TEXT('0'):
- res += FromOctal(pos);
- break;
-
- #ifdef JSON_DEBUG
- default:
- JSON_FAIL(JSON_TEXT("Unsupported escaped character"));
- #endif
- }
-}
-
-#ifdef JSON_LESS_MEMORY
- inline void doflag(const internalJSONNode * flag, bool which, bool x){
- if (which){
- flag -> _name_encoded = x;
- } else {
- flag -> _string_encoded = x;
- }
- }
-
- json_string JSONWorker::FixString(const json_string & value_t, const internalJSONNode * flag, bool which){
- #define setflag(x) doflag(flag, which, x)
-#else
- json_string JSONWorker::FixString(const json_string & value_t, bool & flag){
- #define setflag(x) flag = x
-#endif
- /*
- Do things like unescaping
- */
- setflag(false);
- json_string res;
- res.reserve(value_t.length()); //since it goes one character at a time, want to reserve it first so that it doens't have to reallocating
- const json_char * p = value_t.c_str();
- while(*p){
- switch (*p){
- case JSON_TEXT('\\'):
- setflag(true);
- SpecialChar(++p, res);
- break;
- default:
- res += *p;
- break;
- }
- ++p;
- }
- return res;
-}
-
-#ifdef JSON_UNICODE
- json_string JSONWorker::toSurrogatePair(json_uchar C){
- JSON_ASSERT(sizeof(unsigned int) == 4, JSON_TEXT("size of unsigned int is not 32-bit"));
- JSON_ASSERT(sizeof(unsigned short) == 2, JSON_TEXT("size of unsigned short is not 16-bit"));
- JSON_ASSERT(sizeof(json_uchar) == 4, JSON_TEXT("json_char is not 32-bit"));
- //Compute the high surrogate
- const unsigned int U = (C >> 16) & 31;
- unsigned short HiSurrogate = 0xD800 | (((unsigned short)U - 1) << 6) | ((unsigned short)C) >> 10;
-
- //compute the low surrogate
- unsigned short LoSurrogate = (unsigned short) (0xDC00 | ((unsigned short)C) & 1023);
-
- json_string res;
- res += toUTF8(HiSurrogate);
- res += toUTF8(LoSurrogate);
- return res;
- }
-#endif
-
-json_string JSONWorker::toUTF8(json_uchar p){
- #ifdef JSON_UNICODE
- if (p > 0xFFFF) return toSurrogatePair(p);
- #endif
- json_string res(JSON_TEXT("\\u"));
- #ifdef JSON_UNICODE
- json_uchar hihi = ((p & 0xF000) >> 12) + 48;
- if (hihi > 57) hihi += 7; //A-F don't immediately follow 0-9, so have to further adjust those
- json_uchar hilo = ((p & 0x0F00) >> 8) + 48;
- if (hilo > 57) hilo += 7; //A-F don't immediately follow 0-9, so have to further adjust those
- res += hihi;
- res += hilo;
- json_uchar hi = ((p & 0x00F0) >> 4) + 48;
- #else
- res += JSON_TEXT("00");
- json_uchar hi = (p >> 4) + 48;
- #endif
- //convert the character to be escaped into two digits between 0 and 15
- if (hi > 57) hi += 7; //A-F don't immediately follow 0-9, so have to further adjust those
- json_uchar lo = (p & 0x000F) + 48;
- if (lo > 57) lo += 7; //A-F don't immediately follow 0-9, so have to further adjust those
- res += hi;
- res += lo;
- return res;
-}
-
-json_string JSONWorker::UnfixString(const json_string & value_t, bool flag){
- if (!flag) return value_t;
- /*
- Re-escapes a json_string so that it can be written out into a JSON file
- */
- json_string res;
- res.reserve(value_t.length()); //since it goes one character at a time, want to reserve it first so that it doens't have to reallocating
- const json_char * p = value_t.c_str();
- while(*p){
- switch(*p){
- case JSON_TEXT('\"'): //quote character
- res += JSON_TEXT("\\\"");
- break;
- case JSON_TEXT('\t'): //tab character
- res += JSON_TEXT("\\t");
- break;
- case JSON_TEXT('\n'): //newline character
- res += JSON_TEXT("\\n");
- break;
- case JSON_TEXT('\r'): //return character
- res += JSON_TEXT("\\r");
- break;
- case JSON_TEXT('\\'): //backslash
- res += JSON_TEXT("\\\\");
- break;
- case JSON_TEXT('/'): //forward slash
- res += JSON_TEXT("\\/");
- break;
- case JSON_TEXT('\b'): //backspace
- res += JSON_TEXT("\\b");
- break;
- case JSON_TEXT('\f'): //formfeed
- res += JSON_TEXT("\\f");
- break;
- case JSON_TEXT('\v'): //vertical tab
- res += JSON_TEXT("\\v");
- break;
- case JSON_TEXT('\''): //apostrophe
- res += JSON_TEXT("\\\'");
- break;
- default:
- /*if (((json_uchar)(*p) < 32) || ((json_uchar)(*p) > 126)) {
- //res += toUTF8((json_uchar)(*p));
- } else*/ {
- res += *p;
- }
- break;
- }
- ++p;
- }
- return res;
-}
-
-
-//Create a childnode
-#ifdef JSON_COMMENTS
- #define ARRAY_PARAM bool array //Just to supress warnings
-#else
- #define ARRAY_PARAM bool
-#endif
-inline void JSONWorker::NewNode(const internalJSONNode * parent, const json_string & name, const json_string & value, ARRAY_PARAM){
- #ifdef JSON_COMMENTS
- const json_char * runner = (array) ? value.c_str() : name.c_str();
- json_string _comment;
- if (*runner == '\5') { //multiple comments will be consolidated into one
- newcomment:
- while(*(++runner) != '\5') {
- JSON_ASSERT(*runner, JSON_TEXT("Removing white space failed"));
- _comment += *runner;
- }
- if (*(++runner) == '\5') { //step past the trailing tag
- _comment += '\n';
- goto newcomment;
- }
- }
- internalJSONNode * myinternal;
- if (array){
- myinternal = internalJSONNode::newInternal(name, runner);
- } else {
- myinternal = internalJSONNode::newInternal(++runner, value);
- }
- JSONNode * child = JSONNode::newJSONNode(myinternal);
- child -> set_comment(_comment);
- const_cast<internalJSONNode*>(parent) -> Children.push_back(child); //attach it to the parent node
- #else
- const_cast<internalJSONNode*>(parent) -> Children.push_back(JSONNode::newJSONNode(internalJSONNode::newInternal(name.c_str() + 1, value))); //attach it to the parent node
- #endif
-}
-
-//Create a subarray
-void JSONWorker::DoArray(const internalJSONNode * parent, const json_string & value_t){
- /*
- This takes an array and creates nodes out of them
- */
- JSON_ASSERT(!value_t.empty(), JSON_TEXT("DoArray is empty"));
- JSON_ASSERT_SAFE(value_t[0] == JSON_TEXT('['), JSON_TEXT("DoArray is not an array"), parent -> Nullify(); return;);
- const size_t len = value_t.length();
- if (len <= 2) return; // just a [] (blank array)
-
- //Not sure what's in the array, so we have to use commas
- size_t starting = 1; //ignore the [
- size_t ending = FindNextRelevant(JSON_TEXT(','), value_t, 1);
- while (ending != json_string::npos){
- #ifdef JSON_SAFE
- json_string newValue = value_t.substr(starting, ending - starting);
- JSON_ASSERT_SAFE(FindNextRelevant(JSON_TEXT(':'), newValue, 0) == json_string::npos, JSON_TEXT("Key/Value pairs are not allowed in arrays"), parent -> Nullify(); return;);
- NewNode(parent, JSON_TEXT(""), newValue, true);
- #else
- NewNode(parent, JSON_TEXT(""), value_t.substr(starting, ending - starting), true);
- #endif
- starting = ending + 1;
- ending = FindNextRelevant(JSON_TEXT(','), value_t, starting);
- }
- //since the last one will not find the comma, we have to add it here, but ignore the final ]
-
- #ifdef JSON_SAFE
- json_string newValue = value_t.substr(starting, len - starting - 1);
- JSON_ASSERT_SAFE(FindNextRelevant(JSON_TEXT(':'), newValue, 0) == json_string::npos, JSON_TEXT("Key/Value pairs are not allowed in arrays"), parent -> Nullify(); return;);
- NewNode(parent, JSON_TEXT(""), newValue, true);
- #else
- NewNode(parent, JSON_TEXT(""), value_t.substr(starting, len - starting - 1), true);
- #endif
-}
-
-
-//Create all child nodes
-void JSONWorker::DoNode(const internalJSONNode * parent, const json_string & value_t){
- /*
- This take a node and creates its members and such
- */
- JSON_ASSERT(!value_t.empty(), JSON_TEXT("DoNode is empty"));
- JSON_ASSERT_SAFE(value_t[0] == JSON_TEXT('{'), JSON_TEXT("DoNode is not an node"), parent -> Nullify(); return;);
- const size_t len = value_t.length();
- if (len <= 2) return; // just a {} (blank node)
-
- size_t name_starting = 1; //ignore the {
- size_t name_ending = FindNextRelevant(JSON_TEXT(':'), value_t, 1); //find where the name ends
- JSON_ASSERT_SAFE(name_ending != json_string::npos, JSON_TEXT("Missing :"), parent -> Nullify(); return;);
- json_string name = value_t.substr(name_starting, name_ending - 2); //pull the name out
- size_t value_ending = FindNextRelevant(JSON_TEXT(','), value_t, name_ending); //find the end of the value
- while (value_ending != json_string::npos){
- NewNode(parent, name, value_t.substr(name_ending + 1, value_ending - name_ending - 1), false);
- name_starting = value_ending + 1;
- name_ending = FindNextRelevant(JSON_TEXT(':'), value_t, name_starting);
- JSON_ASSERT_SAFE(name_ending != json_string::npos, JSON_TEXT("Missing :"), parent -> Nullify(); return;);
- name = value_t.substr(name_starting, name_ending - name_starting - 1);
- value_ending = FindNextRelevant(JSON_TEXT(','), value_t, name_ending);
- }
- //since the last one will not find the comma, we have to add it here
- NewNode(parent, name, value_t.substr(name_ending + 1, len - name_ending - 2), false);
-}
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2009 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "..\..\core\commonheaders.h"
+
+#include "JSONWorker.h"
+
+#ifdef JSON_VALIDATE
+JSONNode JSONWorker::validate(const json_string & json){
+ JSONNode res = parse(json);
+ if (!res.validate()) {
+ throw std::invalid_argument(EMPTY_STRING2);
+ }
+ return JSONNode(true, res); //forces it to simply return the original interal, even with ref counting off
+}
+#endif
+
+JSONNode JSONWorker::parse(const json_string & json){
+ json_auto<json_char> s;
+ #if defined JSON_DEBUG || defined JSON_SAFE
+ json_char lastchar;
+ s.set(RemoveWhiteSpace(json, lastchar));
+ #else
+ s.set(RemoveWhiteSpace(json));
+ #endif
+
+ #ifdef JSON_COMMENTS
+ json_char firstchar = s.ptr[0];
+ json_string _comment;
+ json_char * runner = s.ptr;
+ if (firstchar == '\5') { //multiple comments will be consolidated into one
+ newcomment:
+ while(*(++runner) != '\5') {
+ JSON_ASSERT(*runner, JSON_TEXT("Removing white space failed"));
+ _comment += *runner;
+ }
+ firstchar = *(++runner); //step past the trailing tag
+ if (firstchar == '\5') {
+ _comment += '\n';
+ goto newcomment;
+ }
+ }
+ #else
+ const json_char firstchar = s.ptr[0];
+ #endif
+
+ switch (firstchar){
+ case '{':
+ case '[':
+ #if defined JSON_DEBUG || defined JSON_SAFE
+ if (firstchar == '[') {
+ if (lastchar != ']') {
+ JSON_FAIL(JSON_TEXT("Missing final ]"));
+ break;
+ }
+ } else {
+ if (lastchar != '}') {
+ JSON_FAIL(JSON_TEXT("Missing final }"));
+ break;
+ }
+ }
+ #endif
+ #ifdef JSON_COMMENTS
+ JSONNode foo(runner);
+ foo.set_comment(_comment);
+ return JSONNode(true, foo); //forces it to simply return the original interal, even with ref counting off
+ #else
+ return JSONNode(s.ptr);
+ #endif
+ }
+
+ JSON_FAIL(JSON_TEXT("Not JSON!"));
+ throw std::invalid_argument(EMPTY_STRING2);
+}
+
+#define QUOTECASE()\
+ case JSON_TEXT('\"'):\
+ while (*(++p) != JSON_TEXT('\"')) {\
+ JSON_ASSERT_SAFE(*p, JSON_TEXT("Null terminator inside of a quotation"), return json_string::npos;);\
+ }\
+ break;
+
+#ifdef JSON_DEBUG
+ #define NULLCASE(error)\
+ case JSON_TEXT('\0'):\
+ JSON_FAIL_SAFE(error, return json_string::npos;);\
+ break;
+#else
+ #define NULLCASE(error)
+#endif
+
+#define BRACKET(left, right)\
+ case left: {\
+ size_t brac = 1;\
+ while (brac){\
+ switch (*(++p)) {\
+ case right:\
+ --brac;\
+ break;\
+ case left:\
+ ++brac;\
+ break;\
+ QUOTECASE()\
+ NULLCASE(JSON_TEXT("Null terminator inside of a bracket"))\
+ }\
+ }\
+ break;}\
+ case right:\
+ return json_string::npos;
+
+size_t JSONWorker::FindNextRelevant(json_char ch, const json_string & value_t, const size_t pos){
+ const json_char * start = value_t.c_str();
+ const json_char * p = start + pos; //start at the correct offset
+ do {
+ if (*p == ch) return p - start;
+ switch (*p){
+ BRACKET(JSON_TEXT('['), JSON_TEXT(']'))
+ BRACKET(JSON_TEXT('{'), JSON_TEXT('}'))
+ QUOTECASE()
+ }
+ } while(*(++p));
+ return json_string::npos;
+}
+
+#ifdef JSON_COMMENTS
+ #define COMMENT_DELIMITER() *runner++='\5'
+ #define AND_RUNNER ,runner
+ inline void SingleLineComment(const json_char * & p, json_char * & runner){
+ COMMENT_DELIMITER();
+ while((*(++p)) && (*p != JSON_TEXT('\n'))) {
+ *runner++=*p;
+ }
+ COMMENT_DELIMITER();
+ }
+#else
+ #define COMMENT_DELIMITER() (void)0
+ #define AND_RUNNER
+#endif
+
+inline void SingleLineComment(const json_char * & p){
+ while((*(++p)) && (*p != JSON_TEXT('\n')));
+}
+
+#if defined JSON_DEBUG || defined JSON_SAFE
+ json_char * JSONWorker::RemoveWhiteSpace(const json_string & value_t, json_char & last){
+#else
+ json_char * JSONWorker::RemoveWhiteSpace(const json_string & value_t){
+#endif
+ json_char * result;
+ json_char * runner = result = json_malloc<json_char>(value_t.length() + 1); //dealing with raw memory is faster than adding to a json_string
+ JSON_ASSERT(result, JSON_TEXT("Out of memory"));
+ const json_char * p = value_t.c_str();
+ while(*p){
+ switch(*p){
+ case JSON_TEXT(' '): //defined as white space
+ case JSON_TEXT('\t'): //defined as white space
+ case JSON_TEXT('\n'): //defined as white space
+ case JSON_TEXT('\r'): //defined as white space
+ break;
+ case JSON_TEXT('/'): //a C comment
+ if (*(++p) == JSON_TEXT('*')) { //a multiline comment
+ COMMENT_DELIMITER();
+ while ((*(++p) != JSON_TEXT('*')) || (*(p + 1) != JSON_TEXT('/'))) {
+ JSON_ASSERT_SAFE(*p, JSON_TEXT("Null terminator inside of a multiline quote"), COMMENT_DELIMITER(); goto endofloop;);
+ *runner++=*p;
+ }
+ ++p;
+ COMMENT_DELIMITER();
+ break;
+ }
+ //Should be a single line C comment, so let it fall through to use the bash comment stripper
+ JSON_ASSERT_SAFE(*p == JSON_TEXT('/'), JSON_TEXT("stray / character, not quoted, or a comment"), goto endofloop;);
+ case JSON_TEXT('#'): //a bash comment
+ SingleLineComment(p AND_RUNNER);
+ break;
+ case JSON_TEXT('\"'): //a quote
+ *runner++=JSON_TEXT('\"');
+ while(*(++p) != JSON_TEXT('\"')) { //find the end of the quotation, as white space is preserved within it
+ JSON_ASSERT_SAFE(*p, JSON_TEXT("Null terminator inside of a quotation"), goto endofloop;);
+ switch(*p){
+ case JSON_TEXT('\\'):
+ *runner++=JSON_TEXT('\\');
+ *runner++=(*++p == JSON_TEXT('\"')) ? JSON_TEXT('\1') : *p; //an escaped quote will reak havoc will all of my searching functions, so change it into an illegal character in JSON for convertion later on
+ break;
+ default:
+ *runner++=*p;
+ break;
+ }
+ }
+ //no break, let it fall through so that the trailing quote gets added
+ default:
+ JSON_ASSERT_SAFE((json_uchar)*p >= 32, JSON_TEXT("Invalid JSON character detected (lo)"), goto endofloop;);
+ JSON_ASSERT_SAFE((json_uchar)*p <= 126, JSON_TEXT("Invalid JSON character detected (hi)"), goto endofloop;);
+ *runner++=*p;
+ break;
+ }
+ ++p;
+ }
+ #ifdef JSON_SAFE
+ endofloop:
+ #endif
+ #if defined JSON_DEBUG || defined JSON_SAFE
+ last = *(runner - 1);
+ #endif
+ *runner = JSON_TEXT('\0');
+ return result;
+ }
+
+json_string JSONWorker::RemoveWhiteSpaceAndComments(const json_string & value_t){
+ json_string result;
+ result.reserve(value_t.length());
+ const json_char * p = value_t.c_str();
+ while(*p){
+ switch(*p){
+ case JSON_TEXT(' '): //defined as white space
+ case JSON_TEXT('\t'): //defined as white space
+ case JSON_TEXT('\n'): //defined as white space
+ case JSON_TEXT('\r'): //defined as white space
+ break;
+ case JSON_TEXT('/'): //a C comment
+ if (*(++p) == JSON_TEXT('*')) { //a multiline comment
+ while ((*(++p) != JSON_TEXT('*')) || (*(p + 1) != JSON_TEXT('/'))) {
+ JSON_ASSERT_SAFE(*p, JSON_TEXT("Null terminator inside of a multiline quote"), goto endofloop;);
+ }
+ ++p;
+ break;
+ }
+ //Should be a single line C comment, so let it fall through to use the bash comment stripper
+ JSON_ASSERT_SAFE(*p == JSON_TEXT('/'), JSON_TEXT("stray / character, not quoted, or a comment"), goto endofloop;);
+ case JSON_TEXT('#'): //a bash comment
+ SingleLineComment(p);
+ break;
+ case JSON_TEXT('\"'): //a quote
+ result += JSON_TEXT('\"');
+ while(*(++p) != JSON_TEXT('\"')) { //find the end of the quotation, as white space is preserved within it
+ JSON_ASSERT(*p, JSON_TEXT("Null terminator inside of a quotation"));
+ switch(*p){
+ case JSON_TEXT('\\'):
+ result += JSON_TEXT('\\');
+ result += (*++p == JSON_TEXT('\"')) ? JSON_TEXT('\1') : *p; //an escaped quote will reak havoc will all of my searching functions, so change it into an illegal character in JSON for convertion later on
+ break;
+ default:
+ result += *p;
+ break;
+ }
+ }
+ //no break, let it fall through so that the trailing quote gets added
+ default:
+ JSON_ASSERT_SAFE((json_uchar)*p >= 32, JSON_TEXT("Invalid JSON character detected (lo)"), goto endofloop;);
+ JSON_ASSERT_SAFE((json_uchar)*p <= 126, JSON_TEXT("Invalid JSON character detected (hi)"), goto endofloop;);
+ result += *p;
+ break;
+ }
+ ++p;
+ }
+ #ifdef JSON_SAFE
+ endofloop:
+ #endif
+ return result;
+}
+
+/*
+ These three functions analyze json_string literals and convert them into std::strings
+ This includes dealing with special characters and utf characters
+ */
+#ifdef JSON_UNICODE
+ inline json_uchar SurrogatePair(const json_uchar hi, const json_uchar lo){
+ JSON_ASSERT(sizeof(unsigned int) == 4, JSON_TEXT("size of unsigned int is not 32-bit"));
+ JSON_ASSERT(sizeof(json_uchar) == 4, JSON_TEXT("size of json_char is not 32-bit"));
+ return (((hi << 10) & 0x1FFC00) + 0x10000) | lo & 0x3FF;
+ }
+
+ json_string JSONWorker::UTF(const json_char * & pos){
+ json_string result;
+ json_uchar first = UTF8(pos);
+ if ((*(pos + 1) == '\\') && (*(pos + 2) == 'u')) {
+ pos += 2;
+ json_uchar second = UTF8(pos);
+ //surrogate pair, not two characters
+ if ((first > 0xD800) && (first < 0xDBFF) && (second > 0xDC00) && (second < 0xDFFF)) {
+ result += SurrogatePair(first, second);
+ } else {
+ result += first;
+ result += second;
+ }
+ } else {
+ result += first;
+ }
+ JSON_ASSERT(!result.empty(), JSON_TEXT("missing case, somehow UTF returned empty"));
+ return result;
+ }
+#endif
+
+json_uchar JSONWorker::UTF8(const json_char * & pos){
+ #ifdef JSON_UNICODE
+ ++pos;
+ json_uchar temp = Hex(pos) << 8;
+ ++pos;
+ return temp | Hex(pos);
+ #else
+ JSON_ASSERT(*(pos + 1) == JSON_TEXT('0'), JSON_TEXT("wide utf character (hihi)"));
+ JSON_ASSERT(*(pos + 2) == JSON_TEXT('0'), JSON_TEXT("wide utf character (hilo)"));
+ pos += 3;
+ return Hex(pos);
+ #endif
+}
+
+static json_char szU8Buffer[10];
+
+json_char* JSONWorker::UTF8_2(const json_char * & pos){
+ #ifdef JSON_UNICODE
+ ++pos;
+ json_uchar temp = Hex(pos) << 8;
+ ++pos;
+ *szU8Buffer = temp | Hex(pos);
+ szU8Buffer[1] = 0;
+ return szU8Buffer;
+ #else
+ union {
+ unsigned short uChar;
+ unsigned char uByte[2];
+ };
+ pos++;
+ strncpy(szU8Buffer+5,pos,4);
+ szU8Buffer[9] = 0;
+ uChar = strtoul(szU8Buffer+5,NULL,16);
+ if (uChar<0x80) {
+ szU8Buffer[0] = uChar;
+ szU8Buffer[1] = 0;
+ } else if (uChar<0x7ff) {
+ szU8Buffer[0] = 0xc0+(uByte[1]<<2)+(uByte[0]>>6);
+ szU8Buffer[1] = 0x80+(uByte[0]&0x3f);
+ szU8Buffer[2] = 0;
+ } else {
+ szU8Buffer[0] = 0xe0+(uByte[1]>>4);
+ szU8Buffer[1] = 0x80+((uByte[1]&0x0f)<<2)+(uByte[0]>>6);
+ szU8Buffer[2] = 0x80+(uByte[0]&0x3f);
+ szU8Buffer[3] = 0;
+ }
+
+ pos += 3;
+ return szU8Buffer;
+ #endif
+}
+
+json_char JSONWorker::Hex(const json_char * & pos){
+ /*
+ takes the numeric value of the next two characters and convert them
+ \u0058 becomes 0x58
+
+ In case of \u, it's SpecialChar's responsibility to move past the first two chars
+ as this method is also used for \x
+ */
+ //First character
+ json_uchar hi = *pos++ - 48;
+ if (hi > 48){ //A-F don't immediately follow 0-9, so have to pull them down a little
+ hi -= 39;
+ } else if (hi > 9){ //neither do a-f
+ hi -= 7;
+ }
+ //second character
+ json_uchar lo = *pos - 48;
+ if (lo > 48){ //A-F don't immediately follow 0-9, so have to pull them down a little
+ lo -= 39;
+ } else if (lo > 9){ //neither do a-f
+ lo -= 7;
+ }
+ //combine them
+ return (json_char)((hi << 4) | lo);
+}
+
+inline json_char FromOctal(const json_char * & str){
+ JSON_ASSERT(json_strlen(str) > 3, JSON_TEXT("Octal will go out of bounds"));
+ const json_uchar top = ((json_uchar)(*(str++) - 48));
+ const json_uchar middle = (json_uchar)(*(str++) - 48);
+ const json_uchar bottom = (json_uchar)(*str - 48);
+ return (json_char)((top << 6) | (middle << 3) | bottom);
+}
+
+void JSONWorker::SpecialChar(const json_char * & pos, json_string & res){
+ /*
+ Since JSON uses forward slash escaping for special characters within strings, I have to
+ convert these escaped characters into C characters
+ */
+ switch(*pos){
+ case JSON_TEXT('\1'): //quote character (altered by RemoveWhiteSpace)
+ res += JSON_TEXT('\"');
+ break;
+ case JSON_TEXT('t'): //tab character
+ res += JSON_TEXT('\t');
+ break;
+ case JSON_TEXT('n'): //newline character
+ res += JSON_TEXT('\n');
+ break;
+ case JSON_TEXT('r'): //return character
+ res += JSON_TEXT('\r');
+ break;
+ case JSON_TEXT('\\'): //backslash
+ res += JSON_TEXT('\\');
+ break;
+ case JSON_TEXT('/'): //forward slash
+ res += JSON_TEXT('/');
+ break;
+ case JSON_TEXT('b'): //backspace
+ res += JSON_TEXT('\b');
+ break;
+ case JSON_TEXT('f'): //formfeed
+ res += JSON_TEXT('\f');
+ break;
+ case JSON_TEXT('v'): //vertical tab
+ res += JSON_TEXT('\v');
+ break;
+ case JSON_TEXT('\''): //apostrophe
+ res += JSON_TEXT('\'');
+ break;
+ case JSON_TEXT('x'): //hexidecimal ascii code
+ res += Hex(++pos);
+ break;
+ case JSON_TEXT('u'): //utf character
+ #ifdef JSON_UNICODE
+ res += UTF(pos);
+ #else
+ //res += UTF8(pos);
+ res.append(UTF8_2(pos));
+ #endif
+ break;
+
+ //octal encoding
+ case JSON_TEXT('1'):
+ case JSON_TEXT('2'):
+ case JSON_TEXT('3'):
+ case JSON_TEXT('4'):
+ case JSON_TEXT('5'):
+ case JSON_TEXT('6'):
+ case JSON_TEXT('7'):
+ case JSON_TEXT('0'):
+ res += FromOctal(pos);
+ break;
+
+ #ifdef JSON_DEBUG
+ default:
+ JSON_FAIL(JSON_TEXT("Unsupported escaped character"));
+ #endif
+ }
+}
+
+#ifdef JSON_LESS_MEMORY
+ inline void doflag(const internalJSONNode * flag, bool which, bool x){
+ if (which){
+ flag -> _name_encoded = x;
+ } else {
+ flag -> _string_encoded = x;
+ }
+ }
+
+ json_string JSONWorker::FixString(const json_string & value_t, const internalJSONNode * flag, bool which){
+ #define setflag(x) doflag(flag, which, x)
+#else
+ json_string JSONWorker::FixString(const json_string & value_t, bool & flag){
+ #define setflag(x) flag = x
+#endif
+ /*
+ Do things like unescaping
+ */
+ setflag(false);
+ json_string res;
+ res.reserve(value_t.length()); //since it goes one character at a time, want to reserve it first so that it doens't have to reallocating
+ const json_char * p = value_t.c_str();
+ while(*p){
+ switch (*p){
+ case JSON_TEXT('\\'):
+ setflag(true);
+ SpecialChar(++p, res);
+ break;
+ default:
+ res += *p;
+ break;
+ }
+ ++p;
+ }
+ return res;
+}
+
+#ifdef JSON_UNICODE
+ json_string JSONWorker::toSurrogatePair(json_uchar C){
+ JSON_ASSERT(sizeof(unsigned int) == 4, JSON_TEXT("size of unsigned int is not 32-bit"));
+ JSON_ASSERT(sizeof(unsigned short) == 2, JSON_TEXT("size of unsigned short is not 16-bit"));
+ JSON_ASSERT(sizeof(json_uchar) == 4, JSON_TEXT("json_char is not 32-bit"));
+ //Compute the high surrogate
+ const unsigned int U = (C >> 16) & 31;
+ unsigned short HiSurrogate = 0xD800 | (((unsigned short)U - 1) << 6) | ((unsigned short)C) >> 10;
+
+ //compute the low surrogate
+ unsigned short LoSurrogate = (unsigned short) (0xDC00 | ((unsigned short)C) & 1023);
+
+ json_string res;
+ res += toUTF8(HiSurrogate);
+ res += toUTF8(LoSurrogate);
+ return res;
+ }
+#endif
+
+json_string JSONWorker::toUTF8(json_uchar p){
+ #ifdef JSON_UNICODE
+ if (p > 0xFFFF) return toSurrogatePair(p);
+ #endif
+ json_string res(JSON_TEXT("\\u"));
+ #ifdef JSON_UNICODE
+ json_uchar hihi = ((p & 0xF000) >> 12) + 48;
+ if (hihi > 57) hihi += 7; //A-F don't immediately follow 0-9, so have to further adjust those
+ json_uchar hilo = ((p & 0x0F00) >> 8) + 48;
+ if (hilo > 57) hilo += 7; //A-F don't immediately follow 0-9, so have to further adjust those
+ res += hihi;
+ res += hilo;
+ json_uchar hi = ((p & 0x00F0) >> 4) + 48;
+ #else
+ res += JSON_TEXT("00");
+ json_uchar hi = (p >> 4) + 48;
+ #endif
+ //convert the character to be escaped into two digits between 0 and 15
+ if (hi > 57) hi += 7; //A-F don't immediately follow 0-9, so have to further adjust those
+ json_uchar lo = (p & 0x000F) + 48;
+ if (lo > 57) lo += 7; //A-F don't immediately follow 0-9, so have to further adjust those
+ res += hi;
+ res += lo;
+ return res;
+}
+
+json_string JSONWorker::UnfixString(const json_string & value_t, bool flag){
+ if (!flag) return value_t;
+ /*
+ Re-escapes a json_string so that it can be written out into a JSON file
+ */
+ json_string res;
+ res.reserve(value_t.length()); //since it goes one character at a time, want to reserve it first so that it doens't have to reallocating
+ const json_char * p = value_t.c_str();
+ while(*p){
+ switch(*p){
+ case JSON_TEXT('\"'): //quote character
+ res += JSON_TEXT("\\\"");
+ break;
+ case JSON_TEXT('\t'): //tab character
+ res += JSON_TEXT("\\t");
+ break;
+ case JSON_TEXT('\n'): //newline character
+ res += JSON_TEXT("\\n");
+ break;
+ case JSON_TEXT('\r'): //return character
+ res += JSON_TEXT("\\r");
+ break;
+ case JSON_TEXT('\\'): //backslash
+ res += JSON_TEXT("\\\\");
+ break;
+ case JSON_TEXT('/'): //forward slash
+ res += JSON_TEXT("\\/");
+ break;
+ case JSON_TEXT('\b'): //backspace
+ res += JSON_TEXT("\\b");
+ break;
+ case JSON_TEXT('\f'): //formfeed
+ res += JSON_TEXT("\\f");
+ break;
+ case JSON_TEXT('\v'): //vertical tab
+ res += JSON_TEXT("\\v");
+ break;
+ case JSON_TEXT('\''): //apostrophe
+ res += JSON_TEXT("\\\'");
+ break;
+ default:
+ /*if (((json_uchar)(*p) < 32) || ((json_uchar)(*p) > 126)) {
+ //res += toUTF8((json_uchar)(*p));
+ } else*/ {
+ res += *p;
+ }
+ break;
+ }
+ ++p;
+ }
+ return res;
+}
+
+//Create a childnode
+#ifdef JSON_COMMENTS
+ #define ARRAY_PARAM bool array //Just to supress warnings
+#else
+ #define ARRAY_PARAM bool
+#endif
+inline void JSONWorker::NewNode(const internalJSONNode * parent, const json_string & name, const json_string & value, ARRAY_PARAM){
+ #ifdef JSON_COMMENTS
+ const json_char * runner = (array) ? value.c_str() : name.c_str();
+ json_string _comment;
+ if (*runner == '\5') { //multiple comments will be consolidated into one
+ newcomment:
+ while(*(++runner) != '\5') {
+ JSON_ASSERT(*runner, JSON_TEXT("Removing white space failed"));
+ _comment += *runner;
+ }
+ if (*(++runner) == '\5') { //step past the trailing tag
+ _comment += '\n';
+ goto newcomment;
+ }
+ }
+ internalJSONNode * myinternal;
+ if (array){
+ myinternal = internalJSONNode::newInternal(name, runner);
+ } else {
+ myinternal = internalJSONNode::newInternal(++runner, value);
+ }
+ JSONNode * child = JSONNode::newJSONNode(myinternal);
+ child -> set_comment(_comment);
+ const_cast<internalJSONNode*>(parent) -> Children.push_back(child); //attach it to the parent node
+ #else
+ const_cast<internalJSONNode*>(parent) -> Children.push_back(JSONNode::newJSONNode(internalJSONNode::newInternal(name.c_str() + 1, value))); //attach it to the parent node
+ #endif
+}
+
+//Create a subarray
+void JSONWorker::DoArray(const internalJSONNode * parent, const json_string & value_t){
+ /*
+ This takes an array and creates nodes out of them
+ */
+ JSON_ASSERT(!value_t.empty(), JSON_TEXT("DoArray is empty"));
+ JSON_ASSERT_SAFE(value_t[0] == JSON_TEXT('['), JSON_TEXT("DoArray is not an array"), parent -> Nullify(); return;);
+ const size_t len = value_t.length();
+ if (len <= 2) return; // just a [] (blank array)
+
+ //Not sure what's in the array, so we have to use commas
+ size_t starting = 1; //ignore the [
+ size_t ending = FindNextRelevant(JSON_TEXT(','), value_t, 1);
+ while (ending != json_string::npos){
+ #ifdef JSON_SAFE
+ json_string newValue = value_t.substr(starting, ending - starting);
+ JSON_ASSERT_SAFE(FindNextRelevant(JSON_TEXT(':'), newValue, 0) == json_string::npos, JSON_TEXT("Key/Value pairs are not allowed in arrays"), parent -> Nullify(); return;);
+ NewNode(parent, JSON_TEXT(""), newValue, true);
+ #else
+ NewNode(parent, JSON_TEXT(""), value_t.substr(starting, ending - starting), true);
+ #endif
+ starting = ending + 1;
+ ending = FindNextRelevant(JSON_TEXT(','), value_t, starting);
+ }
+ //since the last one will not find the comma, we have to add it here, but ignore the final ]
+
+ #ifdef JSON_SAFE
+ json_string newValue = value_t.substr(starting, len - starting - 1);
+ JSON_ASSERT_SAFE(FindNextRelevant(JSON_TEXT(':'), newValue, 0) == json_string::npos, JSON_TEXT("Key/Value pairs are not allowed in arrays"), parent -> Nullify(); return;);
+ NewNode(parent, JSON_TEXT(""), newValue, true);
+ #else
+ NewNode(parent, JSON_TEXT(""), value_t.substr(starting, len - starting - 1), true);
+ #endif
+}
+
+//Create all child nodes
+void JSONWorker::DoNode(const internalJSONNode * parent, const json_string & value_t){
+ /*
+ This take a node and creates its members and such
+ */
+ JSON_ASSERT(!value_t.empty(), JSON_TEXT("DoNode is empty"));
+ JSON_ASSERT_SAFE(value_t[0] == JSON_TEXT('{'), JSON_TEXT("DoNode is not an node"), parent -> Nullify(); return;);
+ const size_t len = value_t.length();
+ if (len <= 2) return; // just a {} (blank node)
+
+ size_t name_starting = 1; //ignore the {
+ size_t name_ending = FindNextRelevant(JSON_TEXT(':'), value_t, 1); //find where the name ends
+ JSON_ASSERT_SAFE(name_ending != json_string::npos, JSON_TEXT("Missing :"), parent -> Nullify(); return;);
+ json_string name = value_t.substr(name_starting, name_ending - 2); //pull the name out
+ size_t value_ending = FindNextRelevant(JSON_TEXT(','), value_t, name_ending); //find the end of the value
+ while (value_ending != json_string::npos){
+ NewNode(parent, name, value_t.substr(name_ending + 1, value_ending - name_ending - 1), false);
+ name_starting = value_ending + 1;
+ name_ending = FindNextRelevant(JSON_TEXT(':'), value_t, name_starting);
+ JSON_ASSERT_SAFE(name_ending != json_string::npos, JSON_TEXT("Missing :"), parent -> Nullify(); return;);
+ name = value_t.substr(name_starting, name_ending - name_starting - 1);
+ value_ending = FindNextRelevant(JSON_TEXT(','), value_t, name_ending);
+ }
+ //since the last one will not find the comma, we have to add it here
+ NewNode(parent, name, value_t.substr(name_ending + 1, len - name_ending - 2), false);
+}
diff --git a/src/modules/json/JSONWorker.h b/src/modules/json/JSONWorker.h
index 91a4f6d8c4..f425e12e86 100644
--- a/src/modules/json/JSONWorker.h
+++ b/src/modules/json/JSONWorker.h
@@ -1,46 +1,46 @@
-#ifndef JSON_WORKER_H
-#define JSON_WORKER_H
-
-#include "JSONNode.h"
-
-class JSONWorker {
-public:
- static JSONNode parse(const json_string & json);
- #ifdef JSON_VALIDATE
- static JSONNode validate(const json_string & json);
- #endif
- #if defined JSON_DEBUG || defined JSON_SAFE
- static json_char * RemoveWhiteSpace(const json_string & value_t, json_char & last);
- #else
- static json_char * RemoveWhiteSpace(const json_string & value_t);
- #endif
- static json_string RemoveWhiteSpaceAndComments(const json_string & value_t);
-
- static void DoArray(const internalJSONNode * parent, const json_string & value_t);
- static void DoNode(const internalJSONNode * parent, const json_string & value_t);
-
- #ifdef JSON_LESS_MEMORY
- #define NAME_ENCODED this, true
- #define STRING_ENCODED this, false
- static json_string FixString(const json_string & value_t, const internalJSONNode * flag, bool which);
- #else
- #define NAME_ENCODED _name_encoded
- #define STRING_ENCODED _string_encoded
- static json_string FixString(const json_string & value_t, bool & flag);
- #endif
- static json_string UnfixString(const json_string & value_t, bool flag);
-JSON_PRIVATE
- static json_char Hex(const json_char * & pos);
- static json_uchar UTF8(const json_char * & pos);
- static json_char* UTF8_2(const json_char * & pos);
- static json_string toUTF8(json_uchar p);
- #ifdef JSON_UNICODE
- static json_string UTF(const json_char * & pos);
- static json_string toSurrogatePair(json_uchar pos);
- #endif
- static void SpecialChar(const json_char * & pos, json_string & res);
- static size_t FindNextRelevant(json_char ch, const json_string & value_t, const size_t pos);
- static void NewNode(const internalJSONNode * parent, const json_string & name, const json_string & value, bool array);
-};
-
-#endif
+#ifndef JSON_WORKER_H
+#define JSON_WORKER_H
+
+#include "JSONNode.h"
+
+class JSONWorker {
+public:
+ static JSONNode parse(const json_string & json);
+ #ifdef JSON_VALIDATE
+ static JSONNode validate(const json_string & json);
+ #endif
+ #if defined JSON_DEBUG || defined JSON_SAFE
+ static json_char * RemoveWhiteSpace(const json_string & value_t, json_char & last);
+ #else
+ static json_char * RemoveWhiteSpace(const json_string & value_t);
+ #endif
+ static json_string RemoveWhiteSpaceAndComments(const json_string & value_t);
+
+ static void DoArray(const internalJSONNode * parent, const json_string & value_t);
+ static void DoNode(const internalJSONNode * parent, const json_string & value_t);
+
+ #ifdef JSON_LESS_MEMORY
+ #define NAME_ENCODED this, true
+ #define STRING_ENCODED this, false
+ static json_string FixString(const json_string & value_t, const internalJSONNode * flag, bool which);
+ #else
+ #define NAME_ENCODED _name_encoded
+ #define STRING_ENCODED _string_encoded
+ static json_string FixString(const json_string & value_t, bool & flag);
+ #endif
+ static json_string UnfixString(const json_string & value_t, bool flag);
+JSON_PRIVATE
+ static json_char Hex(const json_char * & pos);
+ static json_uchar UTF8(const json_char * & pos);
+ static json_char* UTF8_2(const json_char * & pos);
+ static json_string toUTF8(json_uchar p);
+ #ifdef JSON_UNICODE
+ static json_string UTF(const json_char * & pos);
+ static json_string toSurrogatePair(json_uchar pos);
+ #endif
+ static void SpecialChar(const json_char * & pos, json_string & res);
+ static size_t FindNextRelevant(json_char ch, const json_string & value_t, const size_t pos);
+ static void NewNode(const internalJSONNode * parent, const json_string & name, const json_string & value, bool array);
+};
+
+#endif
diff --git a/src/modules/json/JSONWriter.cpp b/src/modules/json/JSONWriter.cpp
index 550a03dadd..d141a00a01 100644
--- a/src/modules/json/JSONWriter.cpp
+++ b/src/modules/json/JSONWriter.cpp
@@ -1,173 +1,173 @@
-/*
-
-Miranda IM: the free IM client for Microsoft* Windows*
-
-Copyright 2000-2009 Miranda ICQ/IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#include "..\..\core\commonheaders.h"
-
-#include "JSONNode.h"
-#ifdef JSON_WRITER
-#include "JSONWorker.h"
-
-const static json_string WRITER_EMPTY;
-#ifndef JSON_NEWLINE
- const static json_string NEW_LINE(JSON_TEXT("\n"));
-#else
- const static json_string NEW_LINE(JSON_TEXT(JSON_NEWLINE));
-#endif
-
-#ifdef JSON_INDENT
- const static json_string INDENT(JSON_TEXT(JSON_INDENT));
-
- inline json_string makeIndent(unsigned int amount){
- if (amount == 0xFFFFFFFF) return WRITER_EMPTY;
- json_string result;
- result.reserve(amount);
- for(unsigned int i=0; i < amount; ++i){
- result += INDENT;
- }
- return result;
- }
-#else
- inline json_string makeIndent(unsigned int amount){
- if (amount == 0xFFFFFFFF) return WRITER_EMPTY;
- return json_string(amount, JSON_TEXT('\t'));
- }
-#endif
-
-json_string internalJSONNode::WriteName(bool formatted, bool arrayChild) const {
- if (arrayChild){
- return WRITER_EMPTY ;
- } else {
- return JSON_TEXT("\"") + JSONWorker::UnfixString(_name, _name_encoded) + ((formatted) ? JSON_TEXT("\" : ") : JSON_TEXT("\":"));
- }
-}
-
-json_string internalJSONNode::WriteChildren(unsigned int indent){
- //Iterate through the children and write them
- if (Children.empty()) return WRITER_EMPTY;
-
- json_string indent_plus_one;
- json_string indent_this;
- json_string res;
- //handle whether or not it's formatted JSON
- if (indent != 0xFFFFFFFF){ //it's formatted, make the indentation strings
- indent_this = NEW_LINE + makeIndent(indent);
- indent_plus_one = NEW_LINE + makeIndent(++indent);
- }
- //else it's not formatted, leave the indentation strings empty
- const size_t size_minus_one = Children.size() - 1;
- size_t i=0;
- json_foreach(Children, it){
- res += indent_plus_one + (*it) -> internal -> Write(indent, type() == JSON_ARRAY);
- if (i < size_minus_one) res += JSON_TEXT(","); //the last one does not get a comma, but all of the others do
- ++i;
- }
- return res + indent_this;
-}
-
-#ifdef JSON_COMMENTS
- #ifdef JSON_WRITE_BASH_COMMENTS
- const static json_string SINGLELINE(JSON_TEXT("#"));
- #else
- const static json_string SINGLELINE(JSON_TEXT("//"));
- #endif
-
- json_string internalJSONNode::WriteComment(unsigned int indent) const {
- if (indent == 0xFFFFFFFF) return WRITER_EMPTY;
- if (_comment.empty()) return WRITER_EMPTY;
- size_t pos = _comment.find(JSON_TEXT('\n'));
- if (pos == json_string::npos){ //Single line comment
- return NEW_LINE + makeIndent(indent) + SINGLELINE + _comment + NEW_LINE + makeIndent(indent);
- }
-
- /*
- Multiline comments
- */
- #if defined(JSON_WRITE_BASH_COMMENTS) || defined(JSON_WRITE_SINGLE_LINE_COMMENTS)
- json_string result(NEW_LINE + makeIndent(indent));
- #else
- json_string result(NEW_LINE + makeIndent(indent) + JSON_TEXT("/*") + NEW_LINE + makeIndent(indent + 1));
- #endif
- size_t old = 0;
- while(pos != json_string::npos){
- if (pos && _comment[pos - 1] == JSON_TEXT('\r')) --pos;
- #if defined(JSON_WRITE_BASH_COMMENTS) || defined(JSON_WRITE_SINGLE_LINE_COMMENTS)
- result += SINGLELINE;
- #endif
- result += _comment.substr(old, pos - old) + NEW_LINE;
- #if defined(JSON_WRITE_BASH_COMMENTS) || defined(JSON_WRITE_SINGLE_LINE_COMMENTS)
- result += makeIndent(indent);
- #else
- result += makeIndent(indent + 1);
- #endif
- old = (_comment[pos] == JSON_TEXT('\r')) ? pos + 2 : pos + 1;
- pos = _comment.find(JSON_TEXT('\n'), old);
- }
- #if defined(JSON_WRITE_BASH_COMMENTS) || defined(JSON_WRITE_SINGLE_LINE_COMMENTS)
- result += SINGLELINE;
- #endif
- result += _comment.substr(old, pos - old) + NEW_LINE + makeIndent(indent);
- #if defined(JSON_WRITE_BASH_COMMENTS) || defined(JSON_WRITE_SINGLE_LINE_COMMENTS)
- return result;
- #else
- return result + JSON_TEXT("*/") + NEW_LINE + makeIndent(indent);
- #endif
- }
-#else
- json_string internalJSONNode::WriteComment(unsigned int) const {
- return WRITER_EMPTY;
- }
-#endif
-
-json_string internalJSONNode::Write(unsigned int indent, bool arrayChild){
- const bool formatted = indent != 0xFFFFFFFF;
-
- #ifndef JSON_PREPARSE
- if (!(formatted || fetched)) { //It's not formatted or fetched, just do a raw dump
- return WriteComment(indent) + WriteName(false, arrayChild) + _string;
- }
- #endif
-
- //It's either formatted or fetched
- switch (type()) {
- case JSON_NODE: //got members, write the members
- Fetch();
- return WriteComment(indent) + WriteName(formatted, arrayChild) + JSON_TEXT("{") + WriteChildren(indent) + JSON_TEXT("}");
- case JSON_ARRAY: //write out the child nodes int he array
- Fetch();
- return WriteComment(indent) + WriteName(formatted, arrayChild) + JSON_TEXT("[") + WriteChildren(indent) + JSON_TEXT("]");
- case JSON_NUMBER: //write out a literal, without quotes
- case JSON_NULL:
- case JSON_BOOL:
- return WriteComment(indent) + WriteName(formatted, arrayChild) + _string;
- }
-
- JSON_ASSERT_SAFE(type() == JSON_STRING, JSON_TEXT("Writing an unknown JSON node type"), return JSON_TEXT(""););
- //If it go here, then it's a json_string
- #ifndef JSON_PREPARSE
- if (fetched) return WriteComment(indent) + WriteName(formatted, arrayChild) + JSON_TEXT("\"") + JSONWorker::UnfixString(_string, _string_encoded) + JSON_TEXT("\""); //It's already been fetched, meaning that it's unescaped
- return WriteComment(indent) + WriteName(formatted, arrayChild) + _string; //it hasn't yet been fetched, so it's already unescaped, just do a dump
- #else
- return WriteComment(indent) + WriteName(formatted, arrayChild) + JSON_TEXT("\"") + JSONWorker::UnfixString(_string, _string_encoded) + JSON_TEXT("\"");
- #endif
-}
-#endif
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2009 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "..\..\core\commonheaders.h"
+
+#include "JSONNode.h"
+#ifdef JSON_WRITER
+#include "JSONWorker.h"
+
+const static json_string WRITER_EMPTY;
+#ifndef JSON_NEWLINE
+ const static json_string NEW_LINE(JSON_TEXT("\n"));
+#else
+ const static json_string NEW_LINE(JSON_TEXT(JSON_NEWLINE));
+#endif
+
+#ifdef JSON_INDENT
+ const static json_string INDENT(JSON_TEXT(JSON_INDENT));
+
+ inline json_string makeIndent(unsigned int amount){
+ if (amount == 0xFFFFFFFF) return WRITER_EMPTY;
+ json_string result;
+ result.reserve(amount);
+ for(unsigned int i=0; i < amount; ++i){
+ result += INDENT;
+ }
+ return result;
+ }
+#else
+ inline json_string makeIndent(unsigned int amount){
+ if (amount == 0xFFFFFFFF) return WRITER_EMPTY;
+ return json_string(amount, JSON_TEXT('\t'));
+ }
+#endif
+
+json_string internalJSONNode::WriteName(bool formatted, bool arrayChild) const {
+ if (arrayChild){
+ return WRITER_EMPTY ;
+ } else {
+ return JSON_TEXT("\"") + JSONWorker::UnfixString(_name, _name_encoded) + ((formatted) ? JSON_TEXT("\" : ") : JSON_TEXT("\":"));
+ }
+}
+
+json_string internalJSONNode::WriteChildren(unsigned int indent){
+ //Iterate through the children and write them
+ if (Children.empty()) return WRITER_EMPTY;
+
+ json_string indent_plus_one;
+ json_string indent_this;
+ json_string res;
+ //handle whether or not it's formatted JSON
+ if (indent != 0xFFFFFFFF){ //it's formatted, make the indentation strings
+ indent_this = NEW_LINE + makeIndent(indent);
+ indent_plus_one = NEW_LINE + makeIndent(++indent);
+ }
+ //else it's not formatted, leave the indentation strings empty
+ const size_t size_minus_one = Children.size() - 1;
+ size_t i=0;
+ json_foreach(Children, it){
+ res += indent_plus_one + (*it) -> internal -> Write(indent, type() == JSON_ARRAY);
+ if (i < size_minus_one) res += JSON_TEXT(","); //the last one does not get a comma, but all of the others do
+ ++i;
+ }
+ return res + indent_this;
+}
+
+#ifdef JSON_COMMENTS
+ #ifdef JSON_WRITE_BASH_COMMENTS
+ const static json_string SINGLELINE(JSON_TEXT("#"));
+ #else
+ const static json_string SINGLELINE(JSON_TEXT("//"));
+ #endif
+
+ json_string internalJSONNode::WriteComment(unsigned int indent) const {
+ if (indent == 0xFFFFFFFF) return WRITER_EMPTY;
+ if (_comment.empty()) return WRITER_EMPTY;
+ size_t pos = _comment.find(JSON_TEXT('\n'));
+ if (pos == json_string::npos){ //Single line comment
+ return NEW_LINE + makeIndent(indent) + SINGLELINE + _comment + NEW_LINE + makeIndent(indent);
+ }
+
+ /*
+ Multiline comments
+ */
+ #if defined(JSON_WRITE_BASH_COMMENTS) || defined(JSON_WRITE_SINGLE_LINE_COMMENTS)
+ json_string result(NEW_LINE + makeIndent(indent));
+ #else
+ json_string result(NEW_LINE + makeIndent(indent) + JSON_TEXT("/*") + NEW_LINE + makeIndent(indent + 1));
+ #endif
+ size_t old = 0;
+ while(pos != json_string::npos){
+ if (pos && _comment[pos - 1] == JSON_TEXT('\r')) --pos;
+ #if defined(JSON_WRITE_BASH_COMMENTS) || defined(JSON_WRITE_SINGLE_LINE_COMMENTS)
+ result += SINGLELINE;
+ #endif
+ result += _comment.substr(old, pos - old) + NEW_LINE;
+ #if defined(JSON_WRITE_BASH_COMMENTS) || defined(JSON_WRITE_SINGLE_LINE_COMMENTS)
+ result += makeIndent(indent);
+ #else
+ result += makeIndent(indent + 1);
+ #endif
+ old = (_comment[pos] == JSON_TEXT('\r')) ? pos + 2 : pos + 1;
+ pos = _comment.find(JSON_TEXT('\n'), old);
+ }
+ #if defined(JSON_WRITE_BASH_COMMENTS) || defined(JSON_WRITE_SINGLE_LINE_COMMENTS)
+ result += SINGLELINE;
+ #endif
+ result += _comment.substr(old, pos - old) + NEW_LINE + makeIndent(indent);
+ #if defined(JSON_WRITE_BASH_COMMENTS) || defined(JSON_WRITE_SINGLE_LINE_COMMENTS)
+ return result;
+ #else
+ return result + JSON_TEXT("*/") + NEW_LINE + makeIndent(indent);
+ #endif
+ }
+#else
+ json_string internalJSONNode::WriteComment(unsigned int) const {
+ return WRITER_EMPTY;
+ }
+#endif
+
+json_string internalJSONNode::Write(unsigned int indent, bool arrayChild){
+ const bool formatted = indent != 0xFFFFFFFF;
+
+ #ifndef JSON_PREPARSE
+ if (!(formatted || fetched)) { //It's not formatted or fetched, just do a raw dump
+ return WriteComment(indent) + WriteName(false, arrayChild) + _string;
+ }
+ #endif
+
+ //It's either formatted or fetched
+ switch (type()) {
+ case JSON_NODE: //got members, write the members
+ Fetch();
+ return WriteComment(indent) + WriteName(formatted, arrayChild) + JSON_TEXT("{") + WriteChildren(indent) + JSON_TEXT("}");
+ case JSON_ARRAY: //write out the child nodes int he array
+ Fetch();
+ return WriteComment(indent) + WriteName(formatted, arrayChild) + JSON_TEXT("[") + WriteChildren(indent) + JSON_TEXT("]");
+ case JSON_NUMBER: //write out a literal, without quotes
+ case JSON_NULL:
+ case JSON_BOOL:
+ return WriteComment(indent) + WriteName(formatted, arrayChild) + _string;
+ }
+
+ JSON_ASSERT_SAFE(type() == JSON_STRING, JSON_TEXT("Writing an unknown JSON node type"), return JSON_TEXT(""););
+ //If it go here, then it's a json_string
+ #ifndef JSON_PREPARSE
+ if (fetched) return WriteComment(indent) + WriteName(formatted, arrayChild) + JSON_TEXT("\"") + JSONWorker::UnfixString(_string, _string_encoded) + JSON_TEXT("\""); //It's already been fetched, meaning that it's unescaped
+ return WriteComment(indent) + WriteName(formatted, arrayChild) + _string; //it hasn't yet been fetched, so it's already unescaped, just do a dump
+ #else
+ return WriteComment(indent) + WriteName(formatted, arrayChild) + JSON_TEXT("\"") + JSONWorker::UnfixString(_string, _string_encoded) + JSON_TEXT("\"");
+ #endif
+}
+#endif
diff --git a/src/modules/json/NumberToString.h b/src/modules/json/NumberToString.h
index 35c6c98d0a..cf81f2ef22 100644
--- a/src/modules/json/NumberToString.h
+++ b/src/modules/json/NumberToString.h
@@ -1,104 +1,104 @@
-#ifndef NUMBERTOSTRING_H
-#define NUMBERTOSTRING_H
-
-#include "JSONDebug.h"
-#include "JSONMemory.h"
-#include <cstdio>
-
-static unsigned int getlen(unsigned int size){
- switch (size){
- case 1:
- return 5; //3 digits for the number, plus null terminator and negation
- case 2:
- return 7; //5 digits for the number, plus null terminator and negation
- case 4:
- return 12; //10 digits for the number, plus null terminator and negation
- case 8:
- return 22; //20 digits for the number, plus null terminator and negation
- }
- JSON_ASSERT(size == 16, JSON_TEXT("template is not recognized 2^x in size"));
- return 41; //39 digits for the number, plus null terminator and negation
-}
-
-class NumberToString {
-public:
- template<typename T>
- static json_string _itoa(T val, unsigned int size){
- long value = (long)val;
- const unsigned int digits = getlen(size);
- json_auto<json_char> result(digits);
- result.ptr[digits - 1] = JSON_TEXT('\0'); //null terminator
- json_char * runner = &result.ptr[digits - 2];
- bool negative;
-
- //first thing, check if it's negative, if so, make it positive
- if (value < 0){
- value = -value;
- negative = true;
- } else {
- negative = false;
- }
-
- //create the string
- do {
- *runner--=(json_char)(value % 10) + JSON_TEXT('0');
- } while(value /= 10);
-
- //if it's negative, add the negation
- json_string res;
- if (negative){
- *runner = JSON_TEXT('-');
- res = runner;
- } else {
- res = runner + 1;
- }
- return res;
- }
-
- #ifndef JSON_LIBRARY
- template<typename T>
- static json_string _uitoa(T val, unsigned int size){
- unsigned long value = val;
- const unsigned int digits = getlen(size) - 1; //minus one because no '-' char
- json_auto<json_char> result(digits);
- result.ptr[digits - 1] = JSON_TEXT('\0'); //null terminator
- json_char * runner = &result.ptr[digits - 2];
-
- //create the string
- do {
- *runner--=(json_char)(value % 10) + JSON_TEXT('0');
- } while(value /= 10);
-
- json_string res = runner + 1;
- return res;
- }
- #endif
-
- template<typename T>
- static json_string _ftoa(T value){
- json_char result[64];
- #ifdef JSON_UNICODE
- swprintf(result, 63, L"%f", value);
- #else
- snprintf(result, 63, "%f", value);
- #endif
- //strip the trailing zeros
- for(json_char * pos = &result[0]; *pos; ++pos){
- if (*pos == '.') { //only care about after the decimal
- for(json_char * runner = pos + 1; *runner; ++runner){
- if (*runner != JSON_TEXT('0')) pos = runner + 1;
- }
- *pos = JSON_TEXT('\0');
- break;
- }
- }
- return result;
- }
-
- static inline bool areEqual(const json_number & one, const json_number & two){
- const json_number temp = one - two;
- return (temp > 0.0) ? temp < 0.00001 : temp > -0.00001;
- }
-};
-
-#endif
+#ifndef NUMBERTOSTRING_H
+#define NUMBERTOSTRING_H
+
+#include "JSONDebug.h"
+#include "JSONMemory.h"
+#include <cstdio>
+
+static unsigned int getlen(unsigned int size){
+ switch (size){
+ case 1:
+ return 5; //3 digits for the number, plus null terminator and negation
+ case 2:
+ return 7; //5 digits for the number, plus null terminator and negation
+ case 4:
+ return 12; //10 digits for the number, plus null terminator and negation
+ case 8:
+ return 22; //20 digits for the number, plus null terminator and negation
+ }
+ JSON_ASSERT(size == 16, JSON_TEXT("template is not recognized 2^x in size"));
+ return 41; //39 digits for the number, plus null terminator and negation
+}
+
+class NumberToString {
+public:
+ template<typename T>
+ static json_string _itoa(T val, unsigned int size){
+ long value = (long)val;
+ const unsigned int digits = getlen(size);
+ json_auto<json_char> result(digits);
+ result.ptr[digits - 1] = JSON_TEXT('\0'); //null terminator
+ json_char * runner = &result.ptr[digits - 2];
+ bool negative;
+
+ //first thing, check if it's negative, if so, make it positive
+ if (value < 0){
+ value = -value;
+ negative = true;
+ } else {
+ negative = false;
+ }
+
+ //create the string
+ do {
+ *runner--=(json_char)(value % 10) + JSON_TEXT('0');
+ } while(value /= 10);
+
+ //if it's negative, add the negation
+ json_string res;
+ if (negative){
+ *runner = JSON_TEXT('-');
+ res = runner;
+ } else {
+ res = runner + 1;
+ }
+ return res;
+ }
+
+ #ifndef JSON_LIBRARY
+ template<typename T>
+ static json_string _uitoa(T val, unsigned int size){
+ unsigned long value = val;
+ const unsigned int digits = getlen(size) - 1; //minus one because no '-' char
+ json_auto<json_char> result(digits);
+ result.ptr[digits - 1] = JSON_TEXT('\0'); //null terminator
+ json_char * runner = &result.ptr[digits - 2];
+
+ //create the string
+ do {
+ *runner--=(json_char)(value % 10) + JSON_TEXT('0');
+ } while(value /= 10);
+
+ json_string res = runner + 1;
+ return res;
+ }
+ #endif
+
+ template<typename T>
+ static json_string _ftoa(T value){
+ json_char result[64];
+ #ifdef JSON_UNICODE
+ swprintf(result, 63, L"%f", value);
+ #else
+ snprintf(result, 63, "%f", value);
+ #endif
+ //strip the trailing zeros
+ for(json_char * pos = &result[0]; *pos; ++pos){
+ if (*pos == '.') { //only care about after the decimal
+ for(json_char * runner = pos + 1; *runner; ++runner){
+ if (*runner != JSON_TEXT('0')) pos = runner + 1;
+ }
+ *pos = JSON_TEXT('\0');
+ break;
+ }
+ }
+ return result;
+ }
+
+ static inline bool areEqual(const json_number & one, const json_number & two){
+ const json_number temp = one - two;
+ return (temp > 0.0) ? temp < 0.00001 : temp > -0.00001;
+ }
+};
+
+#endif
diff --git a/src/modules/json/libJSON.cpp b/src/modules/json/libJSON.cpp
index 0312898299..a40dde4773 100644
--- a/src/modules/json/libJSON.cpp
+++ b/src/modules/json/libJSON.cpp
@@ -1,506 +1,505 @@
-/*
-
-Miranda IM: the free IM client for Microsoft* Windows*
-
-Copyright 2000-2009 Miranda ICQ/IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#include "..\..\core\commonheaders.h"
-
-#include "libJSON.h"
-
-/*
- This is the implementation of the C interface to libJSON
- This file may be included in any C++ application, but it will
- be completely ignored if JSON_LIBRARY isn't defined. The
- only reason JSON_LIBRARY should be defined is when compiling libJSON
- as a library
-*/
-
-#ifdef JSON_LIBRARY
-
- #include "JSONNode.h"
- #include "JSONWorker.h"
- #include <stdexcept> //some methods throw exceptions
- #ifdef JSON_MEMORY_MANAGE
- auto_expand StringHandler;
- auto_expand_node NodeHandler;
- #define MANAGER_INSERT(x) NodeHandler.insert(x)
- #else
- #define MANAGER_INSERT(x) x
- #endif
-
- #ifdef JSON_SAFE
- static const json_char * EMPTY_CSTRING = JSON_TEXT("");
- #endif
-
- inline json_char * toCString(const json_string & str){
- const size_t len((str.length() + 1) * sizeof(json_char));
- #ifdef JSON_MEMORY_MANAGE
- return (json_char *)StringHandler.insert(memcpy(json_malloc<json_char>(len), str.c_str(), len));
- #else
- return (json_char *)memcpy(json_malloc<json_char>(len), str.c_str(), len);
- #endif
- }
-
- /*
- stuff that's in namespace libJSON
- */
- void json_free(void * str){
- JSON_ASSERT_SAFE(str, JSON_TEXT("freeing null ptr"), return;);
- #ifdef JSON_MEMORY_MANAGE
- StringHandler.remove(str);
- #endif
- libjson_free<void>(str);
- }
-
- void json_delete(JSONNODE * node){
- JSON_ASSERT_SAFE(node, JSON_TEXT("deleting null ptr"), return;);
- #ifdef JSON_MEMORY_MANAGE
- NodeHandler.remove(node);
- #endif
- JSONNode::deleteJSONNode((JSONNode *)node);
- }
-
- #ifdef JSON_MEMORY_MANAGE
- void json_free_all(void){
- StringHandler.clear();
- }
-
- void json_delete_all(void){
- NodeHandler.clear();
- }
- #endif
-
- JSONNODE * json_parse(const json_char * json){
- JSON_ASSERT_SAFE(json, JSON_TEXT("null ptr to json_parse"), return 0;);
- try {
- //use this constructor to simply copy reference instead of copying the temp
- return MANAGER_INSERT(JSONNode::newJSONNode_Shallow(JSONWorker::parse(json)));
- } catch (std::invalid_argument){}
- return 0;
- }
-
- json_char * json_strip_white_space(const json_char * json){
- JSON_ASSERT_SAFE(json, JSON_TEXT("null ptr to json_strip_white_space"), return 0;);
- return toCString(JSONWorker::RemoveWhiteSpaceAndComments(json));
- }
-
- #ifdef JSON_VALIDATE
- JSONNODE * json_validate(const json_char * json){
- JSON_ASSERT_SAFE(json, JSON_TEXT("null ptr to json_validate"), return 0;);
- try {
- //use this constructor to simply copy reference instead of copying the temp
- return MANAGER_INSERT(JSONNode::newJSONNode_Shallow(JSONWorker::validate(json)));
- } catch (std::invalid_argument){}
- return 0;
- }
- #endif
-
- #if defined JSON_DEBUG && !defined JSON_STDERROR
- //When libjson errors, a callback allows the user to know what went wrong
- void json_register_debug_callback(json_error_callback_t callback){
- JSONDebug::register_callback(callback);
- }
- #endif
-
- #ifdef JSON_MUTEX_CALLBACKS
- #ifdef JSON_MUTEX_MANAGE
- void json_register_mutex_callbacks(json_mutex_callback_t lock, json_mutex_callback_t unlock, json_mutex_callback_t destroy, void * manager_lock){
- JSONNode::register_mutex_callbacks(lock, unlock, manager_lock);
- JSONNode::register_mutex_destructor(destroy);
- }
-
- #else
- void json_register_mutex_callbacks(json_mutex_callback_t lock, json_mutex_callback_t unlock, void * manager_lock){
- JSONNode::register_mutex_callbacks(lock, unlock, manager_lock);
- }
- #endif
-
- void json_set_global_mutex(void * mutex){
- JSONNode::set_global_mutex(mutex);
- }
-
- void json_set_mutex(JSONNODE * node, void * mutex){
- JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_set_mutex"), return;);
- ((JSONNode*)node) -> set_mutex(mutex);
- }
-
- void json_lock(JSONNODE * node, int threadid){
- JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_lock"), return;);
- ((JSONNode*)node) -> lock(threadid);
- }
-
- void json_unlock(JSONNODE * node, int threadid){
- JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_unlock"), return;);
- ((JSONNode*)node) -> unlock(threadid);
- }
- #endif
-
- #ifdef JSON_MEMORY_CALLBACKS
- void json_register_memory_callbacks(json_malloc_t mal, json_realloc_t real, json_free_t fre){
- JSONMemory::registerMemoryCallbacks(mal, real, fre);
- }
- #endif
-
-
- /*
- stuff that's in class JSONNode
- */
- //ctors
- JSONNODE * json_new_a(const json_char * name, const json_char * value){
- JSON_ASSERT_SAFE(name, JSON_TEXT("null name to json_new_a"), name = EMPTY_CSTRING;);
- JSON_ASSERT_SAFE(value, JSON_TEXT("null value to json_new_a"), value = EMPTY_CSTRING;);
- #ifdef JSON_MEMORY_CALLBACKS
- return MANAGER_INSERT(new(json_malloc<JSONNode>(1)) JSONNode(name, json_string(value)));
- #else
- return MANAGER_INSERT(new JSONNode(name, json_string(value)));
- #endif
- }
-
- JSONNODE * json_new_i(const json_char * name, long value){
- JSON_ASSERT_SAFE(name, JSON_TEXT("null name to json_new_i"), name = EMPTY_CSTRING;);
- #ifdef JSON_MEMORY_CALLBACKS
- return MANAGER_INSERT(new(json_malloc<JSONNode>(1)) JSONNode(name, value));
- #else
- return MANAGER_INSERT(new JSONNode(name, value));
- #endif
- }
-
- JSONNODE * json_new_f(const json_char * name, json_number value){
- JSON_ASSERT_SAFE(name, JSON_TEXT("null name to json_new_f"), name = EMPTY_CSTRING;);
- #ifdef JSON_MEMORY_CALLBACKS
- return MANAGER_INSERT(new(json_malloc<JSONNode>(1)) JSONNode(name, value));
- #else
- return MANAGER_INSERT(new JSONNode(name, value));
- #endif
- }
-
- JSONNODE * json_new_b(const json_char * name, int value){
- JSON_ASSERT_SAFE(name, JSON_TEXT("null name to json_new_b"), name = EMPTY_CSTRING;);
- #ifdef JSON_MEMORY_CALLBACKS
- return MANAGER_INSERT(new(json_malloc<JSONNode>(1)) JSONNode(name, value != 0 ));
- #else
- return MANAGER_INSERT(new JSONNode(name, (bool)value)) != 0;
- #endif
- }
-
- JSONNODE * json_new(char type){
- #ifdef JSON_MEMORY_CALLBACKS
- return MANAGER_INSERT(new(json_malloc<JSONNode>(1)) JSONNode(type));
- #else
- return MANAGER_INSERT(new JSONNode(type));
- #endif
- }
-
- JSONNODE * json_copy(const JSONNODE * orig){
- JSON_ASSERT_SAFE(orig, JSON_TEXT("null orig to json_copy"), return 0;);
- #ifdef JSON_MEMORY_CALLBACKS
- return MANAGER_INSERT(new(json_malloc<JSONNode>(1)) JSONNode(*((JSONNode*)orig)));
- #else
- return MANAGER_INSERT(new JSONNode(*((JSONNode*)orig)));
- #endif
- }
-
- JSONNODE * json_duplicate(const JSONNODE * orig){
- JSON_ASSERT_SAFE(orig, JSON_TEXT("null orig to json_duplicate"), return 0;);
- return MANAGER_INSERT(JSONNode::newJSONNode_Shallow(((JSONNode*)orig) -> duplicate()));
- }
-
- //assignment
- void json_set_a(JSONNODE * node, const json_char * value){
- JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_set_a"), return;);
- JSON_ASSERT_SAFE(value, JSON_TEXT("null value to json_set_a"), value = EMPTY_CSTRING;);
- *((JSONNode*)node) = json_string(value);
- }
-
- void json_set_i(JSONNODE * node, long value){
- JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_set_i"), return;);
- *((JSONNode*)node) = value;
- }
-
- void json_set_f(JSONNODE * node, json_number value){
- JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_set_f"), return;);
- *((JSONNode*)node) = value;
- }
-
- void json_set_b(JSONNODE * node, int value){
- JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_set_b"), return;);
- *((JSONNode*)node) = value != 0;
- }
-
- void json_set_n(JSONNODE * node, const JSONNODE * orig){
- JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_set_n"), return;);
- JSON_ASSERT_SAFE(orig, JSON_TEXT("null node to json_set_n"), return;);
- *((JSONNode*)node) = *((JSONNode*)orig);
- }
-
- //inspectors
- char json_type(const JSONNODE * node){
- JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_type"), return JSON_NULL;);
- return ((JSONNode*)node) -> type();
- }
-
- json_index_t json_size(const JSONNODE * node){
- JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_size"), return 0;);
- return ((JSONNode*)node) -> size();
- }
-
- int json_empty(const JSONNODE * node){
- JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_empty"), return true;);
- return (int)(((JSONNode*)node) -> empty());
- }
-
- json_char * json_name(const JSONNODE * node){
- JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_name"), return toCString(EMPTY_CSTRING););
- return toCString(((JSONNode*)node) -> name());
- }
-
- #ifdef JSON_COMMENTS
- json_char * json_get_comment(const JSONNODE * node){
- JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_get_comment"), return toCString(EMPTY_CSTRING););
- return toCString(((JSONNode*)node) -> get_comment());
- }
- #endif
-
- json_char * json_as_string(const JSONNODE * node){
- JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_as_string"), return toCString(EMPTY_CSTRING););
- return toCString(((JSONNode*)node) -> as_string());
- }
-
- long json_as_int(const JSONNODE * node){
- JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_as_int"), return 0;);
- return ((JSONNode*)node) -> as_int();
- }
-
- json_number json_as_float(const JSONNODE * node){
- JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_as_float"), return 0.0;);
- return ((JSONNode*)node) -> as_float();
- }
-
- int json_as_bool(const JSONNODE * node){
- JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_as_bool"), return false;);
- return (int)(((JSONNode*)node) -> as_bool());
- }
-
- JSONNODE * json_as_node(const JSONNODE * node){
- JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_as_node"), return 0;);
- return MANAGER_INSERT(JSONNode::newJSONNode_Shallow(((JSONNode*)node) -> as_node()));
- }
-
- JSONNODE * json_as_array(const JSONNODE * node){
- JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_as_array"), return 0;);
- return MANAGER_INSERT(JSONNode::newJSONNode_Shallow(((JSONNode*)node) -> as_array()));
- }
-
- #ifdef JSON_BINARY
- void * json_as_binary(const JSONNODE * node, unsigned long * size){
- JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_as_binary"), if (size){*size = 0;} return 0;);
- const std::string result = ((JSONNode*)node) -> as_binary();
- const size_t len = result.length();
- if (size) *size = len;
- #ifdef JSON_SAFE
- if (result.empty()) return 0;
- #endif
- #ifdef JSON_MEMORY_MANAGE
- return StringHandler.insert(memcpy(json_malloc<char>(len), result.data(), len));
- #else
- return memcpy(json_malloc<char>(len), result.data(), len);
- #endif
- }
- #endif
-
- #ifdef JSON_WRITER
- json_char * json_write(const JSONNODE * node){
- JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_write"), return toCString(EMPTY_CSTRING););
- return toCString(((JSONNode*)node) -> write());
- }
-
- json_char * json_write_formatted(const JSONNODE * node){
- JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_write_formatted"), return toCString(EMPTY_CSTRING););
- return toCString(((JSONNode*)node) -> write_formatted());
- }
- #endif
-
- //modifiers
- void json_set_name(JSONNODE * node, const json_char * name){
- JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_set_name"), return;);
- JSON_ASSERT_SAFE(name, JSON_TEXT("null name to json_set_name"), name = EMPTY_CSTRING;);
- ((JSONNode*)node) -> set_name(name);
- }
-
- #ifdef JSON_COMMENTS
- void json_set_comment(JSONNODE * node, const json_char * comment){
- JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_set_comment"), return;);
- JSON_ASSERT_SAFE(comment, JSON_TEXT("null name to json_set_comment"), comment = EMPTY_CSTRING;);
- ((JSONNode*)node) -> set_comment(comment);
- }
- #endif
-
- void json_clear(JSONNODE * node){
- JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_clear"), return;);
- ((JSONNode*)node) -> clear();
- }
-
- void json_nullify(JSONNODE * node){
- JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_nullify"), return;);
- ((JSONNode*)node) -> nullify();
- }
-
- void json_swap(JSONNODE * node, JSONNODE * node2){
- JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_swap"), return;);
- JSON_ASSERT_SAFE(node2, JSON_TEXT("null node to json_swap"), return;);
- ((JSONNode*)node) -> swap(*(JSONNode*)node2);
- }
-
- void json_merge(JSONNODE * node, JSONNODE * node2){
- JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_merge"), return;);
- JSON_ASSERT_SAFE(node2, JSON_TEXT("null node to json_merge"), return;);
- ((JSONNode*)node) -> merge(*(JSONNode*)node2);
- }
-
- #ifndef JSON_PREPARSE
- void json_preparse(JSONNODE * node){
- JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_preparse"), return;);
- ((JSONNode*)node) -> preparse();
- }
- #endif
-
- #ifdef JSON_BINARY
- void json_set_binary(JSONNODE * node, const void * data, unsigned long length){
- JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_swap"), return;);
- JSON_ASSERT_SAFE(data, JSON_TEXT("null data to json_set_binary"), *((JSONNode*)node) = EMPTY_CSTRING; return;);
- ((JSONNode*)node) -> set_binary((unsigned char *)data, length);
- }
- #endif
-
- void json_cast(JSONNODE * node, char type){
- JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_cast"), return;);
- ((JSONNode*)node) -> cast(type);
- }
-
- //children access
- void json_reserve(JSONNODE * node, json_index_t siz){
- JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_reserve"), return;);
- ((JSONNode*)node) -> reserve(siz);
- }
-
- JSONNODE * json_at(JSONNODE * node, unsigned int pos){
- JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_at"), return 0;);
- try {
- return &((JSONNode*)node) -> at(pos);
- } catch (std::out_of_range){}
- return 0;
- }
-
- JSONNODE * json_get(JSONNODE * node, const json_char * name){
- JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_get"), return 0;);
- JSON_ASSERT_SAFE(name, JSON_TEXT("null node to json_get. Did you mean to use json_at?"), return 0;);
- try {
- return &((JSONNode*)node) -> at(name);
- } catch (std::out_of_range){}
- return 0;
- }
-
-
- #ifdef JSON_CASE_INSENSITIVE_FUNCTIONS
- JSONNODE * json_get_nocase(JSONNODE * node, const json_char * name){
- JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_at_nocase"), return 0;);
- JSON_ASSERT_SAFE(name, JSON_TEXT("null name to json_at_nocase"), return 0;);
- try {
- return &((JSONNode*)node) -> at_nocase(name);
- } catch (std::out_of_range){}
- return 0;
- }
-
- JSONNODE * json_pop_back_nocase(JSONNODE * node, const json_char * name){
- JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_pop_back_nocase"), return 0;);
- JSON_ASSERT_SAFE(name, JSON_TEXT("null name to json_pop_back_nocase"), return 0;);
- return MANAGER_INSERT(((JSONNode*)node) -> pop_back_nocase(name));
- }
- #endif
-
- void json_push_back(JSONNODE * node, JSONNODE * node2){
- JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_push_back"), return;);
- JSON_ASSERT_SAFE(node2, JSON_TEXT("null node2 to json_push_back"), return;);
- #ifdef JSON_MEMORY_MANAGE
- NodeHandler.remove(node2);
- #endif
- ((JSONNode*)node) -> push_back((JSONNode*)node2);
- }
-
- JSONNODE * json_pop_back_at(JSONNODE * node, unsigned int pos){
- JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_pop_back_i"), return 0;);
- return MANAGER_INSERT(((JSONNode*)node) -> pop_back(pos));
- }
-
- JSONNODE * json_pop_back(JSONNODE * node, const json_char * name){
- JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_pop_back"), return 0;);
- JSON_ASSERT_SAFE(name, JSON_TEXT("null name to json_pop_back. Did you mean to use json_pop_back_at?"), return 0;);
- return MANAGER_INSERT(((JSONNode*)node) -> pop_back(name));
- }
-
- #ifdef JSON_ITERATORS
- JSONNODE_ITERATOR json_find(JSONNODE * node, const json_char * name){
- return (JSONNODE_ITERATOR)(((JSONNode*)node) -> find(name));
- }
-
- #ifdef JSON_CASE_INSENSITIVE_FUNCTIONS
- JSONNODE_ITERATOR json_find_nocase(JSONNODE * node, const json_char * name){
- return (JSONNODE_ITERATOR)(((JSONNode*)node) -> find_nocase(name));
- }
- #endif
-
- JSONNODE_ITERATOR json_erase(JSONNODE * node, JSONNODE_ITERATOR it){
- return (JSONNODE_ITERATOR)(((JSONNode*)node) -> erase((JSONNode**)it));
- }
-
- JSONNODE_ITERATOR json_erase_multi(JSONNODE * node, JSONNODE_ITERATOR start, JSONNODE_ITERATOR end){
- return (JSONNODE_ITERATOR)(((JSONNode*)node) -> erase((JSONNode**)start, (JSONNode**)end));
- }
-
- JSONNODE_ITERATOR json_insert(JSONNODE * node, JSONNODE_ITERATOR it, JSONNODE * node2){
- #ifdef JSON_MEMORY_MANAGE
- NodeHandler.remove(node2);
- #endif
- return (JSONNODE_ITERATOR)(((JSONNode*)node) -> insert((JSONNode**)it, (JSONNode*)node2));
- }
-
- JSONNODE_ITERATOR json_insert_multi(JSONNODE * node, JSONNODE_ITERATOR it, JSONNODE_ITERATOR start, JSONNODE_ITERATOR end){
- return (JSONNODE_ITERATOR)(((JSONNode*)node) -> insert((JSONNode**)it, (JSONNode**)start, (JSONNode**)end));
- }
-
- //iterator functions
- JSONNODE_ITERATOR json_begin(JSONNODE * node){
- return (JSONNODE_ITERATOR)(((JSONNode*)node) -> begin());
- }
-
- JSONNODE_ITERATOR json_end(JSONNODE * node){
- return (JSONNODE_ITERATOR)(((JSONNode*)node) -> end());
- }
- #endif
-
- //comparison
- int json_equal(JSONNODE * node, JSONNODE * node2){
- JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_equal"), return false;);
- JSON_ASSERT_SAFE(node2, JSON_TEXT("null node2 to json_equal"), return false;);
- return (int)(*((JSONNode*)node) == *((JSONNode*)node2));
- }
-
-#endif //JSON_LIBRARY
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2009 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "..\..\core\commonheaders.h"
+
+#include "libJSON.h"
+
+/*
+ This is the implementation of the C interface to libJSON
+ This file may be included in any C++ application, but it will
+ be completely ignored if JSON_LIBRARY isn't defined. The
+ only reason JSON_LIBRARY should be defined is when compiling libJSON
+ as a library
+*/
+
+#ifdef JSON_LIBRARY
+
+ #include "JSONNode.h"
+ #include "JSONWorker.h"
+ #include <stdexcept> //some methods throw exceptions
+ #ifdef JSON_MEMORY_MANAGE
+ auto_expand StringHandler;
+ auto_expand_node NodeHandler;
+ #define MANAGER_INSERT(x) NodeHandler.insert(x)
+ #else
+ #define MANAGER_INSERT(x) x
+ #endif
+
+ #ifdef JSON_SAFE
+ static const json_char * EMPTY_CSTRING = JSON_TEXT("");
+ #endif
+
+ inline json_char * toCString(const json_string & str){
+ const size_t len((str.length() + 1) * sizeof(json_char));
+ #ifdef JSON_MEMORY_MANAGE
+ return (json_char *)StringHandler.insert(memcpy(json_malloc<json_char>(len), str.c_str(), len));
+ #else
+ return (json_char *)memcpy(json_malloc<json_char>(len), str.c_str(), len);
+ #endif
+ }
+
+ /*
+ stuff that's in namespace libJSON
+ */
+ void json_free(void * str){
+ JSON_ASSERT_SAFE(str, JSON_TEXT("freeing null ptr"), return;);
+ #ifdef JSON_MEMORY_MANAGE
+ StringHandler.remove(str);
+ #endif
+ libjson_free<void>(str);
+ }
+
+ void json_delete(JSONNODE * node){
+ JSON_ASSERT_SAFE(node, JSON_TEXT("deleting null ptr"), return;);
+ #ifdef JSON_MEMORY_MANAGE
+ NodeHandler.remove(node);
+ #endif
+ JSONNode::deleteJSONNode((JSONNode *)node);
+ }
+
+ #ifdef JSON_MEMORY_MANAGE
+ void json_free_all(void){
+ StringHandler.clear();
+ }
+
+ void json_delete_all(void){
+ NodeHandler.clear();
+ }
+ #endif
+
+ JSONNODE * json_parse(const json_char * json){
+ JSON_ASSERT_SAFE(json, JSON_TEXT("null ptr to json_parse"), return 0;);
+ try {
+ //use this constructor to simply copy reference instead of copying the temp
+ return MANAGER_INSERT(JSONNode::newJSONNode_Shallow(JSONWorker::parse(json)));
+ } catch (std::invalid_argument){}
+ return 0;
+ }
+
+ json_char * json_strip_white_space(const json_char * json){
+ JSON_ASSERT_SAFE(json, JSON_TEXT("null ptr to json_strip_white_space"), return 0;);
+ return toCString(JSONWorker::RemoveWhiteSpaceAndComments(json));
+ }
+
+ #ifdef JSON_VALIDATE
+ JSONNODE * json_validate(const json_char * json){
+ JSON_ASSERT_SAFE(json, JSON_TEXT("null ptr to json_validate"), return 0;);
+ try {
+ //use this constructor to simply copy reference instead of copying the temp
+ return MANAGER_INSERT(JSONNode::newJSONNode_Shallow(JSONWorker::validate(json)));
+ } catch (std::invalid_argument){}
+ return 0;
+ }
+ #endif
+
+ #if defined JSON_DEBUG && !defined JSON_STDERROR
+ //When libjson errors, a callback allows the user to know what went wrong
+ void json_register_debug_callback(json_error_callback_t callback){
+ JSONDebug::register_callback(callback);
+ }
+ #endif
+
+ #ifdef JSON_MUTEX_CALLBACKS
+ #ifdef JSON_MUTEX_MANAGE
+ void json_register_mutex_callbacks(json_mutex_callback_t lock, json_mutex_callback_t unlock, json_mutex_callback_t destroy, void * manager_lock){
+ JSONNode::register_mutex_callbacks(lock, unlock, manager_lock);
+ JSONNode::register_mutex_destructor(destroy);
+ }
+
+ #else
+ void json_register_mutex_callbacks(json_mutex_callback_t lock, json_mutex_callback_t unlock, void * manager_lock){
+ JSONNode::register_mutex_callbacks(lock, unlock, manager_lock);
+ }
+ #endif
+
+ void json_set_global_mutex(void * mutex){
+ JSONNode::set_global_mutex(mutex);
+ }
+
+ void json_set_mutex(JSONNODE * node, void * mutex){
+ JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_set_mutex"), return;);
+ ((JSONNode*)node) -> set_mutex(mutex);
+ }
+
+ void json_lock(JSONNODE * node, int threadid){
+ JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_lock"), return;);
+ ((JSONNode*)node) -> lock(threadid);
+ }
+
+ void json_unlock(JSONNODE * node, int threadid){
+ JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_unlock"), return;);
+ ((JSONNode*)node) -> unlock(threadid);
+ }
+ #endif
+
+ #ifdef JSON_MEMORY_CALLBACKS
+ void json_register_memory_callbacks(json_malloc_t mal, json_realloc_t real, json_free_t fre){
+ JSONMemory::registerMemoryCallbacks(mal, real, fre);
+ }
+ #endif
+
+
+ /*
+ stuff that's in class JSONNode
+ */
+ //ctors
+ JSONNODE * json_new_a(const json_char * name, const json_char * value){
+ JSON_ASSERT_SAFE(name, JSON_TEXT("null name to json_new_a"), name = EMPTY_CSTRING;);
+ JSON_ASSERT_SAFE(value, JSON_TEXT("null value to json_new_a"), value = EMPTY_CSTRING;);
+ #ifdef JSON_MEMORY_CALLBACKS
+ return MANAGER_INSERT(new(json_malloc<JSONNode>(1)) JSONNode(name, json_string(value)));
+ #else
+ return MANAGER_INSERT(new JSONNode(name, json_string(value)));
+ #endif
+ }
+
+ JSONNODE * json_new_i(const json_char * name, long value){
+ JSON_ASSERT_SAFE(name, JSON_TEXT("null name to json_new_i"), name = EMPTY_CSTRING;);
+ #ifdef JSON_MEMORY_CALLBACKS
+ return MANAGER_INSERT(new(json_malloc<JSONNode>(1)) JSONNode(name, value));
+ #else
+ return MANAGER_INSERT(new JSONNode(name, value));
+ #endif
+ }
+
+ JSONNODE * json_new_f(const json_char * name, json_number value){
+ JSON_ASSERT_SAFE(name, JSON_TEXT("null name to json_new_f"), name = EMPTY_CSTRING;);
+ #ifdef JSON_MEMORY_CALLBACKS
+ return MANAGER_INSERT(new(json_malloc<JSONNode>(1)) JSONNode(name, value));
+ #else
+ return MANAGER_INSERT(new JSONNode(name, value));
+ #endif
+ }
+
+ JSONNODE * json_new_b(const json_char * name, int value){
+ JSON_ASSERT_SAFE(name, JSON_TEXT("null name to json_new_b"), name = EMPTY_CSTRING;);
+ #ifdef JSON_MEMORY_CALLBACKS
+ return MANAGER_INSERT(new(json_malloc<JSONNode>(1)) JSONNode(name, value != 0 ));
+ #else
+ return MANAGER_INSERT(new JSONNode(name, (bool)value)) != 0;
+ #endif
+ }
+
+ JSONNODE * json_new(char type){
+ #ifdef JSON_MEMORY_CALLBACKS
+ return MANAGER_INSERT(new(json_malloc<JSONNode>(1)) JSONNode(type));
+ #else
+ return MANAGER_INSERT(new JSONNode(type));
+ #endif
+ }
+
+ JSONNODE * json_copy(const JSONNODE * orig){
+ JSON_ASSERT_SAFE(orig, JSON_TEXT("null orig to json_copy"), return 0;);
+ #ifdef JSON_MEMORY_CALLBACKS
+ return MANAGER_INSERT(new(json_malloc<JSONNode>(1)) JSONNode(*((JSONNode*)orig)));
+ #else
+ return MANAGER_INSERT(new JSONNode(*((JSONNode*)orig)));
+ #endif
+ }
+
+ JSONNODE * json_duplicate(const JSONNODE * orig){
+ JSON_ASSERT_SAFE(orig, JSON_TEXT("null orig to json_duplicate"), return 0;);
+ return MANAGER_INSERT(JSONNode::newJSONNode_Shallow(((JSONNode*)orig) -> duplicate()));
+ }
+
+ //assignment
+ void json_set_a(JSONNODE * node, const json_char * value){
+ JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_set_a"), return;);
+ JSON_ASSERT_SAFE(value, JSON_TEXT("null value to json_set_a"), value = EMPTY_CSTRING;);
+ *((JSONNode*)node) = json_string(value);
+ }
+
+ void json_set_i(JSONNODE * node, long value){
+ JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_set_i"), return;);
+ *((JSONNode*)node) = value;
+ }
+
+ void json_set_f(JSONNODE * node, json_number value){
+ JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_set_f"), return;);
+ *((JSONNode*)node) = value;
+ }
+
+ void json_set_b(JSONNODE * node, int value){
+ JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_set_b"), return;);
+ *((JSONNode*)node) = value != 0;
+ }
+
+ void json_set_n(JSONNODE * node, const JSONNODE * orig){
+ JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_set_n"), return;);
+ JSON_ASSERT_SAFE(orig, JSON_TEXT("null node to json_set_n"), return;);
+ *((JSONNode*)node) = *((JSONNode*)orig);
+ }
+
+ //inspectors
+ char json_type(const JSONNODE * node){
+ JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_type"), return JSON_NULL;);
+ return ((JSONNode*)node) -> type();
+ }
+
+ json_index_t json_size(const JSONNODE * node){
+ JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_size"), return 0;);
+ return ((JSONNode*)node) -> size();
+ }
+
+ int json_empty(const JSONNODE * node){
+ JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_empty"), return true;);
+ return (int)(((JSONNode*)node) -> empty());
+ }
+
+ json_char * json_name(const JSONNODE * node){
+ JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_name"), return toCString(EMPTY_CSTRING););
+ return toCString(((JSONNode*)node) -> name());
+ }
+
+ #ifdef JSON_COMMENTS
+ json_char * json_get_comment(const JSONNODE * node){
+ JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_get_comment"), return toCString(EMPTY_CSTRING););
+ return toCString(((JSONNode*)node) -> get_comment());
+ }
+ #endif
+
+ json_char * json_as_string(const JSONNODE * node){
+ JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_as_string"), return toCString(EMPTY_CSTRING););
+ return toCString(((JSONNode*)node) -> as_string());
+ }
+
+ long json_as_int(const JSONNODE * node){
+ JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_as_int"), return 0;);
+ return ((JSONNode*)node) -> as_int();
+ }
+
+ json_number json_as_float(const JSONNODE * node){
+ JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_as_float"), return 0.0;);
+ return ((JSONNode*)node) -> as_float();
+ }
+
+ int json_as_bool(const JSONNODE * node){
+ JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_as_bool"), return false;);
+ return (int)(((JSONNode*)node) -> as_bool());
+ }
+
+ JSONNODE * json_as_node(const JSONNODE * node){
+ JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_as_node"), return 0;);
+ return MANAGER_INSERT(JSONNode::newJSONNode_Shallow(((JSONNode*)node) -> as_node()));
+ }
+
+ JSONNODE * json_as_array(const JSONNODE * node){
+ JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_as_array"), return 0;);
+ return MANAGER_INSERT(JSONNode::newJSONNode_Shallow(((JSONNode*)node) -> as_array()));
+ }
+
+ #ifdef JSON_BINARY
+ void * json_as_binary(const JSONNODE * node, unsigned long * size){
+ JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_as_binary"), if (size){*size = 0;} return 0;);
+ const std::string result = ((JSONNode*)node) -> as_binary();
+ const size_t len = result.length();
+ if (size) *size = len;
+ #ifdef JSON_SAFE
+ if (result.empty()) return 0;
+ #endif
+ #ifdef JSON_MEMORY_MANAGE
+ return StringHandler.insert(memcpy(json_malloc<char>(len), result.data(), len));
+ #else
+ return memcpy(json_malloc<char>(len), result.data(), len);
+ #endif
+ }
+ #endif
+
+ #ifdef JSON_WRITER
+ json_char * json_write(const JSONNODE * node){
+ JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_write"), return toCString(EMPTY_CSTRING););
+ return toCString(((JSONNode*)node) -> write());
+ }
+
+ json_char * json_write_formatted(const JSONNODE * node){
+ JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_write_formatted"), return toCString(EMPTY_CSTRING););
+ return toCString(((JSONNode*)node) -> write_formatted());
+ }
+ #endif
+
+ //modifiers
+ void json_set_name(JSONNODE * node, const json_char * name){
+ JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_set_name"), return;);
+ JSON_ASSERT_SAFE(name, JSON_TEXT("null name to json_set_name"), name = EMPTY_CSTRING;);
+ ((JSONNode*)node) -> set_name(name);
+ }
+
+ #ifdef JSON_COMMENTS
+ void json_set_comment(JSONNODE * node, const json_char * comment){
+ JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_set_comment"), return;);
+ JSON_ASSERT_SAFE(comment, JSON_TEXT("null name to json_set_comment"), comment = EMPTY_CSTRING;);
+ ((JSONNode*)node) -> set_comment(comment);
+ }
+ #endif
+
+ void json_clear(JSONNODE * node){
+ JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_clear"), return;);
+ ((JSONNode*)node) -> clear();
+ }
+
+ void json_nullify(JSONNODE * node){
+ JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_nullify"), return;);
+ ((JSONNode*)node) -> nullify();
+ }
+
+ void json_swap(JSONNODE * node, JSONNODE * node2){
+ JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_swap"), return;);
+ JSON_ASSERT_SAFE(node2, JSON_TEXT("null node to json_swap"), return;);
+ ((JSONNode*)node) -> swap(*(JSONNode*)node2);
+ }
+
+ void json_merge(JSONNODE * node, JSONNODE * node2){
+ JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_merge"), return;);
+ JSON_ASSERT_SAFE(node2, JSON_TEXT("null node to json_merge"), return;);
+ ((JSONNode*)node) -> merge(*(JSONNode*)node2);
+ }
+
+ #ifndef JSON_PREPARSE
+ void json_preparse(JSONNODE * node){
+ JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_preparse"), return;);
+ ((JSONNode*)node) -> preparse();
+ }
+ #endif
+
+ #ifdef JSON_BINARY
+ void json_set_binary(JSONNODE * node, const void * data, unsigned long length){
+ JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_swap"), return;);
+ JSON_ASSERT_SAFE(data, JSON_TEXT("null data to json_set_binary"), *((JSONNode*)node) = EMPTY_CSTRING; return;);
+ ((JSONNode*)node) -> set_binary((unsigned char *)data, length);
+ }
+ #endif
+
+ void json_cast(JSONNODE * node, char type){
+ JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_cast"), return;);
+ ((JSONNode*)node) -> cast(type);
+ }
+
+ //children access
+ void json_reserve(JSONNODE * node, json_index_t siz){
+ JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_reserve"), return;);
+ ((JSONNode*)node) -> reserve(siz);
+ }
+
+ JSONNODE * json_at(JSONNODE * node, unsigned int pos){
+ JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_at"), return 0;);
+ try {
+ return &((JSONNode*)node) -> at(pos);
+ } catch (std::out_of_range){}
+ return 0;
+ }
+
+ JSONNODE * json_get(JSONNODE * node, const json_char * name){
+ JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_get"), return 0;);
+ JSON_ASSERT_SAFE(name, JSON_TEXT("null node to json_get. Did you mean to use json_at?"), return 0;);
+ try {
+ return &((JSONNode*)node) -> at(name);
+ } catch (std::out_of_range){}
+ return 0;
+ }
+
+ #ifdef JSON_CASE_INSENSITIVE_FUNCTIONS
+ JSONNODE * json_get_nocase(JSONNODE * node, const json_char * name){
+ JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_at_nocase"), return 0;);
+ JSON_ASSERT_SAFE(name, JSON_TEXT("null name to json_at_nocase"), return 0;);
+ try {
+ return &((JSONNode*)node) -> at_nocase(name);
+ } catch (std::out_of_range){}
+ return 0;
+ }
+
+ JSONNODE * json_pop_back_nocase(JSONNODE * node, const json_char * name){
+ JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_pop_back_nocase"), return 0;);
+ JSON_ASSERT_SAFE(name, JSON_TEXT("null name to json_pop_back_nocase"), return 0;);
+ return MANAGER_INSERT(((JSONNode*)node) -> pop_back_nocase(name));
+ }
+ #endif
+
+ void json_push_back(JSONNODE * node, JSONNODE * node2){
+ JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_push_back"), return;);
+ JSON_ASSERT_SAFE(node2, JSON_TEXT("null node2 to json_push_back"), return;);
+ #ifdef JSON_MEMORY_MANAGE
+ NodeHandler.remove(node2);
+ #endif
+ ((JSONNode*)node) -> push_back((JSONNode*)node2);
+ }
+
+ JSONNODE * json_pop_back_at(JSONNODE * node, unsigned int pos){
+ JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_pop_back_i"), return 0;);
+ return MANAGER_INSERT(((JSONNode*)node) -> pop_back(pos));
+ }
+
+ JSONNODE * json_pop_back(JSONNODE * node, const json_char * name){
+ JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_pop_back"), return 0;);
+ JSON_ASSERT_SAFE(name, JSON_TEXT("null name to json_pop_back. Did you mean to use json_pop_back_at?"), return 0;);
+ return MANAGER_INSERT(((JSONNode*)node) -> pop_back(name));
+ }
+
+ #ifdef JSON_ITERATORS
+ JSONNODE_ITERATOR json_find(JSONNODE * node, const json_char * name){
+ return (JSONNODE_ITERATOR)(((JSONNode*)node) -> find(name));
+ }
+
+ #ifdef JSON_CASE_INSENSITIVE_FUNCTIONS
+ JSONNODE_ITERATOR json_find_nocase(JSONNODE * node, const json_char * name){
+ return (JSONNODE_ITERATOR)(((JSONNode*)node) -> find_nocase(name));
+ }
+ #endif
+
+ JSONNODE_ITERATOR json_erase(JSONNODE * node, JSONNODE_ITERATOR it){
+ return (JSONNODE_ITERATOR)(((JSONNode*)node) -> erase((JSONNode**)it));
+ }
+
+ JSONNODE_ITERATOR json_erase_multi(JSONNODE * node, JSONNODE_ITERATOR start, JSONNODE_ITERATOR end){
+ return (JSONNODE_ITERATOR)(((JSONNode*)node) -> erase((JSONNode**)start, (JSONNode**)end));
+ }
+
+ JSONNODE_ITERATOR json_insert(JSONNODE * node, JSONNODE_ITERATOR it, JSONNODE * node2){
+ #ifdef JSON_MEMORY_MANAGE
+ NodeHandler.remove(node2);
+ #endif
+ return (JSONNODE_ITERATOR)(((JSONNode*)node) -> insert((JSONNode**)it, (JSONNode*)node2));
+ }
+
+ JSONNODE_ITERATOR json_insert_multi(JSONNODE * node, JSONNODE_ITERATOR it, JSONNODE_ITERATOR start, JSONNODE_ITERATOR end){
+ return (JSONNODE_ITERATOR)(((JSONNode*)node) -> insert((JSONNode**)it, (JSONNode**)start, (JSONNode**)end));
+ }
+
+ //iterator functions
+ JSONNODE_ITERATOR json_begin(JSONNODE * node){
+ return (JSONNODE_ITERATOR)(((JSONNode*)node) -> begin());
+ }
+
+ JSONNODE_ITERATOR json_end(JSONNODE * node){
+ return (JSONNODE_ITERATOR)(((JSONNode*)node) -> end());
+ }
+ #endif
+
+ //comparison
+ int json_equal(JSONNODE * node, JSONNODE * node2){
+ JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_equal"), return false;);
+ JSON_ASSERT_SAFE(node2, JSON_TEXT("null node2 to json_equal"), return false;);
+ return (int)(*((JSONNode*)node) == *((JSONNode*)node2));
+ }
+
+#endif //JSON_LIBRARY
diff --git a/src/modules/json/libJSON.h b/src/modules/json/libJSON.h
index 3e60fd502a..d552e71720 100644
--- a/src/modules/json/libJSON.h
+++ b/src/modules/json/libJSON.h
@@ -1,212 +1,211 @@
-#ifndef LIBJSON_H
-#define LIBJSON_H
-
-#include "JSONDefs.h" //for typedefs of functions, strings, and nodes
-
-#ifdef _STATIC
-#define LIBJSON_DLL
-#elif LIBJSON_EXPORTS
-#define LIBJSON_DLL _declspec(dllexport)
-#else
-#define LIBJSON_DLL _declspec(dllimport)
-#endif
-
-/*
- This is the C interface to libJSON.
-
- This file also declares various things that are needed for
- C++ programming
-*/
-
-#ifdef JSON_LIBRARY //compiling the library, hide the interface
- #ifdef __cplusplus
- #ifdef JSON_UNIT_TEST
- #include "JSONNode.h"
- #endif
- extern "C" {
- #endif
-
- /*
- stuff that's in namespace libJSON
- */
- LIBJSON_DLL void json_free(void * str);
- LIBJSON_DLL void json_delete(JSONNODE * node);
- #ifdef JSON_MEMORY_MANAGE
- LIBJSON_DLL void json_free_all(void);
- LIBJSON_DLL void json_delete_all(void);
- #endif
- LIBJSON_DLL JSONNODE * json_parse(const json_char * json);
- LIBJSON_DLL json_char * json_strip_white_space(const json_char * json);
- #ifdef JSON_VALIDATE
- LIBJSON_DLL JSONNODE * json_validate(const json_char * json);
- #endif
- #if defined JSON_DEBUG && !defined JSON_STDERROR
- //When libjson errors, a callback allows the user to know what went wrong
- LIBJSON_DLL void json_register_debug_callback(json_error_callback_t callback);
- #endif
- #ifdef JSON_MUTEX_CALLBACKS
- #ifdef JSON_MUTEX_MANAGE
- LIBJSON_DLL void json_register_mutex_callbacks(json_mutex_callback_t lock, json_mutex_callback_t unlock, json_mutex_callback_t destroy, void * manager_lock);
- #else
- LIBJSON_DLL void json_register_mutex_callbacks(json_mutex_callback_t lock, json_mutex_callback_t unlock, void * manager_lock);
- #endif
- LIBJSON_DLL void json_set_global_mutex(void * mutex);
- LIBJSON_DLL void json_set_mutex(JSONNODE * node, void * mutex);
- LIBJSON_DLL void json_lock(JSONNODE * node, int threadid);
- LIBJSON_DLL void json_unlock(JSONNODE * node, int threadid);
- #endif
- #ifdef JSON_MEMORY_CALLBACKS
- LIBJSON_DLL void json_register_memory_callbacks(json_malloc_t mal, json_realloc_t real, json_free_t fre);
- #endif
-
-
- /*
- stuff that's in class JSONNode
- */
- //ctors
- LIBJSON_DLL JSONNODE * json_new_a(const json_char * name, const json_char * value);
- LIBJSON_DLL JSONNODE * json_new_i(const json_char * name, long value);
- LIBJSON_DLL JSONNODE * json_new_f(const json_char * name, json_number value);
- LIBJSON_DLL JSONNODE * json_new_b(const json_char * name, int value); //because C bools are ints and C++ will implicitly cast it
- LIBJSON_DLL JSONNODE * json_new(char type);
- LIBJSON_DLL JSONNODE * json_copy(const JSONNODE * orig);
- LIBJSON_DLL JSONNODE * json_duplicate(const JSONNODE * orig);
-
- //assignment
- LIBJSON_DLL void json_set_a(JSONNODE * node, const json_char * value);
- LIBJSON_DLL void json_set_i(JSONNODE * node, long value);
- LIBJSON_DLL void json_set_f(JSONNODE * node, json_number value);
- LIBJSON_DLL void json_set_b(JSONNODE * node, int value); //because C bools are ints ane C++ will implicit
- LIBJSON_DLL void json_set_n(JSONNODE * node, const JSONNODE * orig);
-
- //inspectors
- LIBJSON_DLL char json_type(const JSONNODE * node);
- LIBJSON_DLL json_index_t json_size(const JSONNODE * node);
- LIBJSON_DLL int json_empty(const JSONNODE * node);
- LIBJSON_DLL json_char * json_name(const JSONNODE * node);
- #ifdef JSON_COMMENTS
- LIBJSON_DLL json_char * json_get_comment(const JSONNODE * node);
- #endif
- LIBJSON_DLL json_char * json_as_string(const JSONNODE * node);
- LIBJSON_DLL long json_as_int(const JSONNODE * node);
- LIBJSON_DLL json_number json_as_float(const JSONNODE * node);
- LIBJSON_DLL int json_as_bool(const JSONNODE * node);
- LIBJSON_DLL JSONNODE * json_as_node(const JSONNODE * node);
- LIBJSON_DLL JSONNODE * json_as_array(const JSONNODE * node);
- #ifdef JSON_BINARY
- LIBJSON_DLL void * json_as_binary(const JSONNODE * node, unsigned long * size);
- #endif
- #ifdef JSON_WRITER
- LIBJSON_DLL json_char * json_write(const JSONNODE * node);
- LIBJSON_DLL json_char * json_write_formatted(const JSONNODE * node);
- #endif
-
- //modifiers
- LIBJSON_DLL void json_set_name(JSONNODE * node, const json_char * name);
- #ifdef JSON_COMMENTS
- LIBJSON_DLL void json_set_comment(JSONNODE * node, const json_char * comment);
- #endif
- LIBJSON_DLL void json_clear(JSONNODE * node);
- LIBJSON_DLL void json_nullify(JSONNODE * node);
- LIBJSON_DLL void json_swap(JSONNODE * node, JSONNODE * node2);
- LIBJSON_DLL void json_merge(JSONNODE * node, JSONNODE * node2);
- #ifndef JSON_PREPARSE
- LIBJSON_DLL void json_preparse(JSONNODE * node);
- #endif
- #ifdef JSON_BINARY
- LIBJSON_DLL void json_set_binary(JSONNODE * node, const void * data, unsigned long length);
- #endif
- LIBJSON_DLL void json_cast(JSONNODE * node, char type);
-
- //children access
- LIBJSON_DLL void json_reserve(JSONNODE * node, json_index_t siz);
- LIBJSON_DLL JSONNODE * json_at(JSONNODE * node, json_index_t pos);
- LIBJSON_DLL JSONNODE * json_get(JSONNODE * node, const json_char * name);
- #ifdef JSON_CASE_INSENSITIVE_FUNCTIONS
- LIBJSON_DLL JSONNODE * json_get_nocase(JSONNODE * node, const json_char * name);
- LIBJSON_DLL JSONNODE * json_pop_back_nocase(JSONNODE * node, const json_char * name);
- #endif
- LIBJSON_DLL void json_push_back(JSONNODE * node, JSONNODE * node2);
- LIBJSON_DLL JSONNODE * json_pop_back_at(JSONNODE * node, json_index_t pos);
- LIBJSON_DLL JSONNODE * json_pop_back(JSONNODE * node, const json_char * name);
- #ifdef JSON_ITERATORS
- LIBJSON_DLL JSONNODE_ITERATOR json_find(JSONNODE * node, const json_char * name);
- #ifdef JSON_CASE_INSENSITIVE_FUNCTIONS
- LIBJSON_DLL JSONNODE_ITERATOR json_find_nocase(JSONNODE * node, const json_char * name);
- #endif
- LIBJSON_DLL JSONNODE_ITERATOR json_erase(JSONNODE * node, JSONNODE_ITERATOR it);
- LIBJSON_DLL JSONNODE_ITERATOR json_erase_multi(JSONNODE * node, JSONNODE_ITERATOR start, JSONNODE_ITERATOR end);
- LIBJSON_DLL JSONNODE_ITERATOR json_insert(JSONNODE * node, JSONNODE_ITERATOR it, JSONNODE * node2);
- LIBJSON_DLL JSONNODE_ITERATOR json_insert_multi(JSONNODE * node, JSONNODE_ITERATOR it, JSONNODE_ITERATOR start, JSONNODE_ITERATOR end);
-
- //iterator functions
- LIBJSON_DLL JSONNODE_ITERATOR json_begin(JSONNODE * node);
- LIBJSON_DLL JSONNODE_ITERATOR json_end(JSONNODE * node);
- #endif
-
- //comparison
- LIBJSON_DLL int json_equal(JSONNODE * node, JSONNODE * node2);
-
- #ifdef __cplusplus
- }
- #endif
-#else
- #ifndef __cplusplus
- #error Using the non-library requires C++
- #endif
- #include "JSONNode.h" //not used in this file, but libJSON.h should be the only file required to use it embedded
- #include "JSONWorker.h"
- #include <stdexcept> //some methods throw exceptions
-
- namespace libJSON {
- //if json is invalid, it throws a std::invalid_argument exception
- inline static JSONNode parse(const json_string & json){
- return JSONWorker::parse(json);
- }
-
- //useful if you have json that you don't want to parse, just want to strip to cut down on space
- inline static json_string strip_white_space(const json_string & json){
- return JSONWorker::RemoveWhiteSpaceAndComments(json);
- }
-
- //if json is invalid, it throws a std::invalid_argument exception (differs from parse because this checks the entire tree)
- #ifdef JSON_VALIDATE
- inline static JSONNode validate(const json_string & json){
- return JSONWorker::validate(json);
- }
- #endif
-
- //When libjson errors, a callback allows the user to know what went wrong
- #if defined JSON_DEBUG && !defined JSON_STDERROR
- inline static void register_debug_callback(json_error_callback_t callback){
- JSONDebug::register_callback(callback);
- }
- #endif
-
- #ifdef JSON_MUTEX_CALLBACKS
- #ifdef JSON_MUTEX_MANAGE
- inline static void register_mutex_callbacks(json_mutex_callback_t lock, json_mutex_callback_t unlock, json_mutex_callback_t destroy, void * manager_lock){
- JSONNode::register_mutex_callbacks(lock, unlock, manager_lock);
- JSONNode::register_mutex_destructor(destroy);
- }
- #else
- inline static void register_mutex_callbacks(json_mutex_callback_t lock, json_mutex_callback_t unlock, void * manager_lock){
- JSONNode::register_mutex_callbacks(lock, unlock, manager_lock);
- }
- #endif
-
- inline static void set_global_mutex(void * mutex){
- JSONNode::set_global_mutex(mutex);
- }
- #endif
-
- #ifdef JSON_MEMORY_CALLBACKS
- inline static void register_memory_callbacks(json_malloc_t mal, json_realloc_t real, json_free_t fre){
- JSONMemory::registerMemoryCallbacks(mal, real, fre);
- }
- #endif
-
- }
-#endif //JSON_LIBRARY
-
-#endif //LIBJSON_H
+#ifndef LIBJSON_H
+#define LIBJSON_H
+
+#include "JSONDefs.h" //for typedefs of functions, strings, and nodes
+
+#ifdef _STATIC
+#define LIBJSON_DLL
+#elif LIBJSON_EXPORTS
+#define LIBJSON_DLL _declspec(dllexport)
+#else
+#define LIBJSON_DLL _declspec(dllimport)
+#endif
+
+/*
+ This is the C interface to libJSON.
+
+ This file also declares various things that are needed for
+ C++ programming
+*/
+
+#ifdef JSON_LIBRARY //compiling the library, hide the interface
+ #ifdef __cplusplus
+ #ifdef JSON_UNIT_TEST
+ #include "JSONNode.h"
+ #endif
+ extern "C" {
+ #endif
+
+ /*
+ stuff that's in namespace libJSON
+ */
+ LIBJSON_DLL void json_free(void * str);
+ LIBJSON_DLL void json_delete(JSONNODE * node);
+ #ifdef JSON_MEMORY_MANAGE
+ LIBJSON_DLL void json_free_all(void);
+ LIBJSON_DLL void json_delete_all(void);
+ #endif
+ LIBJSON_DLL JSONNODE * json_parse(const json_char * json);
+ LIBJSON_DLL json_char * json_strip_white_space(const json_char * json);
+ #ifdef JSON_VALIDATE
+ LIBJSON_DLL JSONNODE * json_validate(const json_char * json);
+ #endif
+ #if defined JSON_DEBUG && !defined JSON_STDERROR
+ //When libjson errors, a callback allows the user to know what went wrong
+ LIBJSON_DLL void json_register_debug_callback(json_error_callback_t callback);
+ #endif
+ #ifdef JSON_MUTEX_CALLBACKS
+ #ifdef JSON_MUTEX_MANAGE
+ LIBJSON_DLL void json_register_mutex_callbacks(json_mutex_callback_t lock, json_mutex_callback_t unlock, json_mutex_callback_t destroy, void * manager_lock);
+ #else
+ LIBJSON_DLL void json_register_mutex_callbacks(json_mutex_callback_t lock, json_mutex_callback_t unlock, void * manager_lock);
+ #endif
+ LIBJSON_DLL void json_set_global_mutex(void * mutex);
+ LIBJSON_DLL void json_set_mutex(JSONNODE * node, void * mutex);
+ LIBJSON_DLL void json_lock(JSONNODE * node, int threadid);
+ LIBJSON_DLL void json_unlock(JSONNODE * node, int threadid);
+ #endif
+ #ifdef JSON_MEMORY_CALLBACKS
+ LIBJSON_DLL void json_register_memory_callbacks(json_malloc_t mal, json_realloc_t real, json_free_t fre);
+ #endif
+
+ /*
+ stuff that's in class JSONNode
+ */
+ //ctors
+ LIBJSON_DLL JSONNODE * json_new_a(const json_char * name, const json_char * value);
+ LIBJSON_DLL JSONNODE * json_new_i(const json_char * name, long value);
+ LIBJSON_DLL JSONNODE * json_new_f(const json_char * name, json_number value);
+ LIBJSON_DLL JSONNODE * json_new_b(const json_char * name, int value); //because C bools are ints and C++ will implicitly cast it
+ LIBJSON_DLL JSONNODE * json_new(char type);
+ LIBJSON_DLL JSONNODE * json_copy(const JSONNODE * orig);
+ LIBJSON_DLL JSONNODE * json_duplicate(const JSONNODE * orig);
+
+ //assignment
+ LIBJSON_DLL void json_set_a(JSONNODE * node, const json_char * value);
+ LIBJSON_DLL void json_set_i(JSONNODE * node, long value);
+ LIBJSON_DLL void json_set_f(JSONNODE * node, json_number value);
+ LIBJSON_DLL void json_set_b(JSONNODE * node, int value); //because C bools are ints ane C++ will implicit
+ LIBJSON_DLL void json_set_n(JSONNODE * node, const JSONNODE * orig);
+
+ //inspectors
+ LIBJSON_DLL char json_type(const JSONNODE * node);
+ LIBJSON_DLL json_index_t json_size(const JSONNODE * node);
+ LIBJSON_DLL int json_empty(const JSONNODE * node);
+ LIBJSON_DLL json_char * json_name(const JSONNODE * node);
+ #ifdef JSON_COMMENTS
+ LIBJSON_DLL json_char * json_get_comment(const JSONNODE * node);
+ #endif
+ LIBJSON_DLL json_char * json_as_string(const JSONNODE * node);
+ LIBJSON_DLL long json_as_int(const JSONNODE * node);
+ LIBJSON_DLL json_number json_as_float(const JSONNODE * node);
+ LIBJSON_DLL int json_as_bool(const JSONNODE * node);
+ LIBJSON_DLL JSONNODE * json_as_node(const JSONNODE * node);
+ LIBJSON_DLL JSONNODE * json_as_array(const JSONNODE * node);
+ #ifdef JSON_BINARY
+ LIBJSON_DLL void * json_as_binary(const JSONNODE * node, unsigned long * size);
+ #endif
+ #ifdef JSON_WRITER
+ LIBJSON_DLL json_char * json_write(const JSONNODE * node);
+ LIBJSON_DLL json_char * json_write_formatted(const JSONNODE * node);
+ #endif
+
+ //modifiers
+ LIBJSON_DLL void json_set_name(JSONNODE * node, const json_char * name);
+ #ifdef JSON_COMMENTS
+ LIBJSON_DLL void json_set_comment(JSONNODE * node, const json_char * comment);
+ #endif
+ LIBJSON_DLL void json_clear(JSONNODE * node);
+ LIBJSON_DLL void json_nullify(JSONNODE * node);
+ LIBJSON_DLL void json_swap(JSONNODE * node, JSONNODE * node2);
+ LIBJSON_DLL void json_merge(JSONNODE * node, JSONNODE * node2);
+ #ifndef JSON_PREPARSE
+ LIBJSON_DLL void json_preparse(JSONNODE * node);
+ #endif
+ #ifdef JSON_BINARY
+ LIBJSON_DLL void json_set_binary(JSONNODE * node, const void * data, unsigned long length);
+ #endif
+ LIBJSON_DLL void json_cast(JSONNODE * node, char type);
+
+ //children access
+ LIBJSON_DLL void json_reserve(JSONNODE * node, json_index_t siz);
+ LIBJSON_DLL JSONNODE * json_at(JSONNODE * node, json_index_t pos);
+ LIBJSON_DLL JSONNODE * json_get(JSONNODE * node, const json_char * name);
+ #ifdef JSON_CASE_INSENSITIVE_FUNCTIONS
+ LIBJSON_DLL JSONNODE * json_get_nocase(JSONNODE * node, const json_char * name);
+ LIBJSON_DLL JSONNODE * json_pop_back_nocase(JSONNODE * node, const json_char * name);
+ #endif
+ LIBJSON_DLL void json_push_back(JSONNODE * node, JSONNODE * node2);
+ LIBJSON_DLL JSONNODE * json_pop_back_at(JSONNODE * node, json_index_t pos);
+ LIBJSON_DLL JSONNODE * json_pop_back(JSONNODE * node, const json_char * name);
+ #ifdef JSON_ITERATORS
+ LIBJSON_DLL JSONNODE_ITERATOR json_find(JSONNODE * node, const json_char * name);
+ #ifdef JSON_CASE_INSENSITIVE_FUNCTIONS
+ LIBJSON_DLL JSONNODE_ITERATOR json_find_nocase(JSONNODE * node, const json_char * name);
+ #endif
+ LIBJSON_DLL JSONNODE_ITERATOR json_erase(JSONNODE * node, JSONNODE_ITERATOR it);
+ LIBJSON_DLL JSONNODE_ITERATOR json_erase_multi(JSONNODE * node, JSONNODE_ITERATOR start, JSONNODE_ITERATOR end);
+ LIBJSON_DLL JSONNODE_ITERATOR json_insert(JSONNODE * node, JSONNODE_ITERATOR it, JSONNODE * node2);
+ LIBJSON_DLL JSONNODE_ITERATOR json_insert_multi(JSONNODE * node, JSONNODE_ITERATOR it, JSONNODE_ITERATOR start, JSONNODE_ITERATOR end);
+
+ //iterator functions
+ LIBJSON_DLL JSONNODE_ITERATOR json_begin(JSONNODE * node);
+ LIBJSON_DLL JSONNODE_ITERATOR json_end(JSONNODE * node);
+ #endif
+
+ //comparison
+ LIBJSON_DLL int json_equal(JSONNODE * node, JSONNODE * node2);
+
+ #ifdef __cplusplus
+ }
+ #endif
+#else
+ #ifndef __cplusplus
+ #error Using the non-library requires C++
+ #endif
+ #include "JSONNode.h" //not used in this file, but libJSON.h should be the only file required to use it embedded
+ #include "JSONWorker.h"
+ #include <stdexcept> //some methods throw exceptions
+
+ namespace libJSON {
+ //if json is invalid, it throws a std::invalid_argument exception
+ inline static JSONNode parse(const json_string & json){
+ return JSONWorker::parse(json);
+ }
+
+ //useful if you have json that you don't want to parse, just want to strip to cut down on space
+ inline static json_string strip_white_space(const json_string & json){
+ return JSONWorker::RemoveWhiteSpaceAndComments(json);
+ }
+
+ //if json is invalid, it throws a std::invalid_argument exception (differs from parse because this checks the entire tree)
+ #ifdef JSON_VALIDATE
+ inline static JSONNode validate(const json_string & json){
+ return JSONWorker::validate(json);
+ }
+ #endif
+
+ //When libjson errors, a callback allows the user to know what went wrong
+ #if defined JSON_DEBUG && !defined JSON_STDERROR
+ inline static void register_debug_callback(json_error_callback_t callback){
+ JSONDebug::register_callback(callback);
+ }
+ #endif
+
+ #ifdef JSON_MUTEX_CALLBACKS
+ #ifdef JSON_MUTEX_MANAGE
+ inline static void register_mutex_callbacks(json_mutex_callback_t lock, json_mutex_callback_t unlock, json_mutex_callback_t destroy, void * manager_lock){
+ JSONNode::register_mutex_callbacks(lock, unlock, manager_lock);
+ JSONNode::register_mutex_destructor(destroy);
+ }
+ #else
+ inline static void register_mutex_callbacks(json_mutex_callback_t lock, json_mutex_callback_t unlock, void * manager_lock){
+ SONNode::register_mutex_callbacks(lock, unlock, manager_lock);
+ }
+ #endif
+
+ inline static void set_global_mutex(void * mutex){
+ JSONNode::set_global_mutex(mutex);
+ }
+ #endif
+
+ #ifdef JSON_MEMORY_CALLBACKS
+ inline static void register_memory_callbacks(json_malloc_t mal, json_realloc_t real, json_free_t fre){
+ JSONMemory::registerMemoryCallbacks(mal, real, fre);
+ }
+ #endif
+
+ }
+#endif //JSON_LIBRARY
+
+#endif //LIBJSON_H