summaryrefslogtreecommitdiff
path: root/src/modules
diff options
context:
space:
mode:
Diffstat (limited to 'src/modules')
-rw-r--r--src/modules/json/JSON_Base64.cpp272
-rw-r--r--src/modules/json/JSON_Base64.h28
-rw-r--r--src/modules/json/internalJSONNode.cpp1140
-rw-r--r--src/modules/json/internalJSONNode.h905
4 files changed, 1170 insertions, 1175 deletions
diff --git a/src/modules/json/JSON_Base64.cpp b/src/modules/json/JSON_Base64.cpp
index 07147afadc..66f2002b6b 100644
--- a/src/modules/json/JSON_Base64.cpp
+++ b/src/modules/json/JSON_Base64.cpp
@@ -1,136 +1,136 @@
-/*
-
-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 "JSON_Base64.h"
-#include "JSONDefs.h"
-
-#ifdef JSON_BINARY //if this is not needed, don't waste space compiling it
-
-static const json_char * chars64 = JSON_TEXT("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");
-#ifdef JSON_UNICODE
- static std::string BASE64_EMPTY_STRING;
-#else
- #define BASE64_EMPTY_STRING EMPTY_STRING
-#endif
-
-json_string JSONBase64::json_encode64(const unsigned char * binary, size_t bytes){
- size_t misaligned = bytes % 3;
- size_t aligned = (bytes - misaligned) / 3; //divide by three once and inc is faster than add 3 each time
- json_string result;
- result.reserve((size_t)(((float)bytes) * 1.37f) + 4);
-
- //do all of the ones that are 3 byte aligned
- for (size_t i=0; i < aligned; ++i){
- result += chars64[(binary[0] & 0xFC) >> 2];
- result += chars64[((binary[0] & 0x03) << 4) + ((binary[1] & 0xF0) >> 4)];
- result += chars64[((binary[1] & 0x0F) << 2) + ((binary[2] & 0xC0) >> 6)];
- result += chars64[binary[2] & 0x3F];
- binary += 3;
- }
-
- if (misaligned){
- //copy the rest into a temporary buffer
- unsigned char temp[3];
- for (unsigned int i=0; i < misaligned; ++i){
- temp[i] = *binary++;
- }
- for (unsigned int i = (unsigned int)misaligned; i < 3; ++i){
- temp[i] = '\0';
- }
-
- //now do the final three bytes
- result += chars64[(temp[0] & 0xFC) >> 2];
- result += chars64[((temp[0] & 0x03) << 4) + ((temp[1] & 0xF0) >> 4)];
- if (misaligned == 2){
- result += chars64[((temp[1] & 0x0F) << 2) + ((temp[2] & 0xC0) >> 6)];
- result += JSON_TEXT('=');
- } else {
- result += JSON_TEXT(" = = ");
- }
- }
- JSON_ASSERT((size_t)(((float)bytes) * 1.37f) + 4 >= result.length(), JSON_TEXT("Didn't reserve enough space for a one-time go"));
- return result;
-}
-
-inline json_char toBinary(json_char c){
- if (c == JSON_TEXT('+')) {
- return JSON_TEXT('>');
- } else if (c == JSON_TEXT('/')) {
- return JSON_TEXT('?');
- } else if (c < JSON_TEXT(':')) {
- return c + JSON_TEXT('\x04');
- } else if (c < JSON_TEXT('[')) {
- return c - JSON_TEXT('\x41');
- }
- return c - 71;
-}
-
-/*
- Must be a std::string because it's binary, and chars must be 1 byte
- */
-std::string JSONBase64::json_decode64(const json_string & encoded){
- const size_t length = encoded.length();
- #if defined JSON_DEBUG || defined JSON_SAFE
- size_t pos = encoded.find_first_not_of(chars64);
- if (pos != json_string::npos){
- JSON_ASSERT_SAFE(encoded[pos] == JSON_TEXT('='), JSON_TEXT("Not Base64"), return BASE64_EMPTY_STRING;);
- if (pos != length - 1){
- JSON_ASSERT_SAFE(pos == length - 2, JSON_TEXT("Not Base64"), return BASE64_EMPTY_STRING;);
- JSON_ASSERT_SAFE(encoded[pos + 1] == JSON_TEXT('='), JSON_TEXT("Not Base64"), return BASE64_EMPTY_STRING;);
- }
- }
- #endif
- const json_char * runner = encoded.c_str();
- size_t aligned = length / 4; //don't do the last ones as they might be = padding
- std::string result;
- if (aligned){
- --aligned;
- result.reserve((size_t)((float)length / 1.37) + 1);
-
- //first do the ones that can not have any padding
- for (unsigned int i=0; i < aligned; ++i){
- const json_char second = toBinary(runner[1]);
- const json_char third = toBinary(runner[2]);
- result += (toBinary(runner[0]) << 2) + ((second & 0x30) >> 4);
- result += ((second & 0xf) << 4) + ((third & 0x3c) >> 2);
- result += ((third & 0x3) << 6) + toBinary(runner[3]);
- runner += 4;
- }
-
- //now do the ones that might have padding, the first two characters can not be padding, so do them quickly
- const char second = toBinary(runner[1]);
- result += (toBinary(runner[0]) << 2) + ((second & 0x30) >> 4);
- if (runner[2] != '=') { //not two = pads
- const char third = toBinary(runner[2]);
- result += ((second & 0xf) << 4) + ((third & 0x3c) >> 2);
- if (runner[3] != '=') { //no padding
- result += ((third & 0x3) << 6) + toBinary(runner[3]);
- }
- }
- }
- return result;
-}
-
-#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 "JSON_Base64.h"
+#include "JSONDefs.h"
+
+#ifdef JSON_BINARY //if this is not needed, don't waste space compiling it
+
+static const json_char * chars64 = JSON_TEXT("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");
+#ifdef JSON_UNICODE
+ static std::string BASE64_EMPTY_STRING;
+#else
+ #define BASE64_EMPTY_STRING EMPTY_STRING
+#endif
+
+json_string JSONBase64::json_encode64(const unsigned char * binary, size_t bytes){
+ size_t misaligned = bytes % 3;
+ size_t aligned = (bytes - misaligned) / 3; //divide by three once and inc is faster than add 3 each time
+ json_string result;
+ result.reserve((size_t)(((float)bytes) * 1.37f) + 4);
+
+ //do all of the ones that are 3 byte aligned
+ for (size_t i=0; i < aligned; ++i){
+ result += chars64[(binary[0] & 0xFC) >> 2];
+ result += chars64[((binary[0] & 0x03) << 4) + ((binary[1] & 0xF0) >> 4)];
+ result += chars64[((binary[1] & 0x0F) << 2) + ((binary[2] & 0xC0) >> 6)];
+ result += chars64[binary[2] & 0x3F];
+ binary += 3;
+ }
+
+ if (misaligned){
+ //copy the rest into a temporary buffer
+ unsigned char temp[3];
+ for (unsigned int i=0; i < misaligned; ++i){
+ temp[i] = *binary++;
+ }
+ for (unsigned int i = (unsigned int)misaligned; i < 3; ++i){
+ temp[i] = '\0';
+ }
+
+ //now do the final three bytes
+ result += chars64[(temp[0] & 0xFC) >> 2];
+ result += chars64[((temp[0] & 0x03) << 4) + ((temp[1] & 0xF0) >> 4)];
+ if (misaligned == 2){
+ result += chars64[((temp[1] & 0x0F) << 2) + ((temp[2] & 0xC0) >> 6)];
+ result += JSON_TEXT('=');
+ } else {
+ result += JSON_TEXT(" = = ");
+ }
+ }
+ JSON_ASSERT((size_t)(((float)bytes) * 1.37f) + 4 >= result.length(), JSON_TEXT("Didn't reserve enough space for a one-time go"));
+ return result;
+}
+
+inline json_char toBinary(json_char c){
+ if (c == JSON_TEXT('+')) {
+ return JSON_TEXT('>');
+ } else if (c == JSON_TEXT('/')) {
+ return JSON_TEXT('?');
+ } else if (c < JSON_TEXT(':')) {
+ return c + JSON_TEXT('\x04');
+ } else if (c < JSON_TEXT('[')) {
+ return c - JSON_TEXT('\x41');
+ }
+ return c - 71;
+}
+
+/*
+ Must be a std::string because it's binary, and chars must be 1 byte
+ */
+std::string JSONBase64::json_decode64(const json_string & encoded){
+ const size_t length = encoded.length();
+ #if defined JSON_DEBUG || defined JSON_SAFE
+ size_t pos = encoded.find_first_not_of(chars64);
+ if (pos != json_string::npos){
+ JSON_ASSERT_SAFE(encoded[pos] == JSON_TEXT('='), JSON_TEXT("Not Base64"), return BASE64_EMPTY_STRING;);
+ if (pos != length - 1){
+ JSON_ASSERT_SAFE(pos == length - 2, JSON_TEXT("Not Base64"), return BASE64_EMPTY_STRING;);
+ JSON_ASSERT_SAFE(encoded[pos + 1] == JSON_TEXT('='), JSON_TEXT("Not Base64"), return BASE64_EMPTY_STRING;);
+ }
+ }
+ #endif
+ const json_char * runner = encoded.c_str();
+ size_t aligned = length / 4; //don't do the last ones as they might be = padding
+ std::string result;
+ if (aligned){
+ --aligned;
+ result.reserve((size_t)((float)length / 1.37) + 1);
+
+ //first do the ones that can not have any padding
+ for (unsigned int i=0; i < aligned; ++i){
+ const json_char second = toBinary(runner[1]);
+ const json_char third = toBinary(runner[2]);
+ result += (toBinary(runner[0]) << 2) + ((second & 0x30) >> 4);
+ result += ((second & 0xf) << 4) + ((third & 0x3c) >> 2);
+ result += ((third & 0x3) << 6) + toBinary(runner[3]);
+ runner += 4;
+ }
+
+ //now do the ones that might have padding, the first two characters can not be padding, so do them quickly
+ const char second = toBinary(runner[1]);
+ result += (toBinary(runner[0]) << 2) + ((second & 0x30) >> 4);
+ if (runner[2] != '=') { //not two = pads
+ const char third = toBinary(runner[2]);
+ result += ((second & 0xf) << 4) + ((third & 0x3c) >> 2);
+ if (runner[3] != '=') { //no padding
+ result += ((third & 0x3) << 6) + toBinary(runner[3]);
+ }
+ }
+ }
+ return result;
+}
+
+#endif
diff --git a/src/modules/json/JSON_Base64.h b/src/modules/json/JSON_Base64.h
index 1e2d76baa8..6c14aeb866 100644
--- a/src/modules/json/JSON_Base64.h
+++ b/src/modules/json/JSON_Base64.h
@@ -1,14 +1,14 @@
-#ifndef JSON_BASE64_H
-#define JSON_BASE64_H
-
-#include "JSONDebug.h"
-#ifdef JSON_BINARY //if this is not needed, don't waste space compiling it
-
-class JSONBase64 {
-public:
- static json_string json_encode64(const unsigned char * binary, size_t bytes);
- static std::string json_decode64(const json_string & encoded);
-};
-
-#endif
-#endif
+#ifndef JSON_BASE64_H
+#define JSON_BASE64_H
+
+#include "JSONDebug.h"
+#ifdef JSON_BINARY //if this is not needed, don't waste space compiling it
+
+class JSONBase64 {
+public:
+ static json_string json_encode64(const unsigned char * binary, size_t bytes);
+ static std::string json_decode64(const json_string & encoded);
+};
+
+#endif
+#endif
diff --git a/src/modules/json/internalJSONNode.cpp b/src/modules/json/internalJSONNode.cpp
index dfe4971827..3137c70b85 100644
--- a/src/modules/json/internalJSONNode.cpp
+++ b/src/modules/json/internalJSONNode.cpp
@@ -1,572 +1,568 @@
-/*
-
-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"
-#include "internalJSONNode.h"
-#include "NumberToString.h" //So that I can convert numbers into strings
-#include "JSONNode.h" //To fill in the foreward declaration
-#include "JSONWorker.h" //For fetching and parsing and such
-
-/*
- The point of these constants is for faster assigning, if I
- were to constantly assign to a string literal, there would be
- lots of copies, but since strings are copy on write, this assignment
- is much faster
-*/
-static const json_string CONST_TRUE(JSON_TEXT("true"));
-static const json_string CONST_FALSE(JSON_TEXT("false"));
-static const json_string CONST_NULL(JSON_TEXT("null"));
-
-#ifdef JSON_UNIT_TEST
- void internalJSONNode::incinternalAllocCount(void){ JSONNode::incinternalAllocCount(); }
- void internalJSONNode::decinternalAllocCount(void){ JSONNode::decinternalAllocCount(); }
-#endif
-
-internalJSONNode::internalJSONNode(const internalJSONNode & orig) :
- _type(orig._type), _name(orig._name), _name_encoded(orig._name_encoded), Children(),
- _string(orig._string), _string_encoded(orig._string_encoded), _value(orig._value)
- initializeRefCount(1)
- initializeFetch(orig.fetched)
- initializeMutex(0)
- initializeComment(orig._comment)
- initializeValid(orig.isValid){
-
-
- incinternalAllocCount();
- #ifdef JSON_MUTEX_CALLBACKS
- _set_mutex(orig.mylock, false);
- #endif
- if (!orig.Children.empty()) {
- Children.reserve(orig.Children.size());
- json_foreach(orig.Children, myrunner){
- Children.push_back(JSONNode::newJSONNode((*myrunner) -> duplicate()));
- }
- }
-}
-
-#ifdef JSON_PREPARSE
- #define SetFetchedFalseOrDo(code) code
-#else
- #define SetFetchedFalseOrDo(code) SetFetched(false)
-#endif
-
-#ifdef JSON_VALIDATE
- #define NOTVALID false
-#else
- #define NOTVALID
-#endif
-
-//this one is specialized because the root can only be array or node
-internalJSONNode::internalJSONNode(const json_string & unparsed) : _type(), _name(),_name_encoded(false), _string(unparsed), _string_encoded(), _value(), Children()
- initializeMutex(0)
- initializeRefCount(1)
- initializeFetch(false)
- initializeComment(0)
- initializeValid(0){
-
- incinternalAllocCount();
- switch (unparsed[0]) {
- case JSON_TEXT('{'): //node
- _type = JSON_NODE;
- #ifdef JSON_PREPARSE
- FetchNode();
- #endif
- break;
- case JSON_TEXT('['): //array
- _type = JSON_ARRAY;
- #ifdef JSON_PREPARSE
- FetchArray();
- #endif
- break;
- default:
- JSON_FAIL_SAFE(JSON_TEXT("root not starting with either { or ["), Nullify(NOTVALID););
- break;
- }
-}
-
-internalJSONNode::internalJSONNode(const json_string & name_t, const json_string & value_t) : _type(), _name_encoded(), _name(JSONWorker::FixString(name_t, NAME_ENCODED)), _string(), _string_encoded(), _value(), Children()
- initializeMutex(0)
- initializeRefCount(1)
- initializeFetch(0)
- initializeComment(0)
- initializeValid(0){
-
- incinternalAllocCount();
-
- if (value_t.empty()) {
- _type = JSON_NULL;
- #ifdef JSON_VALIDATE
- isValid = true;
- #endif
- SetFetched(true);
- return;
- }
-
- _string = value_t;
- const json_char firstchar = value_t[0];
- #if defined JSON_DEBUG || defined JSON_SAFE
- const json_char lastchar = value_t[value_t.length() - 1];
- #endif
-
- switch (firstchar){
- case JSON_TEXT('\"'): //a json_string literal, still escaped and with leading and trailing quotes
- JSON_ASSERT_SAFE(lastchar == JSON_TEXT('\"'), JSON_TEXT("Unterminated quote"), Nullify(NOTVALID); return;);
- _type = JSON_STRING;
- SetFetchedFalseOrDo(FetchString());
- break;
- case JSON_TEXT('{'): //a child node, or set of children
- JSON_ASSERT_SAFE(lastchar == JSON_TEXT('}'), JSON_TEXT("Missing }"), Nullify(NOTVALID); return;);
- _type = JSON_NODE;
- SetFetchedFalseOrDo(FetchNode());
- break;
- case JSON_TEXT('['): //an array
- JSON_ASSERT_SAFE(lastchar == JSON_TEXT(']'), JSON_TEXT("Missing ]"), Nullify(NOTVALID); return;);
- _type = JSON_ARRAY;
- SetFetchedFalseOrDo(FetchArray());
- break;
- case JSON_TEXT('t'):
- JSON_ASSERT_SAFE(value_t == JSON_TEXT("true"), json_string(json_string(JSON_TEXT("unknown JSON literal: ")) + value_t).c_str(), Nullify(NOTVALID); return;);
- _value._bool = true;
- _type = JSON_BOOL;
- SetFetched(true);
- break;
- case JSON_TEXT('f'):
- JSON_ASSERT_SAFE(value_t == JSON_TEXT("false"), json_string(json_string(JSON_TEXT("unknown JSON literal: ")) + value_t).c_str(), Nullify(NOTVALID); return;);
- _value._bool = false;
- _type = JSON_BOOL;
- SetFetched(true);
- break;
- case JSON_TEXT('n'):
- JSON_ASSERT_SAFE(value_t == JSON_TEXT("null"), json_string(json_string(JSON_TEXT("unknown JSON literal: ")) + value_t).c_str(), Nullify(NOTVALID); return;);
- _type = JSON_NULL;
- SetFetched(true);
- #ifdef JSON_VALIDATE
- isValid = true;
- #endif
- break;
- default:
- JSON_ASSERT_SAFE(value_t.find_first_not_of(JSON_TEXT("0123456789.e+-")) == json_string::npos, json_string(json_string(JSON_TEXT("unknown JSON literal: ")) + value_t).c_str(), Nullify(NOTVALID); return;);
- _type = JSON_NUMBER;
- SetFetchedFalseOrDo(FetchNumber());
- break;
- }
-}
-
-internalJSONNode::~internalJSONNode(void){
- decinternalAllocCount();
- #ifdef JSON_MUTEX_CALLBACKS
- _unset_mutex();
- #endif
- //DO NOT delete the children! It automatically gets removed
-}
-
-void internalJSONNode::FetchString(void) const {
- JSON_ASSERT_SAFE(!_string.empty(), JSON_TEXT("JSON json_string type is empty?"), Nullify(NOTVALID); return;);
- JSON_ASSERT_SAFE(_string[0] == JSON_TEXT('\"'), JSON_TEXT("JSON json_string type doesn't start with a quotation?"), Nullify(NOTVALID); return;);
- JSON_ASSERT_SAFE(_string[_string.length() - 1] == JSON_TEXT('\"'), JSON_TEXT("JSON json_string type doesn't end with a quotation?"), Nullify(NOTVALID); return;);
- _string = JSONWorker::FixString(_string.substr(1, _string.length() - 2), STRING_ENCODED);
-}
-
-void internalJSONNode::FetchNode(void) const {
- JSON_ASSERT_SAFE(!_string.empty(), JSON_TEXT("JSON node type is empty?"), Nullify(NOTVALID); return;);
- JSON_ASSERT_SAFE(_string[0] == JSON_TEXT('{'), JSON_TEXT("JSON node type doesn't start with a bracket?"), Nullify(NOTVALID); return;);
- JSON_ASSERT_SAFE(_string[_string.length() - 1] == JSON_TEXT('}'), JSON_TEXT("JSON node type doesn't end with a bracket?"), Nullify(NOTVALID); return;);
- JSONWorker::DoNode(this, _string);
- clearString(_string);
-}
-
-void internalJSONNode::FetchArray(void) const {
- JSON_ASSERT_SAFE(!_string.empty(), JSON_TEXT("JSON node type is empty?"), Nullify(NOTVALID); return;);
- JSON_ASSERT_SAFE(_string[0] == JSON_TEXT('['), JSON_TEXT("JSON node type doesn't start with a square bracket?"), Nullify(NOTVALID); return;);
- JSON_ASSERT_SAFE(_string[_string.length() - 1] == JSON_TEXT(']'), JSON_TEXT("JSON node type doesn't end with a square bracket?"), Nullify(NOTVALID); return;);
- JSONWorker::DoArray(this, _string);
- clearString(_string);
-}
-
-void internalJSONNode::FetchNumber(void) const {
- #ifdef JSON_UNICODE
- {
- const size_t len = _string.length();
- json_auto<char> temp(len + 1);
- wcstombs(temp.ptr, _string.c_str(), len);
- temp.ptr[len] = '\0';
- _value._number = (json_number)atof(temp.ptr);
- }
- #else
- _value._number = (json_number)atof(_string.c_str());
- #endif
-}
-
-#ifndef JSON_PREPARSE
- void internalJSONNode::Fetch(void) const {
- if (fetched) return;
- switch (type()) {
- case JSON_STRING:
- FetchString();
- break;
- case JSON_NODE:
- FetchNode();
- break;
- case JSON_ARRAY:
- FetchArray();
- break;
- case JSON_NUMBER:
- FetchNumber();
- break;
- #if defined JSON_DEBUG || defined JSON_SAFE
- default:
- JSON_FAIL(JSON_TEXT("Fetching an unknown type"));
- Nullify(NOTVALID);
- #endif
- }
- fetched = true;
- }
-#endif
-
-void internalJSONNode::Set(const json_string & val){
- _type = JSON_STRING;
- _string = val;
- _string_encoded = true;
- SetFetched(true);
-}
-
-
-#ifdef JSON_LIBRARY
- void internalJSONNode::Set(long val){
- _type = JSON_NUMBER;
- _value._number = (json_number)val;
- _string = NumberToString::_itoa<long>(val, sizeof(long));
- SetFetched(true);
- }
-
- void internalJSONNode::Set(json_number val){
- _type = JSON_NUMBER;
- _value._number = val;
- _string = NumberToString::_ftoa<json_number>(val);
- SetFetched(true);
- }
-#else
- #define SET(converter, type)\
- void internalJSONNode::Set(type val){\
- _type = JSON_NUMBER;\
- _value._number = (json_number)val;\
- _string = NumberToString::converter<type>(val, sizeof(type));\
- SetFetched(true);\
- }
- #define SET_INTEGER(type) SET(_itoa, type) SET(_uitoa, unsigned type)
- #define SET_FLOAT(type) \
- void internalJSONNode::Set(type val){\
- _type = JSON_NUMBER;\
- _value._number = (json_number)val;\
- _string = NumberToString::_ftoa<type>(val);\
- SetFetched(true);\
- }
-
- SET_INTEGER(char)
- SET_INTEGER(short)
- SET_INTEGER(int)
- SET_INTEGER(long)
- #ifndef JSON_ISO_STRICT
- SET_INTEGER(long long)
- #endif
-
- SET_FLOAT(float)
- SET_FLOAT(double)
-#endif
-
-void internalJSONNode::Set(bool val){
- _type = JSON_BOOL;
- _value._bool = val;
- _string = val ? CONST_TRUE : CONST_FALSE;
- SetFetched(true);
-}
-
-bool internalJSONNode::IsEqualTo(const internalJSONNode * val) const {
- #ifdef JSON_REF_COUNT
- if (this == val) return true; //reference counting the same internal object, so they must be equal
- #endif
- if (type() != val -> type()) return false; //aren't even same type
- if (_name != val -> _name) return false; //names aren't the same
- if (type() == JSON_NULL) return true; //both null, can't be different
- #ifndef JSON_PREPARSE
- Fetch();
- val -> Fetch();
- #endif
- switch (type()) {
- case JSON_STRING:
- return val -> _string == _string;
- case JSON_NUMBER:
- return NumberToString::areEqual(val -> _value._number, _value._number);
- case JSON_BOOL:
- return val -> _value._bool == _value._bool;
- };
-
- JSON_ASSERT(type() == JSON_NODE || type() == JSON_ARRAY, JSON_TEXT("Checking for equality, not sure what type"));
- if (Children.size() != val -> Children.size()) return false; //if they arne't he same size then they certainly aren't equal
-
- //make sure each children is the same
- JSONNode ** valrunner = val -> Children.begin();
- json_foreach(Children, myrunner){
- JSON_ASSERT(*myrunner, JSON_TEXT("a null pointer within the children"));
- JSON_ASSERT(*valrunner, JSON_TEXT("a null pointer within the children"));
- JSON_ASSERT(valrunner != val -> Children.end(), JSON_TEXT("at the end of other one's children, but they're the same size?"));
- if (**myrunner != **valrunner) return false;
- ++valrunner;
- }
- return true;
-}
-
-#ifdef JSON_VALIDATE
-void internalJSONNode::Nullify(bool validation) const {
- isValid = validation;
-#else
-void internalJSONNode::Nullify(void) const {
-#endif
- _type = JSON_NULL;
- _string = CONST_NULL;
- SetFetched(true);
-}
-
-#ifdef JSON_MUTEX_CALLBACKS
- #define JSON_MUTEX_COPY ,mylock
-#else
- #define JSON_MUTEX_COPY
-#endif
-
-#ifdef JSON_LIBRARY
-void internalJSONNode::push_back(JSONNode * node){
-#else
-void internalJSONNode::push_back(const JSONNode & node){
-#endif
- JSON_ASSERT(type() == JSON_ARRAY || type() == JSON_NODE, JSON_TEXT("pushing back to something that is not an array or object"));
- #ifdef JSON_LIBRARY
- #ifdef JSON_MUTEX_CALLBACKS
- if (mylock) node -> set_mutex(mylock);
- #endif
- Children.push_back(node);
- #else
- Children.push_back(JSONNode::newJSONNode(node JSON_MUTEX_COPY));
- #endif
-}
-
-void internalJSONNode::push_front(const JSONNode & node){
- JSON_ASSERT(type() == JSON_ARRAY || type() == JSON_NODE, JSON_TEXT("pushing front to something that is not an array or object"));
- Children.push_front(JSONNode::newJSONNode(node JSON_MUTEX_COPY));
-}
-
-JSONNode * internalJSONNode::pop_back(json_index_t pos){
- JSONNode * result = Children[pos];
- JSONNode ** temp = Children.begin() + pos;
- Children.erase(temp);
- return result;
-}
-
-JSONNode * internalJSONNode::pop_back(const json_string & name_t){
- if (JSONNode ** res = at(name_t)) {
- JSONNode * result = *res;
- Children.erase(res);
- return result;
- }
- return 0;
-}
-
-#ifdef JSON_CASE_INSENSITIVE_FUNCTIONS
- JSONNode * internalJSONNode::pop_back_nocase(const json_string & name_t){
- if (JSONNode ** res = at_nocase(name_t)) {
- JSONNode * result = *res;
- Children.erase(res);
- return result;
- }
- return 0;
- }
-#endif
-
-JSONNode ** internalJSONNode::at(const json_string & name_t){
- Fetch();
- json_foreach(Children, myrunner){
- JSON_ASSERT(*myrunner, JSON_TEXT("a null pointer within the children"));
- if ((*myrunner) -> name() == name_t) return myrunner;
- }
- return 0;
-}
-
-#ifdef JSON_CASE_INSENSITIVE_FUNCTIONS
- bool internalJSONNode::AreEqualNoCase(const json_char * ch_one, const json_char * ch_two){
- while (*ch_one){ //only need to check one, if the other one terminates early, the check will cause it to fail
- const json_char c_one = *ch_one;
- const json_char c_two = *ch_two;
- if (c_one != c_two){
- if ((c_two > 64) && (c_two < 91)) { //A - Z
- if (c_one != (json_char)(c_two + 32)) return false;
- } else if ((c_two > 96) && (c_two < 123)) { //a - z
- if (c_one != (json_char)(c_two - 32)) return false;
- } else { //not a letter, so return false
- return false;
- }
- }
- ++ch_one;
- ++ch_two;
-
- }
- return *ch_two == '\0'; //this one has to be null terminated too, or else json_string two is longer, hence, not equal
- }
-
- JSONNode ** internalJSONNode::at_nocase(const json_string & name_t){
- Fetch();
- json_foreach(Children, myrunner){
- JSON_ASSERT(*myrunner, JSON_TEXT("a null pointer within the children"));
- if (AreEqualNoCase((*myrunner) -> name().c_str(), name_t.c_str())) return myrunner;
- }
- return 0;
- }
-#endif
-
-#ifndef JSON_PREPARSE
- void internalJSONNode::preparse(void){
- Fetch();
- json_foreach(Children, myrunner){
- (*myrunner) -> preparse();
- }
- }
-#endif
-
-#ifdef JSON_VALIDATE
- bool internalJSONNode::validate(void){
- json_foreach(Children, myrunner){
- if ((*myrunner) -> type() != JSON_NULL){
- #ifndef JSON_PREPARSE
- (*myrunner) -> internal -> Fetch();
- #endif
- if ((*myrunner) -> type() == JSON_NULL) return false;
- } else if (!((*myrunner) -> internal -> isValid)) {
- JSON_FAIL(_name + JSON_TEXT(" is null and not valid"));
- return false;
- }
- }
- json_foreach(Children, runner){
- if (!((*runner) -> internal -> validate())) return false;
- }
- return true;
- }
-#endif
-
-#ifdef JSON_DEBUG
- #ifndef JSON_LIBRARY
- JSONNode internalJSONNode::Dump(size_t & totalbytes) const {
- JSONNode dumpage(JSON_NODE);
- dumpage.set_name(JSON_TEXT("internalJSONNode"));
- dumpage.push_back(JSON_NEW(JSONNode(JSON_TEXT("this"), (long)this)));
-
- size_t memory = sizeof(internalJSONNode);
- memory += _name.capacity() * sizeof(json_char);
- memory += _string.capacity() * sizeof(json_char);
- memory += Children.capacity() * sizeof(JSONNode*);
- #ifdef JSON_COMMENTS
- memory += _comment.capacity() * sizeof(json_char);
- #endif
- totalbytes += memory;
- dumpage.push_back(JSON_NEW(JSONNode(JSON_TEXT("bytes used"), memory)));
-
-
- #ifdef JSON_REF_COUNT
- dumpage.push_back(JSON_NEW(JSONNode(JSON_TEXT("refcount"), refcount)));
- #endif
- #ifdef JSON_MUTEX_CALLBACKS
- dumpage.push_back(JSON_NEW(DumpMutex()));
- #endif
-
-
- #define DUMPCASE(ty)\
- case ty:\
- dumpage.push_back(JSON_NEW(JSONNode(JSON_TEXT("_type"), JSON_TEXT(#ty))));\
- break;
-
- switch(type()) {
- DUMPCASE(JSON_NULL)
- DUMPCASE(JSON_STRING)
- DUMPCASE(JSON_NUMBER)
- DUMPCASE(JSON_BOOL)
- DUMPCASE(JSON_ARRAY)
- DUMPCASE(JSON_NODE)
- default:
- dumpage.push_back(JSON_NEW(JSONNode(JSON_TEXT("_type"), JSON_TEXT("Unknown"))));
- }
-
- JSONNode str(JSON_NODE);
- str.set_name(JSON_TEXT("_name"));
- str.push_back(JSON_NEW(JSONNode(json_string(JSON_TEXT("value")), _name)));
- str.push_back(JSON_NEW(JSONNode(JSON_TEXT("length"), _name.length())));
- str.push_back(JSON_NEW(JSONNode(JSON_TEXT("capactiy"), _name.capacity())));
-
- #ifdef JSON_LESS_MEMORY
- dumpage.push_back(JSON_NEW(JSONNode(JSON_TEXT("_name_encoded"), _type & 0x10)));
- #else
- dumpage.push_back(JSON_NEW(JSONNode(JSON_TEXT("_name_encoded"), _name_encoded)));
- #endif
- dumpage.push_back(JSON_NEW(str));
- dumpage.push_back(JSON_NEW(JSONNode(JSON_TEXT("_string_encoded"), _string_encoded)));
- str.clear();
- str.set_name(JSON_TEXT("_string"));
- str.push_back(JSON_NEW(JSONNode(json_string(JSON_TEXT("value")), _string)));
- str.push_back(JSON_NEW(JSONNode(JSON_TEXT("length"), _string.length())));
- str.push_back(JSON_NEW(JSONNode(JSON_TEXT("capactiy"), _string.capacity())));
- dumpage.push_back(JSON_NEW(str));
-
- JSONNode unio(JSON_NODE);
- unio.set_name(JSON_TEXT("_value"));
- unio.push_back(JSON_NEW(JSONNode(JSON_TEXT("_bool"), _value._bool)));
- unio.push_back(JSON_NEW(JSONNode(JSON_TEXT("_number"), _value._number)));
- dumpage.push_back(JSON_NEW(unio));
-
- #ifndef JSON_PREPARSE
- dumpage.push_back(JSON_NEW(JSONNode(JSON_TEXT("fetched"), fetched)));
- #endif
-
- #ifdef JSON_COMMENTS
- str.clear();
- str.set_name(JSON_TEXT("_comment"));
- str.push_back(JSON_NEW(JSONNode(JSON_TEXT("value"), _comment)));
- str.push_back(JSON_NEW(JSONNode(JSON_TEXT("length"), _comment.length())));
- str.push_back(JSON_NEW(JSONNode(JSON_TEXT("capactiy"), _comment.capacity())));
- dumpage.push_back(JSON_NEW(str));
- #endif
-
- JSONNode arra(JSON_NODE);
- arra.set_name(JSON_TEXT("Children"));
- arra.push_back(JSON_NEW(JSONNode(JSON_TEXT("size"), Children.size())));
- arra.push_back(JSON_NEW(JSONNode(JSON_TEXT("capacity"), Children.capacity())));
- JSONNode chil(JSON_ARRAY);
- chil.set_name(JSON_TEXT("array"));
- json_foreach(Children, it){
- chil.push_back(JSON_NEW((*it) -> dump(totalbytes)));
- }
- arra.push_back(JSON_NEW(chil));
- dumpage.push_back(JSON_NEW(arra));
-
- return dumpage;
- }
- #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"
+#include "internalJSONNode.h"
+#include "NumberToString.h" //So that I can convert numbers into strings
+#include "JSONNode.h" //To fill in the foreward declaration
+#include "JSONWorker.h" //For fetching and parsing and such
+
+/*
+ The point of these constants is for faster assigning, if I
+ were to constantly assign to a string literal, there would be
+ lots of copies, but since strings are copy on write, this assignment
+ is much faster
+*/
+static const json_string CONST_TRUE(JSON_TEXT("true"));
+static const json_string CONST_FALSE(JSON_TEXT("false"));
+static const json_string CONST_NULL(JSON_TEXT("null"));
+
+#ifdef JSON_UNIT_TEST
+ void internalJSONNode::incinternalAllocCount(void){ JSONNode::incinternalAllocCount(); }
+ void internalJSONNode::decinternalAllocCount(void){ JSONNode::decinternalAllocCount(); }
+#endif
+
+internalJSONNode::internalJSONNode(const internalJSONNode & orig) :
+ _type(orig._type), _name(orig._name), _name_encoded(orig._name_encoded), Children(),
+ _string(orig._string), _string_encoded(orig._string_encoded), _value(orig._value)
+ initializeRefCount(1)
+ initializeFetch(orig.fetched)
+ initializeMutex(0)
+ initializeComment(orig._comment)
+ initializeValid(orig.isValid){
+
+ incinternalAllocCount();
+ #ifdef JSON_MUTEX_CALLBACKS
+ _set_mutex(orig.mylock, false);
+ #endif
+ if (!orig.Children.empty()) {
+ Children.reserve(orig.Children.size());
+ json_foreach(orig.Children, myrunner){
+ Children.push_back(JSONNode::newJSONNode((*myrunner) -> duplicate()));
+ }
+ }
+}
+
+#ifdef JSON_PREPARSE
+ #define SetFetchedFalseOrDo(code) code
+#else
+ #define SetFetchedFalseOrDo(code) SetFetched(false)
+#endif
+
+#ifdef JSON_VALIDATE
+ #define NOTVALID false
+#else
+ #define NOTVALID
+#endif
+
+//this one is specialized because the root can only be array or node
+internalJSONNode::internalJSONNode(const json_string & unparsed) : _type(), _name(),_name_encoded(false), _string(unparsed), _string_encoded(), _value(), Children()
+ initializeMutex(0)
+ initializeRefCount(1)
+ initializeFetch(false)
+ initializeComment(0)
+ initializeValid(0){
+
+ incinternalAllocCount();
+ switch (unparsed[0]) {
+ case JSON_TEXT('{'): //node
+ _type = JSON_NODE;
+ #ifdef JSON_PREPARSE
+ FetchNode();
+ #endif
+ break;
+ case JSON_TEXT('['): //array
+ _type = JSON_ARRAY;
+ #ifdef JSON_PREPARSE
+ FetchArray();
+ #endif
+ break;
+ default:
+ JSON_FAIL_SAFE(JSON_TEXT("root not starting with either { or ["), Nullify(NOTVALID););
+ break;
+ }
+}
+
+internalJSONNode::internalJSONNode(const json_string & name_t, const json_string & value_t) : _type(), _name_encoded(), _name(JSONWorker::FixString(name_t, NAME_ENCODED)), _string(), _string_encoded(), _value(), Children()
+ initializeMutex(0)
+ initializeRefCount(1)
+ initializeFetch(0)
+ initializeComment(0)
+ initializeValid(0){
+
+ incinternalAllocCount();
+
+ if (value_t.empty()) {
+ _type = JSON_NULL;
+ #ifdef JSON_VALIDATE
+ isValid = true;
+ #endif
+ SetFetched(true);
+ return;
+ }
+
+ _string = value_t;
+ const json_char firstchar = value_t[0];
+ #if defined JSON_DEBUG || defined JSON_SAFE
+ const json_char lastchar = value_t[value_t.length() - 1];
+ #endif
+
+ switch (firstchar){
+ case JSON_TEXT('\"'): //a json_string literal, still escaped and with leading and trailing quotes
+ JSON_ASSERT_SAFE(lastchar == JSON_TEXT('\"'), JSON_TEXT("Unterminated quote"), Nullify(NOTVALID); return;);
+ _type = JSON_STRING;
+ SetFetchedFalseOrDo(FetchString());
+ break;
+ case JSON_TEXT('{'): //a child node, or set of children
+ JSON_ASSERT_SAFE(lastchar == JSON_TEXT('}'), JSON_TEXT("Missing }"), Nullify(NOTVALID); return;);
+ _type = JSON_NODE;
+ SetFetchedFalseOrDo(FetchNode());
+ break;
+ case JSON_TEXT('['): //an array
+ JSON_ASSERT_SAFE(lastchar == JSON_TEXT(']'), JSON_TEXT("Missing ]"), Nullify(NOTVALID); return;);
+ _type = JSON_ARRAY;
+ SetFetchedFalseOrDo(FetchArray());
+ break;
+ case JSON_TEXT('t'):
+ JSON_ASSERT_SAFE(value_t == JSON_TEXT("true"), json_string(json_string(JSON_TEXT("unknown JSON literal: ")) + value_t).c_str(), Nullify(NOTVALID); return;);
+ _value._bool = true;
+ _type = JSON_BOOL;
+ SetFetched(true);
+ break;
+ case JSON_TEXT('f'):
+ JSON_ASSERT_SAFE(value_t == JSON_TEXT("false"), json_string(json_string(JSON_TEXT("unknown JSON literal: ")) + value_t).c_str(), Nullify(NOTVALID); return;);
+ _value._bool = false;
+ _type = JSON_BOOL;
+ SetFetched(true);
+ break;
+ case JSON_TEXT('n'):
+ JSON_ASSERT_SAFE(value_t == JSON_TEXT("null"), json_string(json_string(JSON_TEXT("unknown JSON literal: ")) + value_t).c_str(), Nullify(NOTVALID); return;);
+ _type = JSON_NULL;
+ SetFetched(true);
+ #ifdef JSON_VALIDATE
+ isValid = true;
+ #endif
+ break;
+ default:
+ JSON_ASSERT_SAFE(value_t.find_first_not_of(JSON_TEXT("0123456789.e+-")) == json_string::npos, json_string(json_string(JSON_TEXT("unknown JSON literal: ")) + value_t).c_str(), Nullify(NOTVALID); return;);
+ _type = JSON_NUMBER;
+ SetFetchedFalseOrDo(FetchNumber());
+ break;
+ }
+}
+
+internalJSONNode::~internalJSONNode(void){
+ decinternalAllocCount();
+ #ifdef JSON_MUTEX_CALLBACKS
+ _unset_mutex();
+ #endif
+ //DO NOT delete the children! It automatically gets removed
+}
+
+void internalJSONNode::FetchString(void) const {
+ JSON_ASSERT_SAFE(!_string.empty(), JSON_TEXT("JSON json_string type is empty?"), Nullify(NOTVALID); return;);
+ JSON_ASSERT_SAFE(_string[0] == JSON_TEXT('\"'), JSON_TEXT("JSON json_string type doesn't start with a quotation?"), Nullify(NOTVALID); return;);
+ JSON_ASSERT_SAFE(_string[_string.length() - 1] == JSON_TEXT('\"'), JSON_TEXT("JSON json_string type doesn't end with a quotation?"), Nullify(NOTVALID); return;);
+ _string = JSONWorker::FixString(_string.substr(1, _string.length() - 2), STRING_ENCODED);
+}
+
+void internalJSONNode::FetchNode(void) const {
+ JSON_ASSERT_SAFE(!_string.empty(), JSON_TEXT("JSON node type is empty?"), Nullify(NOTVALID); return;);
+ JSON_ASSERT_SAFE(_string[0] == JSON_TEXT('{'), JSON_TEXT("JSON node type doesn't start with a bracket?"), Nullify(NOTVALID); return;);
+ JSON_ASSERT_SAFE(_string[_string.length() - 1] == JSON_TEXT('}'), JSON_TEXT("JSON node type doesn't end with a bracket?"), Nullify(NOTVALID); return;);
+ JSONWorker::DoNode(this, _string);
+ clearString(_string);
+}
+
+void internalJSONNode::FetchArray(void) const {
+ JSON_ASSERT_SAFE(!_string.empty(), JSON_TEXT("JSON node type is empty?"), Nullify(NOTVALID); return;);
+ JSON_ASSERT_SAFE(_string[0] == JSON_TEXT('['), JSON_TEXT("JSON node type doesn't start with a square bracket?"), Nullify(NOTVALID); return;);
+ JSON_ASSERT_SAFE(_string[_string.length() - 1] == JSON_TEXT(']'), JSON_TEXT("JSON node type doesn't end with a square bracket?"), Nullify(NOTVALID); return;);
+ JSONWorker::DoArray(this, _string);
+ clearString(_string);
+}
+
+void internalJSONNode::FetchNumber(void) const {
+ #ifdef JSON_UNICODE
+ {
+ const size_t len = _string.length();
+ json_auto<char> temp(len + 1);
+ wcstombs(temp.ptr, _string.c_str(), len);
+ temp.ptr[len] = '\0';
+ _value._number = (json_number)atof(temp.ptr);
+ }
+ #else
+ _value._number = (json_number)atof(_string.c_str());
+ #endif
+}
+
+#ifndef JSON_PREPARSE
+ void internalJSONNode::Fetch(void) const {
+ if (fetched) return;
+ switch (type()) {
+ case JSON_STRING:
+ FetchString();
+ break;
+ case JSON_NODE:
+ FetchNode();
+ break;
+ case JSON_ARRAY:
+ FetchArray();
+ break;
+ case JSON_NUMBER:
+ FetchNumber();
+ break;
+ #if defined JSON_DEBUG || defined JSON_SAFE
+ default:
+ JSON_FAIL(JSON_TEXT("Fetching an unknown type"));
+ Nullify(NOTVALID);
+ #endif
+ }
+ fetched = true;
+ }
+#endif
+
+void internalJSONNode::Set(const json_string & val){
+ _type = JSON_STRING;
+ _string = val;
+ _string_encoded = true;
+ SetFetched(true);
+}
+
+#ifdef JSON_LIBRARY
+ void internalJSONNode::Set(long val){
+ _type = JSON_NUMBER;
+ _value._number = (json_number)val;
+ _string = NumberToString::_itoa<long>(val, sizeof(long));
+ SetFetched(true);
+ }
+
+ void internalJSONNode::Set(json_number val){
+ _type = JSON_NUMBER;
+ _value._number = val;
+ _string = NumberToString::_ftoa<json_number>(val);
+ SetFetched(true);
+ }
+#else
+ #define SET(converter, type)\
+ void internalJSONNode::Set(type val){\
+ _type = JSON_NUMBER;\
+ _value._number = (json_number)val;\
+ _string = NumberToString::converter<type>(val, sizeof(type));\
+ SetFetched(true);\
+ }
+ #define SET_INTEGER(type) SET(_itoa, type) SET(_uitoa, unsigned type)
+ #define SET_FLOAT(type) \
+ void internalJSONNode::Set(type val){\
+ _type = JSON_NUMBER;\
+ _value._number = (json_number)val;\
+ _string = NumberToString::_ftoa<type>(val);\
+ SetFetched(true);\
+ }
+
+ SET_INTEGER(char)
+ SET_INTEGER(short)
+ SET_INTEGER(int)
+ SET_INTEGER(long)
+ #ifndef JSON_ISO_STRICT
+ SET_INTEGER(long long)
+ #endif
+
+ SET_FLOAT(float)
+ SET_FLOAT(double)
+#endif
+
+void internalJSONNode::Set(bool val){
+ _type = JSON_BOOL;
+ _value._bool = val;
+ _string = val ? CONST_TRUE : CONST_FALSE;
+ SetFetched(true);
+}
+
+bool internalJSONNode::IsEqualTo(const internalJSONNode * val) const {
+ #ifdef JSON_REF_COUNT
+ if (this == val) return true; //reference counting the same internal object, so they must be equal
+ #endif
+ if (type() != val -> type()) return false; //aren't even same type
+ if (_name != val -> _name) return false; //names aren't the same
+ if (type() == JSON_NULL) return true; //both null, can't be different
+ #ifndef JSON_PREPARSE
+ Fetch();
+ val -> Fetch();
+ #endif
+ switch (type()) {
+ case JSON_STRING:
+ return val -> _string == _string;
+ case JSON_NUMBER:
+ return NumberToString::areEqual(val -> _value._number, _value._number);
+ case JSON_BOOL:
+ return val -> _value._bool == _value._bool;
+ };
+
+ JSON_ASSERT(type() == JSON_NODE || type() == JSON_ARRAY, JSON_TEXT("Checking for equality, not sure what type"));
+ if (Children.size() != val -> Children.size()) return false; //if they arne't he same size then they certainly aren't equal
+
+ //make sure each children is the same
+ JSONNode ** valrunner = val -> Children.begin();
+ json_foreach(Children, myrunner){
+ JSON_ASSERT(*myrunner, JSON_TEXT("a null pointer within the children"));
+ JSON_ASSERT(*valrunner, JSON_TEXT("a null pointer within the children"));
+ JSON_ASSERT(valrunner != val -> Children.end(), JSON_TEXT("at the end of other one's children, but they're the same size?"));
+ if (**myrunner != **valrunner) return false;
+ ++valrunner;
+ }
+ return true;
+}
+
+#ifdef JSON_VALIDATE
+void internalJSONNode::Nullify(bool validation) const {
+ isValid = validation;
+#else
+void internalJSONNode::Nullify(void) const {
+#endif
+ _type = JSON_NULL;
+ _string = CONST_NULL;
+ SetFetched(true);
+}
+
+#ifdef JSON_MUTEX_CALLBACKS
+ #define JSON_MUTEX_COPY ,mylock
+#else
+ #define JSON_MUTEX_COPY
+#endif
+
+#ifdef JSON_LIBRARY
+void internalJSONNode::push_back(JSONNode * node){
+#else
+void internalJSONNode::push_back(const JSONNode & node){
+#endif
+ JSON_ASSERT(type() == JSON_ARRAY || type() == JSON_NODE, JSON_TEXT("pushing back to something that is not an array or object"));
+ #ifdef JSON_LIBRARY
+ #ifdef JSON_MUTEX_CALLBACKS
+ if (mylock) node -> set_mutex(mylock);
+ #endif
+ Children.push_back(node);
+ #else
+ Children.push_back(JSONNode::newJSONNode(node JSON_MUTEX_COPY));
+ #endif
+}
+
+void internalJSONNode::push_front(const JSONNode & node){
+ JSON_ASSERT(type() == JSON_ARRAY || type() == JSON_NODE, JSON_TEXT("pushing front to something that is not an array or object"));
+ Children.push_front(JSONNode::newJSONNode(node JSON_MUTEX_COPY));
+}
+
+JSONNode * internalJSONNode::pop_back(json_index_t pos){
+ JSONNode * result = Children[pos];
+ JSONNode ** temp = Children.begin() + pos;
+ Children.erase(temp);
+ return result;
+}
+
+JSONNode * internalJSONNode::pop_back(const json_string & name_t){
+ if (JSONNode ** res = at(name_t)) {
+ JSONNode * result = *res;
+ Children.erase(res);
+ return result;
+ }
+ return 0;
+}
+
+#ifdef JSON_CASE_INSENSITIVE_FUNCTIONS
+ JSONNode * internalJSONNode::pop_back_nocase(const json_string & name_t){
+ if (JSONNode ** res = at_nocase(name_t)) {
+ JSONNode * result = *res;
+ Children.erase(res);
+ return result;
+ }
+ return 0;
+ }
+#endif
+
+JSONNode ** internalJSONNode::at(const json_string & name_t){
+ Fetch();
+ json_foreach(Children, myrunner){
+ JSON_ASSERT(*myrunner, JSON_TEXT("a null pointer within the children"));
+ if ((*myrunner) -> name() == name_t) return myrunner;
+ }
+ return 0;
+}
+
+#ifdef JSON_CASE_INSENSITIVE_FUNCTIONS
+ bool internalJSONNode::AreEqualNoCase(const json_char * ch_one, const json_char * ch_two){
+ while (*ch_one){ //only need to check one, if the other one terminates early, the check will cause it to fail
+ const json_char c_one = *ch_one;
+ const json_char c_two = *ch_two;
+ if (c_one != c_two){
+ if ((c_two > 64) && (c_two < 91)) { //A - Z
+ if (c_one != (json_char)(c_two + 32)) return false;
+ } else if ((c_two > 96) && (c_two < 123)) { //a - z
+ if (c_one != (json_char)(c_two - 32)) return false;
+ } else { //not a letter, so return false
+ return false;
+ }
+ }
+ ++ch_one;
+ ++ch_two;
+
+ }
+ return *ch_two == '\0'; //this one has to be null terminated too, or else json_string two is longer, hence, not equal
+ }
+
+ JSONNode ** internalJSONNode::at_nocase(const json_string & name_t){
+ Fetch();
+ json_foreach(Children, myrunner){
+ JSON_ASSERT(*myrunner, JSON_TEXT("a null pointer within the children"));
+ if (AreEqualNoCase((*myrunner) -> name().c_str(), name_t.c_str())) return myrunner;
+ }
+ return 0;
+ }
+#endif
+
+#ifndef JSON_PREPARSE
+ void internalJSONNode::preparse(void){
+ Fetch();
+ json_foreach(Children, myrunner){
+ (*myrunner) -> preparse();
+ }
+ }
+#endif
+
+#ifdef JSON_VALIDATE
+ bool internalJSONNode::validate(void){
+ json_foreach(Children, myrunner){
+ if ((*myrunner) -> type() != JSON_NULL){
+ #ifndef JSON_PREPARSE
+ (*myrunner) -> internal -> Fetch();
+ #endif
+ if ((*myrunner) -> type() == JSON_NULL) return false;
+ } else if (!((*myrunner) -> internal -> isValid)) {
+ JSON_FAIL(_name + JSON_TEXT(" is null and not valid"));
+ return false;
+ }
+ }
+ json_foreach(Children, runner){
+ if (!((*runner) -> internal -> validate())) return false;
+ }
+ return true;
+ }
+#endif
+
+#ifdef JSON_DEBUG
+ #ifndef JSON_LIBRARY
+ JSONNode internalJSONNode::Dump(size_t & totalbytes) const {
+ JSONNode dumpage(JSON_NODE);
+ dumpage.set_name(JSON_TEXT("internalJSONNode"));
+ dumpage.push_back(JSON_NEW(JSONNode(JSON_TEXT("this"), (long)this)));
+
+ size_t memory = sizeof(internalJSONNode);
+ memory += _name.capacity() * sizeof(json_char);
+ memory += _string.capacity() * sizeof(json_char);
+ memory += Children.capacity() * sizeof(JSONNode*);
+ #ifdef JSON_COMMENTS
+ memory += _comment.capacity() * sizeof(json_char);
+ #endif
+ totalbytes += memory;
+ dumpage.push_back(JSON_NEW(JSONNode(JSON_TEXT("bytes used"), memory)));
+
+ #ifdef JSON_REF_COUNT
+ dumpage.push_back(JSON_NEW(JSONNode(JSON_TEXT("refcount"), refcount)));
+ #endif
+ #ifdef JSON_MUTEX_CALLBACKS
+ dumpage.push_back(JSON_NEW(DumpMutex()));
+ #endif
+
+ #define DUMPCASE(ty)\
+ case ty:\
+ dumpage.push_back(JSON_NEW(JSONNode(JSON_TEXT("_type"), JSON_TEXT(#ty))));\
+ break;
+
+ switch(type()) {
+ DUMPCASE(JSON_NULL)
+ DUMPCASE(JSON_STRING)
+ DUMPCASE(JSON_NUMBER)
+ DUMPCASE(JSON_BOOL)
+ DUMPCASE(JSON_ARRAY)
+ DUMPCASE(JSON_NODE)
+ default:
+ dumpage.push_back(JSON_NEW(JSONNode(JSON_TEXT("_type"), JSON_TEXT("Unknown"))));
+ }
+
+ JSONNode str(JSON_NODE);
+ str.set_name(JSON_TEXT("_name"));
+ str.push_back(JSON_NEW(JSONNode(json_string(JSON_TEXT("value")), _name)));
+ str.push_back(JSON_NEW(JSONNode(JSON_TEXT("length"), _name.length())));
+ str.push_back(JSON_NEW(JSONNode(JSON_TEXT("capactiy"), _name.capacity())));
+
+ #ifdef JSON_LESS_MEMORY
+ dumpage.push_back(JSON_NEW(JSONNode(JSON_TEXT("_name_encoded"), _type & 0x10)));
+ #else
+ dumpage.push_back(JSON_NEW(JSONNode(JSON_TEXT("_name_encoded"), _name_encoded)));
+ #endif
+ dumpage.push_back(JSON_NEW(str));
+ dumpage.push_back(JSON_NEW(JSONNode(JSON_TEXT("_string_encoded"), _string_encoded)));
+ str.clear();
+ str.set_name(JSON_TEXT("_string"));
+ str.push_back(JSON_NEW(JSONNode(json_string(JSON_TEXT("value")), _string)));
+ str.push_back(JSON_NEW(JSONNode(JSON_TEXT("length"), _string.length())));
+ str.push_back(JSON_NEW(JSONNode(JSON_TEXT("capactiy"), _string.capacity())));
+ dumpage.push_back(JSON_NEW(str));
+
+ JSONNode unio(JSON_NODE);
+ unio.set_name(JSON_TEXT("_value"));
+ unio.push_back(JSON_NEW(JSONNode(JSON_TEXT("_bool"), _value._bool)));
+ unio.push_back(JSON_NEW(JSONNode(JSON_TEXT("_number"), _value._number)));
+ dumpage.push_back(JSON_NEW(unio));
+
+ #ifndef JSON_PREPARSE
+ dumpage.push_back(JSON_NEW(JSONNode(JSON_TEXT("fetched"), fetched)));
+ #endif
+
+ #ifdef JSON_COMMENTS
+ str.clear();
+ str.set_name(JSON_TEXT("_comment"));
+ str.push_back(JSON_NEW(JSONNode(JSON_TEXT("value"), _comment)));
+ str.push_back(JSON_NEW(JSONNode(JSON_TEXT("length"), _comment.length())));
+ str.push_back(JSON_NEW(JSONNode(JSON_TEXT("capactiy"), _comment.capacity())));
+ dumpage.push_back(JSON_NEW(str));
+ #endif
+
+ JSONNode arra(JSON_NODE);
+ arra.set_name(JSON_TEXT("Children"));
+ arra.push_back(JSON_NEW(JSONNode(JSON_TEXT("size"), Children.size())));
+ arra.push_back(JSON_NEW(JSONNode(JSON_TEXT("capacity"), Children.capacity())));
+ JSONNode chil(JSON_ARRAY);
+ chil.set_name(JSON_TEXT("array"));
+ json_foreach(Children, it){
+ chil.push_back(JSON_NEW((*it) -> dump(totalbytes)));
+ }
+ arra.push_back(JSON_NEW(chil));
+ dumpage.push_back(JSON_NEW(arra));
+
+ return dumpage;
+ }
+ #endif
+#endif
diff --git a/src/modules/json/internalJSONNode.h b/src/modules/json/internalJSONNode.h
index 9e9f9de983..8832bbd828 100644
--- a/src/modules/json/internalJSONNode.h
+++ b/src/modules/json/internalJSONNode.h
@@ -1,453 +1,452 @@
-#ifndef INTERNAL_JSONNODE_H
-#define INTERNAL_JSONNODE_H
-
-#include "JSONDebug.h"
-#include "JSONChildren.h"
-#include "JSONMemory.h"
-#ifdef JSON_DEBUG
- #include <climits> //to check int value
-#endif
-
-/*
- This class is the work horse of libJSON, it handles all of the
- functinality of JSONNode. This object is reference counted for
- speed and memory reasons.
-
- If JSON_REF_COUNT is not on, this internal structure still has an important
- purpose, as it can be passed around by JSONNoders that are flagged as temporary
-*/
-
-class JSONNode; //forward declaration
-
-#ifndef JSON_LIBRARY
- #define DECL_SET_INTEGER(type) void Set(type); void Set(unsigned type);
-#endif
-
-#ifdef JSON_MUTEX_CALLBACKS
- #define initializeMutex(x) ,mylock(x)
-#else
- #define initializeMutex(x)
-#endif
-
-#ifdef JSON_PREPARSE
- #define SetFetched(b) (void)0
- #define Fetch() (void)0
- #define initializeFetch(x)
-#else
- #define initializeFetch(x) ,fetched(x)
-#endif
-
-#ifdef JSON_REF_COUNT
- #define initializeRefCount(x) ,refcount(x)
-#else
- #define initializeRefCount(x)
-#endif
-
-#ifdef JSON_COMMENTS
- #define initializeComment(x) ,_comment(x)
-#else
- #define initializeComment(x)
-#endif
-
-#ifndef JSON_UNIT_TEST
- #define incAllocCount() (void)0
- #define decAllocCount() (void)0
- #define incinternalAllocCount() (void)0
- #define decinternalAllocCount() (void)0
-#endif
-
-#ifdef JSON_VALIDATE
- #define initializeValid(x) ,isValid(x)
-#else
- #define initializeValid(x)
-#endif
-
-class internalJSONNode {
-public:
- internalJSONNode(char mytype = JSON_NULL);
- internalJSONNode(const json_string & unparsed);
- internalJSONNode(const json_string & name_t, const json_string & value_t);
- internalJSONNode(const internalJSONNode & orig);
- internalJSONNode & operator = (const internalJSONNode &);
- ~internalJSONNode(void);
-
- static internalJSONNode * newInternal(char mytype = JSON_NULL);
- static internalJSONNode * newInternal(const json_string & unparsed);
- static internalJSONNode * newInternal(const json_string & name_t, const json_string & value_t);
- static internalJSONNode * newInternal(const internalJSONNode & orig); //not copyable, only by this class
- static void deleteInternal(internalJSONNode * ptr);
-
- json_index_t size(void) const;
- bool empty(void) const;
- unsigned char type(void) const;
-
- json_string name(void) const;
- void setname(const json_string & newname);
- #ifdef JSON_COMMENTS
- void setcomment(const json_string & comment);
- json_string getcomment(void) const;
- #endif
- json_string as_string(void) const;
- long as_int(void) const;
- json_number as_float(void) const;
- bool as_bool(void) const;
-
- #ifndef JSON_PREPARSE
- void preparse(void);
- #endif
-
- #ifdef JSON_LIBRARY
- void push_back(JSONNode * node);
- #else
- void push_back(const JSONNode & node);
- #endif
- void reserve(json_index_t size);
- void push_front(const JSONNode & node);
- JSONNode * pop_back(json_index_t pos);
- JSONNode * pop_back(const json_string & name_t);
- #ifdef JSON_CASE_INSENSITIVE_FUNCTIONS
- JSONNode * pop_back_nocase(const json_string & name_t);
- #endif
-
- JSONNode * at(json_index_t pos);
- //These return ** because pop_back needs them
- JSONNode ** at(const json_string & name_t);
- #ifdef JSON_CASE_INSENSITIVE_FUNCTIONS
- JSONNode ** at_nocase(const json_string & name_t);
- #endif
-
- void Set(const json_string & val);
- #ifdef JSON_LIBRARY
- void Set(json_number val);
- void Set(long val);
- #else
- DECL_SET_INTEGER(char)
- DECL_SET_INTEGER(short)
- DECL_SET_INTEGER(int)
- DECL_SET_INTEGER(long)
- #ifndef JSON_ISO_STRICT
- DECL_SET_INTEGER(long long)
- #endif
-
- void Set(float val);
- void Set(double val);
- #endif
- void Set(bool val);
-
- bool IsEqualTo(const json_string & val)const ;
- bool IsEqualTo(bool val) const;
- bool IsEqualTo(const internalJSONNode * val) const;
-
- template<typename T>
- bool IsEqualToNum(T val) const;
-
- internalJSONNode * incRef(void);
- #ifdef JSON_REF_COUNT
- void decRef(void);
- bool hasNoReferences(void);
- #endif
- internalJSONNode * makeUnique(void);
-
- JSONNode ** begin(void) const;
- JSONNode ** end(void) const;
- #ifdef JSON_REF_COUNT
- size_t refcount BITS(20);
- #endif
- bool Fetched(void) const;
- #ifdef JSON_MUTEX_CALLBACKS
- void * mylock;
- void _set_mutex(void * mutex, bool unset = true);
- void _unset_mutex(void);
- #endif
- #ifdef JSON_UNIT_TEST
- static void incinternalAllocCount(void);
- static void decinternalAllocCount(void);
- #endif
-
- #ifdef JSON_WRITER
- json_string WriteName(bool formatted, bool arrayChild) const;
- json_string WriteChildren(unsigned int indent);
- json_string WriteComment(unsigned int indent) const;
- json_string Write(unsigned int indent, bool arrayChild);
- #endif
- #ifdef JSON_DEBUG
- #ifndef JSON_LIBRARY
- JSONNode Dump(size_t & totalmemory) const;
- JSONNode DumpMutex(void) const;
- #endif
- #endif
-
- //json parts
- mutable unsigned char _type BITS(3);
- mutable bool _name_encoded BITS(1); //must be above name due to initialization list order
- json_string _name;
-
- mutable json_string _string; //these are both mutable because the string can change when it's fetched
- mutable bool _string_encoded BITS(1);
-
- //the value of the json
- union value_union_t {
- bool _bool;
- json_number _number;
- };
- mutable value_union_t _value; //internal structure changes depending on type
-
- jsonChildren Children; //container that holds all of my children
-
- #ifdef JSON_VALIDATE
- mutable bool isValid BITS(1); //this does not need to be initialized, it's only used if it's null
- void Nullify(bool validation = true) const;
- bool validate(void);
- #else
- void Nullify(void) const;
- #endif
-
- //Fetching and such
- #ifndef JSON_PREPARSE
- mutable bool fetched BITS(1);
- void SetFetched(bool val) const;
- void Fetch(void) const; //it's const because it doesn't change the VALUE of the function
- #endif
-
- #ifdef JSON_COMMENTS
- json_string _comment;
- #endif
-
- void FetchString(void) const;
- void FetchNode(void) const;
- void FetchArray(void) const;
- void FetchNumber(void) const;
- #ifdef JSON_CASE_INSENSITIVE_FUNCTIONS
- static bool AreEqualNoCase(const json_char * ch_one, const json_char * ch_two);
- #endif
-};
-
-inline internalJSONNode::internalJSONNode(char mytype) : _type(mytype), Children(), _name(), _name_encoded(), _string(), _string_encoded(), _value()
- initializeMutex(0)
- initializeRefCount(1)
- initializeFetch(true)
- initializeComment(0)
- initializeValid(true){
-
- incinternalAllocCount();
-}
-
-inline internalJSONNode * internalJSONNode::incRef(void){
- #ifdef JSON_REF_COUNT
- ++refcount;
- return this;
- #else
- return makeUnique();
- #endif
-}
-
-inline json_index_t internalJSONNode::size(void) const {
- Fetch();
- return Children.size();
-}
-
-inline bool internalJSONNode::empty(void) const {
- if (type() != JSON_NODE && type() != JSON_ARRAY) return true;
- Fetch();
- return Children.empty();
-}
-
-inline unsigned char internalJSONNode::type(void) const {
- #ifdef JSON_LESS_MEMORY
- return _type & 0xF;
- #else
- return _type;
- #endif
-}
-
-inline json_string internalJSONNode::name(void) const {
- return _name;
-}
-
-inline void internalJSONNode::setname(const json_string & newname){
- _name = newname;
- #ifdef JSON_LESS_MEMORY
- _type |= 0x10;
- #else
- _name_encoded = true;
- #endif
-}
-
-#ifdef JSON_COMMENTS
- inline void internalJSONNode::setcomment(const json_string & comment){
- _comment = comment;
- }
-
- inline json_string internalJSONNode::getcomment(void) const {
- return _comment;
- }
-#endif
-
-inline json_string internalJSONNode::as_string(void) const {
- Fetch();
- return _string;
-}
-
-inline long internalJSONNode::as_int(void) const {
- Fetch();
- switch(type()) {
- case JSON_NULL:
- return 0;
- case JSON_BOOL:
- return _value._bool ? 1 : 0;
- }
- JSON_ASSERT(type() == JSON_NUMBER, JSON_TEXT("as_int returning undefined results"));
- JSON_ASSERT(_value._number > LONG_MIN, _string + JSON_TEXT(" is outside the lower range of long"));
- JSON_ASSERT(_value._number < LONG_MAX, _string + JSON_TEXT(" is outside the upper range of long"));
- JSON_ASSERT(_value._number == (json_number)((int)_value._number), json_string(JSON_TEXT("as_int will truncate ")) + _string);
- return (int)_value._number;
-}
-
-inline json_number internalJSONNode::as_float(void) const {
- Fetch();
- switch(type()) {
- case JSON_NULL:
- return (json_number)0.0;
- case JSON_BOOL:
- return (json_number)(_value._bool ? 1.0 : 0.0);
- }
- JSON_ASSERT(type() == JSON_NUMBER, JSON_TEXT("as_float returning undefined results"));
- return _value._number;
-}
-
-inline bool internalJSONNode::as_bool(void) const {
- Fetch();
- switch(type()) {
- case JSON_NUMBER:
- return _value._number != 0.0f;
- case JSON_NULL:
- return false;
- }
- JSON_ASSERT(type() == JSON_BOOL, JSON_TEXT("as_bool returning undefined results"));
- return _value._bool;
-}
-
-inline bool internalJSONNode::IsEqualTo(const json_string & val) const {
- if (type() != JSON_STRING) return false;
- Fetch();
- return val == _string;
-}
-
-inline bool internalJSONNode::IsEqualTo(bool val) const {
- if (type() != JSON_BOOL) return false;
- Fetch();
- return val == _value._bool;
-}
-
-template<typename T>
-inline bool internalJSONNode::IsEqualToNum(T val) const {
- if (type() != JSON_NUMBER) return false;
- Fetch();
- return (json_number)val == _value._number;
-}
-
-#ifdef JSON_REF_COUNT
- inline void internalJSONNode::decRef(void){
- JSON_ASSERT(refcount != 0, JSON_TEXT("decRef on a 0 refcount internal"));
- --refcount;
- }
-
- inline bool internalJSONNode::hasNoReferences(void){
- return refcount == 0;
- }
-#endif
-
-inline internalJSONNode * internalJSONNode::makeUnique(void){
- #ifdef JSON_REF_COUNT
- if (refcount > 1){
- decRef();
- return newInternal(*this);
- }
- JSON_ASSERT(refcount == 1, JSON_TEXT("makeUnique on a 0 refcount internal"));
- return this;
- #else
- return newInternal(*this);
- #endif
-}
-
-#ifndef JSON_PREPARSE
- inline void internalJSONNode::SetFetched(bool val) const {
- fetched = val;
- }
-#endif
-
-inline bool internalJSONNode::Fetched(void) const {
- #ifndef JSON_PREPARSE
- return fetched;
- #else
- return true;
- #endif
-}
-
-inline JSONNode ** internalJSONNode::begin(void) const {
- Fetch();
- return Children.begin();
-}
-
-inline JSONNode ** internalJSONNode::end(void) const {
- Fetch();
- return Children.end();
-}
-
-inline JSONNode * internalJSONNode::at(json_index_t pos){
- Fetch();
- return Children[pos];
-}
-
-inline void internalJSONNode::reserve(json_index_t size){
- Fetch();
- Children.reserve2(size);
-}
-
-/*
- These functions are to allow allocation to be completely controlled by the callbacks
-*/
-
-inline void internalJSONNode::deleteInternal(internalJSONNode * ptr){
- #ifdef JSON_MEMORY_CALLBACKS
- ptr -> ~internalJSONNode();
- libjson_free<internalJSONNode>(ptr);
- #else
- delete ptr;
- #endif
-}
-
-inline internalJSONNode * internalJSONNode::newInternal(char mytype){
- #ifdef JSON_MEMORY_CALLBACKS
- return new(json_malloc<internalJSONNode>(1)) internalJSONNode(mytype);
- #else
- return new internalJSONNode(mytype);
- #endif
-}
-
-inline internalJSONNode * internalJSONNode::newInternal(const json_string & unparsed){
- #ifdef JSON_MEMORY_CALLBACKS
- return new(json_malloc<internalJSONNode>(1)) internalJSONNode(unparsed);
- #else
- return new internalJSONNode(unparsed);
- #endif
-}
-
-inline internalJSONNode * internalJSONNode::newInternal(const json_string & name_t, const json_string & value_t){
- #ifdef JSON_MEMORY_CALLBACKS
- return new(json_malloc<internalJSONNode>(1)) internalJSONNode(name_t, value_t);
- #else
- return new internalJSONNode(name_t, value_t);
- #endif
-}
-
-inline internalJSONNode * internalJSONNode::newInternal(const internalJSONNode & orig){
- #ifdef JSON_MEMORY_CALLBACKS
- return new(json_malloc<internalJSONNode>(1)) internalJSONNode(orig);
- #else
- return new internalJSONNode(orig);
- #endif
-}
-
-
-#endif
+#ifndef INTERNAL_JSONNODE_H
+#define INTERNAL_JSONNODE_H
+
+#include "JSONDebug.h"
+#include "JSONChildren.h"
+#include "JSONMemory.h"
+#ifdef JSON_DEBUG
+ #include <climits> //to check int value
+#endif
+
+/*
+ This class is the work horse of libJSON, it handles all of the
+ functinality of JSONNode. This object is reference counted for
+ speed and memory reasons.
+
+ If JSON_REF_COUNT is not on, this internal structure still has an important
+ purpose, as it can be passed around by JSONNoders that are flagged as temporary
+*/
+
+class JSONNode; //forward declaration
+
+#ifndef JSON_LIBRARY
+ #define DECL_SET_INTEGER(type) void Set(type); void Set(unsigned type);
+#endif
+
+#ifdef JSON_MUTEX_CALLBACKS
+ #define initializeMutex(x) ,mylock(x)
+#else
+ #define initializeMutex(x)
+#endif
+
+#ifdef JSON_PREPARSE
+ #define SetFetched(b) (void)0
+ #define Fetch() (void)0
+#define initializeFetch(x)
+#else
+ #define initializeFetch(x) ,fetched(x)
+#endif
+
+#ifdef JSON_REF_COUNT
+ #define initializeRefCount(x) ,refcount(x)
+#else
+ #define initializeRefCount(x)
+#endif
+
+#ifdef JSON_COMMENTS
+ #define initializeComment(x) ,_comment(x)
+#else
+ #define initializeComment(x)
+#endif
+
+#ifndef JSON_UNIT_TEST
+ #define incAllocCount() (void)0
+ #define decAllocCount() (void)0
+ #define incinternalAllocCount() (void)0
+ #define decinternalAllocCount() (void)0
+#endif
+
+#ifdef JSON_VALIDATE
+ #define initializeValid(x) ,isValid(x)
+#else
+ #define initializeValid(x)
+#endif
+
+class internalJSONNode {
+public:
+ internalJSONNode(char mytype = JSON_NULL);
+ internalJSONNode(const json_string & unparsed);
+ internalJSONNode(const json_string & name_t, const json_string & value_t);
+ internalJSONNode(const internalJSONNode & orig);
+ internalJSONNode & operator = (const internalJSONNode &);
+ ~internalJSONNode(void);
+
+ static internalJSONNode * newInternal(char mytype = JSON_NULL);
+ static internalJSONNode * newInternal(const json_string & unparsed);
+ static internalJSONNode * newInternal(const json_string & name_t, const json_string & value_t);
+ static internalJSONNode * newInternal(const internalJSONNode & orig); //not copyable, only by this class
+ static void deleteInternal(internalJSONNode * ptr);
+
+ json_index_t size(void) const;
+ bool empty(void) const;
+ unsigned char type(void) const;
+
+ json_string name(void) const;
+ void setname(const json_string & newname);
+ #ifdef JSON_COMMENTS
+ void setcomment(const json_string & comment);
+ json_string getcomment(void) const;
+ #endif
+ json_string as_string(void) const;
+ long as_int(void) const;
+ json_number as_float(void) const;
+ bool as_bool(void) const;
+
+ #ifndef JSON_PREPARSE
+ void preparse(void);
+ #endif
+
+ #ifdef JSON_LIBRARY
+ void push_back(JSONNode * node);
+ #else
+ void push_back(const JSONNode & node);
+ #endif
+ void reserve(json_index_t size);
+ void push_front(const JSONNode & node);
+ JSONNode * pop_back(json_index_t pos);
+ JSONNode * pop_back(const json_string & name_t);
+ #ifdef JSON_CASE_INSENSITIVE_FUNCTIONS
+ JSONNode * pop_back_nocase(const json_string & name_t);
+ #endif
+
+ JSONNode * at(json_index_t pos);
+ //These return ** because pop_back needs them
+ JSONNode ** at(const json_string & name_t);
+ #ifdef JSON_CASE_INSENSITIVE_FUNCTIONS
+ JSONNode ** at_nocase(const json_string & name_t);
+ #endif
+
+ void Set(const json_string & val);
+ #ifdef JSON_LIBRARY
+ void Set(json_number val);
+ void Set(long val);
+ #else
+ DECL_SET_INTEGER(char)
+ DECL_SET_INTEGER(short)
+ DECL_SET_INTEGER(int)
+ DECL_SET_INTEGER(long)
+ #ifndef JSON_ISO_STRICT
+ DECL_SET_INTEGER(long long)
+ #endif
+
+ void Set(float val);
+ void Set(double val);
+ #endif
+ void Set(bool val);
+
+ bool IsEqualTo(const json_string & val)const ;
+ bool IsEqualTo(bool val) const;
+ bool IsEqualTo(const internalJSONNode * val) const;
+
+ template<typename T>
+ bool IsEqualToNum(T val) const;
+
+ internalJSONNode * incRef(void);
+ #ifdef JSON_REF_COUNT
+ void decRef(void);
+ bool hasNoReferences(void);
+ #endif
+ internalJSONNode * makeUnique(void);
+
+ JSONNode ** begin(void) const;
+ JSONNode ** end(void) const;
+ #ifdef JSON_REF_COUNT
+ size_t refcount BITS(20);
+ #endif
+ bool Fetched(void) const;
+ #ifdef JSON_MUTEX_CALLBACKS
+ void * mylock;
+ void _set_mutex(void * mutex, bool unset = true);
+ void _unset_mutex(void);
+ #endif
+ #ifdef JSON_UNIT_TEST
+ static void incinternalAllocCount(void);
+ static void decinternalAllocCount(void);
+ #endif
+
+ #ifdef JSON_WRITER
+ json_string WriteName(bool formatted, bool arrayChild) const;
+ json_string WriteChildren(unsigned int indent);
+ json_string WriteComment(unsigned int indent) const;
+ json_string Write(unsigned int indent, bool arrayChild);
+ #endif
+ #ifdef JSON_DEBUG
+ #ifndef JSON_LIBRARY
+ JSONNode Dump(size_t & totalmemory) const;
+ JSONNode DumpMutex(void) const;
+ #endif
+ #endif
+
+ //json parts
+ mutable unsigned char _type BITS(3);
+ mutable bool _name_encoded BITS(1); //must be above name due to initialization list order
+ json_string _name;
+
+ mutable json_string _string; //these are both mutable because the string can change when it's fetched
+ mutable bool _string_encoded BITS(1);
+
+ //the value of the json
+ union value_union_t {
+ bool _bool;
+ json_number _number;
+ };
+ mutable value_union_t _value; //internal structure changes depending on type
+
+ jsonChildren Children; //container that holds all of my children
+
+ #ifdef JSON_VALIDATE
+ mutable bool isValid BITS(1); //this does not need to be initialized, it's only used if it's null
+ void Nullify(bool validation = true) const;
+ bool validate(void);
+ #else
+ void Nullify(void) const;
+ #endif
+
+ //Fetching and such
+ #ifndef JSON_PREPARSE
+ mutable bool fetched BITS(1);
+ void SetFetched(bool val) const;
+ void Fetch(void) const; //it's const because it doesn't change the VALUE of the function
+ #endif
+
+ #ifdef JSON_COMMENTS
+ json_string _comment;
+ #endif
+
+ void FetchString(void) const;
+ void FetchNode(void) const;
+ void FetchArray(void) const;
+ void FetchNumber(void) const;
+ #ifdef JSON_CASE_INSENSITIVE_FUNCTIONS
+ static bool AreEqualNoCase(const json_char * ch_one, const json_char * ch_two);
+ #endif
+};
+
+inline internalJSONNode::internalJSONNode(char mytype) : _type(mytype), Children(), _name(), _name_encoded(), _string(), _string_encoded(), _value()
+ initializeMutex(0)
+ initializeRefCount(1)
+ initializeFetch(true)
+ initializeComment(0)
+ initializeValid(true){
+
+ incinternalAllocCount();
+}
+
+inline internalJSONNode * internalJSONNode::incRef(void){
+ #ifdef JSON_REF_COUNT
+ ++refcount;
+ return this;
+ #else
+ return makeUnique();
+ #endif
+}
+
+inline json_index_t internalJSONNode::size(void) const {
+ Fetch();
+ return Children.size();
+}
+
+inline bool internalJSONNode::empty(void) const {
+ if (type() != JSON_NODE && type() != JSON_ARRAY) return true;
+ Fetch();
+ return Children.empty();
+}
+
+inline unsigned char internalJSONNode::type(void) const {
+ #ifdef JSON_LESS_MEMORY
+ return _type & 0xF;
+ #else
+ return _type;
+ #endif
+}
+
+inline json_string internalJSONNode::name(void) const {
+ return _name;
+}
+
+inline void internalJSONNode::setname(const json_string & newname){
+ _name = newname;
+ #ifdef JSON_LESS_MEMORY
+ _type |= 0x10;
+ #else
+ _name_encoded = true;
+ #endif
+}
+
+#ifdef JSON_COMMENTS
+ inline void internalJSONNode::setcomment(const json_string & comment){
+ _comment = comment;
+ }
+
+ inline json_string internalJSONNode::getcomment(void) const {
+ return _comment;
+ }
+#endif
+
+inline json_string internalJSONNode::as_string(void) const {
+ Fetch();
+ return _string;
+}
+
+inline long internalJSONNode::as_int(void) const {
+ Fetch();
+ switch(type()) {
+ case JSON_NULL:
+ return 0;
+ case JSON_BOOL:
+ return _value._bool ? 1 : 0;
+ }
+ JSON_ASSERT(type() == JSON_NUMBER, JSON_TEXT("as_int returning undefined results"));
+ JSON_ASSERT(_value._number > LONG_MIN, _string + JSON_TEXT(" is outside the lower range of long"));
+ JSON_ASSERT(_value._number < LONG_MAX, _string + JSON_TEXT(" is outside the upper range of long"));
+ JSON_ASSERT(_value._number == (json_number)((int)_value._number), json_string(JSON_TEXT("as_int will truncate ")) + _string);
+ return (int)_value._number;
+}
+
+inline json_number internalJSONNode::as_float(void) const {
+ Fetch();
+ switch(type()) {
+ case JSON_NULL:
+ return (json_number)0.0;
+ case JSON_BOOL:
+ return (json_number)(_value._bool ? 1.0 : 0.0);
+ }
+ JSON_ASSERT(type() == JSON_NUMBER, JSON_TEXT("as_float returning undefined results"));
+ return _value._number;
+}
+
+inline bool internalJSONNode::as_bool(void) const {
+ Fetch();
+ switch(type()) {
+ case JSON_NUMBER:
+ return _value._number != 0.0f;
+ case JSON_NULL:
+ return false;
+ }
+ JSON_ASSERT(type() == JSON_BOOL, JSON_TEXT("as_bool returning undefined results"));
+ return _value._bool;
+}
+
+inline bool internalJSONNode::IsEqualTo(const json_string & val) const {
+ if (type() != JSON_STRING) return false;
+ Fetch();
+ return val == _string;
+}
+
+inline bool internalJSONNode::IsEqualTo(bool val) const {
+ if (type() != JSON_BOOL) return false;
+ Fetch();
+ return val == _value._bool;
+}
+
+template<typename T>
+inline bool internalJSONNode::IsEqualToNum(T val) const {
+ if (type() != JSON_NUMBER) return false;
+ Fetch();
+ return (json_number)val == _value._number;
+}
+
+#ifdef JSON_REF_COUNT
+ inline void internalJSONNode::decRef(void){
+ JSON_ASSERT(refcount != 0, JSON_TEXT("decRef on a 0 refcount internal"));
+ --refcount;
+ }
+
+ inline bool internalJSONNode::hasNoReferences(void){
+ return refcount == 0;
+ }
+#endif
+
+inline internalJSONNode * internalJSONNode::makeUnique(void){
+ #ifdef JSON_REF_COUNT
+ if (refcount > 1){
+ decRef();
+ return newInternal(*this);
+ }
+ JSON_ASSERT(refcount == 1, JSON_TEXT("makeUnique on a 0 refcount internal"));
+ return this;
+ #else
+ return newInternal(*this);
+ #endif
+}
+
+#ifndef JSON_PREPARSE
+ inline void internalJSONNode::SetFetched(bool val) const {
+ fetched = val;
+ }
+#endif
+
+inline bool internalJSONNode::Fetched(void) const {
+ #ifndef JSON_PREPARSE
+ return fetched;
+ #else
+ return true;
+ #endif
+}
+
+inline JSONNode ** internalJSONNode::begin(void) const {
+ Fetch();
+ return Children.begin();
+}
+
+inline JSONNode ** internalJSONNode::end(void) const {
+ Fetch();
+ return Children.end();
+}
+
+inline JSONNode * internalJSONNode::at(json_index_t pos){
+ Fetch();
+ return Children[pos];
+}
+
+inline void internalJSONNode::reserve(json_index_t size){
+ Fetch();
+ Children.reserve2(size);
+}
+
+/*
+ These functions are to allow allocation to be completely controlled by the callbacks
+*/
+
+inline void internalJSONNode::deleteInternal(internalJSONNode * ptr){
+ #ifdef JSON_MEMORY_CALLBACKS
+ ptr -> ~internalJSONNode();
+ libjson_free<internalJSONNode>(ptr);
+ #else
+ delete ptr;
+ #endif
+}
+
+inline internalJSONNode * internalJSONNode::newInternal(char mytype){
+ #ifdef JSON_MEMORY_CALLBACKS
+ return new(json_malloc<internalJSONNode>(1)) internalJSONNode(mytype);
+ #else
+ return new internalJSONNode(mytype);
+ #endif
+}
+
+inline internalJSONNode * internalJSONNode::newInternal(const json_string & unparsed){
+ #ifdef JSON_MEMORY_CALLBACKS
+ return new(json_malloc<internalJSONNode>(1)) internalJSONNode(unparsed);
+ #else
+ return new internalJSONNode(unparsed);
+ #endif
+}
+
+inline internalJSONNode * internalJSONNode::newInternal(const json_string & name_t, const json_string & value_t){
+ #ifdef JSON_MEMORY_CALLBACKS
+ return new(json_malloc<internalJSONNode>(1)) internalJSONNode(name_t, value_t);
+ #else
+ return new internalJSONNode(name_t, value_t);
+ #endif
+}
+
+inline internalJSONNode * internalJSONNode::newInternal(const internalJSONNode & orig){
+ #ifdef JSON_MEMORY_CALLBACKS
+ return new(json_malloc<internalJSONNode>(1)) internalJSONNode(orig);
+ #else
+ return new internalJSONNode(orig);
+ #endif
+}
+
+#endif