mirror of
https://github.com/vale981/openAV-Luppp
synced 2025-03-05 09:01:39 -05:00
-libjson added but not used. Initial code added in Worker
This commit is contained in:
parent
2ffe57a0f5
commit
f3596341ee
210 changed files with 43426 additions and 2 deletions
361
src/libjson/JSONOptions.h
Normal file
361
src/libjson/JSONOptions.h
Normal file
|
@ -0,0 +1,361 @@
|
|||
#ifndef JSON_OPTIONS_H
|
||||
#define JSON_OPTIONS_H
|
||||
|
||||
/**
|
||||
* 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
|
||||
#define NDEBUG
|
||||
|
||||
|
||||
/*
|
||||
* JSON_STRICT removes all of libjson's extensions. Meaning no comments, no special numbers
|
||||
*/
|
||||
//#define JSON_STRICT
|
||||
|
||||
|
||||
/*
|
||||
* 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_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_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 off, no base64 support is included
|
||||
*/
|
||||
#define JSON_BINARY
|
||||
|
||||
|
||||
/*
|
||||
* JSON_EXPOSE_BASE64 is used to turn on the functionality of libjson's base64 encoding
|
||||
* and decoding. This may be useful if you want to obfuscate your json, or send binary data over
|
||||
* a network
|
||||
*/
|
||||
#define JSON_EXPOSE_BASE64
|
||||
|
||||
|
||||
/*
|
||||
* 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_STREAM turns on libjson's streaming functionality. This allows you to give parts of
|
||||
* your json into a stream, which will automatically hit a callback when full nodes are
|
||||
* completed
|
||||
*/
|
||||
#define JSON_STREAM
|
||||
|
||||
|
||||
/*
|
||||
* JSON_MEMORY_CALLBACKS exposes functions to register callbacks for allocating, resizing,
|
||||
* and freeing memory. Because libjson is designed for customizability, 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 not 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_MEMORY_POOL Turns on libjson's iteraction with mempool++. It is more efficient that simply
|
||||
* connecting mempool++ to the callbacks because it integrates things internally and uses a number
|
||||
* of memory pools. This value tells libjson how large of a memory pool to start out with. 500KB
|
||||
* should suffice for most cases. libjson will distribute that within the pool for the best
|
||||
* performance depending on other settings.
|
||||
*/
|
||||
//#define JSON_MEMORY_POOL 524288
|
||||
|
||||
|
||||
/*
|
||||
* 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_NO_C_CONSTS removes consts from the C interface. It still acts the same way, but
|
||||
* this may be useful for using the header with languages or variants that don't have const
|
||||
*/
|
||||
//#define JSON_NO_C_CONSTS
|
||||
|
||||
|
||||
/*
|
||||
* JSON_OCTAL allows libjson to use octal values in numbers.
|
||||
*/
|
||||
//#define JSON_OCTAL
|
||||
|
||||
|
||||
/*
|
||||
* JSON_WRITE_PRIORITY turns on libjson's writing capabilties. Without this libjson can only
|
||||
* read and parse json, this allows it to write back out. Changing the value of the writer
|
||||
* changes how libjson compiles, and how fast it will go when writing
|
||||
*/
|
||||
#define JSON_WRITE_PRIORITY MED
|
||||
|
||||
|
||||
/*
|
||||
* JSON_READ_PRIORITY turns on libjson's reading capabilties. Changing the value of the reader
|
||||
* changes how libjson compiles, and how fast it will go when writing
|
||||
*/
|
||||
#define JSON_READ_PRIORITY HIGH
|
||||
|
||||
|
||||
/*
|
||||
* 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_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_ESCAPE_WRITES tells the libjson engine to escape special characters when it writes
|
||||
* out. If this option is turned off, the json it outputs may not adhere to JSON standards
|
||||
*/
|
||||
#define JSON_ESCAPE_WRITES
|
||||
|
||||
|
||||
/*
|
||||
* 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_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_ARRAY_SIZE_ON_ON_LINE allows you to put small arrays of primitives all on one line
|
||||
* in a write_formatted. This is common for tuples, like coordinates. If must be defined
|
||||
* as an integer
|
||||
*/
|
||||
//#define JSON_ARRAY_SIZE_ON_ONE_LINE 2
|
||||
|
||||
|
||||
/*
|
||||
* JSON_VALIDATE turns on validation features of libjson.
|
||||
*/
|
||||
#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_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
|
||||
|
||||
|
||||
/*
|
||||
* JSON_BOOL_TYPE lets you change the bool type for the C interface. Because before C99 there
|
||||
* was no bool, and even then it's just a typedef, you may want to use something else. If this
|
||||
* is not defined, it will revert to int
|
||||
*/
|
||||
//#define JSON_BOOL_TYPE char
|
||||
|
||||
|
||||
/*
|
||||
* JSON_INT_TYPE lets you change the int type for as_int. If you ommit this option, the default
|
||||
* long will be used
|
||||
*/
|
||||
//#define JSON_INT_TYPE long
|
||||
|
||||
|
||||
/*
|
||||
* JSON_NUMBER_TYPE lets you change the number type for as_float as well as the internal storage for the
|
||||
* number. If you omit this option, the default double will be used for most cases and float for JSON_LESS_MEMORY
|
||||
*/
|
||||
//#define JSON_NUMBER_TYPE double
|
||||
|
||||
|
||||
/*
|
||||
* JSON_STRING_HEADER allows you to change the type of string that libjson uses both for the
|
||||
* interface and internally. It must implement most of the STL string interface, but not all
|
||||
* of it. Things like wxString or QString should wourk without much trouble
|
||||
*/
|
||||
//#define JSON_STRING_HEADER "../TestSuite/StringTest.h"
|
||||
|
||||
|
||||
/*
|
||||
* 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_NO_EXCEPTIONS turns off any exception throwing by the library. It may still use exceptions
|
||||
* internally, but the interface will never throw anything.
|
||||
*/
|
||||
//#define JSON_NO_EXCEPTIONS
|
||||
|
||||
|
||||
/*
|
||||
* JSON_DEPRECATED_FUNCTIONS turns on functions that have been deprecated, this is for backwards
|
||||
* compatibility between major releases. It is highly recommended that you move your functions
|
||||
* over to the new equivalents
|
||||
*/
|
||||
#define JSON_DEPRECATED_FUNCTIONS
|
||||
|
||||
|
||||
/*
|
||||
* JSON_CASTABLE allows you to call as_bool on a number and have it do the 0 or not 0 check,
|
||||
* it also allows you to ask for a string from a number, or boolean, and have it return the right thing.
|
||||
* Without this option, those types of requests are undefined. It also exposes the as_array, as_node, and cast
|
||||
* functions
|
||||
*/
|
||||
#define JSON_CASTABLE
|
||||
|
||||
|
||||
/*
|
||||
* JSON_SECURITY_MAX_NEST_LEVEL is a security measure added to make prevent against DoS attacks
|
||||
* This only affects validation, as if you are worried about security attacks, then you are
|
||||
* most certainly validating json before sending it to be parsed. This option allows you to limitl how many
|
||||
* levels deep a JSON Node can go. 128 is a good depth to start with
|
||||
*/
|
||||
#define JSON_SECURITY_MAX_NEST_LEVEL 128
|
||||
|
||||
|
||||
/*
|
||||
* JSON_SECURITY_MAX_STRING_LENGTH is another security measure, preventing DoS attacks with very long
|
||||
* strings of JSON. 32MB is the default value for this, this allows large images to be embedded
|
||||
*/
|
||||
#define JSON_SECURITY_MAX_STRING_LENGTH 33554432
|
||||
|
||||
|
||||
/*
|
||||
* JSON_SECURITY_MAX_STREAM_OBJECTS is a security measure for streams. It prevents DoS attacks with
|
||||
* large number of objects hitting the stream all at once. 128 is a lot of objects, but not out of
|
||||
* the question for high speed systems.
|
||||
*/
|
||||
#define JSON_SECURITY_MAX_STREAM_OBJECTS 128
|
||||
|
||||
#endif
|
||||
|
13
src/libjson/License.txt
Normal file
13
src/libjson/License.txt
Normal file
|
@ -0,0 +1,13 @@
|
|||
This license is also available in Documentation.pdf
|
||||
|
||||
Copyright 2010 Jonathan Wallace. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY JONATHAN WALLACE ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JONATHAN WALLACE OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
The views and conclusions contained in the software and documentation are those of the authors and should not be interpreted as representing official policies, either expressed or implied, of Jonathan Wallace.
|
BIN
src/libjson/Objects_static/JSONAllocator.o
Normal file
BIN
src/libjson/Objects_static/JSONAllocator.o
Normal file
Binary file not shown.
BIN
src/libjson/Objects_static/JSONChildren.o
Normal file
BIN
src/libjson/Objects_static/JSONChildren.o
Normal file
Binary file not shown.
BIN
src/libjson/Objects_static/JSONDebug.o
Normal file
BIN
src/libjson/Objects_static/JSONDebug.o
Normal file
Binary file not shown.
BIN
src/libjson/Objects_static/JSONIterators.o
Normal file
BIN
src/libjson/Objects_static/JSONIterators.o
Normal file
Binary file not shown.
BIN
src/libjson/Objects_static/JSONMemory.o
Normal file
BIN
src/libjson/Objects_static/JSONMemory.o
Normal file
Binary file not shown.
BIN
src/libjson/Objects_static/JSONNode.o
Normal file
BIN
src/libjson/Objects_static/JSONNode.o
Normal file
Binary file not shown.
BIN
src/libjson/Objects_static/JSONNode_Mutex.o
Normal file
BIN
src/libjson/Objects_static/JSONNode_Mutex.o
Normal file
Binary file not shown.
BIN
src/libjson/Objects_static/JSONPreparse.o
Normal file
BIN
src/libjson/Objects_static/JSONPreparse.o
Normal file
Binary file not shown.
BIN
src/libjson/Objects_static/JSONStream.o
Normal file
BIN
src/libjson/Objects_static/JSONStream.o
Normal file
Binary file not shown.
BIN
src/libjson/Objects_static/JSONValidator.o
Normal file
BIN
src/libjson/Objects_static/JSONValidator.o
Normal file
Binary file not shown.
BIN
src/libjson/Objects_static/JSONWorker.o
Normal file
BIN
src/libjson/Objects_static/JSONWorker.o
Normal file
Binary file not shown.
BIN
src/libjson/Objects_static/JSONWriter.o
Normal file
BIN
src/libjson/Objects_static/JSONWriter.o
Normal file
Binary file not shown.
BIN
src/libjson/Objects_static/internalJSONNode.o
Normal file
BIN
src/libjson/Objects_static/internalJSONNode.o
Normal file
Binary file not shown.
BIN
src/libjson/Objects_static/libjson.o
Normal file
BIN
src/libjson/Objects_static/libjson.o
Normal file
Binary file not shown.
BIN
src/libjson/_internal/Dependencies/._libbase64++
Normal file
BIN
src/libjson/_internal/Dependencies/._libbase64++
Normal file
Binary file not shown.
BIN
src/libjson/_internal/Dependencies/._mempool++
Normal file
BIN
src/libjson/_internal/Dependencies/._mempool++
Normal file
Binary file not shown.
BIN
src/libjson/_internal/Dependencies/libbase64++/._libbase64++.h
Normal file
BIN
src/libjson/_internal/Dependencies/libbase64++/._libbase64++.h
Normal file
Binary file not shown.
270
src/libjson/_internal/Dependencies/libbase64++/libbase64++.h
Normal file
270
src/libjson/_internal/Dependencies/libbase64++/libbase64++.h
Normal file
|
@ -0,0 +1,270 @@
|
|||
#ifndef LIBBASE64_CPP_H
|
||||
#define LIBBASE64_CPP_H
|
||||
|
||||
#include <string>
|
||||
//#define LIBBASE64_THROW_STD_INVALID_ARGUMENT
|
||||
|
||||
//version info
|
||||
#define __LIBBASE64_MAJOR__ 1
|
||||
#define __LIBBASE64_MINOR__ 1
|
||||
#define __LIBBASE64_PATCH__ 0
|
||||
#define __LIBBASE64_VERSION__ (__LIBBASE64_MAJOR__ * 10000 + __LIBBASE64_MINOR__ * 100 + __LIBBASE64_PATCH__)
|
||||
|
||||
//code coverage and asserts
|
||||
#ifdef NDEBUG
|
||||
#define LIBBASE64_ASSERT(cond, msg) (void)0
|
||||
#define CREATEBOUNDCHECKER(type, name, ubound, lbound) (void)0
|
||||
#define GETITEM_BOUNDCHECK(loc, name) (*(loc))
|
||||
#else
|
||||
#include <iostream>
|
||||
#define LIBBASE64_ASSERT(cond, msg) if (!(cond)){ std::cerr << msg << std::endl; throw false; }
|
||||
|
||||
template<typename T>
|
||||
class libbase64_boundChecker {
|
||||
public:
|
||||
libbase64_boundChecker(const T * lbound, const T * ubound) : upperbound(ubound), lowerbound(lbound){};
|
||||
T getLocation(const T * loc){
|
||||
LIBBASE64_ASSERT(loc < upperbound, "Array index above bounds");
|
||||
LIBBASE64_ASSERT(loc >= lowerbound, "Array index below bounds");
|
||||
return *loc;
|
||||
}
|
||||
private:
|
||||
const T * lowerbound;
|
||||
const T * upperbound;
|
||||
};
|
||||
#define CREATEBOUNDCHECKER(type, name, ubound, lbound) libbase64_boundChecker<type> name(ubound, lbound)
|
||||
#define GETITEM_BOUNDCHECK(loc, name) name.getLocation(loc)
|
||||
|
||||
#ifdef LIBBASE64CODECOVERAGE
|
||||
#define LIBBASE64CODECOVERAGEBRANCH { static bool f_codeCoverage_ = false; if (f_codeCoverage_ == false){ libbase64::getCoverageHits<STRINGTYPE, CHARTYPE, UCHARTYPE, SAFETY>(true); f_codeCoverage_ = true; } }
|
||||
#endif
|
||||
#endif
|
||||
#ifndef LIBBASE64CODECOVERAGE
|
||||
#define LIBBASE64CODECOVERAGEBRANCH (void)0
|
||||
#endif
|
||||
|
||||
//predictive branching optimizations
|
||||
#ifdef __GNUC__
|
||||
#define LIBBASE64_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100)
|
||||
#if (LIBBASE64_GCC_VERSION >= 29600)
|
||||
#define libbase64_likely(x) __builtin_expect((long)((bool)(x)),1)
|
||||
#define libbase64_unlikely(x) __builtin_expect((long)((bool)(x)),0)
|
||||
#endif
|
||||
#endif
|
||||
#ifndef libbase64_likely
|
||||
#define libbase64_likely(x) x
|
||||
#define libbase64_unlikely(x) x
|
||||
#endif
|
||||
|
||||
|
||||
namespace libbase64 {
|
||||
#ifdef LIBBASE64CODECOVERAGE //Gets the number of branches that has been made
|
||||
template<class STRINGTYPE, typename CHARTYPE, typename UCHARTYPE, bool SAFETY>
|
||||
static size_t getCoverageHits(bool inc){
|
||||
static size_t hits = 0;
|
||||
if (inc) ++hits;
|
||||
return hits;
|
||||
}
|
||||
#endif
|
||||
|
||||
//characters used in convertions
|
||||
namespace libbase64_characters {
|
||||
template<typename T>
|
||||
inline static const T * getChar64(void){
|
||||
static const T char64s[64] = {
|
||||
(T)'A', (T)'B', (T)'C', (T)'D', (T)'E', (T)'F', (T)'G', (T)'H', (T)'I', (T)'J', (T)'K', (T)'L', (T)'M',
|
||||
(T)'N', (T)'O', (T)'P', (T)'Q', (T)'R', (T)'S', (T)'T', (T)'U', (T)'V', (T)'W', (T)'X', (T)'Y', (T)'Z',
|
||||
(T)'a', (T)'b', (T)'c', (T)'d', (T)'e', (T)'f', (T)'g', (T)'h', (T)'i', (T)'j', (T)'k', (T)'l', (T)'m',
|
||||
(T)'n', (T)'o', (T)'p', (T)'q', (T)'r', (T)'s', (T)'t', (T)'u', (T)'v', (T)'w', (T)'x', (T)'y', (T)'z',
|
||||
(T)'0', (T)'1', (T)'2', (T)'3', (T)'4', (T)'5', (T)'6', (T)'7', (T)'8', (T)'9', (T)'+', (T)'/'
|
||||
};
|
||||
return char64s;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline static T getChar(unsigned char bin){
|
||||
CREATEBOUNDCHECKER(T, char64bounds, getChar64<T>(), getChar64<T>() + 64);
|
||||
return GETITEM_BOUNDCHECK(getChar64<T>() + bin, char64bounds);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline static T toBinary(T c) {
|
||||
static T binaryConvert[80] = {62,48,49,50,63,52,53,54,55,56,57,58,59,60,61,249,250,251,252,253,254,255,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51};
|
||||
CREATEBOUNDCHECKER(T, binaryConvertsbounds, binaryConvert, binaryConvert + 80);
|
||||
return GETITEM_BOUNDCHECK(binaryConvert + c - 43, binaryConvertsbounds);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static inline T & emptyString(void){
|
||||
static T t;
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
namespace libbase64_Calculator {
|
||||
inline static size_t getEncodingSize(size_t bytes){
|
||||
return (bytes + 2 - ((bytes + 2) % 3)) / 3 * 4;
|
||||
}
|
||||
inline static size_t getDecodingSize(size_t res){
|
||||
return res * 3 / 4;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Encodes data into a base64 string of STRINGTYPE
|
||||
*/
|
||||
template<class STRINGTYPE, typename CHARTYPE, typename UCHARTYPE, bool SAFETY>
|
||||
static STRINGTYPE encode(const unsigned char * binary, size_t bytes){
|
||||
CREATEBOUNDCHECKER(unsigned char, binarybounds, binary, binary + bytes);
|
||||
|
||||
//make sure that there is actually something to encode
|
||||
if (SAFETY){
|
||||
if (libbase64_unlikely(bytes == 0)){
|
||||
LIBBASE64CODECOVERAGEBRANCH;
|
||||
return libbase64_characters::emptyString<STRINGTYPE>();
|
||||
}
|
||||
}
|
||||
|
||||
//calculate length and how misaligned it is
|
||||
size_t misaligned = bytes % 3;
|
||||
STRINGTYPE result;
|
||||
result.reserve(libbase64_Calculator::getEncodingSize(bytes));
|
||||
|
||||
//do all of the ones that are 3 byte aligned
|
||||
for (size_t i = 0, aligned((bytes - misaligned) / 3); i < aligned; ++i){
|
||||
LIBBASE64CODECOVERAGEBRANCH;
|
||||
result += libbase64_characters::getChar<CHARTYPE>((GETITEM_BOUNDCHECK(binary, binarybounds) & 0xFC) >> 2);
|
||||
result += libbase64_characters::getChar<CHARTYPE>(((GETITEM_BOUNDCHECK(binary, binarybounds) & 0x03) << 4) + ((GETITEM_BOUNDCHECK(binary + 1, binarybounds) & 0xF0) >> 4));
|
||||
result += libbase64_characters::getChar<CHARTYPE>(((GETITEM_BOUNDCHECK(binary + 1, binarybounds) & 0x0F) << 2) + ((GETITEM_BOUNDCHECK(binary + 2, binarybounds) & 0xC0) >> 6));
|
||||
result += libbase64_characters::getChar<CHARTYPE>(GETITEM_BOUNDCHECK(binary + 2, binarybounds) & 0x3F);
|
||||
binary += 3;
|
||||
}
|
||||
|
||||
//handle any additional characters at the end of it
|
||||
if (libbase64_likely(misaligned != 0)){
|
||||
LIBBASE64CODECOVERAGEBRANCH;
|
||||
//copy the rest into a temporary buffer, need it for the null terminators
|
||||
unsigned char temp[3] = { '\0', '\0', '\0' };
|
||||
for (unsigned char i = 0; i < (unsigned char)misaligned; ++i){
|
||||
LIBBASE64CODECOVERAGEBRANCH;
|
||||
temp[i] = GETITEM_BOUNDCHECK(binary++, binarybounds);
|
||||
}
|
||||
|
||||
//now do the final three bytes
|
||||
result += libbase64_characters::getChar<CHARTYPE>((temp[0] & 0xFC) >> 2);
|
||||
result += libbase64_characters::getChar<CHARTYPE>(((temp[0] & 0x03) << 4) + ((temp[1] & 0xF0) >> 4));
|
||||
if (misaligned == 2){
|
||||
LIBBASE64CODECOVERAGEBRANCH;
|
||||
result += libbase64_characters::getChar<CHARTYPE>(((temp[1] & 0x0F) << 2) + ((temp[2] & 0xC0) >> 6));
|
||||
} else {
|
||||
LIBBASE64CODECOVERAGEBRANCH;
|
||||
result += (CHARTYPE)'=';
|
||||
}
|
||||
result += (CHARTYPE)'=';
|
||||
} else {
|
||||
LIBBASE64CODECOVERAGEBRANCH;
|
||||
}
|
||||
|
||||
LIBBASE64_ASSERT(libbase64_Calculator::getEncodingSize(bytes) == result.length(), "Reserve wasn't the correct guess");
|
||||
return result;
|
||||
}
|
||||
|
||||
template<class STRINGTYPE, typename CHARTYPE, typename UCHARTYPE, bool SAFETY>
|
||||
static std::string decode(const STRINGTYPE & encoded){
|
||||
//check length to be sure its acceptable for base64
|
||||
const size_t length = encoded.length();
|
||||
|
||||
if (SAFETY){
|
||||
if (libbase64_unlikely((length % 4) != 0)){
|
||||
LIBBASE64CODECOVERAGEBRANCH;
|
||||
return libbase64_characters::emptyString<std::string>();
|
||||
}
|
||||
if (libbase64_unlikely(length == 0)){
|
||||
LIBBASE64CODECOVERAGEBRANCH;
|
||||
return libbase64_characters::emptyString<std::string>();
|
||||
}
|
||||
|
||||
//check to be sure there aren't odd characters or characters in the wrong places
|
||||
size_t pos = encoded.find_first_not_of(libbase64_characters::getChar64<CHARTYPE>());
|
||||
if (libbase64_unlikely(pos != STRINGTYPE::npos)){
|
||||
LIBBASE64CODECOVERAGEBRANCH;
|
||||
if (libbase64_unlikely(encoded[pos] != (CHARTYPE)'=')){
|
||||
LIBBASE64CODECOVERAGEBRANCH; //INVALID_CHAR
|
||||
#ifdef LIBBASE64_THROW_STD_INVALID_ARGUMENT
|
||||
throw std::invalid_argument("invalid character in base64");
|
||||
#else
|
||||
return libbase64_characters::emptyString<std::string>();
|
||||
#endif
|
||||
}
|
||||
if (pos != length - 1){
|
||||
LIBBASE64CODECOVERAGEBRANCH;
|
||||
if (libbase64_unlikely(pos != length - 2)){
|
||||
LIBBASE64CODECOVERAGEBRANCH; //EQUAL_WRONG_PLACE
|
||||
#ifdef LIBBASE64_THROW_STD_INVALID_ARGUMENT
|
||||
throw std::invalid_argument("equal sign in wrong place in base64");
|
||||
#else
|
||||
return libbase64_characters::emptyString<std::string>();
|
||||
#endif
|
||||
}
|
||||
if (libbase64_unlikely(encoded[pos + 1] != (CHARTYPE)'=')){
|
||||
LIBBASE64CODECOVERAGEBRANCH; //EQUAL_NOT_LAST
|
||||
#ifdef LIBBASE64_THROW_STD_INVALID_ARGUMENT
|
||||
throw std::invalid_argument("invalid character in base64");
|
||||
#else
|
||||
return libbase64_characters::emptyString<std::string>();
|
||||
#endif
|
||||
}
|
||||
LIBBASE64CODECOVERAGEBRANCH;
|
||||
} else {
|
||||
LIBBASE64CODECOVERAGEBRANCH;
|
||||
}
|
||||
} else {
|
||||
LIBBASE64CODECOVERAGEBRANCH;
|
||||
}
|
||||
}
|
||||
|
||||
const CHARTYPE * runner = encoded.data();
|
||||
const CHARTYPE * end = runner + encoded.length();
|
||||
CREATEBOUNDCHECKER(CHARTYPE, encodedbounds, runner, end);
|
||||
size_t aligned = length / 4; //don't do the last ones as they might be = padding
|
||||
std::string result;
|
||||
--aligned;
|
||||
result.reserve(libbase64_Calculator::getDecodingSize(length));
|
||||
|
||||
//first do the ones that can not have any padding
|
||||
for (unsigned int i = 0; i < aligned; ++i){
|
||||
const CHARTYPE second = libbase64_characters::toBinary<UCHARTYPE>(GETITEM_BOUNDCHECK(runner + 1, encodedbounds));
|
||||
const CHARTYPE third = libbase64_characters::toBinary<UCHARTYPE>(GETITEM_BOUNDCHECK(runner + 2, encodedbounds));
|
||||
result += (libbase64_characters::toBinary<UCHARTYPE>(GETITEM_BOUNDCHECK(runner, encodedbounds)) << 2) + ((second & 0x30) >> 4);
|
||||
result += ((second & 0xf) << 4) + ((third & 0x3c) >> 2);
|
||||
result += ((third & 0x3) << 6) + libbase64_characters::toBinary<UCHARTYPE>(GETITEM_BOUNDCHECK(runner + 3, encodedbounds));
|
||||
runner += 4;
|
||||
}
|
||||
|
||||
//now do the ones that might have padding, the first two characters can not be padding, so do them quickly
|
||||
const CHARTYPE second = libbase64_characters::toBinary<UCHARTYPE>(GETITEM_BOUNDCHECK(runner + 1, encodedbounds));
|
||||
result += (libbase64_characters::toBinary<UCHARTYPE>(GETITEM_BOUNDCHECK(runner + 0, encodedbounds)) << 2) + ((second & 0x30) >> 4);
|
||||
runner += 2;
|
||||
if ((runner != end) && (*runner != (CHARTYPE)'=')){ //not two = pads
|
||||
LIBBASE64CODECOVERAGEBRANCH;
|
||||
const CHARTYPE third = libbase64_characters::toBinary<UCHARTYPE>(GETITEM_BOUNDCHECK(runner, encodedbounds));
|
||||
result += ((second & 0xf) << 4) + ((third & 0x3c) >> 2);
|
||||
++runner;
|
||||
if ((runner != end) && (*runner != (CHARTYPE)'=')){ //no padding
|
||||
LIBBASE64CODECOVERAGEBRANCH;
|
||||
result += ((third & 0x3) << 6) + libbase64_characters::toBinary<UCHARTYPE>(GETITEM_BOUNDCHECK(runner, encodedbounds));
|
||||
} else {
|
||||
LIBBASE64CODECOVERAGEBRANCH;
|
||||
}
|
||||
} else {
|
||||
LIBBASE64CODECOVERAGEBRANCH;
|
||||
}
|
||||
|
||||
LIBBASE64_ASSERT(libbase64_Calculator::getDecodingSize(length) >= result.length(), "Reserve wasn't the correct guess, too small");
|
||||
LIBBASE64_ASSERT((result.length() <= 3) || (libbase64_Calculator::getDecodingSize(length) > result.length() - 3), "Reserve wasn't the correct guess, too big");
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
BIN
src/libjson/_internal/Dependencies/mempool++/._mempool.h
Normal file
BIN
src/libjson/_internal/Dependencies/mempool++/._mempool.h
Normal file
Binary file not shown.
1088
src/libjson/_internal/Dependencies/mempool++/mempool.h
Normal file
1088
src/libjson/_internal/Dependencies/mempool++/mempool.h
Normal file
File diff suppressed because it is too large
Load diff
BIN
src/libjson/_internal/Source/._JSONAllocator.cpp
Normal file
BIN
src/libjson/_internal/Source/._JSONAllocator.cpp
Normal file
Binary file not shown.
BIN
src/libjson/_internal/Source/._JSONAllocator.h
Normal file
BIN
src/libjson/_internal/Source/._JSONAllocator.h
Normal file
Binary file not shown.
BIN
src/libjson/_internal/Source/._JSONChildren.cpp
Normal file
BIN
src/libjson/_internal/Source/._JSONChildren.cpp
Normal file
Binary file not shown.
BIN
src/libjson/_internal/Source/._JSONChildren.h
Normal file
BIN
src/libjson/_internal/Source/._JSONChildren.h
Normal file
Binary file not shown.
BIN
src/libjson/_internal/Source/._JSONDebug.cpp
Normal file
BIN
src/libjson/_internal/Source/._JSONDebug.cpp
Normal file
Binary file not shown.
BIN
src/libjson/_internal/Source/._JSONDebug.h
Normal file
BIN
src/libjson/_internal/Source/._JSONDebug.h
Normal file
Binary file not shown.
BIN
src/libjson/_internal/Source/._JSONDefs
Normal file
BIN
src/libjson/_internal/Source/._JSONDefs
Normal file
Binary file not shown.
BIN
src/libjson/_internal/Source/._JSONDefs.h
Normal file
BIN
src/libjson/_internal/Source/._JSONDefs.h
Normal file
Binary file not shown.
BIN
src/libjson/_internal/Source/._JSONGlobals.h
Normal file
BIN
src/libjson/_internal/Source/._JSONGlobals.h
Normal file
Binary file not shown.
BIN
src/libjson/_internal/Source/._JSONIterators.cpp
Normal file
BIN
src/libjson/_internal/Source/._JSONIterators.cpp
Normal file
Binary file not shown.
BIN
src/libjson/_internal/Source/._JSONMemory.cpp
Normal file
BIN
src/libjson/_internal/Source/._JSONMemory.cpp
Normal file
Binary file not shown.
BIN
src/libjson/_internal/Source/._JSONMemory.h
Normal file
BIN
src/libjson/_internal/Source/._JSONMemory.h
Normal file
Binary file not shown.
BIN
src/libjson/_internal/Source/._JSONMemoryPool.h
Normal file
BIN
src/libjson/_internal/Source/._JSONMemoryPool.h
Normal file
Binary file not shown.
BIN
src/libjson/_internal/Source/._JSONNode.cpp
Normal file
BIN
src/libjson/_internal/Source/._JSONNode.cpp
Normal file
Binary file not shown.
BIN
src/libjson/_internal/Source/._JSONNode.h
Normal file
BIN
src/libjson/_internal/Source/._JSONNode.h
Normal file
Binary file not shown.
BIN
src/libjson/_internal/Source/._JSONNode_Mutex.cpp
Normal file
BIN
src/libjson/_internal/Source/._JSONNode_Mutex.cpp
Normal file
Binary file not shown.
BIN
src/libjson/_internal/Source/._JSONPreparse.cpp
Normal file
BIN
src/libjson/_internal/Source/._JSONPreparse.cpp
Normal file
Binary file not shown.
BIN
src/libjson/_internal/Source/._JSONPreparse.h
Normal file
BIN
src/libjson/_internal/Source/._JSONPreparse.h
Normal file
Binary file not shown.
BIN
src/libjson/_internal/Source/._JSONSharedString.h
Normal file
BIN
src/libjson/_internal/Source/._JSONSharedString.h
Normal file
Binary file not shown.
BIN
src/libjson/_internal/Source/._JSONSingleton.h
Normal file
BIN
src/libjson/_internal/Source/._JSONSingleton.h
Normal file
Binary file not shown.
BIN
src/libjson/_internal/Source/._JSONStats.h
Normal file
BIN
src/libjson/_internal/Source/._JSONStats.h
Normal file
Binary file not shown.
BIN
src/libjson/_internal/Source/._JSONStream.cpp
Normal file
BIN
src/libjson/_internal/Source/._JSONStream.cpp
Normal file
Binary file not shown.
BIN
src/libjson/_internal/Source/._JSONStream.h
Normal file
BIN
src/libjson/_internal/Source/._JSONStream.h
Normal file
Binary file not shown.
BIN
src/libjson/_internal/Source/._JSONValidator.h
Normal file
BIN
src/libjson/_internal/Source/._JSONValidator.h
Normal file
Binary file not shown.
BIN
src/libjson/_internal/Source/._JSONWorker.cpp
Normal file
BIN
src/libjson/_internal/Source/._JSONWorker.cpp
Normal file
Binary file not shown.
BIN
src/libjson/_internal/Source/._JSONWorker.h
Normal file
BIN
src/libjson/_internal/Source/._JSONWorker.h
Normal file
Binary file not shown.
BIN
src/libjson/_internal/Source/._JSONWriter.cpp
Normal file
BIN
src/libjson/_internal/Source/._JSONWriter.cpp
Normal file
Binary file not shown.
BIN
src/libjson/_internal/Source/._JSON_Base64.h
Normal file
BIN
src/libjson/_internal/Source/._JSON_Base64.h
Normal file
Binary file not shown.
BIN
src/libjson/_internal/Source/._NumberToString.h
Normal file
BIN
src/libjson/_internal/Source/._NumberToString.h
Normal file
Binary file not shown.
BIN
src/libjson/_internal/Source/._internalJSONNode.cpp
Normal file
BIN
src/libjson/_internal/Source/._internalJSONNode.cpp
Normal file
Binary file not shown.
BIN
src/libjson/_internal/Source/._internalJSONNode.h
Normal file
BIN
src/libjson/_internal/Source/._internalJSONNode.h
Normal file
Binary file not shown.
BIN
src/libjson/_internal/Source/._libjson.cpp
Normal file
BIN
src/libjson/_internal/Source/._libjson.cpp
Normal file
Binary file not shown.
13
src/libjson/_internal/Source/JSONAllocator.cpp
Normal file
13
src/libjson/_internal/Source/JSONAllocator.cpp
Normal file
|
@ -0,0 +1,13 @@
|
|||
#include "JSONAllocator.h"
|
||||
|
||||
#if defined(JSON_MEMORY_CALLBACKS) || defined(JSON_MEMORY_POOL)
|
||||
#include "JSONMemory.h"
|
||||
|
||||
void * JSONAllocatorRelayer::alloc(size_t bytes) json_nothrow {
|
||||
return JSONMemory::json_malloc(bytes);
|
||||
}
|
||||
|
||||
void JSONAllocatorRelayer::dealloc(void * ptr) json_nothrow {
|
||||
JSONMemory::json_free(ptr);
|
||||
}
|
||||
#endif
|
82
src/libjson/_internal/Source/JSONAllocator.h
Normal file
82
src/libjson/_internal/Source/JSONAllocator.h
Normal file
|
@ -0,0 +1,82 @@
|
|||
#ifndef JSON_ALLOCATOR_H
|
||||
#define JSON_ALLOCATOR_H
|
||||
|
||||
#include "JSONStats.h"
|
||||
#if defined(JSON_MEMORY_CALLBACKS) || defined(JSON_MEMORY_POOL)
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
//need these for the json_nothrow
|
||||
#include "JSONDefs/Visual_C.h"
|
||||
#include "JSONDefs/GNU_C.h"
|
||||
#include "JSONDefs/Unknown_C.h"
|
||||
|
||||
class JSONAllocatorRelayer {
|
||||
public:
|
||||
static void * alloc(size_t bytes) json_nothrow json_hot;
|
||||
static void dealloc(void * ptr) json_nothrow json_hot;
|
||||
};
|
||||
|
||||
template <class T> class json_allocator;
|
||||
|
||||
// specialize for void:
|
||||
template <> class json_allocator<void> {
|
||||
public:
|
||||
typedef void* pointer;
|
||||
typedef const void* const_pointer;
|
||||
// reference to void members are impossible.
|
||||
typedef void value_type;
|
||||
template <class U> struct rebind { typedef json_allocator<U> other; };
|
||||
};
|
||||
|
||||
template <class T> class json_allocator {
|
||||
public:
|
||||
typedef size_t size_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
typedef T* pointer;
|
||||
typedef const T* const_pointer;
|
||||
typedef T& reference;
|
||||
typedef const T& const_reference;
|
||||
typedef T value_type;
|
||||
template <class U> struct rebind { typedef json_allocator<U> other; };
|
||||
|
||||
//LIBJSON_OBJECT(json_allocator);
|
||||
|
||||
inline json_allocator() json_nothrow {
|
||||
//LIBJSON_CTOR;
|
||||
}
|
||||
inline json_allocator(const json_allocator&) json_nothrow {
|
||||
//LIBJSON_COPY_CTOR;
|
||||
}
|
||||
template <class U> inline json_allocator(const json_allocator<U>&) json_nothrow {
|
||||
//LIBJSON_COPY_CTOR;
|
||||
}
|
||||
inline ~json_allocator() json_nothrow {
|
||||
//LIBJSON_DTOR;
|
||||
}
|
||||
|
||||
inline pointer address(reference x) const { return &x; }
|
||||
inline const_pointer address(const_reference x) const { return &x; }
|
||||
|
||||
inline pointer allocate(size_type n, json_allocator<void>::const_pointer = 0) json_hot {
|
||||
return (pointer)JSONAllocatorRelayer::alloc(n * sizeof(T));
|
||||
}
|
||||
inline void deallocate(pointer p, size_type) json_hot {
|
||||
JSONAllocatorRelayer::dealloc(p);
|
||||
}
|
||||
|
||||
inline size_type max_size() const json_nothrow { return 0xEFFFFFFF; }
|
||||
|
||||
inline void construct(pointer p, const T& val){
|
||||
new(p)T(val);
|
||||
};
|
||||
inline void destroy(pointer p){
|
||||
((T*)p) -> ~T();
|
||||
}
|
||||
};
|
||||
|
||||
template <class T1, class T2> inline bool operator==(const json_allocator<T1>&, const json_allocator<T2>&) json_nothrow { return true; }
|
||||
template <class T1, class T2> inline bool operator!=(const json_allocator<T1>&, const json_allocator<T2>&) json_nothrow { return false; }
|
||||
|
||||
#endif
|
||||
#endif
|
94
src/libjson/_internal/Source/JSONChildren.cpp
Normal file
94
src/libjson/_internal/Source/JSONChildren.cpp
Normal file
|
@ -0,0 +1,94 @@
|
|||
#include "JSONChildren.h"
|
||||
#include "JSONNode.h"
|
||||
|
||||
/*
|
||||
* reserves a certain number of bytes, in memory saving mode it creates a special
|
||||
* type of child container that will not autoshrink
|
||||
*/
|
||||
void jsonChildren::reserve2(jsonChildren *& mine, json_index_t amount) json_nothrow {
|
||||
if (mine -> array != 0){
|
||||
if (mine -> mycapacity < amount){
|
||||
mine -> inc(amount - mine -> mycapacity);
|
||||
#ifdef JSON_LESS_MEMORY
|
||||
mine = jsonChildren_Reserved::newChildren_Reserved(mine, amount);
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
mine -> reserve(amount);
|
||||
}
|
||||
}
|
||||
|
||||
void jsonChildren::inc(void) json_nothrow {
|
||||
JSON_ASSERT(this != 0, JSON_TEXT("Children is null inc"));
|
||||
if (json_unlikely(mysize == mycapacity)){ //it's full
|
||||
if (json_unlikely(mycapacity == 0)){ //the array hasn't been created yet
|
||||
JSON_ASSERT(!array, JSON_TEXT("Expanding a 0 capacity array, but not null"));
|
||||
#ifdef JSON_LESS_MEMORY
|
||||
array = json_malloc<JSONNode*>(1);
|
||||
mycapacity = 1;
|
||||
#else
|
||||
array = json_malloc<JSONNode*>(8); //8 seems average for JSON, and it's only 64 bytes
|
||||
mycapacity = 8;
|
||||
#endif
|
||||
} else {
|
||||
#ifdef JSON_LESS_MEMORY
|
||||
mycapacity += 1; //increment the size of the array
|
||||
#else
|
||||
mycapacity <<= 1; //double the size of the array
|
||||
#endif
|
||||
array = json_realloc<JSONNode*>(array, mycapacity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void jsonChildren::inc(json_index_t amount) json_nothrow {
|
||||
JSON_ASSERT(this != 0, JSON_TEXT("Children is null inc(amount)"));
|
||||
if (json_unlikely(amount == 0)) return;
|
||||
if (json_likely(mysize + amount >= mycapacity)){ //it's full
|
||||
if (json_unlikely(mycapacity == 0)){ //the array hasn't been created yet
|
||||
JSON_ASSERT(!array, JSON_TEXT("Expanding a 0 capacity array, but not null"));
|
||||
#ifdef JSON_LESS_MEMORY
|
||||
array = json_malloc<JSONNode*>(amount);
|
||||
mycapacity = amount;
|
||||
#else
|
||||
array = json_malloc<JSONNode*>(amount > 8 ? amount : 8); //8 seems average for JSON, and it's only 64 bytes
|
||||
mycapacity = amount > 8 ? amount : 8;
|
||||
#endif
|
||||
} else {
|
||||
#ifdef JSON_LESS_MEMORY
|
||||
mycapacity = mysize + amount; //increment the size of the array
|
||||
#else
|
||||
while(mysize + amount > mycapacity){
|
||||
mycapacity <<= 1; //double the size of the array
|
||||
}
|
||||
#endif
|
||||
array = json_realloc<JSONNode*>(array, mycapacity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//actually deletes everything within the vector, this is safe to do on an empty or even a null array
|
||||
void jsonChildren::deleteAll(void) json_nothrow {
|
||||
JSON_ASSERT(this != 0, JSON_TEXT("Children is null deleteAll"));
|
||||
json_foreach(this, runner){
|
||||
JSON_ASSERT(*runner != JSON_TEXT('\0'), JSON_TEXT("a null pointer within the children"));
|
||||
JSONNode::deleteJSONNode(*runner); //this is why I can't do forward declaration
|
||||
}
|
||||
}
|
||||
|
||||
void jsonChildren::doerase(JSONNode ** position, json_index_t number) json_nothrow {
|
||||
JSON_ASSERT(this != 0, JSON_TEXT("Children is null doerase"));
|
||||
JSON_ASSERT(array != 0, JSON_TEXT("erasing something from a null array 2"));
|
||||
JSON_ASSERT(position >= array, JSON_TEXT("position is beneath the start of the array 2"));
|
||||
JSON_ASSERT(position + number <= array + mysize, JSON_TEXT("erasing out of bounds 2"));
|
||||
if (position + number >= array + mysize){
|
||||
mysize = (json_index_t)(position - array);
|
||||
#ifndef JSON_ISO_STRICT
|
||||
JSON_ASSERT((long long)position - (long long)array >= 0, JSON_TEXT("doing negative allocation"));
|
||||
#endif
|
||||
} else {
|
||||
std::memmove(position, position + number, (mysize - (position - array) - number) * sizeof(JSONNode *));
|
||||
mysize -= number;
|
||||
}
|
||||
}
|
329
src/libjson/_internal/Source/JSONChildren.h
Normal file
329
src/libjson/_internal/Source/JSONChildren.h
Normal file
|
@ -0,0 +1,329 @@
|
|||
#ifndef JSONCHILDREN_H
|
||||
#define JSONCHILDREN_H
|
||||
|
||||
#include "JSONMemory.h"
|
||||
#include "JSONDebug.h" //for JSON_ASSERT macro
|
||||
|
||||
#ifdef JSON_LESS_MEMORY
|
||||
#ifdef __GNUC__
|
||||
#pragma pack(push, 1)
|
||||
#elif _MSC_VER
|
||||
#pragma pack(push, jsonChildren, 1)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define json_foreach(chldrn, itrtr)\
|
||||
JSONNode ** itrtr = chldrn -> begin();\
|
||||
for(JSONNode ** itrtr##_end = chldrn -> end(); itrtr != itrtr##_end; ++itrtr)
|
||||
|
||||
/*
|
||||
This class is essentially a vector that has been heavily optimized for the specific purpose
|
||||
of holding JSONNode children. It acts the same way as a vector, it has a automatically
|
||||
expanding array. On destruction, this container automatically destroys everything contained
|
||||
in it as well, so that you libjson doesn't have to do that.
|
||||
|
||||
T is JSONNode*, I can't define it that way directly because JSONNode uses this container, and because
|
||||
the container deletes the children automatically, forward declaration can't be used
|
||||
*/
|
||||
|
||||
class JSONNode; //forward declaration
|
||||
|
||||
#ifdef JSON_LESS_MEMORY
|
||||
#define childrenVirtual virtual
|
||||
#else
|
||||
#define childrenVirtual
|
||||
#endif
|
||||
|
||||
class jsonChildren {
|
||||
public:
|
||||
LIBJSON_OBJECT(jsonChildren);
|
||||
//starts completely empty and the array is not allocated
|
||||
jsonChildren(void) json_nothrow : array(0), mysize(0), mycapacity(0) {
|
||||
LIBJSON_CTOR;
|
||||
}
|
||||
|
||||
#ifdef JSON_LESS_MEMORY
|
||||
jsonChildren(JSONNode** ar, json_index_t si, json_index_t ca) json_nothrow : array(ar), mysize(si), mycapacity(ca) {
|
||||
LIBJSON_CTOR;
|
||||
}
|
||||
#endif
|
||||
|
||||
//deletes the array and everything that is contained within it (using delete)
|
||||
childrenVirtual ~jsonChildren(void) json_nothrow {
|
||||
if (json_unlikely(array != 0)){ //the following function calls are safe, but take more time than a check here
|
||||
deleteAll();
|
||||
libjson_free<JSONNode*>(array);
|
||||
}
|
||||
LIBJSON_DTOR;
|
||||
}
|
||||
|
||||
//increase the size of the array
|
||||
void inc(json_index_t amount) json_nothrow;
|
||||
void inc(void) json_nothrow;
|
||||
|
||||
//Adds something to the vector, doubling the array if necessary
|
||||
void push_back(JSONNode * item) json_nothrow {
|
||||
JSON_ASSERT(this != 0, JSON_TEXT("Children is null push_back"));
|
||||
inc();
|
||||
array[mysize++] = item;
|
||||
}
|
||||
|
||||
//Adds something to the front of the vector, doubling the array if necessary
|
||||
void push_front(JSONNode * item) json_nothrow {
|
||||
JSON_ASSERT(this != 0, JSON_TEXT("Children is null push_front"));
|
||||
inc();
|
||||
std::memmove(array + 1, array, mysize++ * sizeof(JSONNode *));
|
||||
array[0] = item;
|
||||
}
|
||||
|
||||
//gets an item out of the vector by it's position
|
||||
inline JSONNode * operator[] (json_index_t position) const json_nothrow {
|
||||
JSON_ASSERT(this != 0, JSON_TEXT("Children is null []"));
|
||||
JSON_ASSERT(position < mysize, JSON_TEXT("Using [] out of bounds"));
|
||||
JSON_ASSERT(position < mycapacity, JSON_TEXT("Using [] out of bounds"));
|
||||
JSON_ASSERT(array != 0, JSON_TEXT("Array is null"));
|
||||
return array[position];
|
||||
}
|
||||
|
||||
//returns the allocated capacity, but keep in mind that some might not be valid
|
||||
inline json_index_t capacity() const json_nothrow {
|
||||
JSON_ASSERT(this != 0, JSON_TEXT("Children is null capacity"));
|
||||
return mycapacity;
|
||||
}
|
||||
|
||||
//returns the number of valid objects within the vector
|
||||
inline json_index_t size() const json_nothrow {
|
||||
JSON_ASSERT(this != 0, JSON_TEXT("Children is null size"));
|
||||
return mysize;
|
||||
}
|
||||
|
||||
//tests whether or not the vector is empty
|
||||
inline bool empty() const json_nothrow {
|
||||
JSON_ASSERT(this != 0, JSON_TEXT("Children is null empty"));
|
||||
return mysize == 0;
|
||||
}
|
||||
|
||||
//clears (and deletes) everything from the vector and sets it's size to 0
|
||||
inline void clear() json_nothrow {
|
||||
JSON_ASSERT(this != 0, JSON_TEXT("Children is null clear"));
|
||||
if (json_likely(array != 0)){ //don't bother clearing anything if there is nothing in it
|
||||
JSON_ASSERT(mycapacity != 0, JSON_TEXT("mycapacity is not zero, but array is null"));
|
||||
deleteAll();
|
||||
mysize = 0;
|
||||
}
|
||||
JSON_ASSERT(mysize == 0, JSON_TEXT("mysize is not zero after clear"));
|
||||
}
|
||||
|
||||
//returns the beginning of the array
|
||||
inline JSONNode ** begin(void) const json_nothrow {
|
||||
JSON_ASSERT(this != 0, JSON_TEXT("Children is null begin"));
|
||||
return array;
|
||||
}
|
||||
|
||||
//returns the end of the array
|
||||
inline JSONNode ** end(void) const json_nothrow {
|
||||
JSON_ASSERT(this != 0, JSON_TEXT("Children is null end"));
|
||||
return array + mysize;
|
||||
}
|
||||
|
||||
//makes sure that even after shirnking and expanding, the iterator is in same relative position
|
||||
template <bool reverse>
|
||||
struct iteratorKeeper {
|
||||
public:
|
||||
LIBJSON_OBJECT(jsonChildren::iteratorKeeper);
|
||||
iteratorKeeper(jsonChildren * pthis, JSONNode ** & position) json_nothrow :
|
||||
myRelativeOffset(reverse ? (json_index_t)(pthis -> array + (size_t)pthis -> mysize - position) : (json_index_t)(position - pthis -> array)),
|
||||
myChildren(pthis),
|
||||
myPos(position){
|
||||
LIBJSON_CTOR;
|
||||
}
|
||||
|
||||
~iteratorKeeper(void) json_nothrow {
|
||||
LIBJSON_DTOR;
|
||||
if (reverse){
|
||||
myPos = myChildren -> array + myChildren -> mysize - myRelativeOffset;
|
||||
} else {
|
||||
myPos = myChildren -> array + myRelativeOffset;
|
||||
}
|
||||
}
|
||||
private:
|
||||
iteratorKeeper(const iteratorKeeper &);
|
||||
iteratorKeeper & operator = (const iteratorKeeper &);
|
||||
|
||||
json_index_t myRelativeOffset;
|
||||
jsonChildren * myChildren;
|
||||
JSONNode ** & myPos;
|
||||
};
|
||||
|
||||
//This function DOES NOT delete the item it points to
|
||||
inline void erase(JSONNode ** & position) json_nothrow {
|
||||
JSON_ASSERT(this != 0, JSON_TEXT("Children is null erase"));
|
||||
JSON_ASSERT(array != 0, JSON_TEXT("erasing something from a null array 1"));
|
||||
JSON_ASSERT(position >= array, JSON_TEXT("position is beneath the start of the array 1"));
|
||||
JSON_ASSERT(position <= array + mysize, JSON_TEXT("erasing out of bounds 1"));
|
||||
std::memmove(position, position + 1, (mysize-- - (position - array) - 1) * sizeof(JSONNode *));
|
||||
iteratorKeeper<false> ik(this, position);
|
||||
shrink();
|
||||
}
|
||||
|
||||
//This function DOES NOT delete the item it points to
|
||||
inline void erase(JSONNode ** & position, json_index_t number) json_nothrow {
|
||||
JSON_ASSERT(this != 0, JSON_TEXT("Children is null erase 2"));
|
||||
doerase(position, number);
|
||||
iteratorKeeper<false> ik(this, position);
|
||||
shrink();
|
||||
}
|
||||
|
||||
|
||||
//This function DOES NOT delete the item it points to
|
||||
inline void erase(JSONNode ** position, json_index_t number, JSONNode ** & starter) json_nothrow {
|
||||
JSON_ASSERT(this != 0, JSON_TEXT("Children is null erase 3"));
|
||||
doerase(position, number);
|
||||
iteratorKeeper<false> ik(this, starter);
|
||||
shrink();
|
||||
}
|
||||
|
||||
#ifdef JSON_LIBRARY
|
||||
void insert(JSONNode ** & position, JSONNode * item) json_nothrow{
|
||||
#else
|
||||
void insert(JSONNode ** & position, JSONNode * item, bool reverse = false) json_nothrow {
|
||||
#endif
|
||||
JSON_ASSERT(this != 0, JSON_TEXT("Children is null insert"));
|
||||
//position isnt relative to array because of realloc
|
||||
JSON_ASSERT(position >= array, JSON_TEXT("position is beneath the start of the array insert 1"));
|
||||
JSON_ASSERT(position <= array + mysize, JSON_TEXT("position is above the end of the array insert 1"));
|
||||
#ifndef JSON_LIBRARY
|
||||
if (reverse){
|
||||
iteratorKeeper<true> ik(this, position);
|
||||
inc();
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
iteratorKeeper<false> ik(this, position);
|
||||
inc();
|
||||
}
|
||||
|
||||
std::memmove(position + 1, position, (mysize++ - (position - array)) * sizeof(JSONNode *));
|
||||
*position = item;
|
||||
}
|
||||
|
||||
void insert(JSONNode ** & position, JSONNode ** items, json_index_t num) json_nothrow {
|
||||
JSON_ASSERT(this != 0, JSON_TEXT("Children is null insert 2"));
|
||||
JSON_ASSERT(position >= array, JSON_TEXT("position is beneath the start of the array insert 2"));
|
||||
JSON_ASSERT(position <= array + mysize, JSON_TEXT("position is above the end of the array insert 2"));
|
||||
{
|
||||
iteratorKeeper<false> ik(this, position);
|
||||
inc(num);
|
||||
}
|
||||
const size_t ptrs = ((JSONNode **)(array + mysize)) - position;
|
||||
std::memmove(position + num, position, ptrs * sizeof(JSONNode *));
|
||||
std::memcpy(position, items, num * sizeof(JSONNode *));
|
||||
mysize += num;
|
||||
}
|
||||
|
||||
inline void reserve(json_index_t amount) json_nothrow {
|
||||
JSON_ASSERT(this != 0, JSON_TEXT("Children is null reserve"));
|
||||
JSON_ASSERT(array == 0, JSON_TEXT("reserve is not meant to expand a preexisting array"));
|
||||
JSON_ASSERT(mycapacity == 0, JSON_TEXT("reservec is not meant to expand a preexisting array"));
|
||||
JSON_ASSERT(mysize == 0, JSON_TEXT("reserves is not meant to expand a preexisting array"));
|
||||
array = json_malloc<JSONNode*>(mycapacity = amount);
|
||||
}
|
||||
|
||||
//it is static because mine might change pointers entirely
|
||||
static void reserve2(jsonChildren *& mine, json_index_t amount) json_nothrow;
|
||||
|
||||
//shrinks the array to only as large as it needs to be to hold everything within it
|
||||
inline childrenVirtual void shrink() json_nothrow {
|
||||
JSON_ASSERT(this != 0, JSON_TEXT("Children is null shrink"));
|
||||
if (json_unlikely(mysize == 0)){ //size is zero, we should completely free the array
|
||||
libjson_free<JSONNode*>(array); //free does checks for a null pointer, so don't bother checking
|
||||
array = 0;
|
||||
#ifdef JSON_LESS_MEMORY
|
||||
} else { //need to shrink it, using realloc
|
||||
JSON_ASSERT(array != 0, JSON_TEXT("shrinking a null array that is not size 0"));
|
||||
array = json_realloc<JSONNode*>(array, mysize);
|
||||
#endif
|
||||
}
|
||||
mycapacity = mysize;
|
||||
}
|
||||
|
||||
|
||||
inline static void deleteChildren(jsonChildren * ptr) json_nothrow {
|
||||
#ifdef JSON_MEMORY_CALLBACKS
|
||||
ptr -> ~jsonChildren();
|
||||
libjson_free<jsonChildren>(ptr);
|
||||
#else
|
||||
delete ptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline static jsonChildren * newChildren(void) {
|
||||
#ifdef JSON_MEMORY_CALLBACKS
|
||||
return new(json_malloc<jsonChildren>(1)) jsonChildren();
|
||||
#else
|
||||
return new jsonChildren();
|
||||
#endif
|
||||
}
|
||||
|
||||
JSONNode ** array; //the expandable array
|
||||
|
||||
json_index_t mysize; //the number of valid items
|
||||
json_index_t mycapacity; //the number of possible items
|
||||
JSON_PROTECTED
|
||||
//to make sure it's not copyable
|
||||
jsonChildren(const jsonChildren &);
|
||||
jsonChildren & operator = (const jsonChildren &);
|
||||
|
||||
void deleteAll(void) json_nothrow json_hot; //implemented in JSONNode.cpp
|
||||
void doerase(JSONNode ** position, json_index_t number) json_nothrow;
|
||||
};
|
||||
|
||||
#ifdef JSON_LESS_MEMORY
|
||||
class jsonChildren_Reserved : public jsonChildren {
|
||||
public:
|
||||
LIBJSON_OBJECT(jsonChildren_Reserved);
|
||||
jsonChildren_Reserved(jsonChildren * orig, json_index_t siz) json_nothrow : jsonChildren(orig -> array, orig -> mysize, orig -> mycapacity), myreserved(siz) {
|
||||
orig -> array = 0;
|
||||
deleteChildren(orig);
|
||||
LIBJSON_CTOR;
|
||||
}
|
||||
jsonChildren_Reserved(const jsonChildren_Reserved & orig) json_nothrow : jsonChildren(orig.array, orig.mysize, orig.mycapacity), myreserved(orig.myreserved){
|
||||
LIBJSON_COPY_CTOR;
|
||||
}
|
||||
inline virtual ~jsonChildren_Reserved() json_nothrow {
|
||||
LIBJSON_DTOR;
|
||||
};
|
||||
inline virtual void shrink() json_nothrow {
|
||||
JSON_ASSERT(this != 0, JSON_TEXT("Children is null shrink reserved"));
|
||||
if (json_unlikely(mysize == 0)){ //size is zero, we should completely free the array
|
||||
libjson_free<JSONNode*>(array); //free does checks for a null pointer, so don't bother checking
|
||||
array = 0;
|
||||
} else if (mysize > myreserved){
|
||||
JSON_ASSERT(array != 0, JSON_TEXT("shrinking a null array that is not size 0"));
|
||||
array = json_realloc<JSONNode*>(array, mysize);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef JSON_LESS_MEMORY
|
||||
inline static jsonChildren * newChildren_Reserved(jsonChildren * orig, json_index_t siz) json_nothrow {
|
||||
#ifdef JSON_MEMORY_CALLBACKS
|
||||
return new(json_malloc<jsonChildren_Reserved>(1)) jsonChildren_Reserved(orig, siz);
|
||||
#else
|
||||
return new jsonChildren_Reserved(orig, siz);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
JSON_PRIVATE
|
||||
jsonChildren_Reserved & operator = (const jsonChildren_Reserved &);
|
||||
json_index_t myreserved;
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef JSON_LESS_MEMORY
|
||||
#ifdef __GNUC__
|
||||
#pragma pack(pop)
|
||||
#elif _MSC_VER
|
||||
#pragma pack(pop, jsonChildren)
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
42
src/libjson/_internal/Source/JSONDebug.cpp
Normal file
42
src/libjson/_internal/Source/JSONDebug.cpp
Normal file
|
@ -0,0 +1,42 @@
|
|||
#include "JSONDebug.h"
|
||||
#ifdef JSON_DEBUG
|
||||
|
||||
#ifdef JSON_STDERROR
|
||||
#include <iostream> //need std::cerr
|
||||
#else
|
||||
#include "JSONSingleton.h"
|
||||
//otherwise, use a callback to tell the end user what happened
|
||||
json_error_callback_t JSONDebug::register_callback(json_error_callback_t callback) json_nothrow {
|
||||
json_error_callback_t res = JSONSingleton<json_error_callback_t>::get();
|
||||
JSONSingleton<json_error_callback_t>::set(callback);
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
//Something went wrong or an assert failed
|
||||
void JSONDebug::_JSON_FAIL(const json_string & msg) json_nothrow {
|
||||
#ifdef JSON_STDERROR //no callback, just use stderror
|
||||
#ifndef JSON_UNICODE
|
||||
std::cerr << msg << std::endl;
|
||||
#else
|
||||
std::cerr << std::string(msg.begin(), msg.end()) << std::endl;
|
||||
#endif
|
||||
#else
|
||||
if (json_error_callback_t ErrorCallback = JSONSingleton<json_error_callback_t>::get()){ //only do anything if the callback is registered
|
||||
#ifdef JSON_LIBRARY
|
||||
ErrorCallback(msg.c_str());
|
||||
#else
|
||||
ErrorCallback(msg);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//asserts that condition is true, more useful than cassert because it lets you keep going
|
||||
void JSONDebug::_JSON_ASSERT(bool condition, const json_string & msg) json_nothrow {
|
||||
if (json_unlikely(!condition)){
|
||||
_JSON_FAIL(msg);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
59
src/libjson/_internal/Source/JSONDebug.h
Normal file
59
src/libjson/_internal/Source/JSONDebug.h
Normal file
|
@ -0,0 +1,59 @@
|
|||
#ifndef LIBJSON_GUARD_DEBUG_H
|
||||
#define LIBJSON_GUARD_DEBUG_H
|
||||
|
||||
#include "JSONDefs.h"
|
||||
#include "JSONStats.h"
|
||||
|
||||
#ifdef JSON_DEBUG
|
||||
#ifdef JSON_SAFE
|
||||
#define JSON_ASSERT_SAFE(condition, msg, code)\
|
||||
{\
|
||||
if (json_unlikely(!(condition))){\
|
||||
JSON_FAIL(msg);\
|
||||
code\
|
||||
}\
|
||||
}
|
||||
#define JSON_FAIL_SAFE(msg, code)\
|
||||
{\
|
||||
JSON_FAIL(msg);\
|
||||
code\
|
||||
}
|
||||
#else
|
||||
#define JSON_ASSERT_SAFE(condition, msg, code) JSON_ASSERT(condition, msg)
|
||||
#define JSON_FAIL_SAFE(msg, code) JSON_FAIL(msg)
|
||||
#endif
|
||||
|
||||
#define JSON_FAIL(msg) JSONDebug::_JSON_FAIL(msg)
|
||||
#define JSON_ASSERT(bo, msg) JSONDebug::_JSON_ASSERT(bo, msg)
|
||||
|
||||
class JSONDebug {
|
||||
public:
|
||||
#ifndef JSON_STDERROR
|
||||
static json_error_callback_t register_callback(json_error_callback_t callback) json_nothrow json_cold;
|
||||
#endif
|
||||
static void _JSON_FAIL(const json_string & msg) json_nothrow json_cold;
|
||||
static void _JSON_ASSERT(bool condition, const json_string & msg) json_nothrow json_cold;
|
||||
};
|
||||
#else
|
||||
#ifdef JSON_SAFE
|
||||
#define JSON_ASSERT_SAFE(condition, msg, code)\
|
||||
{\
|
||||
if (json_unlikely(!(condition))){\
|
||||
code\
|
||||
}\
|
||||
}
|
||||
#define JSON_FAIL_SAFE(msg, code)\
|
||||
{\
|
||||
code\
|
||||
}
|
||||
#else
|
||||
#define JSON_ASSERT_SAFE(condition, msg, code)
|
||||
#define JSON_FAIL_SAFE(msg, code)
|
||||
#endif
|
||||
|
||||
#define JSON_ASSERT(condition, msg)
|
||||
#define JSON_FAIL(msg)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
184
src/libjson/_internal/Source/JSONDefs.h
Normal file
184
src/libjson/_internal/Source/JSONDefs.h
Normal file
|
@ -0,0 +1,184 @@
|
|||
#ifndef JSONDEFS_H
|
||||
#define JSONDEFS_H
|
||||
|
||||
/*
|
||||
Defines all of the types of functions and various other definitions
|
||||
that are used in C applications, this is very useful if dynamically loading
|
||||
the library instead of linking.
|
||||
*/
|
||||
|
||||
#include "../../JSONOptions.h"
|
||||
#include "JSONDefs/Unknown_C.h"
|
||||
#include "JSONDefs/GNU_C.h"
|
||||
#include "JSONDefs/Visual_C.h"
|
||||
#include "JSONDefs/Strings_Defs.h"
|
||||
|
||||
#define __LIBJSON_MAJOR__ 7
|
||||
#define __LIBJSON_MINOR__ 6
|
||||
#define __LIBJSON_PATCH__ 1
|
||||
#define __LIBJSON_VERSION__ (__LIBJSON_MAJOR__ * 10000 + __LIBJSON_MINOR__ * 100 + __LIBJSON_PATCH__)
|
||||
|
||||
#define JSON_NULL '\0'
|
||||
#define JSON_STRING '\1'
|
||||
#define JSON_NUMBER '\2'
|
||||
#define JSON_BOOL '\3'
|
||||
#define JSON_ARRAY '\4'
|
||||
#define JSON_NODE '\5'
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if defined(JSON_MEMORY_CALLBACKS) || defined(JSON_MEMORY_POOL)
|
||||
#include "JSONAllocator.h"
|
||||
#else
|
||||
#define json_allocator std::allocator
|
||||
#endif
|
||||
|
||||
#ifdef JSON_STRING_HEADER
|
||||
#include JSON_STRING_HEADER
|
||||
#else
|
||||
typedef std::basic_string<json_char, std::char_traits<json_char>, json_allocator<json_char> > json_string;
|
||||
#endif
|
||||
#endif
|
||||
#define JSON_MAP(x, y) std::map<x, y, std::less<x>, json_allocator<std::pair<const x, y> > >
|
||||
|
||||
#ifdef JSON_NO_EXCEPTIONS
|
||||
#define json_throw(x)
|
||||
#define json_try
|
||||
#define json_catch(exception, code)
|
||||
#else
|
||||
#define json_throw(x) throw(x)
|
||||
#define json_try try
|
||||
#define json_catch(exception, code) catch(exception){ code }
|
||||
#endif
|
||||
|
||||
#ifdef JSON_STRICT
|
||||
#ifndef JSON_UNICODE
|
||||
#error, JSON_UNICODE is required for JSON_STRICT
|
||||
#endif
|
||||
#ifdef JSON_COMMENTS
|
||||
#error, JSON_COMMENTS is required to be off for JSON_STRICT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef JSON_ISO_STRICT
|
||||
#ifdef JSON_UNICODE
|
||||
#error, You can not use unicode under ANSI Strict C++
|
||||
#endif
|
||||
#else
|
||||
#ifdef __GNUC__
|
||||
#ifdef __STRICT_ANSI__
|
||||
#warning, Using -ansi GCC option, but JSON_ISO_STRICT not on, turning it on for you
|
||||
#define JSON_ISO_STRICT
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef JSON_NUMBER_TYPE
|
||||
typedef JSON_NUMBER_TYPE json_number;
|
||||
#define JSON_FLOAT_THRESHHOLD 0.00001
|
||||
#else
|
||||
#ifdef JSON_LESS_MEMORY
|
||||
typedef float json_number;
|
||||
#define JSON_FLOAT_THRESHHOLD 0.00001f
|
||||
#else
|
||||
typedef double json_number;
|
||||
#define JSON_FLOAT_THRESHHOLD 0.00001
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef JSON_LESS_MEMORY
|
||||
/* PACKED and BITS stored in compiler specific headers */
|
||||
#define START_MEM_SCOPE {
|
||||
#define END_MEM_SCOPE }
|
||||
#else
|
||||
#define PACKED(x)
|
||||
#define BITS(x)
|
||||
#define START_MEM_SCOPE
|
||||
#define END_MEM_SCOPE
|
||||
#endif
|
||||
|
||||
#if defined JSON_DEBUG || defined JSON_SAFE
|
||||
#ifdef JSON_LIBRARY
|
||||
typedef void (*json_error_callback_t)(const json_char *);
|
||||
#else
|
||||
typedef void (*json_error_callback_t)(const json_string &);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef JSON_INDEX_TYPE
|
||||
typedef JSON_INDEX_TYPE json_index_t;
|
||||
#else
|
||||
typedef unsigned int json_index_t;
|
||||
#endif
|
||||
|
||||
#ifdef JSON_BOOL_TYPE
|
||||
typedef JSON_BOOL_TYPE json_bool_t;
|
||||
#else
|
||||
typedef int json_bool_t;
|
||||
#endif
|
||||
|
||||
#ifdef JSON_INT_TYPE
|
||||
typedef JSON_INT_TYPE json_int_t;
|
||||
#else
|
||||
typedef long json_int_t;
|
||||
#endif
|
||||
|
||||
#define JSONSTREAM_SELF (void*)-1
|
||||
typedef void (*json_stream_e_callback_t)(void * identifier);
|
||||
|
||||
typedef void (*json_mutex_callback_t)(void *);
|
||||
typedef void (*json_free_t)(void *);
|
||||
#ifndef JSON_LIBRARY
|
||||
typedef void * (*json_malloc_t)(size_t);
|
||||
typedef void * (*json_realloc_t)(void *, size_t);
|
||||
#else
|
||||
#define JSONNODE void /* so that JSONNODE* is void* */
|
||||
typedef JSONNODE** JSONNODE_ITERATOR;
|
||||
#ifdef JSON_STREAM
|
||||
#define JSONSTREAM void
|
||||
typedef void (*json_stream_callback_t)(JSONNODE *, void * identifier);
|
||||
#endif
|
||||
typedef void * (*json_malloc_t)(unsigned long);
|
||||
typedef void * (*json_realloc_t)(void *, unsigned long);
|
||||
#endif
|
||||
|
||||
#ifdef JSON_DEBUG
|
||||
#ifdef NDEBUG
|
||||
#ifdef __GNUC__
|
||||
#warning, Have JSON_DEBUG on in a release build
|
||||
#else
|
||||
#error, Have JSON_DEBUG on in a release build
|
||||
#endif
|
||||
#endif
|
||||
#else
|
||||
#ifndef NDEBUG
|
||||
#ifdef __GNUC__
|
||||
#warning, Release build of libjson, but NDEBUG is not on
|
||||
#else
|
||||
#error, Release build of libjson, but NDEBUG is not on
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef JSON_UNIT_TEST
|
||||
#define JSON_PRIVATE public:
|
||||
#define JSON_PROTECTED public:
|
||||
#else
|
||||
#define JSON_PRIVATE private:
|
||||
#define JSON_PROTECTED protected:
|
||||
#endif
|
||||
#ifdef JSON_STREAM
|
||||
#ifndef JSON_READ_PRIORITY
|
||||
#error, JSON_STREAM also requires JSON_READ_PRIORITY
|
||||
#endif
|
||||
#endif
|
||||
#ifdef JSON_VALIDATE
|
||||
#ifndef JSON_READ_PRIORITY
|
||||
#error, JSON_VALIDATE also requires JSON_READ_PRIORITY
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define JSON_TEMP_COMMENT_IDENTIFIER JSON_TEXT('#')
|
||||
|
||||
#endif
|
184
src/libjson/_internal/Source/JSONDefs.h~
Normal file
184
src/libjson/_internal/Source/JSONDefs.h~
Normal file
|
@ -0,0 +1,184 @@
|
|||
#ifndef JSONDEFS_H
|
||||
#define JSONDEFS_H
|
||||
|
||||
/*
|
||||
Defines all of the types of functions and various other definitions
|
||||
that are used in C applications, this is very useful if dynamically loading
|
||||
the library instead of linking.
|
||||
*/
|
||||
|
||||
#include "../../JSONOptions.h"
|
||||
#include "JSONDefs/Unknown_C.h"
|
||||
#include "JSONDefs/GNU_C.h"
|
||||
#include "JSONDefs/Visual_C.h"
|
||||
#include "JSONDefs/Strings_Defs.h"
|
||||
|
||||
#define __LIBJSON_MAJOR__ 7
|
||||
#define __LIBJSON_MINOR__ 6
|
||||
#define __LIBJSON_PATCH__ 0
|
||||
#define __LIBJSON_VERSION__ (__LIBJSON_MAJOR__ * 10000 + __LIBJSON_MINOR__ * 100 + __LIBJSON_PATCH__)
|
||||
|
||||
#define JSON_NULL '\0'
|
||||
#define JSON_STRING '\1'
|
||||
#define JSON_NUMBER '\2'
|
||||
#define JSON_BOOL '\3'
|
||||
#define JSON_ARRAY '\4'
|
||||
#define JSON_NODE '\5'
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if defined(JSON_MEMORY_CALLBACKS) || defined(JSON_MEMORY_POOL)
|
||||
#include "JSONAllocator.h"
|
||||
#else
|
||||
#define json_allocator std::allocator
|
||||
#endif
|
||||
|
||||
#ifdef JSON_STRING_HEADER
|
||||
#include JSON_STRING_HEADER
|
||||
#else
|
||||
typedef std::basic_string<json_char, std::char_traits<json_char>, json_allocator<json_char> > json_string;
|
||||
#endif
|
||||
#endif
|
||||
#define JSON_MAP(x, y) std::map<x, y, std::less<x>, json_allocator<std::pair<const x, y> > >
|
||||
|
||||
#ifdef JSON_NO_EXCEPTIONS
|
||||
#define json_throw(x)
|
||||
#define json_try
|
||||
#define json_catch(exception, code)
|
||||
#else
|
||||
#define json_throw(x) throw(x)
|
||||
#define json_try try
|
||||
#define json_catch(exception, code) catch(exception){ code }
|
||||
#endif
|
||||
|
||||
#ifdef JSON_STRICT
|
||||
#ifndef JSON_UNICODE
|
||||
#error, JSON_UNICODE is required for JSON_STRICT
|
||||
#endif
|
||||
#ifdef JSON_COMMENTS
|
||||
#error, JSON_COMMENTS is required to be off for JSON_STRICT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef JSON_ISO_STRICT
|
||||
#ifdef JSON_UNICODE
|
||||
#error, You can not use unicode under ANSI Strict C++
|
||||
#endif
|
||||
#else
|
||||
#ifdef __GNUC__
|
||||
#ifdef __STRICT_ANSI__
|
||||
#warning, Using -ansi GCC option, but JSON_ISO_STRICT not on, turning it on for you
|
||||
#define JSON_ISO_STRICT
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef JSON_NUMBER_TYPE
|
||||
typedef JSON_NUMBER_TYPE json_number;
|
||||
#define JSON_FLOAT_THRESHHOLD 0.00001
|
||||
#else
|
||||
#ifdef JSON_LESS_MEMORY
|
||||
typedef float json_number;
|
||||
#define JSON_FLOAT_THRESHHOLD 0.00001f
|
||||
#else
|
||||
typedef double json_number;
|
||||
#define JSON_FLOAT_THRESHHOLD 0.00001
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef JSON_LESS_MEMORY
|
||||
/* PACKED and BITS stored in compiler specific headers */
|
||||
#define START_MEM_SCOPE {
|
||||
#define END_MEM_SCOPE }
|
||||
#else
|
||||
#define PACKED(x)
|
||||
#define BITS(x)
|
||||
#define START_MEM_SCOPE
|
||||
#define END_MEM_SCOPE
|
||||
#endif
|
||||
|
||||
#if defined JSON_DEBUG || defined JSON_SAFE
|
||||
#ifdef JSON_LIBRARY
|
||||
typedef void (*json_error_callback_t)(const json_char *);
|
||||
#else
|
||||
typedef void (*json_error_callback_t)(const json_string &);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef JSON_INDEX_TYPE
|
||||
typedef JSON_INDEX_TYPE json_index_t;
|
||||
#else
|
||||
typedef unsigned int json_index_t;
|
||||
#endif
|
||||
|
||||
#ifdef JSON_BOOL_TYPE
|
||||
typedef JSON_BOOL_TYPE json_bool_t;
|
||||
#else
|
||||
typedef int json_bool_t;
|
||||
#endif
|
||||
|
||||
#ifdef JSON_INT_TYPE
|
||||
typedef JSON_INT_TYPE json_int_t;
|
||||
#else
|
||||
typedef long json_int_t;
|
||||
#endif
|
||||
|
||||
#define JSONSTREAM_SELF (void*)-1
|
||||
typedef void (*json_stream_e_callback_t)(void * identifier);
|
||||
|
||||
typedef void (*json_mutex_callback_t)(void *);
|
||||
typedef void (*json_free_t)(void *);
|
||||
#ifndef JSON_LIBRARY
|
||||
typedef void * (*json_malloc_t)(size_t);
|
||||
typedef void * (*json_realloc_t)(void *, size_t);
|
||||
#else
|
||||
#define JSONNODE void /* so that JSONNODE* is void* */
|
||||
typedef JSONNODE** JSONNODE_ITERATOR;
|
||||
#ifdef JSON_STREAM
|
||||
#define JSONSTREAM void
|
||||
typedef void (*json_stream_callback_t)(JSONNODE *, void * identifier);
|
||||
#endif
|
||||
typedef void * (*json_malloc_t)(unsigned long);
|
||||
typedef void * (*json_realloc_t)(void *, unsigned long);
|
||||
#endif
|
||||
|
||||
#ifdef JSON_DEBUG
|
||||
#ifdef NDEBUG
|
||||
#ifdef __GNUC__
|
||||
#warning, Have JSON_DEBUG on in a release build
|
||||
#else
|
||||
#error, Have JSON_DEBUG on in a release build
|
||||
#endif
|
||||
#endif
|
||||
#else
|
||||
#ifndef NDEBUG
|
||||
#ifdef __GNUC__
|
||||
#warning, Release build of libjson, but NDEBUG is not on
|
||||
#else
|
||||
#error, Release build of libjson, but NDEBUG is not on
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef JSON_UNIT_TEST
|
||||
#define JSON_PRIVATE public:
|
||||
#define JSON_PROTECTED public:
|
||||
#else
|
||||
#define JSON_PRIVATE private:
|
||||
#define JSON_PROTECTED protected:
|
||||
#endif
|
||||
#ifdef JSON_STREAM
|
||||
#ifndef JSON_READ_PRIORITY
|
||||
#error, JSON_STREAM also requires JSON_READ_PRIORITY
|
||||
#endif
|
||||
#endif
|
||||
#ifdef JSON_VALIDATE
|
||||
#ifndef JSON_READ_PRIORITY
|
||||
#error, JSON_VALIDATE also requires JSON_READ_PRIORITY
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define JSON_TEMP_COMMENT_IDENTIFIER JSON_TEXT('#')
|
||||
|
||||
#endif
|
BIN
src/libjson/_internal/Source/JSONDefs/._GNU_C.h
Normal file
BIN
src/libjson/_internal/Source/JSONDefs/._GNU_C.h
Normal file
Binary file not shown.
BIN
src/libjson/_internal/Source/JSONDefs/._Strings_Defs.h
Normal file
BIN
src/libjson/_internal/Source/JSONDefs/._Strings_Defs.h
Normal file
Binary file not shown.
BIN
src/libjson/_internal/Source/JSONDefs/._Unknown_C.h
Normal file
BIN
src/libjson/_internal/Source/JSONDefs/._Unknown_C.h
Normal file
Binary file not shown.
BIN
src/libjson/_internal/Source/JSONDefs/._Visual_C.h
Normal file
BIN
src/libjson/_internal/Source/JSONDefs/._Visual_C.h
Normal file
Binary file not shown.
67
src/libjson/_internal/Source/JSONDefs/GNU_C.h
Normal file
67
src/libjson/_internal/Source/JSONDefs/GNU_C.h
Normal file
|
@ -0,0 +1,67 @@
|
|||
#ifndef JSON_GNU_C_HEADER
|
||||
#define JSON_GUN_C_HEADER
|
||||
|
||||
#ifdef __GNUC__
|
||||
|
||||
#define json_deprecated(method, warning) method __attribute__((deprecated))
|
||||
|
||||
#if (__GNUC__ >= 3)
|
||||
#define JSON_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
|
||||
#else
|
||||
#define JSON_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100)
|
||||
#endif
|
||||
|
||||
#if (JSON_GCC_VERSION >= 40300)
|
||||
#define json_hot __attribute__ ((hot))
|
||||
#define json_cold __attribute__ ((cold))
|
||||
#define json_pure json_nothrow __attribute__ ((pure, hot))
|
||||
#define json_malloc_attr json_nothrow __attribute__ ((malloc, hot))
|
||||
|
||||
/* Can do priorities */
|
||||
#if (JSON_WRITE_PRIORITY == HIGH)
|
||||
#define json_write_priority __attribute__ ((hot))
|
||||
#elif (JSON_WRITE_PRIORITY == LOW)
|
||||
#define json_write_priority __attribute__ ((cold))
|
||||
#else
|
||||
#define json_write_priority
|
||||
#endif
|
||||
|
||||
#if (JSON_READ_PRIORITY == HIGH)
|
||||
#define json_read_priority __attribute__ ((hot))
|
||||
#elif (JSON_READ_PRIORITY == LOW)
|
||||
#define json_read_priority __attribute__ ((cold))
|
||||
#else
|
||||
#define json_read_priority
|
||||
#endif
|
||||
|
||||
#define json_likely(x) __builtin_expect((long)((bool)(x)),1)
|
||||
#define json_unlikely(x) __builtin_expect((long)((bool)(x)),0)
|
||||
#else
|
||||
#if (JSON_GCC_VERSION >= 29600)
|
||||
#define json_pure json_nothrow __attribute__ ((pure))
|
||||
#define json_likely(x) __builtin_expect((long)((bool)(x)),1)
|
||||
#define json_unlikely(x) __builtin_expect((long)((bool)(x)),0)
|
||||
#else
|
||||
#define json_pure json_nothrow
|
||||
#define json_likely(x) x
|
||||
#define json_unlikely(x) x
|
||||
#endif
|
||||
|
||||
#define json_malloc_attr json_nothrow __attribute__ ((malloc))
|
||||
#define json_write_priority
|
||||
#define json_read_priority
|
||||
#define json_hot
|
||||
#define json_cold
|
||||
#endif
|
||||
|
||||
#define json_nothrow throw()
|
||||
#define json_throws(x) throw(x)
|
||||
|
||||
#ifdef JSON_LESS_MEMORY
|
||||
#define PACKED(x) :x __attribute__ ((packed))
|
||||
#define BITS(x) :x
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
36
src/libjson/_internal/Source/JSONDefs/Strings_Defs.h
Normal file
36
src/libjson/_internal/Source/JSONDefs/Strings_Defs.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
#ifndef STRINGS_DEFS_HEADER
|
||||
#define STRINGS_DEFS_HEADER
|
||||
|
||||
#include "../../../JSONOptions.h"
|
||||
|
||||
#ifdef JSON_UNICODE
|
||||
#define json_char wchar_t
|
||||
#define json_uchar wchar_t
|
||||
#ifdef __cplusplus
|
||||
#include <cwchar> /* need wide characters */
|
||||
#ifndef JSON_STRING_HEADER
|
||||
#include <string>
|
||||
#endif
|
||||
#else
|
||||
#include <wchar.h> /* need wide characters */
|
||||
#endif
|
||||
#define JSON_TEXT(s) L ## s
|
||||
#define json_strlen wcslen
|
||||
#define json_strcmp wcscmp
|
||||
#else
|
||||
#define json_char char
|
||||
#define json_uchar unsigned char
|
||||
#ifdef __cplusplus
|
||||
#ifndef JSON_STRING_HEADER
|
||||
#include <string>
|
||||
#endif
|
||||
#else
|
||||
#include <string.h> /* still need it for strlen and such */
|
||||
#endif
|
||||
#define JSON_TEXT(s) s
|
||||
#define json_strlen strlen
|
||||
#define json_strcmp strcmp
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
26
src/libjson/_internal/Source/JSONDefs/Unknown_C.h
Normal file
26
src/libjson/_internal/Source/JSONDefs/Unknown_C.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
#ifndef JSON_UNKNOWN_C_HEADER
|
||||
#define JSON_UNKNOWN_C_HEADER
|
||||
|
||||
#if !defined(__GNUC__) && !defined(_MSC_VER)
|
||||
|
||||
#define json_deprecated(method, warning) method
|
||||
|
||||
#define json_nothrow
|
||||
#define json_throws(x)
|
||||
#define json_pure json_nothrow
|
||||
#define json_read_priority
|
||||
#define json_write_priority
|
||||
#define json_malloc_attr json_nothrow
|
||||
#define json_hot
|
||||
#define json_cold
|
||||
#define json_likely(x) x
|
||||
#define json_unlikely(x) x
|
||||
|
||||
#ifdef JSON_LESS_MEMORY
|
||||
#define PACKED(x) :x
|
||||
#define BITS(x) :x
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
26
src/libjson/_internal/Source/JSONDefs/Visual_C.h
Normal file
26
src/libjson/_internal/Source/JSONDefs/Visual_C.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
#ifndef JSON_VISUAL_C_HEADER
|
||||
#define JSON_VISUAL_C_HEADER
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
#define json_deprecated(method, warning) __declspec(deprecated(warning)) method
|
||||
|
||||
#define json_nothrow
|
||||
#define json_throws(x)
|
||||
#define json_pure json_nothrow
|
||||
#define json_read_priority
|
||||
#define json_write_priority
|
||||
#define json_malloc_attr json_nothrow
|
||||
#define json_hot
|
||||
#define json_cold
|
||||
#define json_likely(x) x
|
||||
#define json_unlikely(x) x
|
||||
|
||||
#ifdef JSON_LESS_MEMORY
|
||||
#define PACKED(x) :x
|
||||
#define BITS(x) :x
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
95
src/libjson/_internal/Source/JSONGlobals.h
Normal file
95
src/libjson/_internal/Source/JSONGlobals.h
Normal file
|
@ -0,0 +1,95 @@
|
|||
#ifndef JSON_GLOBALS_H
|
||||
#define JSON_GLOBALS_H
|
||||
|
||||
#include "JSONDefs.h"
|
||||
|
||||
/*
|
||||
* The use of singletons for globals makes globals not
|
||||
* actually be initialized until it is first needed, this
|
||||
* makes the library faster to load, and have a smaller
|
||||
* memory footprint
|
||||
*/
|
||||
|
||||
#define json_global_decl(TYPE, NAME, VALUE) \
|
||||
class jsonSingleton ## NAME { \
|
||||
public: \
|
||||
inline static TYPE & getValue() json_nothrow { \
|
||||
static jsonSingleton ## NAME single; \
|
||||
return single.val; \
|
||||
} \
|
||||
protected: \
|
||||
inline jsonSingleton ## NAME() json_nothrow : val(VALUE) {} \
|
||||
TYPE val; \
|
||||
}
|
||||
|
||||
#define json_global_decl_strconfig(TYPE, NAME, VALUE) \
|
||||
class jsonSingleton ## NAME { \
|
||||
public: \
|
||||
inline static TYPE & getValue() json_nothrow { \
|
||||
static jsonSingleton ## NAME single; \
|
||||
return single.val; \
|
||||
} \
|
||||
protected: \
|
||||
inline jsonSingleton ## NAME() json_nothrow { \
|
||||
const std::string tmp = std::string(VALUE); \
|
||||
val = json_string(tmp.begin(), tmp.end()); \
|
||||
} \
|
||||
TYPE val; \
|
||||
}
|
||||
|
||||
#define json_global(NAME) jsonSingleton ## NAME::getValue()
|
||||
|
||||
#include <string>
|
||||
json_global_decl(json_string, EMPTY_JSON_STRING, );
|
||||
json_global_decl(std::string, EMPTY_STD_STRING, );
|
||||
|
||||
json_global_decl(json_string, CONST_TRUE, JSON_TEXT("true"));
|
||||
json_global_decl(json_string, CONST_FALSE, JSON_TEXT("false"));
|
||||
json_global_decl(json_string, CONST_NULL, JSON_TEXT("null"));
|
||||
|
||||
#ifndef JSON_NEWLINE
|
||||
json_global_decl(json_string, NEW_LINE, JSON_TEXT("\n"));
|
||||
#else
|
||||
json_global_decl_strconfig(json_string, NEW_LINE, JSON_NEWLINE);
|
||||
#endif
|
||||
|
||||
#ifdef JSON_WRITE_BASH_COMMENTS
|
||||
json_global_decl(json_string, SINGLELINE_COMMENT, JSON_TEXT("#"));
|
||||
#else
|
||||
json_global_decl(json_string, SINGLELINE_COMMENT, JSON_TEXT("//"));
|
||||
#endif
|
||||
|
||||
#ifdef JSON_INDENT
|
||||
json_global_decl_strconfig(json_string, INDENT, JSON_INDENT);
|
||||
#endif
|
||||
|
||||
#ifdef JSON_MUTEX_CALLBACKS
|
||||
#include <map>
|
||||
json_global_decl(JSON_MAP(void *, unsigned int), MUTEX_MANAGER, );
|
||||
json_global_decl(JSON_MAP(int, JSON_MAP(void *, unsigned int) ), THREAD_LOCKS, );
|
||||
#endif
|
||||
|
||||
#ifdef JSON_LIBRARY
|
||||
#ifdef JSON_MEMORY_MANAGE
|
||||
#include "JSONMemory.h"
|
||||
json_global_decl(auto_expand, STRING_HANDLER, );
|
||||
json_global_decl(auto_expand_node, NODE_HANDLER, );
|
||||
#ifdef JSON_STREAM
|
||||
json_global_decl(auto_expand_stream, STREAM_HANDLER, );
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//These are common error responses
|
||||
json_global_decl(json_string, ERROR_TOO_LONG, JSON_TEXT("Exceeding JSON_SECURITY_MAX_STRING_LENGTH"));
|
||||
json_global_decl(json_string, ERROR_UNKNOWN_LITERAL, JSON_TEXT("Unknown JSON literal: "));
|
||||
json_global_decl(json_string, ERROR_NON_CONTAINER, JSON_TEXT("Calling container method on non-container: "));
|
||||
json_global_decl(json_string, ERROR_NON_ITERATABLE, JSON_TEXT("Calling iterator method on non-iteratable: "));
|
||||
json_global_decl(json_string, ERROR_NULL_IN_CHILDREN, JSON_TEXT("a null pointer within the children"));
|
||||
json_global_decl(json_string, ERROR_UNDEFINED, JSON_TEXT("Undefined results: "));
|
||||
json_global_decl(json_string, ERROR_LOWER_RANGE, JSON_TEXT(" is outside the lower range of "));
|
||||
json_global_decl(json_string, ERROR_UPPER_RANGE, JSON_TEXT(" is outside the upper range of "));
|
||||
json_global_decl(json_string, ERROR_NOT_BASE64, JSON_TEXT("Not base64"));
|
||||
json_global_decl(json_string, ERROR_OUT_OF_MEMORY, JSON_TEXT("Out of memory"));
|
||||
|
||||
#endif
|
214
src/libjson/_internal/Source/JSONIterators.cpp
Normal file
214
src/libjson/_internal/Source/JSONIterators.cpp
Normal file
|
@ -0,0 +1,214 @@
|
|||
#include "JSONNode.h"
|
||||
|
||||
#ifdef JSON_ITERATORS
|
||||
#ifdef JSON_REF_COUNT
|
||||
#define JSON_ASSERT_UNIQUE(x) JSON_ASSERT(internal -> refcount == 1, json_string(JSON_TEXT(x)) + JSON_TEXT(" in non single reference"))
|
||||
#else
|
||||
#define JSON_ASSERT_UNIQUE(x) (void)0
|
||||
#endif
|
||||
|
||||
#ifdef JSON_MUTEX_CALLBACKS
|
||||
#define JSON_MUTEX_COPY2 ,internal -> mylock
|
||||
#else
|
||||
#define JSON_MUTEX_COPY2
|
||||
#endif
|
||||
|
||||
JSONNode::json_iterator JSONNode::find(const json_string & name_t) json_nothrow {
|
||||
JSON_CHECK_INTERNAL();
|
||||
JSON_ASSERT(type() == JSON_NODE, json_global(ERROR_NON_ITERATABLE) + JSON_TEXT("find"));
|
||||
makeUniqueInternal();
|
||||
if (JSONNode ** res = internal -> at(name_t)){
|
||||
return ptr_to_json_iterator(res);
|
||||
}
|
||||
return end();
|
||||
}
|
||||
|
||||
#ifdef JSON_CASE_INSENSITIVE_FUNCTIONS
|
||||
JSONNode::json_iterator JSONNode::find_nocase(const json_string & name_t) json_nothrow {
|
||||
JSON_CHECK_INTERNAL();
|
||||
JSON_ASSERT(type() == JSON_NODE, json_global(ERROR_NON_ITERATABLE) + JSON_TEXT("find_nocase"));
|
||||
makeUniqueInternal();
|
||||
if (JSONNode ** res = internal -> at_nocase(name_t)){
|
||||
return ptr_to_json_iterator(res);
|
||||
}
|
||||
return end();
|
||||
}
|
||||
#endif
|
||||
|
||||
JSONNode::json_iterator JSONNode::erase(json_iterator pos) json_nothrow {
|
||||
JSON_CHECK_INTERNAL();
|
||||
JSON_ASSERT(type() == JSON_NODE || type() == JSON_ARRAY, json_global(ERROR_NON_ITERATABLE) + JSON_TEXT("erase"));
|
||||
JSON_ASSERT_UNIQUE("erase 1");
|
||||
JSON_ASSERT_SAFE(pos < end(), JSON_TEXT("erase out of range"), return end(););
|
||||
JSON_ASSERT_SAFE(pos >= begin(), JSON_TEXT("erase out of range"), return begin(););
|
||||
deleteJSONNode(*(json_iterator_ptr(pos)));
|
||||
internal -> CHILDREN -> erase(json_iterator_ptr(pos));
|
||||
return (empty()) ? end() : pos;
|
||||
}
|
||||
|
||||
JSONNode::json_iterator JSONNode::erase(json_iterator _start, const json_iterator & _end) json_nothrow {
|
||||
if (_start == _end) return _start;
|
||||
JSON_CHECK_INTERNAL();
|
||||
JSON_ASSERT(type() == JSON_NODE || type() == JSON_ARRAY, json_global(ERROR_NON_ITERATABLE) + JSON_TEXT("erase"));
|
||||
JSON_ASSERT_UNIQUE("erase 3");
|
||||
JSON_ASSERT_SAFE(_start <= end(), JSON_TEXT("erase out of lo range"), return end(););
|
||||
JSON_ASSERT_SAFE(_end <= end(), JSON_TEXT("erase out of hi range"), return end(););
|
||||
JSON_ASSERT_SAFE(_start >= begin(), JSON_TEXT("erase out of lo range"), return begin(););
|
||||
JSON_ASSERT_SAFE(_end >= begin(), JSON_TEXT("erase out of hi range"), return begin(););
|
||||
for (JSONNode ** pos = json_iterator_ptr(_start); pos < json_iterator_ptr(_end); ++pos){
|
||||
deleteJSONNode(*pos);
|
||||
}
|
||||
|
||||
internal -> CHILDREN -> erase(json_iterator_ptr(_start), (json_index_t)(json_iterator_ptr(_end) - json_iterator_ptr(_start)));
|
||||
return (empty()) ? end() : _start;
|
||||
}
|
||||
|
||||
#ifdef JSON_LIBRARY
|
||||
JSONNode::json_iterator JSONNode::insert(json_iterator pos, JSONNode * x) json_nothrow {
|
||||
#else
|
||||
JSONNode::json_iterator JSONNode::insert(json_iterator pos, const JSONNode & x) json_nothrow {
|
||||
#endif
|
||||
JSON_CHECK_INTERNAL();
|
||||
JSON_ASSERT(type() == JSON_NODE || type() == JSON_ARRAY, json_global(ERROR_NON_ITERATABLE) + JSON_TEXT("insert"));
|
||||
JSON_ASSERT_UNIQUE("insert 1");
|
||||
if (json_iterator_ptr(pos) >= internal -> CHILDREN -> end()){
|
||||
internal -> push_back(x);
|
||||
return end() - 1;
|
||||
}
|
||||
JSON_ASSERT_SAFE(pos >= begin(), JSON_TEXT("insert out of lo range"), return begin(););
|
||||
#ifdef JSON_LIBRARY
|
||||
internal -> CHILDREN -> insert(json_iterator_ptr(pos), x);
|
||||
#else
|
||||
internal -> CHILDREN -> insert(json_iterator_ptr(pos), newJSONNode(x));
|
||||
#endif
|
||||
return pos;
|
||||
}
|
||||
|
||||
JSONNode::json_iterator JSONNode::insertFFF(json_iterator pos, JSONNode ** const _start, JSONNode ** const _end) json_nothrow {
|
||||
JSON_CHECK_INTERNAL();
|
||||
JSON_ASSERT(type() == JSON_NODE || type() == JSON_ARRAY, json_global(ERROR_NON_ITERATABLE) + JSON_TEXT("insertFFF"));
|
||||
JSON_ASSERT_UNIQUE("insertFFF");
|
||||
JSON_ASSERT_SAFE(pos <= end(), JSON_TEXT("insert out of high range"), return end(););
|
||||
JSON_ASSERT_SAFE(pos >= begin(), JSON_TEXT("insert out of low range"), return begin(););
|
||||
const json_index_t num = (json_index_t)(_end - _start);
|
||||
json_auto<JSONNode *> mem(num);
|
||||
JSONNode ** runner = mem.ptr;
|
||||
for (JSONNode ** po = _start; po < _end; ++po){
|
||||
*runner++ = newJSONNode(*(*po) JSON_MUTEX_COPY2);
|
||||
}
|
||||
internal -> CHILDREN -> insert(json_iterator_ptr(pos), mem.ptr, num);
|
||||
return pos;
|
||||
}
|
||||
|
||||
#ifndef JSON_LIBRARY
|
||||
JSONNode::const_iterator JSONNode::find(const json_string & name_t) const json_nothrow {
|
||||
JSON_CHECK_INTERNAL();
|
||||
JSON_ASSERT(type() == JSON_NODE, json_global(ERROR_NON_ITERATABLE) + JSON_TEXT("find"));
|
||||
if (JSONNode ** res = internal -> at(name_t)){
|
||||
return JSONNode::const_iterator(res);
|
||||
}
|
||||
return JSONNode::const_iterator(internal -> end());
|
||||
}
|
||||
|
||||
#ifdef JSON_CASE_INSENSITIVE_FUNCTIONS
|
||||
JSONNode::const_iterator JSONNode::find_nocase(const json_string & name_t) const json_nothrow {
|
||||
JSON_CHECK_INTERNAL();
|
||||
JSON_ASSERT(type() == JSON_NODE, json_global(ERROR_NON_ITERATABLE) + JSON_TEXT("find_nocase"));
|
||||
if (JSONNode ** res = internal -> at_nocase(name_t)){
|
||||
return JSONNode::const_iterator(res);
|
||||
}
|
||||
return JSONNode::const_iterator(internal -> end());
|
||||
}
|
||||
#endif
|
||||
|
||||
JSONNode::reverse_iterator JSONNode::erase(reverse_iterator pos) json_nothrow {
|
||||
JSON_CHECK_INTERNAL();
|
||||
JSON_ASSERT(type() == JSON_NODE || type() == JSON_ARRAY, json_global(ERROR_NON_ITERATABLE) + JSON_TEXT("erase"));
|
||||
JSON_ASSERT_UNIQUE("erase 2");
|
||||
JSON_ASSERT_SAFE(pos < rend(), JSON_TEXT("erase out of range"), return rend(););
|
||||
JSON_ASSERT_SAFE(pos >= rbegin(), JSON_TEXT("erase out of range"), return rbegin(););
|
||||
deleteJSONNode(*(pos.it));
|
||||
internal -> CHILDREN -> erase(pos.it);
|
||||
return (empty()) ? rend() : pos + 1;
|
||||
}
|
||||
|
||||
JSONNode::reverse_iterator JSONNode::erase(reverse_iterator _start, const reverse_iterator & _end) json_nothrow {
|
||||
if (_start == _end) return _start;
|
||||
JSON_CHECK_INTERNAL();
|
||||
JSON_ASSERT(type() == JSON_NODE || type() == JSON_ARRAY, json_global(ERROR_NON_ITERATABLE) + JSON_TEXT("erase"));
|
||||
JSON_ASSERT_UNIQUE("erase 4");
|
||||
JSON_ASSERT_SAFE(_start <= rend(), JSON_TEXT("erase out of lo range"), return rend(););
|
||||
JSON_ASSERT_SAFE(_end <= rend(), JSON_TEXT("erase out of hi range"), return rend(););
|
||||
JSON_ASSERT_SAFE(_start >= rbegin(), JSON_TEXT("erase out of lo range"), return rbegin(););
|
||||
JSON_ASSERT_SAFE(_end >= rbegin(), JSON_TEXT("erase out of hi range"), return rbegin(););
|
||||
for (JSONNode ** pos = _start.it; pos > _end.it; --pos){
|
||||
deleteJSONNode(*pos);
|
||||
}
|
||||
const json_index_t num = (json_index_t)(_start.it - _end.it);
|
||||
internal -> CHILDREN -> erase(_end.it + 1, num, _start.it);
|
||||
return (empty()) ? rend() : _start + num;
|
||||
}
|
||||
|
||||
JSONNode::reverse_iterator JSONNode::insert(reverse_iterator pos, const JSONNode & x) json_nothrow {
|
||||
JSON_CHECK_INTERNAL();
|
||||
JSON_ASSERT(type() == JSON_NODE || type() == JSON_ARRAY, json_global(ERROR_NON_ITERATABLE) + JSON_TEXT("insert"));
|
||||
JSON_ASSERT_UNIQUE("insert 1");
|
||||
if (pos.it < internal -> CHILDREN -> begin()){
|
||||
internal -> push_front(x);
|
||||
return rend() - 1;
|
||||
}
|
||||
JSON_ASSERT_SAFE(pos >= rbegin(), JSON_TEXT("insert out of range"), return rbegin(););
|
||||
internal -> CHILDREN -> insert(++pos.it, newJSONNode(x), true);
|
||||
return pos;
|
||||
}
|
||||
|
||||
JSONNode::reverse_iterator JSONNode::insertRFF(reverse_iterator pos, JSONNode ** const _start, JSONNode ** const _end) json_nothrow {
|
||||
JSON_CHECK_INTERNAL();
|
||||
JSON_ASSERT(type() == JSON_NODE || type() == JSON_ARRAY, json_global(ERROR_NON_ITERATABLE) + JSON_TEXT("insertRFF"));
|
||||
JSON_ASSERT_UNIQUE("insert RFF");
|
||||
JSON_ASSERT_SAFE(pos <= rend(), JSON_TEXT("insert out of range"), return rend(););
|
||||
JSON_ASSERT_SAFE(pos >= rbegin(), JSON_TEXT("insert out of range"), return rbegin(););
|
||||
const json_index_t num = (json_index_t)(_end - _start);
|
||||
json_auto<JSONNode *> mem(num);
|
||||
JSONNode ** runner = mem.ptr + num;
|
||||
for (JSONNode ** po = _start; po < _end; ++po){ //fill it backwards
|
||||
*(--runner) = newJSONNode(*(*po) JSON_MUTEX_COPY2);
|
||||
}
|
||||
internal -> CHILDREN -> insert(++pos.it, mem.ptr, num);
|
||||
return pos - num + 1;
|
||||
}
|
||||
|
||||
JSONNode::iterator JSONNode::insertFRR(json_iterator pos, JSONNode ** const _start, JSONNode ** const _end) json_nothrow {
|
||||
JSON_CHECK_INTERNAL();
|
||||
JSON_ASSERT(type() == JSON_NODE || type() == JSON_ARRAY, json_global(ERROR_NON_ITERATABLE) + JSON_TEXT("insertFRR"));
|
||||
JSON_ASSERT_UNIQUE("insert FRR");
|
||||
JSON_ASSERT_SAFE(pos <= end(), JSON_TEXT("insert out of range"), return end(););
|
||||
JSON_ASSERT_SAFE(pos >= begin(), JSON_TEXT("insert out of range"), return begin(););
|
||||
const json_index_t num = (json_index_t)(_start - _end);
|
||||
json_auto<JSONNode *> mem(num);
|
||||
JSONNode ** runner = mem.ptr;
|
||||
for (JSONNode ** po = _start; po > _end; --po){
|
||||
*runner++ = newJSONNode(*(*po) JSON_MUTEX_COPY2);
|
||||
}
|
||||
internal -> CHILDREN -> insert(pos.it, mem.ptr, num);
|
||||
return pos;
|
||||
}
|
||||
|
||||
JSONNode::reverse_iterator JSONNode::insertRRR(reverse_iterator pos, JSONNode ** const _start, JSONNode ** const _end) json_nothrow {
|
||||
JSON_CHECK_INTERNAL();
|
||||
JSON_ASSERT(type() == JSON_NODE || type() == JSON_ARRAY, json_global(ERROR_NON_ITERATABLE) + JSON_TEXT("insertRRR"));
|
||||
JSON_ASSERT_UNIQUE("insert RRR");
|
||||
JSON_ASSERT_SAFE(pos <= rend(), JSON_TEXT("insert out of range"), return rend(););
|
||||
JSON_ASSERT_SAFE(pos >= rbegin(), JSON_TEXT("insert out of range"), return rbegin(););
|
||||
const json_index_t num = (json_index_t)(_start - _end);
|
||||
json_auto<JSONNode *> mem(num);
|
||||
JSONNode ** runner = mem.ptr;
|
||||
for (JSONNode ** po = _start; po > _end; --po){
|
||||
*runner++ = newJSONNode(*(*po) JSON_MUTEX_COPY2);
|
||||
}
|
||||
internal -> CHILDREN -> insert(++pos.it, mem.ptr, num);
|
||||
return pos - num + 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
149
src/libjson/_internal/Source/JSONMemory.cpp
Normal file
149
src/libjson/_internal/Source/JSONMemory.cpp
Normal file
|
@ -0,0 +1,149 @@
|
|||
#include "JSONMemory.h"
|
||||
|
||||
#ifdef JSON_MEMORY_MANAGE
|
||||
#include "JSONNode.h"
|
||||
void auto_expand::purge(void) json_nothrow {
|
||||
for(JSON_MAP(void *, void *)::iterator i = mymap.begin(), en = mymap.end(); i != en; ++i){
|
||||
#if defined(JSON_DEBUG) || defined(JSON_SAFE)
|
||||
void * temp = (void*)i -> first; //because its pass by reference
|
||||
libjson_free<void>(temp);
|
||||
#else
|
||||
libjson_free<void>((void*)i -> first);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void auto_expand_node::purge(void) json_nothrow {
|
||||
for(JSON_MAP(void *, JSONNode *)::iterator i = mymap.begin(), en = mymap.end(); i != en; ++i){
|
||||
JSONNode::deleteJSONNode((JSONNode *)i -> second);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef JSON_STREAM
|
||||
#include "JSONStream.h"
|
||||
void auto_expand_stream::purge(void) json_nothrow {
|
||||
for(JSON_MAP(void *, JSONStream *)::iterator i = mymap.begin(), en = mymap.end(); i != en; ++i){
|
||||
JSONStream::deleteJSONStream((JSONStream *)i -> second);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(JSON_MEMORY_CALLBACKS) || defined(JSON_MEMORY_POOL)
|
||||
|
||||
#ifdef JSON_MEMORY_POOL
|
||||
#include "JSONMemoryPool.h"
|
||||
static bucket_pool_8<MEMPOOL_1, MEMPOOL_2, MEMPOOL_3, MEMPOOL_4, MEMPOOL_5, MEMPOOL_6, MEMPOOL_7, MEMPOOL_8> json_generic_mempool;
|
||||
|
||||
//This class is only meant to initiate the mempool to start out using std::malloc/realloc/free
|
||||
class mempool_callback_setter {
|
||||
public:
|
||||
LIBJSON_OBJECT(mempool_callback_setter);
|
||||
inline mempool_callback_setter(void) json_nothrow {
|
||||
` LIBJSON_CTOR;
|
||||
mempool_callbacks::set(std::malloc, std::realloc, std::free);
|
||||
}
|
||||
private:
|
||||
inline mempool_callback_setter(const mempool_callback_setter & o);
|
||||
inline mempool_callback_setter & operator = (const mempool_callback_setter & o);
|
||||
};
|
||||
static mempool_callback_setter __mempoolcallbacksetter;
|
||||
#endif
|
||||
|
||||
#include "JSONSingleton.h"
|
||||
|
||||
void * JSONMemory::json_malloc(size_t siz) json_nothrow {
|
||||
#ifdef JSON_MEMORY_POOL
|
||||
return json_generic_mempool.allocate(siz);
|
||||
#else
|
||||
if (json_malloc_t callback = JSONSingleton<json_malloc_t>::get()){
|
||||
#if(defined(JSON_DEBUG) && (!defined(JSON_MEMORY_CALLBACKS))) //in debug mode without mem callback, see if the malloc was successful
|
||||
void * result = callback(siz);
|
||||
JSON_ASSERT(result, JSON_TEXT("Out of memory"));
|
||||
return result;
|
||||
#else
|
||||
return callback(siz);
|
||||
#endif
|
||||
}
|
||||
#if(defined(JSON_DEBUG) && (!defined(JSON_MEMORY_CALLBACKS))) //in debug mode without mem callback, see if the malloc was successful
|
||||
void * result = std::malloc(siz);
|
||||
JSON_ASSERT(result, JSON_TEXT("Out of memory"));
|
||||
return result;
|
||||
#else
|
||||
return std::malloc(siz);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void JSONMemory::json_free(void * ptr) json_nothrow {
|
||||
#ifdef JSON_MEMORY_POOL
|
||||
json_generic_mempool.deallocate(ptr);
|
||||
#else
|
||||
if (json_free_t callback = JSONSingleton<json_free_t>::get()){
|
||||
callback(ptr);
|
||||
} else {
|
||||
std::free(ptr);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void * JSONMemory::json_realloc(void * ptr, size_t siz) json_nothrow {
|
||||
#ifdef JSON_MEMORY_POOL
|
||||
return json_generic_mempool.reallocate(ptr, siz);
|
||||
#else
|
||||
if (json_realloc_t callback = JSONSingleton<json_realloc_t>::get()){
|
||||
#if(defined(JSON_DEBUG) && (!defined(JSON_MEMORY_CALLBACKS))) //in debug mode without mem callback, see if the malloc was successful
|
||||
void * result = callback(ptr, siz);
|
||||
JSON_ASSERT(result, JSON_TEXT("Out of memory"));
|
||||
return result;
|
||||
#else
|
||||
return callback(ptr, siz);
|
||||
#endif
|
||||
}
|
||||
#if(defined(JSON_DEBUG) && (!defined(JSON_MEMORY_CALLBACKS))) //in debug mode without mem callback, see if the malloc was successful
|
||||
void * result = std::realloc(ptr, siz);
|
||||
JSON_ASSERT(result, JSON_TEXT("Out of memory"));
|
||||
return result;
|
||||
#else
|
||||
return std::realloc(ptr, siz);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef JSON_MEMORY_POOL
|
||||
//it is okay to pass null to these callbacks, no make sure they function exists
|
||||
static void * malloc_proxy(size_t siz) json_nothrow {
|
||||
if (json_malloc_t callback = JSONSingleton<json_malloc_t>::get()){
|
||||
return callback(siz);
|
||||
}
|
||||
return std::malloc(siz);
|
||||
}
|
||||
|
||||
static void * realloc_proxy(void * ptr, size_t siz) json_nothrow {
|
||||
if (json_realloc_t callback = JSONSingleton<json_realloc_t>::get()){
|
||||
return callback(ptr, siz);
|
||||
}
|
||||
return std::realloc(ptr, siz);
|
||||
}
|
||||
|
||||
static void free_proxy(void * ptr){
|
||||
if (json_free_t callback = JSONSingleton<json_free_t>::get()){
|
||||
callback(ptr);
|
||||
} else {
|
||||
std::free(ptr);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void JSONMemory::registerMemoryCallbacks(json_malloc_t mal, json_realloc_t real, json_free_t fre) json_nothrow {
|
||||
JSONSingleton<json_malloc_t>::set(mal);
|
||||
JSONSingleton<json_realloc_t>::set(real);
|
||||
JSONSingleton<json_free_t>::set(fre);
|
||||
#ifdef JSON_MEMORY_POOL
|
||||
mempool_callbacks::set(malloc_proxy, realloc_proxy, free_proxy);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#endif
|
175
src/libjson/_internal/Source/JSONMemory.h
Normal file
175
src/libjson/_internal/Source/JSONMemory.h
Normal file
|
@ -0,0 +1,175 @@
|
|||
#ifndef JSON_MEMORY_H
|
||||
#define JSON_MEMORY_H
|
||||
|
||||
#include <cstdlib> //for malloc, realloc, and free
|
||||
#include <cstring> //for memmove
|
||||
#include "JSONDebug.h"
|
||||
|
||||
#if defined(JSON_DEBUG) || defined(JSON_SAFE)
|
||||
#define JSON_FREE_PASSTYPE &
|
||||
#else
|
||||
#define JSON_FREE_PASSTYPE
|
||||
#endif
|
||||
|
||||
#if defined(JSON_MEMORY_CALLBACKS) || defined(JSON_MEMORY_POOL)
|
||||
class JSONMemory {
|
||||
public:
|
||||
static void * json_malloc(size_t siz) json_malloc_attr;
|
||||
static void * json_realloc(void * ptr, size_t siz) json_malloc_attr;
|
||||
static void json_free(void * ptr) json_nothrow;
|
||||
static void registerMemoryCallbacks(json_malloc_t mal, json_realloc_t real, json_free_t fre) json_nothrow json_cold;
|
||||
private:
|
||||
JSONMemory(void);
|
||||
};
|
||||
|
||||
template <typename T> static inline T * json_malloc(size_t count) json_malloc_attr;
|
||||
template <typename T> static inline T * json_malloc(size_t count) json_nothrow {
|
||||
return (T *)JSONMemory::json_malloc(sizeof(T) * count);
|
||||
}
|
||||
|
||||
template <typename T> static inline T * json_realloc(T * ptr, size_t count) json_malloc_attr;
|
||||
template <typename T> static inline T * json_realloc(T * ptr, size_t count) json_nothrow {
|
||||
return (T *)JSONMemory::json_realloc(ptr, sizeof(T) * count);
|
||||
}
|
||||
|
||||
template <typename T> static inline void libjson_free(T * JSON_FREE_PASSTYPE ptr) json_nothrow {
|
||||
JSONMemory::json_free(ptr);
|
||||
#if defined(JSON_DEBUG) || defined(JSON_SAFE) //in debug or safe mode, set the pointer to 0 so that it can't be used again
|
||||
ptr = 0;
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
|
||||
template <typename T> static inline T * json_malloc(size_t count) json_malloc_attr;
|
||||
template <typename T> static inline T * json_malloc(size_t count) json_nothrow {
|
||||
#ifdef JSON_DEBUG //in debug mode, see if the malloc was successful
|
||||
void * result = std::malloc(count * sizeof(T));
|
||||
JSON_ASSERT(result != 0, JSON_TEXT("Out of memory"));
|
||||
#ifdef JSON_NULL_MEMORY
|
||||
std::memset(result, '\0', count * sizeof(T));
|
||||
#endif
|
||||
return (T *)result;
|
||||
#else
|
||||
return (T *)std::malloc(count * sizeof(T));
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename T> static inline void libjson_free(T * JSON_FREE_PASSTYPE ptr) json_nothrow {
|
||||
std::free(ptr);
|
||||
#if defined(JSON_DEBUG) || defined(JSON_SAFE) //in debug or safe mode, set the pointer to 0 so that it can't be used again
|
||||
ptr = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename T> static inline T * json_realloc(T * ptr, size_t count) json_malloc_attr;
|
||||
template <typename T> static inline T * json_realloc(T * ptr, size_t count) json_nothrow {
|
||||
#ifdef JSON_DEBUG //in debug mode, check the results of realloc to be sure it was successful
|
||||
void * result = std::realloc(ptr, count * sizeof(T));
|
||||
JSON_ASSERT(result != 0, JSON_TEXT("Out of memory"));
|
||||
return (T *)result;
|
||||
#else
|
||||
return (T *)std::realloc(ptr, count * sizeof(T));
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef JSON_MEMORY_MANAGE
|
||||
#include <map>
|
||||
class JSONNode;
|
||||
struct auto_expand {
|
||||
public:
|
||||
LIBJSON_OBJECT(auto_expand);
|
||||
auto_expand(void) json_nothrow : mymap(){ LIBJSON_CTOR;}
|
||||
~auto_expand(void) json_nothrow { purge(); LIBJSON_DTOR; }
|
||||
void purge(void) json_nothrow;
|
||||
inline void clear(void) json_nothrow { purge(); mymap.clear(); }
|
||||
inline void * insert(void * ptr) json_nothrow { mymap[ptr] = ptr; return ptr; }
|
||||
inline void remove(void * ptr) json_nothrow {
|
||||
JSON_MAP(void *, void *)::iterator i = mymap.find(ptr);
|
||||
JSON_ASSERT(i != mymap.end(), JSON_TEXT("Removing a non-managed item"));
|
||||
mymap.erase(i);
|
||||
}
|
||||
JSON_MAP(void *, void *) mymap;
|
||||
private:
|
||||
auto_expand(const auto_expand &);
|
||||
auto_expand & operator = (const auto_expand &);
|
||||
};
|
||||
|
||||
struct auto_expand_node {
|
||||
public:
|
||||
LIBJSON_OBJECT(auto_expand_node);
|
||||
auto_expand_node(void) json_nothrow : mymap(){ LIBJSON_CTOR; }
|
||||
~auto_expand_node(void) json_nothrow { purge(); LIBJSON_DTOR; }
|
||||
void purge(void) json_nothrow ;
|
||||
inline void clear(void) json_nothrow { purge(); mymap.clear(); }
|
||||
inline JSONNode * insert(JSONNode * ptr) json_nothrow { mymap[ptr] = ptr; return ptr; }
|
||||
inline void remove(void * ptr) json_nothrow {
|
||||
JSON_MAP(void *, JSONNode *)::iterator i = mymap.find(ptr);
|
||||
if(json_likely(i != mymap.end())) mymap.erase(i);
|
||||
}
|
||||
JSON_MAP(void *, JSONNode *) mymap;
|
||||
private:
|
||||
auto_expand_node(const auto_expand_node &);
|
||||
auto_expand_node & operator = (const auto_expand_node &);
|
||||
};
|
||||
|
||||
#ifdef JSON_STREAM
|
||||
class JSONStream;
|
||||
struct auto_expand_stream {
|
||||
public:
|
||||
LIBJSON_OBJECT(auto_expand_stream);
|
||||
auto_expand_stream(void) json_nothrow : mymap(){ LIBJSON_CTOR; }
|
||||
~auto_expand_stream(void) json_nothrow { purge(); LIBJSON_DTOR; }
|
||||
void purge(void) json_nothrow ;
|
||||
inline void clear(void) json_nothrow { purge(); mymap.clear(); }
|
||||
inline JSONStream * insert(JSONStream * ptr) json_nothrow { mymap[ptr] = ptr; return ptr; }
|
||||
inline void remove(void * ptr) json_nothrow {
|
||||
JSON_MAP(void *, JSONStream *)::iterator i = mymap.find(ptr);
|
||||
if(json_likely(i != mymap.end())) mymap.erase(i);
|
||||
}
|
||||
JSON_MAP(void *, JSONStream *) mymap;
|
||||
private:
|
||||
auto_expand_stream(const auto_expand_stream &);
|
||||
auto_expand_stream & operator = (const auto_expand_stream &);
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//The C++ way, use an self-deleting pointer and let the optimizer decide when it gets destroyed
|
||||
template <typename T>
|
||||
class json_auto {
|
||||
public:
|
||||
LIBJSON_OBJECT(json_auto);
|
||||
json_auto(void) json_nothrow : ptr(0){ LIBJSON_CTOR; }
|
||||
json_auto(size_t count) json_nothrow : ptr(json_malloc<T>(count)){ LIBJSON_CTOR; }
|
||||
json_auto(T * arg) json_nothrow : ptr(arg){ LIBJSON_CTOR; }
|
||||
~json_auto(void) json_nothrow {
|
||||
libjson_free<T>(ptr);
|
||||
LIBJSON_DTOR;
|
||||
}
|
||||
inline void set(T * p) json_nothrow{
|
||||
ptr = p;
|
||||
}
|
||||
T * ptr;
|
||||
private:
|
||||
json_auto(const json_auto &);
|
||||
json_auto & operator =(const json_auto &);
|
||||
};
|
||||
|
||||
//Clears a string, if required, frees the memory
|
||||
static inline void clearString(json_string & str) json_nothrow {
|
||||
#ifdef JSON_LESS_MEMORY
|
||||
json_string().swap(str);
|
||||
#else
|
||||
str.clear();
|
||||
#endif
|
||||
}
|
||||
|
||||
//Shrinks a string
|
||||
static inline void shrinkString(json_string & str) json_nothrow {
|
||||
#ifdef JSON_LESS_MEMORY
|
||||
if (str.capacity() != str.length()) str = json_string(str.begin(), str.end());
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
38
src/libjson/_internal/Source/JSONMemoryPool.h
Normal file
38
src/libjson/_internal/Source/JSONMemoryPool.h
Normal file
|
@ -0,0 +1,38 @@
|
|||
#ifndef LIBJSON_GUARD_MEMORY_POOL_H
|
||||
#define LIBJSON_GUARD_MEMORY_POOL_H
|
||||
|
||||
#ifdef JSON_MEMORY_POOL
|
||||
|
||||
#include "../Dependencies/mempool++/mempool.h"
|
||||
|
||||
//this macro expands to the number of bytes a pool gets based on block size and number of 32s of the total pool it gets
|
||||
#define jsonPoolPart(bytes_per_block, thirty_seconds_of_mem) bytes_per_block, ((thirty_seconds_of_mem * JSON_MEMORY_POOL / 32) / bytes_per_block)
|
||||
|
||||
#ifdef JSON_PREPARSE
|
||||
#define NODEPOOL jsonPoolPart(sizeof(JSONNode), 1)
|
||||
#define INTERNALNODEPOOL jsonPoolPart(sizeof(internalJSONNode), 3)
|
||||
#define MEMPOOL_1 jsonPoolPart(8, 2)
|
||||
#define MEMPOOL_2 jsonPoolPart(16, 2)
|
||||
#define MEMPOOL_3 jsonPoolPart(32, 2)
|
||||
#define MEMPOOL_4 jsonPoolPart(64, 2)
|
||||
#define MEMPOOL_5 jsonPoolPart(128, 3)
|
||||
#define MEMPOOL_6 jsonPoolPart(256, 4)
|
||||
#define MEMPOOL_7 jsonPoolPart(512, 5)
|
||||
#define MEMPOOL_8 jsonPoolPart(4096, 8)
|
||||
#else
|
||||
#define NODEPOOL jsonPoolPart(sizeof(JSONNode), 2)
|
||||
#define INTERNALNODEPOOL jsonPoolPart(sizeof(internalJSONNode), 7)
|
||||
#define MEMPOOL_1 jsonPoolPart(8, 1)
|
||||
#define MEMPOOL_2 jsonPoolPart(16, 1)
|
||||
#define MEMPOOL_3 jsonPoolPart(32, 1)
|
||||
#define MEMPOOL_4 jsonPoolPart(64, 1)
|
||||
#define MEMPOOL_5 jsonPoolPart(128, 3)
|
||||
#define MEMPOOL_6 jsonPoolPart(256, 3)
|
||||
#define MEMPOOL_7 jsonPoolPart(512, 5)
|
||||
#define MEMPOOL_8 jsonPoolPart(4096, 8)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
356
src/libjson/_internal/Source/JSONNode.cpp
Normal file
356
src/libjson/_internal/Source/JSONNode.cpp
Normal file
|
@ -0,0 +1,356 @@
|
|||
#include "JSONNode.h"
|
||||
|
||||
#define IMPLEMENT_CTOR(type)\
|
||||
JSONNode::JSONNode(const json_string & name_t, type value_t) json_nothrow : internal(internalJSONNode::newInternal()){\
|
||||
internal -> Set(value_t);\
|
||||
internal -> setname(name_t);\
|
||||
LIBJSON_CTOR;\
|
||||
}
|
||||
IMPLEMENT_FOR_ALL_TYPES(IMPLEMENT_CTOR)
|
||||
|
||||
#ifndef JSON_LIBRARY
|
||||
JSONNode::JSONNode(const json_string & name_t, const json_char * value_t) json_nothrow : internal(internalJSONNode::newInternal()){
|
||||
internal -> Set(json_string(value_t));
|
||||
internal -> setname(name_t);
|
||||
LIBJSON_CTOR;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (defined(JSON_PREPARSE) && defined(JSON_READ_PRIORITY))
|
||||
#include "JSONWorker.h"
|
||||
JSONNode JSONNode::stringType(const json_string & str){
|
||||
JSONNode res;
|
||||
res.set_name(json_global(EMPTY_JSON_STRING));
|
||||
#ifdef JSON_LESS_MEMORY
|
||||
res = JSONWorker::FixString(str, res.internal, false);
|
||||
#else
|
||||
res = JSONWorker::FixString(str, res.internal -> _string_encoded);
|
||||
#endif
|
||||
return res;
|
||||
}
|
||||
|
||||
void JSONNode::set_name_(const json_string & newname) json_nothrow {
|
||||
#ifdef JSON_LESS_MEMORY
|
||||
json_string _newname = JSONWorker::FixString(newname, internal, true);
|
||||
#else
|
||||
json_string _newname = JSONWorker::FixString(newname, internal -> _name_encoded);
|
||||
#endif
|
||||
set_name(_newname);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef JSON_CASTABLE
|
||||
JSONNode JSONNode::as_node(void) const json_nothrow {
|
||||
JSON_CHECK_INTERNAL();
|
||||
if (type() == JSON_NODE){
|
||||
return *this;
|
||||
} else if (type() == JSON_ARRAY){
|
||||
JSONNode res(duplicate());
|
||||
res.internal -> _type = JSON_NODE;
|
||||
return res;
|
||||
}
|
||||
#ifdef JSON_MUTEX_CALLBACKS
|
||||
if (internal -> mylock != 0){
|
||||
JSONNode res(JSON_NODE);
|
||||
res.set_mutex(internal -> mylock);
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
return JSONNode(JSON_NODE);
|
||||
}
|
||||
|
||||
JSONNode JSONNode::as_array(void) const json_nothrow {
|
||||
JSON_CHECK_INTERNAL();
|
||||
if (type() == JSON_ARRAY){
|
||||
return *this;
|
||||
} else if (type() == JSON_NODE){
|
||||
JSONNode res(duplicate());
|
||||
res.internal -> _type = JSON_ARRAY;
|
||||
json_foreach(res.internal -> CHILDREN, runner){
|
||||
(*runner) -> clear_name();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
#ifdef JSON_MUTEX_CALLBACKS
|
||||
if (internal -> mylock != 0){
|
||||
JSONNode res(JSON_ARRAY);
|
||||
res.set_mutex(internal -> mylock);
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
return JSONNode(JSON_ARRAY);
|
||||
}
|
||||
|
||||
void JSONNode::cast(char newtype) json_nothrow {
|
||||
JSON_CHECK_INTERNAL();
|
||||
if (newtype == type()) return;
|
||||
|
||||
switch(newtype){
|
||||
case JSON_NULL:
|
||||
nullify();
|
||||
return;
|
||||
case JSON_STRING:
|
||||
*this = as_string();
|
||||
return;
|
||||
case JSON_NUMBER:
|
||||
*this = as_float();
|
||||
return;
|
||||
case JSON_BOOL:
|
||||
*this = as_bool();
|
||||
return;
|
||||
case JSON_ARRAY:
|
||||
*this = as_array();
|
||||
return;
|
||||
case JSON_NODE:
|
||||
*this = as_node();
|
||||
return;
|
||||
}
|
||||
JSON_FAIL(JSON_TEXT("cast to unknown type"));
|
||||
}
|
||||
#endif
|
||||
|
||||
//different just to supress the warning
|
||||
#ifdef JSON_REF_COUNT
|
||||
void JSONNode::merge(JSONNode & other) json_nothrow {
|
||||
#else
|
||||
void JSONNode::merge(JSONNode &) json_nothrow {
|
||||
#endif
|
||||
JSON_CHECK_INTERNAL();
|
||||
#ifdef JSON_REF_COUNT
|
||||
if (internal == other.internal) return;
|
||||
JSON_ASSERT(*this == other, JSON_TEXT("merging two nodes that aren't equal"));
|
||||
if (internal -> refcount < other.internal -> refcount){
|
||||
*this = other;
|
||||
} else {
|
||||
other = *this;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef JSON_REF_COUNT
|
||||
void JSONNode::merge(JSONNode * other) json_nothrow {
|
||||
JSON_CHECK_INTERNAL();
|
||||
if (internal == other -> internal) return;
|
||||
*other = *this;
|
||||
}
|
||||
|
||||
//different just to supress the warning
|
||||
void JSONNode::merge(unsigned int num, ...) json_nothrow {
|
||||
#else
|
||||
void JSONNode::merge(unsigned int, ...) json_nothrow {
|
||||
#endif
|
||||
JSON_CHECK_INTERNAL();
|
||||
#ifdef JSON_REF_COUNT
|
||||
va_list args;
|
||||
va_start(args, num);
|
||||
for(unsigned int i = 0; i < num; ++i){
|
||||
merge(va_arg(args, JSONNode*));
|
||||
}
|
||||
va_end(args);
|
||||
#endif
|
||||
}
|
||||
|
||||
JSONNode JSONNode::duplicate(void) const json_nothrow {
|
||||
JSON_CHECK_INTERNAL();
|
||||
JSONNode mycopy(*this);
|
||||
#ifdef JSON_REF_COUNT
|
||||
JSON_ASSERT(internal == mycopy.internal, JSON_TEXT("copy ctor failed to ref count correctly"));
|
||||
mycopy.makeUniqueInternal();
|
||||
#endif
|
||||
JSON_ASSERT(internal != mycopy.internal, JSON_TEXT("makeUniqueInternal failed"));
|
||||
return mycopy;
|
||||
}
|
||||
|
||||
JSONNode & JSONNode::at(json_index_t pos) json_throws(std::out_of_range) {
|
||||
JSON_CHECK_INTERNAL();
|
||||
if (json_unlikely(pos >= internal -> size())){
|
||||
JSON_FAIL(JSON_TEXT("at() out of bounds"));
|
||||
json_throw(std::out_of_range(json_global(EMPTY_STD_STRING)));
|
||||
}
|
||||
return (*this)[pos];
|
||||
}
|
||||
|
||||
const JSONNode & JSONNode::at(json_index_t pos) const json_throws(std::out_of_range) {
|
||||
JSON_CHECK_INTERNAL();
|
||||
if (json_unlikely(pos >= internal -> size())){
|
||||
JSON_FAIL(JSON_TEXT("at() const out of bounds"));
|
||||
json_throw(std::out_of_range(json_global(EMPTY_STD_STRING)));
|
||||
}
|
||||
return (*this)[pos];
|
||||
}
|
||||
|
||||
JSONNode & JSONNode::operator[](json_index_t pos) json_nothrow {
|
||||
JSON_CHECK_INTERNAL();
|
||||
JSON_ASSERT(pos < internal -> size(), JSON_TEXT("[] out of bounds"));
|
||||
makeUniqueInternal();
|
||||
return *(internal -> at(pos));
|
||||
}
|
||||
|
||||
const JSONNode & JSONNode::operator[](json_index_t pos) const json_nothrow {
|
||||
JSON_CHECK_INTERNAL();
|
||||
JSON_ASSERT(pos < internal -> size(), JSON_TEXT("[] const out of bounds"));
|
||||
return *(internal -> at(pos));
|
||||
}
|
||||
|
||||
JSONNode & JSONNode::at(const json_string & name_t) json_throws(std::out_of_range) {
|
||||
JSON_CHECK_INTERNAL();
|
||||
JSON_ASSERT(type() == JSON_NODE, json_global(ERROR_NON_ITERATABLE) + JSON_TEXT("at"));
|
||||
makeUniqueInternal();
|
||||
if (JSONNode ** res = internal -> at(name_t)){
|
||||
return *(*res);
|
||||
}
|
||||
JSON_FAIL(json_string(JSON_TEXT("at could not find child by name: ")) + name_t);
|
||||
json_throw(std::out_of_range(json_global(EMPTY_STD_STRING)));
|
||||
}
|
||||
|
||||
const JSONNode & JSONNode::at(const json_string & name_t) const json_throws(std::out_of_range) {
|
||||
JSON_CHECK_INTERNAL();
|
||||
JSON_ASSERT(type() == JSON_NODE, json_global(ERROR_NON_ITERATABLE) + JSON_TEXT("at"));
|
||||
if (JSONNode ** res = internal -> at(name_t)){
|
||||
return *(*res);
|
||||
}
|
||||
JSON_FAIL(json_string(JSON_TEXT("at const could not find child by name: ")) + name_t);
|
||||
json_throw(std::out_of_range(json_global(EMPTY_STD_STRING)));
|
||||
}
|
||||
|
||||
#ifdef JSON_CASE_INSENSITIVE_FUNCTIONS
|
||||
JSONNode & JSONNode::at_nocase(const json_string & name_t) json_throws(std::out_of_range) {
|
||||
JSON_CHECK_INTERNAL();
|
||||
JSON_ASSERT(type() == JSON_NODE, json_global(ERROR_NON_ITERATABLE) + JSON_TEXT("at_nocase"));
|
||||
makeUniqueInternal();
|
||||
if (JSONNode ** res = internal -> at_nocase(name_t)){
|
||||
return *(*res);
|
||||
}
|
||||
JSON_FAIL(json_string(JSON_TEXT("at_nocase could not find child by name: ")) + name_t);
|
||||
json_throw(std::out_of_range(json_global(EMPTY_STD_STRING)));
|
||||
}
|
||||
|
||||
const JSONNode & JSONNode::at_nocase(const json_string & name_t) const json_throws(std::out_of_range) {
|
||||
JSON_CHECK_INTERNAL();
|
||||
JSON_ASSERT(type() == JSON_NODE, json_global(ERROR_NON_ITERATABLE) + JSON_TEXT("at_nocase"));
|
||||
if (JSONNode ** res = internal -> at_nocase(name_t)){
|
||||
return *(*res);
|
||||
}
|
||||
JSON_FAIL(json_string(JSON_TEXT("at_nocase const could not find child by name: ")) + name_t);
|
||||
json_throw(std::out_of_range(json_global(EMPTY_STD_STRING)));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef JSON_LIBRARY
|
||||
struct auto_delete {
|
||||
public:
|
||||
auto_delete(JSONNode * node) json_nothrow : mynode(node){};
|
||||
~auto_delete(void) json_nothrow { JSONNode::deleteJSONNode(mynode); };
|
||||
JSONNode * mynode;
|
||||
private:
|
||||
auto_delete(const auto_delete &);
|
||||
auto_delete & operator = (const auto_delete &);
|
||||
};
|
||||
#endif
|
||||
|
||||
JSONNode JSON_PTR_LIB JSONNode::pop_back(json_index_t pos) json_throws(std::out_of_range) {
|
||||
JSON_CHECK_INTERNAL();
|
||||
if (json_unlikely(pos >= internal -> size())){
|
||||
JSON_FAIL(JSON_TEXT("pop_back out of bounds"));
|
||||
json_throw(std::out_of_range(json_global(EMPTY_STD_STRING)));
|
||||
}
|
||||
makeUniqueInternal();
|
||||
#ifdef JSON_LIBRARY
|
||||
return internal -> pop_back(pos);
|
||||
#else
|
||||
auto_delete temp(internal -> pop_back(pos));
|
||||
return *temp.mynode;
|
||||
#endif
|
||||
}
|
||||
|
||||
JSONNode JSON_PTR_LIB JSONNode::pop_back(const json_string & name_t) json_throws(std::out_of_range) {
|
||||
JSON_CHECK_INTERNAL();
|
||||
JSON_ASSERT(type() == JSON_NODE, json_global(ERROR_NON_ITERATABLE) + JSON_TEXT("pop_back"));
|
||||
#ifdef JSON_LIBRARY
|
||||
return internal -> pop_back(name_t);
|
||||
#else
|
||||
if (JSONNode * res = internal -> pop_back(name_t)){
|
||||
auto_delete temp(res);
|
||||
return *(temp.mynode);
|
||||
}
|
||||
JSON_FAIL(json_string(JSON_TEXT("pop_back const could not find child by name: ")) + name_t);
|
||||
json_throw(std::out_of_range(json_global(EMPTY_STD_STRING)));
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef JSON_CASE_INSENSITIVE_FUNCTIONS
|
||||
JSONNode JSON_PTR_LIB JSONNode::pop_back_nocase(const json_string & name_t) json_throws(std::out_of_range) {
|
||||
JSON_CHECK_INTERNAL();
|
||||
JSON_ASSERT(type() == JSON_NODE, json_global(ERROR_NON_ITERATABLE) + JSON_TEXT("pop_back_no_case"));
|
||||
#ifdef JSON_LIBRARY
|
||||
return internal -> pop_back_nocase(name_t);
|
||||
#else
|
||||
if (JSONNode * res = internal -> pop_back_nocase(name_t)){
|
||||
auto_delete temp(res);
|
||||
return *(temp.mynode);
|
||||
}
|
||||
JSON_FAIL(json_string(JSON_TEXT("pop_back_nocase could not find child by name: ")) + name_t);
|
||||
json_throw(std::out_of_range(json_global(EMPTY_STD_STRING)));
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef JSON_MEMORY_POOL
|
||||
#include "JSONMemoryPool.h"
|
||||
memory_pool<NODEPOOL> json_node_mempool;
|
||||
#endif
|
||||
|
||||
void JSONNode::deleteJSONNode(JSONNode * ptr) json_nothrow {
|
||||
#ifdef JSON_MEMORY_POOL
|
||||
ptr -> ~JSONNode();
|
||||
json_node_mempool.deallocate((void*)ptr);
|
||||
#elif defined(JSON_MEMORY_CALLBACKS)
|
||||
ptr -> ~JSONNode();
|
||||
libjson_free<JSONNode>(ptr);
|
||||
#else
|
||||
delete ptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline JSONNode * _newJSONNode(const JSONNode & orig) {
|
||||
#ifdef JSON_MEMORY_POOL
|
||||
return new((JSONNode*)json_node_mempool.allocate()) JSONNode(orig);
|
||||
#elif defined(JSON_MEMORY_CALLBACKS)
|
||||
return new(json_malloc<JSONNode>(1)) JSONNode(orig);
|
||||
#else
|
||||
return new JSONNode(orig);
|
||||
#endif
|
||||
}
|
||||
|
||||
JSONNode * JSONNode::newJSONNode(const JSONNode & orig JSON_MUTEX_COPY_DECL) {
|
||||
#ifdef JSON_MUTEX_CALLBACKS
|
||||
if (parentMutex != 0){
|
||||
JSONNode * temp = _newJSONNode(orig);
|
||||
temp -> set_mutex(parentMutex);
|
||||
return temp;
|
||||
}
|
||||
#endif
|
||||
return _newJSONNode(orig);
|
||||
}
|
||||
|
||||
JSONNode * JSONNode::newJSONNode(internalJSONNode * internal_t) {
|
||||
#ifdef JSON_MEMORY_POOL
|
||||
return new((JSONNode*)json_node_mempool.allocate()) JSONNode(internal_t);
|
||||
#elif defined(JSON_MEMORY_CALLBACKS)
|
||||
return new(json_malloc<JSONNode>(1)) JSONNode(internal_t);
|
||||
#else
|
||||
return new JSONNode(internal_t);
|
||||
#endif
|
||||
}
|
||||
|
||||
JSONNode * JSONNode::newJSONNode_Shallow(const JSONNode & orig) {
|
||||
#ifdef JSON_MEMORY_POOL
|
||||
return new((JSONNode*)json_node_mempool.allocate()) JSONNode(true, const_cast<JSONNode &>(orig));
|
||||
#elif defined(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
|
||||
}
|
||||
|
||||
|
985
src/libjson/_internal/Source/JSONNode.h
Normal file
985
src/libjson/_internal/Source/JSONNode.h
Normal file
|
@ -0,0 +1,985 @@
|
|||
#ifndef JSONNODE_H
|
||||
#define JSONNODE_H
|
||||
|
||||
#include "JSONDebug.h" //for string type
|
||||
#include "internalJSONNode.h" //internal structure for json value
|
||||
#include <stdexcept>
|
||||
#include <cstdarg> //for the ... parameter
|
||||
|
||||
#ifdef JSON_BINARY
|
||||
#include "JSON_Base64.h"
|
||||
#endif
|
||||
|
||||
#ifdef JSON_LESS_MEMORY
|
||||
#ifdef __GNUC__
|
||||
#pragma pack(push, 1)
|
||||
#elif _MSC_VER
|
||||
#pragma pack(push, JSONNode_pack, 1)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef JSON_REF_COUNT
|
||||
#define makeUniqueInternal() (void)0
|
||||
#endif
|
||||
|
||||
#define JSON_CHECK_INTERNAL() JSON_ASSERT(internal != 0, JSON_TEXT("no internal"))
|
||||
|
||||
#ifdef JSON_MUTEX_CALLBACKS
|
||||
#define JSON_MUTEX_COPY_DECL ,void * parentMutex
|
||||
#define JSON_MUTEX_COPY_DECL2 ,void * parentMutex = 0
|
||||
#else
|
||||
#define JSON_MUTEX_COPY_DECL
|
||||
#define JSON_MUTEX_COPY_DECL2
|
||||
#endif
|
||||
|
||||
#ifdef JSON_LIBRARY
|
||||
#define JSON_PTR_LIB *
|
||||
#define JSON_NEW(x) JSONNode::newJSONNode_Shallow(x)
|
||||
|
||||
|
||||
#define DECLARE_FOR_ALL_TYPES(foo)\
|
||||
foo(json_int_t)json_nothrow;\
|
||||
foo(json_number) json_nothrow;\
|
||||
foo(bool) json_nothrow;\
|
||||
foo(const json_string &) json_nothrow;
|
||||
|
||||
#define DECLARE_FOR_ALL_CAST_TYPES_CONST(foo)\
|
||||
foo(json_int_t) const json_nothrow;\
|
||||
foo(json_number) const json_nothrow;\
|
||||
foo(bool) const json_nothrow;\
|
||||
foo(const json_string &) const json_nothrow;\
|
||||
|
||||
#define DECLARE_FOR_ALL_TYPES_CONST(foo)\
|
||||
DECLARE_FOR_ALL_CAST_TYPES_CONST(foo)\
|
||||
foo(const JSONNode &) const json_nothrow;
|
||||
|
||||
#define IMPLEMENT_FOR_ALL_NUMBERS(foo)\
|
||||
foo(json_int_t)\
|
||||
foo(json_number)
|
||||
|
||||
|
||||
#else
|
||||
#define JSON_PTR_LIB
|
||||
#define JSON_NEW(x) x
|
||||
|
||||
#ifdef JSON_ISO_STRICT
|
||||
#define DECLARE_FOR_LONG_LONG(foo)
|
||||
#define DECLARE_FOR_LONG_LONG_CONST(foo)
|
||||
#define IMPLEMENT_FOR_LONG_LONG(foo)
|
||||
#define DECLARE_FOR_LONG_DOUBLE(foo)
|
||||
#define DECLARE_FOR_LONG_DOUBLE_CONST(foo)
|
||||
#define IMPLEMENT_FOR_LONG_DOUBLE(foo)
|
||||
#else
|
||||
#define DECLARE_FOR_LONG_LONG(foo) foo(long long) json_nothrow; foo(unsigned long long) json_nothrow;
|
||||
#define DECLARE_FOR_LONG_LONG_CONST(foo) foo(long long) const json_nothrow; foo(unsigned long long) const json_nothrow;
|
||||
#define IMPLEMENT_FOR_LONG_LONG(foo) foo(long long) foo(unsigned long long)
|
||||
#define DECLARE_FOR_LONG_DOUBLE(foo) foo(long double) json_nothrow;
|
||||
#define DECLARE_FOR_LONG_DOUBLE_CONST(foo) foo(long double) const json_nothrow;
|
||||
#define IMPLEMENT_FOR_LONG_DOUBLE(foo) foo(long double)
|
||||
#endif
|
||||
|
||||
#define DECLARE_FOR_ALL_TYPES(foo)\
|
||||
foo(char) json_nothrow; foo(unsigned char) json_nothrow;\
|
||||
foo(short) json_nothrow; foo(unsigned short) json_nothrow;\
|
||||
foo(int) json_nothrow; foo(unsigned int) json_nothrow;\
|
||||
foo(long) json_nothrow; foo(unsigned long) json_nothrow;\
|
||||
foo(float) json_nothrow; foo(double) json_nothrow;\
|
||||
foo(bool) json_nothrow;\
|
||||
foo(const json_string &) json_nothrow;\
|
||||
foo(const json_char *) json_nothrow;\
|
||||
DECLARE_FOR_LONG_LONG(foo)\
|
||||
DECLARE_FOR_LONG_DOUBLE(foo)
|
||||
|
||||
#define DECLARE_FOR_ALL_CAST_TYPES_CONST(foo)\
|
||||
foo(char) const json_nothrow; foo(unsigned char) const json_nothrow;\
|
||||
foo(short) const json_nothrow; foo(unsigned short) const json_nothrow;\
|
||||
foo(int) const json_nothrow; foo(unsigned int) const json_nothrow;\
|
||||
foo(long) const json_nothrow; foo(unsigned long) const json_nothrow;\
|
||||
foo(float) const json_nothrow; foo(double) const json_nothrow;\
|
||||
foo(bool) const json_nothrow;\
|
||||
foo(const json_string &) const json_nothrow;\
|
||||
DECLARE_FOR_LONG_LONG_CONST(foo)\
|
||||
DECLARE_FOR_LONG_DOUBLE_CONST(foo)
|
||||
|
||||
#define DECLARE_FOR_ALL_TYPES_CONST(foo)\
|
||||
DECLARE_FOR_ALL_CAST_TYPES_CONST(foo)\
|
||||
foo(const JSONNode &) const json_nothrow;\
|
||||
foo(const json_char *) const json_nothrow;
|
||||
|
||||
#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)\
|
||||
IMPLEMENT_FOR_LONG_LONG(foo)\
|
||||
IMPLEMENT_FOR_LONG_DOUBLE(foo)
|
||||
|
||||
#endif
|
||||
|
||||
#define IMPLEMENT_FOR_ALL_TYPES(foo)\
|
||||
IMPLEMENT_FOR_ALL_NUMBERS(foo)\
|
||||
foo(const json_string &)\
|
||||
foo(bool)
|
||||
|
||||
/*
|
||||
This class is mostly just a wrapper class around internalJSONNode, this class keeps
|
||||
the reference count and handles copy on write and such. This class is also responsible
|
||||
for argument checking and throwing exceptions if needed.
|
||||
*/
|
||||
|
||||
|
||||
class JSONNode {
|
||||
public:
|
||||
LIBJSON_OBJECT(JSONNode);
|
||||
explicit JSONNode(char mytype = JSON_NODE) json_nothrow json_hot;
|
||||
#define DECLARE_CTOR(type) explicit JSONNode(const json_string & name_t, type value_t)
|
||||
DECLARE_FOR_ALL_TYPES(DECLARE_CTOR)
|
||||
|
||||
JSONNode(const JSONNode & orig) json_nothrow json_hot;
|
||||
~JSONNode(void) json_nothrow json_hot;
|
||||
|
||||
#if (defined(JSON_PREPARSE) && defined(JSON_READ_PRIORITY))
|
||||
static JSONNode stringType(const json_string & str);
|
||||
void set_name_(const json_string & newname) json_nothrow json_write_priority;
|
||||
#endif
|
||||
|
||||
json_index_t size(void) const json_nothrow json_read_priority;
|
||||
bool empty(void) const json_nothrow json_read_priority;
|
||||
void clear(void) json_nothrow json_cold;
|
||||
unsigned char type(void) const json_nothrow json_read_priority;
|
||||
|
||||
json_string name(void) const json_nothrow json_read_priority;
|
||||
void set_name(const json_string & newname) json_nothrow json_write_priority;
|
||||
#ifdef JSON_COMMENTS
|
||||
void set_comment(const json_string & comment) json_nothrow;
|
||||
json_string get_comment(void) const json_nothrow;
|
||||
#endif
|
||||
#if !defined(JSON_PREPARSE) && defined(JSON_READ_PRIORITY)
|
||||
void preparse(void) json_nothrow json_read_priority;
|
||||
#endif
|
||||
|
||||
|
||||
json_string as_string(void) const json_nothrow json_read_priority;
|
||||
json_int_t as_int(void) const json_nothrow json_read_priority;
|
||||
json_number as_float(void) const json_nothrow json_read_priority;
|
||||
bool as_bool(void) const json_nothrow json_read_priority;
|
||||
|
||||
#ifdef JSON_CASTABLE
|
||||
JSONNode as_node(void) const json_nothrow json_read_priority;
|
||||
JSONNode as_array(void) const json_nothrow json_read_priority;
|
||||
void cast(char newtype) json_nothrow;
|
||||
#endif
|
||||
|
||||
#ifdef JSON_BINARY
|
||||
std::string as_binary(void) const json_nothrow json_cold;
|
||||
void set_binary(const unsigned char * bin, size_t bytes) json_nothrow json_cold;
|
||||
#endif
|
||||
|
||||
JSONNode & at(json_index_t pos) json_throws(std::out_of_range);
|
||||
const JSONNode & at(json_index_t pos) const json_throws(std::out_of_range);
|
||||
|
||||
JSONNode & operator[](json_index_t pos) json_nothrow;
|
||||
const JSONNode & operator[](json_index_t pos) const json_nothrow;
|
||||
|
||||
JSONNode & at(const json_string & name_t) json_throws(std::out_of_range);
|
||||
const JSONNode & at(const json_string & name_t) const json_throws(std::out_of_range);
|
||||
#ifdef JSON_CASE_INSENSITIVE_FUNCTIONS
|
||||
JSONNode & at_nocase(const json_string & name_t) json_throws(std::out_of_range);
|
||||
const JSONNode & at_nocase(const json_string & name_t) const json_throws(std::out_of_range);
|
||||
#endif
|
||||
JSONNode & operator[](const json_string & name_t) json_nothrow;
|
||||
const JSONNode & operator[](const json_string & name_t) const json_nothrow;
|
||||
|
||||
#ifdef JSON_LIBRARY
|
||||
void push_back(JSONNode * node) json_nothrow;
|
||||
#else
|
||||
void push_back(const JSONNode & node) json_nothrow;
|
||||
#endif
|
||||
void reserve(json_index_t siz) json_nothrow;
|
||||
JSONNode JSON_PTR_LIB pop_back(json_index_t pos) json_throws(std::out_of_range);
|
||||
JSONNode JSON_PTR_LIB pop_back(const json_string & name_t) json_throws(std::out_of_range);
|
||||
#ifdef JSON_CASE_INSENSITIVE_FUNCTIONS
|
||||
JSONNode JSON_PTR_LIB pop_back_nocase(const json_string & name_t) json_throws(std::out_of_range);
|
||||
#endif
|
||||
|
||||
DECLARE_FOR_ALL_TYPES(JSONNode & operator =)
|
||||
JSONNode & operator = (const JSONNode &) json_nothrow;
|
||||
|
||||
DECLARE_FOR_ALL_TYPES_CONST(bool operator ==)
|
||||
DECLARE_FOR_ALL_TYPES_CONST(bool operator !=)
|
||||
|
||||
|
||||
void nullify(void) json_nothrow;
|
||||
void swap(JSONNode & other) json_nothrow;
|
||||
void merge(JSONNode & other) json_nothrow json_cold;
|
||||
void merge(unsigned int num, ...) json_nothrow json_cold;
|
||||
JSONNode duplicate(void) const json_nothrow;
|
||||
|
||||
|
||||
//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;
|
||||
struct const_iterator {
|
||||
inline const_iterator& operator ++(void) json_nothrow { ++it; return *this; }
|
||||
inline const_iterator& operator --(void) json_nothrow { --it; return *this; }
|
||||
inline const_iterator& operator +=(long i) json_nothrow { it += i; return *this; }
|
||||
inline const_iterator& operator -=(long i) json_nothrow { it -= i; return *this; }
|
||||
inline const_iterator operator ++(int) json_nothrow {
|
||||
const_iterator result(*this);
|
||||
++it;
|
||||
return result;
|
||||
}
|
||||
inline const_iterator operator --(int) json_nothrow {
|
||||
const_iterator result(*this);
|
||||
--it;
|
||||
return result;
|
||||
}
|
||||
inline const_iterator operator +(long i) const json_nothrow {
|
||||
const_iterator result(*this);
|
||||
result.it += i;
|
||||
return result;
|
||||
}
|
||||
inline const_iterator operator -(long i) const json_nothrow {
|
||||
const_iterator result(*this);
|
||||
result.it -= i;
|
||||
return result;
|
||||
}
|
||||
inline const JSONNode& operator [](size_t pos) const json_nothrow { return const_cast<const JSONNode&>(*it[pos]); };
|
||||
inline const JSONNode& operator *(void) const json_nothrow { return const_cast<const JSONNode&>(*(*it)); }
|
||||
inline const JSONNode* operator ->(void) const json_nothrow { return const_cast<const JSONNode*>(*it); }
|
||||
inline bool operator == (const const_iterator & other) const json_nothrow { return it == other.it; }
|
||||
inline bool operator != (const const_iterator & other) const json_nothrow { return it != other.it; }
|
||||
inline bool operator > (const const_iterator & other) const json_nothrow { return it > other.it; }
|
||||
inline bool operator >= (const const_iterator & other) const json_nothrow { return it >= other.it; }
|
||||
inline bool operator < (const const_iterator & other) const json_nothrow { return it < other.it; }
|
||||
inline bool operator <= (const const_iterator & other) const json_nothrow { return it <= other.it; }
|
||||
|
||||
inline bool operator == (const iterator & other) const json_nothrow { return it == other.it; }
|
||||
inline bool operator != (const iterator & other) const json_nothrow { return it != other.it; }
|
||||
inline bool operator > (const iterator & other) const json_nothrow { return it > other.it; }
|
||||
inline bool operator >= (const iterator & other) const json_nothrow { return it >= other.it; }
|
||||
inline bool operator < (const iterator & other) const json_nothrow { return it < other.it; }
|
||||
inline bool operator <= (const iterator & other) const json_nothrow { return it <= other.it; }
|
||||
|
||||
inline const_iterator & operator =(const const_iterator & orig) json_nothrow { it = orig.it; return *this; }
|
||||
const_iterator (const const_iterator & orig) json_nothrow : it(orig.it) {}
|
||||
private:
|
||||
JSONNode ** it;
|
||||
const_iterator(JSONNode ** starter) : it(starter) {}
|
||||
friend class JSONNode;
|
||||
friend struct iterator;
|
||||
};
|
||||
const_iterator begin(void) const json_nothrow;
|
||||
const_iterator end(void) const json_nothrow;
|
||||
|
||||
struct iterator {
|
||||
inline iterator& operator ++(void) json_nothrow { ++it; return *this; }
|
||||
inline iterator& operator --(void) json_nothrow { --it; return *this; }
|
||||
inline iterator& operator +=(long i) json_nothrow { it += i; return *this; }
|
||||
inline iterator& operator -=(long i) json_nothrow { it -= i; return *this; }
|
||||
inline iterator operator ++(int) json_nothrow {
|
||||
iterator result(*this);
|
||||
++it;
|
||||
return result;
|
||||
}
|
||||
inline iterator operator --(int) json_nothrow {
|
||||
iterator result(*this);
|
||||
--it;
|
||||
return result;
|
||||
}
|
||||
inline iterator operator +(long i) const json_nothrow {
|
||||
iterator result(*this);
|
||||
result.it += i;
|
||||
return result;
|
||||
}
|
||||
inline iterator operator -(long i) const json_nothrow {
|
||||
iterator result(*this);
|
||||
result.it -= i;
|
||||
return result;
|
||||
}
|
||||
inline JSONNode& operator [](size_t pos) const json_nothrow { return *it[pos]; };
|
||||
inline JSONNode& operator *(void) const json_nothrow { return *(*it); }
|
||||
inline JSONNode* operator ->(void) const json_nothrow { return *it; }
|
||||
inline bool operator == (const iterator & other) const json_nothrow { return it == other.it; }
|
||||
inline bool operator != (const iterator & other) const json_nothrow { return it != other.it; }
|
||||
inline bool operator > (const iterator & other) const json_nothrow { return it > other.it; }
|
||||
inline bool operator >= (const iterator & other) const json_nothrow { return it >= other.it; }
|
||||
inline bool operator < (const iterator & other) const json_nothrow { return it < other.it; }
|
||||
inline bool operator <= (const iterator & other) const json_nothrow { return it <= other.it; }
|
||||
inline iterator & operator = (const iterator & orig) json_nothrow { it = orig.it; return *this; }
|
||||
|
||||
inline bool operator == (const const_iterator & other) const json_nothrow { return it == other.it; }
|
||||
inline bool operator != (const const_iterator & other) const json_nothrow { return it != other.it; }
|
||||
inline bool operator > (const const_iterator & other) const json_nothrow { return it > other.it; }
|
||||
inline bool operator >= (const const_iterator & other) const json_nothrow { return it >= other.it; }
|
||||
inline bool operator < (const const_iterator & other) const json_nothrow { return it < other.it; }
|
||||
inline bool operator <= (const const_iterator & other) const json_nothrow { return it <= other.it; }
|
||||
inline iterator & operator = (const const_iterator & orig) json_nothrow { it = orig.it; return *this; }
|
||||
|
||||
iterator (const iterator & orig) json_nothrow : it(orig.it) {}
|
||||
inline operator const_iterator() const json_nothrow { return const_iterator(it); }
|
||||
private:
|
||||
JSONNode ** it;
|
||||
iterator(JSONNode ** starter) json_nothrow : it(starter) {}
|
||||
friend class JSONNode;
|
||||
friend struct const_iterator;
|
||||
};
|
||||
typedef iterator json_iterator;
|
||||
|
||||
struct reverse_iterator;
|
||||
struct reverse_const_iterator {
|
||||
inline reverse_const_iterator& operator ++(void) json_nothrow{ --it; return *this; }
|
||||
inline reverse_const_iterator& operator --(void) json_nothrow{ ++it; return *this; }
|
||||
inline reverse_const_iterator& operator +=(long i) json_nothrow{ it -= i; return *this; }
|
||||
inline reverse_const_iterator& operator -=(long i) json_nothrow{ it += i; return *this; }
|
||||
inline reverse_const_iterator operator ++(int) json_nothrow{
|
||||
reverse_const_iterator result(*this);
|
||||
--it;
|
||||
return result;
|
||||
}
|
||||
inline reverse_const_iterator operator --(int) json_nothrow{
|
||||
reverse_const_iterator result(*this);
|
||||
++it;
|
||||
return result;
|
||||
}
|
||||
inline reverse_const_iterator operator +(long i) const json_nothrow {
|
||||
reverse_const_iterator result(*this);
|
||||
result.it -= i;
|
||||
return result;
|
||||
}
|
||||
inline reverse_const_iterator operator -(long i) const json_nothrow {
|
||||
reverse_const_iterator result(*this);
|
||||
result.it += i;
|
||||
return result;
|
||||
}
|
||||
inline const JSONNode& operator [](size_t pos) const json_nothrow { return const_cast<const JSONNode&>(*it[pos]); };
|
||||
inline const JSONNode& operator *(void) const json_nothrow { return const_cast<const JSONNode&>(*(*it)); }
|
||||
inline const JSONNode* operator ->(void) const json_nothrow { return const_cast<const JSONNode*>(*it); }
|
||||
inline bool operator == (const reverse_const_iterator & other) const json_nothrow { return it == other.it; }
|
||||
inline bool operator != (const reverse_const_iterator & other) const json_nothrow { return it != other.it; }
|
||||
inline bool operator < (const reverse_const_iterator & other) const json_nothrow { return it > other.it; }
|
||||
inline bool operator <= (const reverse_const_iterator & other) const json_nothrow { return it >= other.it; }
|
||||
inline bool operator > (const reverse_const_iterator & other) const json_nothrow { return it < other.it; }
|
||||
inline bool operator >= (const reverse_const_iterator & other) const json_nothrow { return it <= other.it; }
|
||||
|
||||
inline bool operator == (const reverse_iterator & other) const json_nothrow { return it == other.it; }
|
||||
inline bool operator != (const reverse_iterator & other) const json_nothrow { return it != other.it; }
|
||||
inline bool operator < (const reverse_iterator & other) const json_nothrow { return it > other.it; }
|
||||
inline bool operator <= (const reverse_iterator & other) const json_nothrow { return it >= other.it; }
|
||||
inline bool operator > (const reverse_iterator & other) const json_nothrow { return it < other.it; }
|
||||
inline bool operator >= (const reverse_iterator & other) const json_nothrow { return it <= other.it; }
|
||||
|
||||
inline reverse_const_iterator & operator = (const reverse_const_iterator & orig) json_nothrow { it = orig.it; return *this; }
|
||||
reverse_const_iterator (const reverse_const_iterator & orig) json_nothrow : it(orig.it) {}
|
||||
private:
|
||||
JSONNode ** it;
|
||||
reverse_const_iterator(JSONNode ** starter) json_nothrow : it(starter) {}
|
||||
friend class JSONNode;
|
||||
friend struct reverse_iterator;
|
||||
};
|
||||
reverse_const_iterator rbegin(void) const json_nothrow;
|
||||
reverse_const_iterator rend(void) const json_nothrow;
|
||||
|
||||
struct reverse_iterator {
|
||||
inline reverse_iterator& operator ++(void) json_nothrow { --it; return *this; }
|
||||
inline reverse_iterator& operator --(void) json_nothrow { ++it; return *this; }
|
||||
inline reverse_iterator& operator +=(long i) json_nothrow { it -= i; return *this; }
|
||||
inline reverse_iterator& operator -=(long i) json_nothrow { it += i; return *this; }
|
||||
inline reverse_iterator operator ++(int) json_nothrow {
|
||||
reverse_iterator result(*this);
|
||||
--it;
|
||||
return result;
|
||||
}
|
||||
inline reverse_iterator operator --(int) json_nothrow {
|
||||
reverse_iterator result(*this);
|
||||
++it;
|
||||
return result;
|
||||
}
|
||||
inline reverse_iterator operator +(long i) const json_nothrow {
|
||||
reverse_iterator result(*this);
|
||||
result.it -= i;
|
||||
return result;
|
||||
}
|
||||
inline reverse_iterator operator -(long i) const json_nothrow {
|
||||
reverse_iterator result(*this);
|
||||
result.it += i;
|
||||
return result;
|
||||
}
|
||||
inline JSONNode& operator [](size_t pos) const json_nothrow { return *it[pos]; };
|
||||
inline JSONNode& operator *(void) const json_nothrow { return *(*it); }
|
||||
inline JSONNode* operator ->(void) const json_nothrow { return *it; }
|
||||
inline bool operator == (const reverse_iterator & other) const json_nothrow { return it == other.it; }
|
||||
inline bool operator != (const reverse_iterator & other) const json_nothrow { return it != other.it; }
|
||||
inline bool operator < (const reverse_iterator & other) const json_nothrow { return it > other.it; }
|
||||
inline bool operator <= (const reverse_iterator & other) const json_nothrow { return it >= other.it; }
|
||||
inline bool operator > (const reverse_iterator & other) const json_nothrow { return it < other.it; }
|
||||
inline bool operator >= (const reverse_iterator & other) const json_nothrow { return it <= other.it; }
|
||||
|
||||
inline bool operator == (const reverse_const_iterator & other) const json_nothrow { return it == other.it; }
|
||||
inline bool operator != (const reverse_const_iterator & other) const json_nothrow { return it != other.it; }
|
||||
inline bool operator < (const reverse_const_iterator & other) const json_nothrow { return it > other.it; }
|
||||
inline bool operator <= (const reverse_const_iterator & other) const json_nothrow { return it >= other.it; }
|
||||
inline bool operator > (const reverse_const_iterator & other) const json_nothrow { return it < other.it; }
|
||||
inline bool operator >= (const reverse_const_iterator & other) const json_nothrow { return it <= other.it; }
|
||||
|
||||
inline reverse_iterator & operator = (const reverse_iterator & orig) json_nothrow { it = orig.it; return *this; }
|
||||
reverse_iterator (const reverse_iterator & orig) json_nothrow : it(orig.it) {}
|
||||
inline operator reverse_const_iterator() const json_nothrow { return reverse_const_iterator(it); }
|
||||
private:
|
||||
JSONNode ** it;
|
||||
reverse_iterator(JSONNode ** starter) json_nothrow : it(starter) {}
|
||||
friend class JSONNode;
|
||||
friend struct reverse_const_iterator;
|
||||
};
|
||||
reverse_iterator rbegin(void) json_nothrow;
|
||||
reverse_iterator rend(void) json_nothrow;
|
||||
|
||||
const_iterator find(const json_string & name_t) const json_nothrow;
|
||||
#ifdef JSON_CASE_INSENSITIVE_FUNCTIONS
|
||||
const_iterator find_nocase(const json_string & name_t) const json_nothrow;
|
||||
#endif
|
||||
|
||||
reverse_iterator erase(reverse_iterator pos) json_nothrow;
|
||||
reverse_iterator erase(reverse_iterator start, const reverse_iterator & end) json_nothrow;
|
||||
|
||||
iterator insert(iterator pos, const JSONNode & x) json_nothrow;
|
||||
reverse_iterator insert(reverse_iterator pos, const JSONNode & x) json_nothrow;
|
||||
iterator insert(iterator pos, const reverse_iterator & _start, const reverse_iterator & _end) json_nothrow;
|
||||
reverse_iterator insert(reverse_iterator pos, const iterator & _start, const iterator & _end) json_nothrow;
|
||||
reverse_iterator insert(reverse_iterator pos, const reverse_iterator & _start, const reverse_iterator & _end) json_nothrow;
|
||||
|
||||
json_iterator insert(json_iterator pos, const const_iterator & _start, const const_iterator & _end) json_nothrow;
|
||||
reverse_iterator insert(reverse_iterator pos, const const_iterator & _start, const const_iterator & _end) json_nothrow;
|
||||
json_iterator insert(json_iterator pos, const reverse_const_iterator & _start, const reverse_const_iterator & _end) json_nothrow;
|
||||
reverse_iterator insert(reverse_iterator pos, const reverse_const_iterator & _start, const reverse_const_iterator & _end) json_nothrow;
|
||||
#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) json_nothrow;
|
||||
#endif
|
||||
|
||||
json_iterator begin(void) json_nothrow;
|
||||
json_iterator end(void) json_nothrow;
|
||||
|
||||
json_iterator find(const json_string & name_t) json_nothrow;
|
||||
#ifdef JSON_CASE_INSENSITIVE_FUNCTIONS
|
||||
json_iterator find_nocase(const json_string & name_t) json_nothrow;
|
||||
#endif
|
||||
json_iterator erase(json_iterator pos) json_nothrow;
|
||||
json_iterator erase(json_iterator start, const json_iterator & end) json_nothrow;
|
||||
json_iterator insert(json_iterator pos, const json_iterator & _start, const json_iterator & _end) json_nothrow;
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef JSON_MUTEX_CALLBACKS
|
||||
static void register_mutex_callbacks(json_mutex_callback_t lock, json_mutex_callback_t unlock, void * manager_lock) json_nothrow json_cold;
|
||||
#ifdef JSON_MUTEX_MANAGE
|
||||
static void register_mutex_destructor(json_mutex_callback_t destroy) json_nothrow json_cold;
|
||||
#endif
|
||||
static void set_global_mutex(void * mutex) json_nothrow json_cold;
|
||||
void set_mutex(void * mutex) json_nothrow json_cold;
|
||||
void lock(int thread) json_nothrow json_cold;
|
||||
void unlock(int thread) json_nothrow json_cold;
|
||||
struct auto_lock {
|
||||
public:
|
||||
auto_lock(JSONNode & node, int thread) json_nothrow: mynode(&node), mythread(thread){
|
||||
mynode -> lock(mythread);
|
||||
}
|
||||
auto_lock(JSONNode * node, int thread) json_nothrow: mynode(node), mythread(thread){
|
||||
mynode -> lock(mythread);
|
||||
}
|
||||
~auto_lock(void) json_nothrow{
|
||||
mynode -> unlock(mythread);
|
||||
}
|
||||
private:
|
||||
auto_lock & operator = (const auto_lock &);
|
||||
auto_lock(const auto_lock &);
|
||||
JSONNode * mynode;
|
||||
int mythread;
|
||||
};
|
||||
static void * getThisLock(JSONNode * pthis) json_nothrow json_cold;
|
||||
#endif
|
||||
|
||||
#ifdef JSON_WRITE_PRIORITY
|
||||
#ifdef JSON_LESS_MEMORY
|
||||
#define DEFAULT_APPROX_SIZE 8
|
||||
#define DEFAULT_APPROX_SIZE_FORMATTED 16
|
||||
#else
|
||||
#define DEFAULT_APPROX_SIZE 1024
|
||||
#define DEFAULT_APPROX_SIZE_FORMATTED 2048
|
||||
#endif
|
||||
json_string write(size_t approxsize = DEFAULT_APPROX_SIZE) const json_nothrow json_write_priority;
|
||||
json_string write_formatted(size_t approxsize = DEFAULT_APPROX_SIZE_FORMATTED) const json_nothrow json_write_priority;
|
||||
#endif
|
||||
|
||||
#ifdef JSON_DEBUG
|
||||
#ifndef JSON_LIBRARY
|
||||
JSONNode dump(void) const json_nothrow;
|
||||
#endif
|
||||
#endif
|
||||
static void deleteJSONNode(JSONNode * ptr) json_nothrow json_hot;
|
||||
static JSONNode * newJSONNode_Shallow(const JSONNode & orig) json_hot;
|
||||
|
||||
#define DECLARE_CAST_OP(type) operator type()
|
||||
//DECLARE_FOR_ALL_CAST_TYPES_CONST(DECLARE_CAST_OP)
|
||||
JSON_PRIVATE
|
||||
static JSONNode * newJSONNode(const JSONNode & orig JSON_MUTEX_COPY_DECL2) json_hot;
|
||||
static JSONNode * newJSONNode(internalJSONNode * internal_t) json_hot;
|
||||
#ifdef JSON_READ_PRIORITY
|
||||
//used by JSONWorker
|
||||
JSONNode(const json_string & unparsed) json_nothrow : internal(internalJSONNode::newInternal(unparsed)){ //root, specialized because it can only be array or node
|
||||
LIBJSON_CTOR;
|
||||
}
|
||||
#endif
|
||||
JSONNode(internalJSONNode * internal_t) json_nothrow : internal(internal_t){ //do not increment anything, this is only used in one case and it's already taken care of
|
||||
LIBJSON_CTOR;
|
||||
}
|
||||
JSONNode(bool, JSONNode & orig) json_nothrow json_hot;
|
||||
|
||||
void decRef(void) json_nothrow json_hot; //decrements internal's counter, deletes it if needed
|
||||
#ifdef JSON_REF_COUNT
|
||||
void makeUniqueInternal(void) json_nothrow; //makes internal it's own
|
||||
void merge(JSONNode * other) json_nothrow json_cold;
|
||||
#endif
|
||||
|
||||
#ifdef JSON_DEBUG
|
||||
#ifndef JSON_LIBRARY
|
||||
JSONNode dump(size_t & totalmemory) json_nothrow;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef JSON_ITERATORS
|
||||
#ifndef JSON_LIBRARY
|
||||
json_iterator insertFRR(json_iterator pos, JSONNode ** const _start, JSONNode ** const _end) json_nothrow;
|
||||
reverse_iterator insertRRR(reverse_iterator pos, JSONNode ** const _start, JSONNode ** const _end) json_nothrow;
|
||||
reverse_iterator insertRFF(reverse_iterator pos, JSONNode ** const _start, JSONNode ** const _end) json_nothrow;
|
||||
#endif
|
||||
json_iterator insertFFF(json_iterator pos, JSONNode ** const _start, JSONNode ** const _end) json_nothrow;
|
||||
#endif
|
||||
|
||||
inline void clear_name(void) json_nothrow {
|
||||
JSON_CHECK_INTERNAL();
|
||||
makeUniqueInternal();
|
||||
internal -> clearname();
|
||||
}
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#define CAST_OP(type)\
|
||||
inline JSONNode::operator type() const json_nothrow {\
|
||||
return static_cast<type>(*internal);\
|
||||
}
|
||||
//IMPLEMENT_FOR_ALL_TYPES(CAST_OP)
|
||||
|
||||
|
||||
inline JSONNode::JSONNode(char mytype) json_nothrow : 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"));
|
||||
LIBJSON_CTOR;
|
||||
}
|
||||
|
||||
inline JSONNode::JSONNode(const JSONNode & orig) json_nothrow : internal(orig.internal -> incRef()){
|
||||
LIBJSON_COPY_CTOR;
|
||||
}
|
||||
|
||||
//this allows a temp node to simply transfer its contents, even with ref counting off
|
||||
inline JSONNode::JSONNode(bool, JSONNode & orig) json_nothrow : internal(orig.internal){
|
||||
orig.internal = 0;
|
||||
LIBJSON_CTOR;
|
||||
}
|
||||
|
||||
inline JSONNode::~JSONNode(void) json_nothrow{
|
||||
if (internal != 0) decRef();
|
||||
LIBJSON_DTOR;
|
||||
}
|
||||
|
||||
inline json_index_t JSONNode::size(void) const json_nothrow {
|
||||
JSON_CHECK_INTERNAL();
|
||||
return internal -> size();
|
||||
}
|
||||
|
||||
inline bool JSONNode::empty(void) const json_nothrow {
|
||||
JSON_CHECK_INTERNAL();
|
||||
return internal -> empty();
|
||||
}
|
||||
|
||||
inline void JSONNode::clear(void) json_nothrow {
|
||||
JSON_CHECK_INTERNAL();
|
||||
if (!empty()){
|
||||
makeUniqueInternal();
|
||||
internal -> CHILDREN -> clear();
|
||||
}
|
||||
}
|
||||
|
||||
inline unsigned char JSONNode::type(void) const json_nothrow {
|
||||
JSON_CHECK_INTERNAL();
|
||||
return internal -> type();
|
||||
}
|
||||
|
||||
inline json_string JSONNode::name(void) const json_nothrow {
|
||||
JSON_CHECK_INTERNAL();
|
||||
return internal -> name();
|
||||
}
|
||||
|
||||
inline void JSONNode::set_name(const json_string & newname) json_nothrow{
|
||||
JSON_CHECK_INTERNAL();
|
||||
makeUniqueInternal();
|
||||
internal -> setname(newname);
|
||||
}
|
||||
|
||||
#ifdef JSON_COMMENTS
|
||||
inline void JSONNode::set_comment(const json_string & newname) json_nothrow{
|
||||
JSON_CHECK_INTERNAL();
|
||||
makeUniqueInternal();
|
||||
internal -> setcomment(newname);
|
||||
}
|
||||
|
||||
inline json_string JSONNode::get_comment(void) const json_nothrow {
|
||||
JSON_CHECK_INTERNAL();
|
||||
return internal -> getcomment();
|
||||
}
|
||||
#endif
|
||||
|
||||
//#ifdef JSON_DEPRECATED_FUNCTIONS
|
||||
inline json_string JSONNode::as_string(void) const json_nothrow {
|
||||
JSON_CHECK_INTERNAL();
|
||||
return static_cast<json_string>(*internal);
|
||||
}
|
||||
|
||||
inline json_int_t JSONNode::as_int(void) const json_nothrow {
|
||||
JSON_CHECK_INTERNAL();
|
||||
return static_cast<json_int_t>(*internal);
|
||||
}
|
||||
|
||||
inline json_number JSONNode::as_float(void) const json_nothrow {
|
||||
JSON_CHECK_INTERNAL();
|
||||
return static_cast<json_number>(*internal);
|
||||
}
|
||||
|
||||
inline bool JSONNode::as_bool(void) const json_nothrow {
|
||||
JSON_CHECK_INTERNAL();
|
||||
return static_cast<bool>(*internal);
|
||||
}
|
||||
//#endif
|
||||
|
||||
#ifdef JSON_BINARY
|
||||
inline void JSONNode::set_binary(const unsigned char * bin, size_t bytes) json_nothrow{
|
||||
JSON_CHECK_INTERNAL();
|
||||
*this = JSONBase64::json_encode64(bin, bytes);
|
||||
}
|
||||
|
||||
inline std::string JSONNode::as_binary(void) const json_nothrow {
|
||||
JSON_ASSERT_SAFE(type() == JSON_STRING, JSON_TEXT("using as_binary for a non-string type"), return json_global(EMPTY_STD_STRING););
|
||||
JSON_CHECK_INTERNAL();
|
||||
return JSONBase64::json_decode64(as_string());
|
||||
}
|
||||
#endif
|
||||
|
||||
inline JSONNode & JSONNode::operator[](const json_string & name_t) json_nothrow {
|
||||
JSON_CHECK_INTERNAL();
|
||||
makeUniqueInternal();
|
||||
return *(*(internal -> at(name_t)));
|
||||
}
|
||||
|
||||
inline const JSONNode & JSONNode::operator[](const json_string & name_t) const json_nothrow {
|
||||
JSON_CHECK_INTERNAL();
|
||||
return *(*(internal -> at(name_t)));
|
||||
}
|
||||
|
||||
#ifdef JSON_LIBRARY
|
||||
inline void JSONNode::push_back(JSONNode * child) json_nothrow{
|
||||
#else
|
||||
inline void JSONNode::push_back(const JSONNode & child) json_nothrow{
|
||||
#endif
|
||||
JSON_CHECK_INTERNAL();
|
||||
makeUniqueInternal();
|
||||
internal -> push_back(child);
|
||||
}
|
||||
|
||||
inline void JSONNode::reserve(json_index_t siz) json_nothrow{
|
||||
makeUniqueInternal();
|
||||
internal -> reserve(siz);
|
||||
}
|
||||
|
||||
inline JSONNode & JSONNode::operator = (const JSONNode & orig) json_nothrow {
|
||||
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_nothrow {
|
||||
JSON_CHECK_INTERNAL();
|
||||
*this = json_string(val);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define NODE_SET_TYPED(type)\
|
||||
inline JSONNode & JSONNode::operator = (type val) json_nothrow {\
|
||||
LIBJSON_ASSIGNMENT;\
|
||||
JSON_CHECK_INTERNAL();\
|
||||
makeUniqueInternal();\
|
||||
internal -> Set(val);\
|
||||
return *this;\
|
||||
}
|
||||
IMPLEMENT_FOR_ALL_TYPES(NODE_SET_TYPED)
|
||||
|
||||
|
||||
/*
|
||||
This section is the equality operators
|
||||
*/
|
||||
|
||||
#define NODE_CHECK_EQUALITY(type)\
|
||||
inline bool JSONNode::operator == (type val) const json_nothrow {\
|
||||
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_nothrow {
|
||||
JSON_CHECK_INTERNAL();
|
||||
return internal -> IsEqualTo(val);
|
||||
}
|
||||
|
||||
#ifndef JSON_LIBRARY
|
||||
inline bool JSONNode::operator == (const json_char * val) const json_nothrow {
|
||||
JSON_CHECK_INTERNAL();
|
||||
return *this == json_string(val);
|
||||
}
|
||||
#endif
|
||||
|
||||
inline bool JSONNode::operator == (bool val) const json_nothrow {
|
||||
JSON_CHECK_INTERNAL();
|
||||
return internal -> IsEqualTo(val);
|
||||
}
|
||||
inline bool JSONNode::operator == (const JSONNode & val) const json_nothrow {
|
||||
JSON_CHECK_INTERNAL();
|
||||
return internal -> IsEqualTo(val.internal);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
This section is the inequality operators
|
||||
*/
|
||||
|
||||
|
||||
#define NODE_CHECK_INEQUALITY(type)\
|
||||
inline bool JSONNode::operator != (type val) const json_nothrow {\
|
||||
JSON_CHECK_INTERNAL();\
|
||||
return !(*this == val);\
|
||||
}
|
||||
|
||||
IMPLEMENT_FOR_ALL_TYPES(NODE_CHECK_INEQUALITY)
|
||||
NODE_CHECK_INEQUALITY(const JSONNode &)
|
||||
#ifndef JSON_LIBRARY
|
||||
NODE_CHECK_INEQUALITY(const json_char * )
|
||||
#endif
|
||||
|
||||
inline void JSONNode::nullify(void) json_nothrow {
|
||||
JSON_CHECK_INTERNAL();
|
||||
makeUniqueInternal();
|
||||
internal -> Nullify();
|
||||
}
|
||||
|
||||
inline void JSONNode::swap(JSONNode & other) json_nothrow {
|
||||
JSON_CHECK_INTERNAL();
|
||||
internalJSONNode * temp = other.internal;
|
||||
other.internal = internal;
|
||||
internal = temp;
|
||||
JSON_CHECK_INTERNAL();
|
||||
}
|
||||
|
||||
inline void JSONNode::decRef(void) json_nothrow { //decrements internal's counter, deletes it if needed
|
||||
JSON_CHECK_INTERNAL();
|
||||
#ifdef JSON_REF_COUNT
|
||||
internal -> decRef();
|
||||
if (internal -> hasNoReferences()){
|
||||
internalJSONNode::deleteInternal(internal);
|
||||
}
|
||||
#else
|
||||
internalJSONNode::deleteInternal(internal);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef JSON_REF_COUNT
|
||||
inline void JSONNode::makeUniqueInternal() json_nothrow { //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_nothrow {
|
||||
JSON_CHECK_INTERNAL();
|
||||
JSON_ASSERT(type() == JSON_NODE || type() == JSON_ARRAY, json_global(ERROR_NON_ITERATABLE) + JSON_TEXT("begin"));
|
||||
makeUniqueInternal();
|
||||
return json_iterator(internal -> begin());
|
||||
}
|
||||
|
||||
inline JSONNode::json_iterator JSONNode::end(void) json_nothrow {
|
||||
JSON_CHECK_INTERNAL();
|
||||
JSON_ASSERT(type() == JSON_NODE || type() == JSON_ARRAY, json_global(ERROR_NON_ITERATABLE) + JSON_TEXT("end"));
|
||||
makeUniqueInternal();
|
||||
return json_iterator(internal -> end());
|
||||
}
|
||||
|
||||
#ifndef JSON_LIBRARY
|
||||
inline JSONNode::const_iterator JSONNode::begin(void) const json_nothrow {
|
||||
JSON_CHECK_INTERNAL();
|
||||
JSON_ASSERT(type() == JSON_NODE || type() == JSON_ARRAY, json_global(ERROR_NON_ITERATABLE) + JSON_TEXT("begin"));
|
||||
return JSONNode::const_iterator(internal -> begin());
|
||||
}
|
||||
|
||||
inline JSONNode::const_iterator JSONNode::end(void) const json_nothrow {
|
||||
JSON_CHECK_INTERNAL();
|
||||
JSON_ASSERT(type() == JSON_NODE || type() == JSON_ARRAY, json_global(ERROR_NON_ITERATABLE) + JSON_TEXT("end"));
|
||||
return JSONNode::const_iterator(internal -> end());
|
||||
}
|
||||
|
||||
inline JSONNode::reverse_iterator JSONNode::rbegin(void) json_nothrow {
|
||||
JSON_CHECK_INTERNAL();
|
||||
JSON_ASSERT(type() == JSON_NODE || type() == JSON_ARRAY, json_global(ERROR_NON_ITERATABLE) + JSON_TEXT("rbegin"));
|
||||
makeUniqueInternal();
|
||||
return JSONNode::reverse_iterator(internal -> end() - 1);
|
||||
}
|
||||
|
||||
inline JSONNode::reverse_iterator JSONNode::rend(void) json_nothrow {
|
||||
JSON_CHECK_INTERNAL();
|
||||
JSON_ASSERT(type() == JSON_NODE || type() == JSON_ARRAY, json_global(ERROR_NON_ITERATABLE) + JSON_TEXT("rend"));
|
||||
makeUniqueInternal();
|
||||
return JSONNode::reverse_iterator(internal -> begin() - 1);
|
||||
}
|
||||
|
||||
inline JSONNode::reverse_const_iterator JSONNode::rbegin(void) const json_nothrow {
|
||||
JSON_CHECK_INTERNAL();
|
||||
JSON_ASSERT(type() == JSON_NODE || type() == JSON_ARRAY, json_global(ERROR_NON_ITERATABLE) + JSON_TEXT("rbegin"));
|
||||
return JSONNode::reverse_const_iterator(internal -> end() - 1);
|
||||
}
|
||||
|
||||
inline JSONNode::reverse_const_iterator JSONNode::rend(void) const json_nothrow {
|
||||
JSON_CHECK_INTERNAL();
|
||||
JSON_ASSERT(type() == JSON_NODE || type() == JSON_ARRAY, json_global(ERROR_NON_ITERATABLE) + JSON_TEXT("rend"));
|
||||
return JSONNode::reverse_const_iterator(internal -> begin() - 1);
|
||||
}
|
||||
|
||||
inline JSONNode::iterator JSONNode::insert(json_iterator pos, const const_iterator & _start, const const_iterator & _end) json_nothrow {
|
||||
return insertFFF(pos, _start.it, _end.it);
|
||||
}
|
||||
|
||||
inline JSONNode::reverse_iterator JSONNode::insert(reverse_iterator pos, const const_iterator & _start, const const_iterator & _end) json_nothrow {
|
||||
return insertRFF(pos, _start.it, _end.it);
|
||||
}
|
||||
|
||||
inline JSONNode::reverse_iterator JSONNode::insert(reverse_iterator pos, const iterator & _start, const iterator & _end) json_nothrow {
|
||||
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) json_nothrow {
|
||||
return insertRRR(pos, _start.it, _end.it);
|
||||
}
|
||||
|
||||
inline JSONNode::reverse_iterator JSONNode::insert(reverse_iterator pos, const reverse_iterator & _start, const reverse_iterator & _end) json_nothrow {
|
||||
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) json_nothrow {
|
||||
return insertFRR(pos, _start.it, _end.it);
|
||||
}
|
||||
|
||||
inline JSONNode::iterator JSONNode::insert(iterator pos, const reverse_iterator & _start, const reverse_iterator & _end) json_nothrow {
|
||||
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) json_nothrow {
|
||||
return insertFFF(pos, json_iterator_ptr(_start), json_iterator_ptr(_end));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef JSON_WRITE_PRIORITY
|
||||
inline json_string JSONNode::write(size_t approxsize) const json_nothrow {
|
||||
JSON_CHECK_INTERNAL();
|
||||
JSON_ASSERT_SAFE(type() == JSON_NODE || type() == JSON_ARRAY, JSON_TEXT("Writing a non-writable node"), return json_global(EMPTY_JSON_STRING););
|
||||
json_string result;
|
||||
result.reserve(approxsize);
|
||||
internal -> Write(0xFFFFFFFF, true, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
inline json_string JSONNode::write_formatted(size_t approxsize) const json_nothrow {
|
||||
JSON_CHECK_INTERNAL();
|
||||
JSON_ASSERT_SAFE(type() == JSON_NODE || type() == JSON_ARRAY, JSON_TEXT("Writing a non-writable node"), return json_global(EMPTY_JSON_STRING););
|
||||
json_string result;
|
||||
result.reserve(approxsize);
|
||||
internal -> Write(0, true, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined(JSON_PREPARSE) && defined(JSON_READ_PRIORITY)
|
||||
inline void JSONNode::preparse(void) json_nothrow {
|
||||
JSON_CHECK_INTERNAL();
|
||||
internal -> preparse();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef JSON_DEBUG
|
||||
#ifndef JSON_LIBRARY
|
||||
inline JSONNode JSONNode::dump(void) const json_nothrow {
|
||||
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_nothrow {
|
||||
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
|
||||
|
||||
#ifdef JSON_LESS_MEMORY
|
||||
#ifdef __GNUC__
|
||||
#pragma pack(pop)
|
||||
#elif _MSC_VER
|
||||
#pragma pack(pop, JSONNode_pack)
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
203
src/libjson/_internal/Source/JSONNode_Mutex.cpp
Normal file
203
src/libjson/_internal/Source/JSONNode_Mutex.cpp
Normal file
|
@ -0,0 +1,203 @@
|
|||
#include "JSONNode.h"
|
||||
#include "JSONGlobals.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 {
|
||||
public:
|
||||
LIBJSON_OBJECT(AutoLock);
|
||||
AutoLock(void) json_nothrow {
|
||||
LIBJSON_CTOR;
|
||||
json_lock_callback(manager_mutex);
|
||||
}
|
||||
~AutoLock(void) json_nothrow {
|
||||
LIBJSON_DTOR;
|
||||
json_unlock_callback(manager_mutex);
|
||||
}
|
||||
private:
|
||||
AutoLock(const AutoLock &);
|
||||
AutoLock & operator = (const AutoLock &);
|
||||
};
|
||||
|
||||
#ifdef JSON_MUTEX_MANAGE
|
||||
json_mutex_callback_t json_destroy = 0;
|
||||
|
||||
//make sure that the global mutex is taken care of too
|
||||
struct auto_global {
|
||||
public:
|
||||
LIBJSON_OBJECT(auto_global;)
|
||||
auto_global(void) json_nothrow { LIBJSON_CTOR; }
|
||||
~auto_global(void) json_nothrow {
|
||||
LIBJSON_DTOR;
|
||||
if (global_mutex){
|
||||
JSON_ASSERT_SAFE(json_destroy != 0, JSON_TEXT("No json_destroy in mutex managed mode"), return;);
|
||||
json_destroy(global_mutex);
|
||||
}
|
||||
}
|
||||
private:
|
||||
auto_global(const auto_global &);
|
||||
auto_global & operator = (const auto_global &);
|
||||
};
|
||||
auto_global cleanupGlobal;
|
||||
#endif
|
||||
|
||||
void JSONNode::register_mutex_callbacks(json_mutex_callback_t lock, json_mutex_callback_t unlock, void * manager_lock) json_nothrow {
|
||||
json_lock_callback = lock;
|
||||
json_unlock_callback = unlock;
|
||||
manager_mutex = manager_lock;
|
||||
}
|
||||
|
||||
void JSONNode::set_global_mutex(void * mutex) json_nothrow {
|
||||
global_mutex = mutex;
|
||||
}
|
||||
|
||||
void JSONNode::set_mutex(void * mutex) json_nothrow {
|
||||
makeUniqueInternal();
|
||||
internal -> _set_mutex(mutex);
|
||||
}
|
||||
|
||||
void * JSONNode::getThisLock(JSONNode * pthis) json_nothrow {
|
||||
if (pthis -> internal -> mylock != 0){
|
||||
return pthis -> internal -> mylock;
|
||||
}
|
||||
JSON_ASSERT(global_mutex != 0, JSON_TEXT("No global_mutex")); //this is safe, because it's just goingi to return 0 anyway
|
||||
return global_mutex;
|
||||
}
|
||||
|
||||
void JSONNode::lock(int thread) json_nothrow {
|
||||
JSON_ASSERT_SAFE(json_lock_callback != 0, JSON_TEXT("No locking callback"), return;);
|
||||
|
||||
AutoLock lockControl;
|
||||
|
||||
//first, figure out what needs to be locked
|
||||
void * thislock = getThisLock(this);
|
||||
#ifdef JSON_SAFE
|
||||
if (json_unlikely(thislock == 0)) return;
|
||||
#endif
|
||||
|
||||
//make sure that the same thread isn't locking it more than once (possible due to complex ref counting)
|
||||
JSON_MAP(int, JSON_MAP(void *, unsigned int) )::iterator it = json_global(THREAD_LOCKS).find(thread);
|
||||
if (it == json_global(THREAD_LOCKS).end()){
|
||||
JSON_MAP(void *, unsigned int) newthread;
|
||||
newthread[thislock] = 1;
|
||||
json_global(THREAD_LOCKS).insert(std::pair<int, JSON_MAP(void *, unsigned int) >(thread, newthread));
|
||||
} else { //this thread already has some things locked, check if the current mutex is
|
||||
JSON_MAP(void *, unsigned int) & newthread = it -> second;
|
||||
JSON_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_nothrow{
|
||||
JSON_ASSERT_SAFE(json_unlock_callback != 0, 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 == 0) return;
|
||||
#endif
|
||||
|
||||
//get it out of the map
|
||||
JSON_MAP(int, JSON_MAP(void *, unsigned int) )::iterator it = json_global(THREAD_LOCKS).find(thread);
|
||||
JSON_ASSERT_SAFE(it != json_global(THREAD_LOCKS).end(), JSON_TEXT("thread unlocking something it didn't lock"), return;);
|
||||
|
||||
//get the mutex out of the thread
|
||||
JSON_MAP(void *, unsigned int) & newthread = it -> second;
|
||||
JSON_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_nothrow {
|
||||
json_destroy = destroy;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void internalJSONNode::_set_mutex(void * mutex, bool unset) json_nothrow {
|
||||
if (unset) _unset_mutex(); //for reference counting
|
||||
mylock = mutex;
|
||||
if (mutex != 0){
|
||||
#ifdef JSON_MUTEX_MANAGE
|
||||
JSON_MAP(void *, unsigned int)::iterator it = json_global(MUTEX_MANAGER).find(mutex);
|
||||
if (it == json_global(MUTEX_MANAGER).end()){
|
||||
json_global(MUTEX_MANAGER).insert(std::pair<void *, unsigned int>(mutex, 1));
|
||||
} else {
|
||||
++it -> second;
|
||||
}
|
||||
#endif
|
||||
if (isContainer()){
|
||||
json_foreach(CHILDREN, myrunner){
|
||||
(*myrunner) -> set_mutex(mutex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void internalJSONNode::_unset_mutex(void) json_nothrow {
|
||||
#ifdef JSON_MUTEX_MANAGE
|
||||
if (mylock != 0){
|
||||
JSON_MAP(void *, unsigned int)::iterator it = json_global(MUTEX_MANAGER).find(mylock);
|
||||
JSON_ASSERT_SAFE(it != json_global(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;);
|
||||
json_global(MUTEX_MANAGER).erase(it);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef JSON_DEBUG
|
||||
#ifndef JSON_LIBRARY
|
||||
JSONNode internalJSONNode::DumpMutex(void) const json_nothrow {
|
||||
JSONNode mut(JSON_NODE);
|
||||
mut.set_name(JSON_TEXT("mylock"));
|
||||
#ifdef JSON_MUTEX_MANAGE
|
||||
if (mylock != 0){
|
||||
mut.push_back(JSON_NEW(JSONNode(JSON_TEXT("this"), (long)mylock)));
|
||||
JSON_MAP(void *, unsigned int)::iterator it = json_global(MUTEX_MANAGER).find(mylock);
|
||||
if (it == json_global(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
|
499
src/libjson/_internal/Source/JSONPreparse.cpp
Normal file
499
src/libjson/_internal/Source/JSONPreparse.cpp
Normal file
|
@ -0,0 +1,499 @@
|
|||
/*
|
||||
* JSONPreparse.cpp
|
||||
* TestSuite
|
||||
*
|
||||
* Created by Wallace on 4/13/11.
|
||||
* Copyright 2011 Streamwide. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "JSONPreparse.h"
|
||||
|
||||
#if (defined(JSON_PREPARSE) && defined(JSON_READ_PRIORITY))
|
||||
|
||||
#ifdef JSON_COMMENTS
|
||||
json_string extractComment(json_string::const_iterator & ptr, json_string::const_iterator & end);
|
||||
json_string extractComment(json_string::const_iterator & ptr, json_string::const_iterator & end){
|
||||
json_string::const_iterator start;
|
||||
json_string result;
|
||||
looplabel:
|
||||
if (json_unlikely(((ptr != end) && (*ptr == JSON_TEMP_COMMENT_IDENTIFIER)))){
|
||||
start = ++ptr;
|
||||
for(; (ptr != end) && (*(ptr) != JSON_TEMP_COMMENT_IDENTIFIER); ++ptr){}
|
||||
result += json_string(start, ptr);
|
||||
if (json_unlikely(ptr == end)) return result;
|
||||
++ptr;
|
||||
if (json_unlikely(((ptr != end) && (*ptr == JSON_TEMP_COMMENT_IDENTIFIER)))){
|
||||
result += JSON_TEXT('\n');
|
||||
goto looplabel;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#define GET_COMMENT(x, y, name) json_string name = extractComment(x, y)
|
||||
#define RETURN_NODE(node, name){\
|
||||
JSONNode res = node;\
|
||||
res.set_comment(name);\
|
||||
return res;\
|
||||
}
|
||||
#define RETURN_NODE_NOCOPY(node, name){\
|
||||
node.set_comment(name);\
|
||||
return node;\
|
||||
}
|
||||
#define SET_COMMENT(node, name) node.set_comment(name)
|
||||
#define COMMENT_ARG(name) ,name
|
||||
#else
|
||||
#define GET_COMMENT(x, y, name) (void)0
|
||||
#define RETURN_NODE(node, name) return node
|
||||
#define RETURN_NODE_NOCOPY(node, name) return node
|
||||
#define SET_COMMENT(node, name) (void)0
|
||||
#define COMMENT_ARG(name)
|
||||
#endif
|
||||
|
||||
inline bool isHex(json_char c) json_pure;
|
||||
inline bool isHex(json_char c) json_nothrow {
|
||||
return (((c >= JSON_TEXT('0')) && (c <= JSON_TEXT('9'))) ||
|
||||
((c >= JSON_TEXT('A')) && (c <= JSON_TEXT('F'))) ||
|
||||
((c >= JSON_TEXT('a')) && (c <= JSON_TEXT('f'))));
|
||||
}
|
||||
|
||||
#ifdef JSON_STRICT
|
||||
#include "NumberToString.h"
|
||||
#endif
|
||||
|
||||
json_number FetchNumber(const json_string & _string) json_nothrow;
|
||||
json_number FetchNumber(const json_string & _string) json_nothrow {
|
||||
#ifdef JSON_STRICT
|
||||
return NumberToString::_atof(_string.c_str());
|
||||
#else
|
||||
#ifdef JSON_UNICODE
|
||||
const size_t len = _string.length();
|
||||
#if defined(_MSC_VER) && defined(JSON_SAFE)
|
||||
const size_t bytes = (len * (sizeof(json_char) / sizeof(char))) + 1;
|
||||
json_auto<char> temp(bytes);
|
||||
size_t res;
|
||||
errno_t err = std::wcstombs_s(&res, temp.ptr, bytes, _string.c_str(), len);
|
||||
if (err != 0){
|
||||
return (json_number)0.0;
|
||||
}
|
||||
#elif defined(JSON_SAFE)
|
||||
const size_t bytes = (len * (sizeof(json_char) / sizeof(char))) + 1;
|
||||
json_auto<char> temp(bytes);
|
||||
size_t res = std::wcstombs(temp.ptr, _string.c_str(), len);
|
||||
if (res == (size_t)-1){ //-1 is error code for this function
|
||||
return (json_number)0.0;
|
||||
}
|
||||
#else
|
||||
json_auto<char> temp(len + 1);
|
||||
size_t res = std::wcstombs(temp.ptr, _string.c_str(), len);
|
||||
#endif
|
||||
temp.ptr[res] = JSON_TEXT('\0');
|
||||
return (json_number)std::atof(temp.ptr);
|
||||
#else
|
||||
return (json_number)std::atof(_string.c_str());
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
JSONNode JSONPreparse::isValidNumber(json_string::const_iterator & ptr, json_string::const_iterator & end){
|
||||
//ptr points at the first character in the number
|
||||
//ptr will end up past the last character
|
||||
json_string::const_iterator start = ptr;
|
||||
bool decimal = false;
|
||||
bool scientific = false;
|
||||
|
||||
//first letter is weird
|
||||
switch(*ptr){
|
||||
#ifndef JSON_STRICT
|
||||
case JSON_TEXT('.'):
|
||||
decimal = true;
|
||||
break;
|
||||
case JSON_TEXT('+'):
|
||||
#endif
|
||||
|
||||
case JSON_TEXT('-'):
|
||||
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('8'):
|
||||
case JSON_TEXT('9'):
|
||||
break;
|
||||
case JSON_TEXT('0'):
|
||||
++ptr;
|
||||
switch(*ptr){
|
||||
case JSON_TEXT('.'):
|
||||
decimal = true;
|
||||
break;
|
||||
case JSON_TEXT('e'):
|
||||
case JSON_TEXT('E'):
|
||||
scientific = true;
|
||||
++ptr;
|
||||
if (ptr == end) throw false;
|
||||
switch(*ptr){
|
||||
case JSON_TEXT('-'):
|
||||
case JSON_TEXT('+'):
|
||||
case JSON_TEXT('0'):
|
||||
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('8'):
|
||||
case JSON_TEXT('9'):
|
||||
break;
|
||||
default:
|
||||
throw false;
|
||||
}
|
||||
break;
|
||||
|
||||
#ifndef JSON_STRICT
|
||||
case JSON_TEXT('x'):
|
||||
while(isHex(*++ptr)){};
|
||||
return JSONNode(json_global(EMPTY_JSON_STRING), FetchNumber(json_string(start, end - 1)));
|
||||
#ifdef JSON_OCTAL
|
||||
#ifdef __GNUC__
|
||||
case JSON_TEXT('0') ... JSON_TEXT('7'): //octal
|
||||
#else
|
||||
case JSON_TEXT('0'):
|
||||
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'):
|
||||
#endif
|
||||
while((*++ptr >= JSON_TEXT('0')) && (*ptr <= JSON_TEXT('7'))){};
|
||||
if ((*ptr != JSON_TEXT('8')) && (*ptr != JSON_TEXT('9'))){
|
||||
return JSONNode(json_global(EMPTY_JSON_STRING), FetchNumber(json_string(start, ptr - 1)));
|
||||
}
|
||||
throw false;
|
||||
case JSON_TEXT('8'):
|
||||
case JSON_TEXT('9'):
|
||||
break;
|
||||
#else
|
||||
#ifdef __GNUC__
|
||||
case JSON_TEXT('0') ... JSON_TEXT('9'):
|
||||
#else
|
||||
case JSON_TEXT('0'):
|
||||
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('8'):
|
||||
case JSON_TEXT('9'):
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
#else
|
||||
#ifdef __GNUC__
|
||||
case JSON_TEXT('0') ... JSON_TEXT('9'):
|
||||
#else
|
||||
case JSON_TEXT('0'):
|
||||
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('8'):
|
||||
case JSON_TEXT('9'):
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
default: //just a 0
|
||||
return JSONNode(json_global(EMPTY_JSON_STRING), FetchNumber(json_string(start, ptr - 1)));;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw false;
|
||||
}
|
||||
++ptr;
|
||||
|
||||
//next digits
|
||||
while (true){
|
||||
switch(*ptr){
|
||||
case JSON_TEXT('.'):
|
||||
if (json_unlikely(decimal)) throw false; //multiple decimals
|
||||
if (json_unlikely(scientific)) throw false;
|
||||
decimal = true;
|
||||
break;
|
||||
case JSON_TEXT('e'):
|
||||
case JSON_TEXT('E'):
|
||||
if (json_likely(scientific)) throw false;
|
||||
scientific = true;
|
||||
++ptr;
|
||||
switch(*ptr){
|
||||
case JSON_TEXT('-'):
|
||||
case JSON_TEXT('+'):
|
||||
#ifdef __GNUC__
|
||||
case JSON_TEXT('0') ... JSON_TEXT('9'):
|
||||
#else
|
||||
case JSON_TEXT('0'):
|
||||
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('8'):
|
||||
case JSON_TEXT('9'):
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
throw false;
|
||||
}
|
||||
break;
|
||||
#ifdef __GNUC__
|
||||
case JSON_TEXT('0') ... JSON_TEXT('9'):
|
||||
#else
|
||||
case JSON_TEXT('0'):
|
||||
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('8'):
|
||||
case JSON_TEXT('9'):
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
return JSONNode(json_global(EMPTY_JSON_STRING), FetchNumber(json_string(start, ptr)));;
|
||||
}
|
||||
++ptr;
|
||||
}
|
||||
throw false;
|
||||
}
|
||||
|
||||
#ifndef JSON_STRICT
|
||||
#define LETTERCASE(x, y)\
|
||||
case JSON_TEXT(x):\
|
||||
case JSON_TEXT(y)
|
||||
#define LETTERCHECK(x, y)\
|
||||
if (json_unlikely((*++ptr != JSON_TEXT(x)) && (*ptr != JSON_TEXT(y)))) throw false
|
||||
#else
|
||||
#define LETTERCASE(x, y)\
|
||||
case JSON_TEXT(x)
|
||||
#define LETTERCHECK(x, y)\
|
||||
if (json_unlikely(*++ptr != JSON_TEXT(x))) throw false
|
||||
#endif
|
||||
JSONNode JSONPreparse::isValidMember(json_string::const_iterator & ptr, json_string::const_iterator & end){
|
||||
//ptr is on the first character of the member
|
||||
//ptr will end up immediately after the last character in the member
|
||||
if (ptr == end) throw false;
|
||||
|
||||
switch(*ptr){
|
||||
case JSON_TEXT('\"'):{
|
||||
return JSONNode::stringType(isValidString(++ptr, end));
|
||||
}
|
||||
case JSON_TEXT('{'):
|
||||
return isValidObject(++ptr, end);
|
||||
case JSON_TEXT('['):
|
||||
return isValidArray(++ptr, end);
|
||||
LETTERCASE('t', 'T'):
|
||||
LETTERCHECK('r', 'R');
|
||||
LETTERCHECK('u', 'U');
|
||||
LETTERCHECK('e', 'E');
|
||||
++ptr;
|
||||
return JSONNode(json_global(EMPTY_JSON_STRING), true);
|
||||
LETTERCASE('f', 'F'):
|
||||
LETTERCHECK('a', 'A');
|
||||
LETTERCHECK('l', 'L');
|
||||
LETTERCHECK('s', 'S');
|
||||
LETTERCHECK('e', 'E');
|
||||
++ptr;
|
||||
return JSONNode(json_global(EMPTY_JSON_STRING), false);
|
||||
LETTERCASE('n', 'N'):
|
||||
LETTERCHECK('u', 'U');
|
||||
LETTERCHECK('l', 'L');
|
||||
LETTERCHECK('l', 'L');
|
||||
++ptr;
|
||||
return JSONNode(JSON_NULL);
|
||||
#ifndef JSON_STRICT
|
||||
case JSON_TEXT('}'): //null in libjson
|
||||
case JSON_TEXT(']'): //null in libjson
|
||||
case JSON_TEXT(','): //null in libjson
|
||||
return JSONNode(JSON_NULL);
|
||||
#endif
|
||||
}
|
||||
//a number
|
||||
return isValidNumber(ptr, end);
|
||||
}
|
||||
|
||||
json_string JSONPreparse::isValidString(json_string::const_iterator & ptr, json_string::const_iterator & end){
|
||||
//ptr is pointing to the first character after the quote
|
||||
//ptr will end up behind the closing "
|
||||
json_string::const_iterator start = ptr;
|
||||
|
||||
while(ptr != end){
|
||||
switch(*ptr){
|
||||
case JSON_TEXT('\\'):
|
||||
switch(*(++ptr)){
|
||||
case JSON_TEXT('\"'):
|
||||
case JSON_TEXT('\\'):
|
||||
case JSON_TEXT('/'):
|
||||
case JSON_TEXT('b'):
|
||||
case JSON_TEXT('f'):
|
||||
case JSON_TEXT('n'):
|
||||
case JSON_TEXT('r'):
|
||||
case JSON_TEXT('t'):
|
||||
break;
|
||||
case JSON_TEXT('u'):
|
||||
if (json_unlikely(!isHex(*++ptr))) throw false;
|
||||
if (json_unlikely(!isHex(*++ptr))) throw false;
|
||||
//fallthrough to \x
|
||||
#ifndef JSON_STRICT
|
||||
case JSON_TEXT('x'): //hex
|
||||
#endif
|
||||
if (json_unlikely(!isHex(*++ptr))) throw false;
|
||||
if (json_unlikely(!isHex(*++ptr))) throw false;
|
||||
break;
|
||||
#ifndef JSON_OCTAL
|
||||
#ifdef __GNUC__
|
||||
case JSON_TEXT('0') ... JSON_TEXT('7'): //octal
|
||||
#else
|
||||
case JSON_TEXT('0'):
|
||||
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'):
|
||||
#endif
|
||||
if (json_unlikely((*++ptr < JSON_TEXT('0')) || (*ptr > JSON_TEXT('7')))) throw false;
|
||||
if (json_unlikely((*++ptr < JSON_TEXT('0')) || (*ptr > JSON_TEXT('7')))) throw false;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
throw false;
|
||||
}
|
||||
break;
|
||||
case JSON_TEXT('\"'):
|
||||
return json_string(start, ptr++);
|
||||
}
|
||||
++ptr;
|
||||
}
|
||||
throw false;
|
||||
}
|
||||
|
||||
void JSONPreparse::isValidNamedObject(json_string::const_iterator & ptr, json_string::const_iterator & end, JSONNode & parent COMMENT_PARAM(comment)) {
|
||||
//ptr should be right before the string name
|
||||
{
|
||||
json_string _name = isValidString(++ptr, end);
|
||||
if (json_unlikely(*ptr++ != JSON_TEXT(':'))) throw false;
|
||||
JSONNode res = isValidMember(ptr, end);
|
||||
res.set_name_(_name);
|
||||
SET_COMMENT(res, comment);
|
||||
#ifdef JSON_LIBRARY
|
||||
parent.push_back(&res);
|
||||
#else
|
||||
parent.push_back(res);
|
||||
#endif
|
||||
}
|
||||
if (ptr == end) throw false;
|
||||
switch(*ptr){
|
||||
case JSON_TEXT(','):
|
||||
++ptr;
|
||||
{
|
||||
GET_COMMENT(ptr, end, nextcomment);
|
||||
isValidNamedObject(ptr, end, parent COMMENT_ARG(nextcomment)); //will handle all of them
|
||||
}
|
||||
return;
|
||||
case JSON_TEXT('}'):
|
||||
++ptr;
|
||||
return;
|
||||
default:
|
||||
throw false;
|
||||
}
|
||||
}
|
||||
|
||||
JSONNode JSONPreparse::isValidObject(json_string::const_iterator & ptr, json_string::const_iterator & end) {
|
||||
//ptr should currently be pointing past the {, so this must be the start of a name, or the closing }
|
||||
//ptr will end up past the last }
|
||||
JSONNode res(JSON_NODE);
|
||||
GET_COMMENT(ptr, end, comment);
|
||||
switch(*ptr){
|
||||
case JSON_TEXT('\"'):
|
||||
isValidNamedObject(ptr, end, res COMMENT_ARG(comment));
|
||||
return res;
|
||||
case JSON_TEXT('}'):
|
||||
++ptr;
|
||||
return res;
|
||||
default:
|
||||
throw false;
|
||||
}
|
||||
}
|
||||
|
||||
void pushArrayMember(JSONNode & res, json_string::const_iterator & ptr, json_string::const_iterator & end);
|
||||
void pushArrayMember(JSONNode & res, json_string::const_iterator & ptr, json_string::const_iterator & end){
|
||||
GET_COMMENT(ptr, end, comment);
|
||||
JSONNode temp = JSONPreparse::isValidMember(ptr, end);
|
||||
SET_COMMENT(temp, comment);
|
||||
#ifdef JSON_LIBRARY
|
||||
res.push_back(&temp);
|
||||
#else
|
||||
res.push_back(temp);
|
||||
#endif
|
||||
}
|
||||
|
||||
JSONNode JSONPreparse::isValidArray(json_string::const_iterator & ptr, json_string::const_iterator & end) {
|
||||
//ptr should currently be pointing past the [, so this must be the start of a member, or the closing ]
|
||||
//ptr will end up past the last ]
|
||||
JSONNode res(JSON_ARRAY);
|
||||
do{
|
||||
switch(*ptr){
|
||||
case JSON_TEXT(']'):
|
||||
++ptr;
|
||||
return res;
|
||||
default:
|
||||
pushArrayMember(res, ptr, end);
|
||||
switch(*ptr){
|
||||
case JSON_TEXT(','):
|
||||
break;
|
||||
case JSON_TEXT(']'):
|
||||
++ptr;
|
||||
return res;
|
||||
default:
|
||||
throw false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} while (++ptr != end);
|
||||
throw false;
|
||||
}
|
||||
|
||||
JSONNode JSONPreparse::isValidRoot(const json_string & json) json_throws(std::invalid_argument) {
|
||||
json_string::const_iterator it = json.begin();
|
||||
json_string::const_iterator end = json.end();
|
||||
try {
|
||||
GET_COMMENT(it, end, comment);
|
||||
switch(*it){
|
||||
case JSON_TEXT('{'):
|
||||
RETURN_NODE(isValidObject(++it, end), comment);
|
||||
case JSON_TEXT('['):
|
||||
RETURN_NODE(isValidArray(++it, end), comment);
|
||||
}
|
||||
} catch (...){}
|
||||
|
||||
#ifndef JSON_NO_EXCEPTIONS
|
||||
throw std::invalid_argument(json_global(EMPTY_STD_STRING));
|
||||
#else
|
||||
return JSONNode(JSON_NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
28
src/libjson/_internal/Source/JSONPreparse.h
Normal file
28
src/libjson/_internal/Source/JSONPreparse.h
Normal file
|
@ -0,0 +1,28 @@
|
|||
#ifndef LIBJSON_GUARD_PREPARSE_H
|
||||
#define LIBJSON_GUARD_PREPARSE_H
|
||||
|
||||
#include "JSONDebug.h"
|
||||
#include "JSONNode.h"
|
||||
|
||||
#if (defined(JSON_PREPARSE) && defined(JSON_READ_PRIORITY))
|
||||
|
||||
#ifdef JSON_COMMENTS
|
||||
#define COMMENT_PARAM(name) ,const json_string & name
|
||||
#else
|
||||
#define COMMENT_PARAM(name)
|
||||
#endif
|
||||
|
||||
class JSONPreparse {
|
||||
public:
|
||||
static JSONNode isValidNumber(json_string::const_iterator & ptr, json_string::const_iterator & end) json_read_priority;
|
||||
static JSONNode isValidMember(json_string::const_iterator & ptr, json_string::const_iterator & end) json_read_priority;
|
||||
static json_string isValidString(json_string::const_iterator & ptr, json_string::const_iterator & end) json_read_priority;
|
||||
static void isValidNamedObject(json_string::const_iterator & ptr, json_string::const_iterator & end, JSONNode & parent COMMENT_PARAM(comment)) json_read_priority;
|
||||
static JSONNode isValidObject(json_string::const_iterator & ptr, json_string::const_iterator & end) json_read_priority;
|
||||
static JSONNode isValidArray(json_string::const_iterator & ptr, json_string::const_iterator & end) json_read_priority;
|
||||
static JSONNode isValidRoot(const json_string & json) json_throws(std::invalid_argument) json_read_priority;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
308
src/libjson/_internal/Source/JSONSharedString.h
Normal file
308
src/libjson/_internal/Source/JSONSharedString.h
Normal file
|
@ -0,0 +1,308 @@
|
|||
#ifndef JSON_SHARED_STRING_H
|
||||
#define JSON_SHARED_STRING_H
|
||||
|
||||
/*
|
||||
* This class allows json objects to share string
|
||||
* Since libjson is a parser, it does a lot of substrings, but since
|
||||
* a string with all of the information already exists, those substrings
|
||||
* can be infered by an offset and length and a pointer to the master
|
||||
* string
|
||||
*
|
||||
* EXPERIMENTAL, Not used yet
|
||||
*/
|
||||
|
||||
#include "JSONDebug.h"
|
||||
#include "JSONGlobals.h"
|
||||
#include "JSONMemory.h"
|
||||
|
||||
/*
|
||||
mallocs: 3351
|
||||
frees: 3351
|
||||
reallocs: 3
|
||||
bytes: 298751 (291 KB)
|
||||
max bytes at once: 3624 (3 KB)
|
||||
avg bytes at once: 970 (0 KB)
|
||||
*/
|
||||
|
||||
#ifdef JSON_LESS_MEMORY
|
||||
#ifdef __GNUC__
|
||||
#pragma pack(push, 1)
|
||||
#elif _MSC_VER
|
||||
#pragma pack(push, json_shared_string_pack, 1)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
class json_shared_string {
|
||||
public:
|
||||
|
||||
|
||||
struct iterator;
|
||||
struct const_iterator {
|
||||
const_iterator(const json_char * p, const json_shared_string * pa) : parent(pa), it(p){}
|
||||
|
||||
inline const_iterator& operator ++(void) json_nothrow { ++it; return *this; }
|
||||
inline const_iterator& operator --(void) json_nothrow { --it; return *this; }
|
||||
inline const_iterator& operator +=(long i) json_nothrow { it += i; return *this; }
|
||||
inline const_iterator& operator -=(long i) json_nothrow { it -= i; return *this; }
|
||||
inline const_iterator operator ++(int) json_nothrow {
|
||||
const_iterator result(*this);
|
||||
++it;
|
||||
return result;
|
||||
}
|
||||
inline const_iterator operator --(int) json_nothrow {
|
||||
const_iterator result(*this);
|
||||
--it;
|
||||
return result;
|
||||
}
|
||||
inline const_iterator operator +(long i) const json_nothrow {
|
||||
const_iterator result(*this);
|
||||
result.it += i;
|
||||
return result;
|
||||
}
|
||||
inline const_iterator operator -(long i) const json_nothrow {
|
||||
const_iterator result(*this);
|
||||
result.it -= i;
|
||||
return result;
|
||||
}
|
||||
inline const json_char & operator [](size_t pos) const json_nothrow { return it[pos]; };
|
||||
inline const json_char & operator *(void) const json_nothrow { return *it; }
|
||||
inline const json_char * operator ->(void) const json_nothrow { return it; }
|
||||
inline bool operator == (const const_iterator & other) const json_nothrow { return it == other.it; }
|
||||
inline bool operator != (const const_iterator & other) const json_nothrow { return it != other.it; }
|
||||
inline bool operator > (const const_iterator & other) const json_nothrow { return it > other.it; }
|
||||
inline bool operator >= (const const_iterator & other) const json_nothrow { return it >= other.it; }
|
||||
inline bool operator < (const const_iterator & other) const json_nothrow { return it < other.it; }
|
||||
inline bool operator <= (const const_iterator & other) const json_nothrow { return it <= other.it; }
|
||||
|
||||
inline bool operator == (const iterator & other) const json_nothrow { return it == other.it; }
|
||||
inline bool operator != (const iterator & other) const json_nothrow { return it != other.it; }
|
||||
inline bool operator > (const iterator & other) const json_nothrow { return it > other.it; }
|
||||
inline bool operator >= (const iterator & other) const json_nothrow { return it >= other.it; }
|
||||
inline bool operator < (const iterator & other) const json_nothrow { return it < other.it; }
|
||||
inline bool operator <= (const iterator & other) const json_nothrow { return it <= other.it; }
|
||||
|
||||
inline const_iterator & operator =(const const_iterator & orig) json_nothrow { it = orig.it; return *this; }
|
||||
const_iterator (const const_iterator & orig) json_nothrow : it(orig.it) {}
|
||||
private:
|
||||
const json_shared_string * parent;
|
||||
const json_char * it;
|
||||
friend class json_shared_string;
|
||||
friend struct iterator;
|
||||
};
|
||||
|
||||
struct iterator {
|
||||
iterator(const json_char * p, const json_shared_string * pa) : parent(pa), it(p){}
|
||||
|
||||
inline iterator& operator ++(void) json_nothrow { ++it; return *this; }
|
||||
inline iterator& operator --(void) json_nothrow { --it; return *this; }
|
||||
inline iterator& operator +=(long i) json_nothrow { it += i; return *this; }
|
||||
inline iterator& operator -=(long i) json_nothrow { it -= i; return *this; }
|
||||
inline iterator operator ++(int) json_nothrow {
|
||||
iterator result(*this);
|
||||
++it;
|
||||
return result;
|
||||
}
|
||||
inline iterator operator --(int) json_nothrow {
|
||||
iterator result(*this);
|
||||
--it;
|
||||
return result;
|
||||
}
|
||||
inline iterator operator +(long i) const json_nothrow {
|
||||
iterator result(*this);
|
||||
result.it += i;
|
||||
return result;
|
||||
}
|
||||
inline iterator operator -(long i) const json_nothrow {
|
||||
iterator result(*this);
|
||||
result.it -= i;
|
||||
return result;
|
||||
}
|
||||
inline const json_char & operator [](size_t pos) const json_nothrow { return it[pos]; };
|
||||
inline const json_char & operator *(void) const json_nothrow { return *it; }
|
||||
inline const json_char * operator ->(void) const json_nothrow { return it; }
|
||||
inline bool operator == (const const_iterator & other) const json_nothrow { return it == other.it; }
|
||||
inline bool operator != (const const_iterator & other) const json_nothrow { return it != other.it; }
|
||||
inline bool operator > (const const_iterator & other) const json_nothrow { return it > other.it; }
|
||||
inline bool operator >= (const const_iterator & other) const json_nothrow { return it >= other.it; }
|
||||
inline bool operator < (const const_iterator & other) const json_nothrow { return it < other.it; }
|
||||
inline bool operator <= (const const_iterator & other) const json_nothrow { return it <= other.it; }
|
||||
|
||||
inline bool operator == (const iterator & other) const json_nothrow { return it == other.it; }
|
||||
inline bool operator != (const iterator & other) const json_nothrow { return it != other.it; }
|
||||
inline bool operator > (const iterator & other) const json_nothrow { return it > other.it; }
|
||||
inline bool operator >= (const iterator & other) const json_nothrow { return it >= other.it; }
|
||||
inline bool operator < (const iterator & other) const json_nothrow { return it < other.it; }
|
||||
inline bool operator <= (const iterator & other) const json_nothrow { return it <= other.it; }
|
||||
|
||||
inline iterator & operator =(const iterator & orig) json_nothrow { it = orig.it; return *this; }
|
||||
iterator (const iterator & orig) json_nothrow : it(orig.it) {}
|
||||
private:
|
||||
const json_shared_string * parent;
|
||||
const json_char * it;
|
||||
friend class json_shared_string;
|
||||
friend struct const_iterator;
|
||||
};
|
||||
|
||||
|
||||
|
||||
inline json_shared_string::iterator begin(void){
|
||||
iterator res = iterator(data(), this);
|
||||
return res;
|
||||
}
|
||||
inline json_shared_string::iterator end(void){
|
||||
iterator res = iterator(data() + len, this);
|
||||
return res;
|
||||
}
|
||||
inline json_shared_string::const_iterator begin(void) const {
|
||||
const_iterator res = const_iterator(data(), this);
|
||||
return res;
|
||||
}
|
||||
inline json_shared_string::const_iterator end(void) const {
|
||||
const_iterator res = const_iterator(data() + len, this);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
inline json_string::iterator std_begin(void){
|
||||
return _str -> mystring.begin() + offset;
|
||||
}
|
||||
inline json_string::iterator std_end(void){
|
||||
return std_begin() + len;
|
||||
}
|
||||
|
||||
inline json_string::const_iterator std_begin(void) const{
|
||||
return _str -> mystring.begin() + offset;
|
||||
}
|
||||
inline json_string::const_iterator std_end(void) const{
|
||||
return std_begin() + len;
|
||||
}
|
||||
|
||||
inline json_shared_string(void) : offset(0), len(0), _str(new(json_malloc<json_shared_string_internal>(1)) json_shared_string_internal(json_global(EMPTY_JSON_STRING))) {}
|
||||
|
||||
inline json_shared_string(const json_string & str) : offset(0), len(str.length()), _str(new(json_malloc<json_shared_string_internal>(1)) json_shared_string_internal(str)) {}
|
||||
|
||||
inline json_shared_string(const json_shared_string & str, size_t _offset, size_t _len) : _str(str._str), offset(str.offset + _offset), len(_len) {
|
||||
++_str -> refCount;
|
||||
}
|
||||
|
||||
inline json_shared_string(const json_shared_string & str, size_t _offset) : _str(str._str), offset(str.offset + _offset), len(str.len - _offset) {
|
||||
++_str -> refCount;
|
||||
}
|
||||
|
||||
inline json_shared_string(const iterator & s, const iterator & e) : _str(s.parent -> _str), offset(s.it - s.parent -> _str -> mystring.data()), len(e.it - s.it){
|
||||
++_str -> refCount;
|
||||
}
|
||||
|
||||
inline ~json_shared_string(void){
|
||||
deref();
|
||||
}
|
||||
|
||||
inline bool empty(void) const { return len == 0; }
|
||||
|
||||
size_t find(json_char ch, size_t pos = 0) const {
|
||||
if (_str -> refCount == 1) return _str -> mystring.find(ch, pos);
|
||||
json_string::const_iterator e = std_end();
|
||||
for(json_string::const_iterator b = std_begin() + pos; b != e; ++b){
|
||||
if (*b == ch) return b - std_begin();
|
||||
}
|
||||
return json_string::npos;
|
||||
}
|
||||
|
||||
inline json_char & operator[] (size_t loc){
|
||||
return _str -> mystring[loc + offset];
|
||||
}
|
||||
inline json_char operator[] (size_t loc) const {
|
||||
return _str -> mystring[loc + offset];
|
||||
}
|
||||
inline void clear(){ len = 0; }
|
||||
inline size_t length() const { return len; }
|
||||
inline const json_char * c_str() const { return toString().c_str(); }
|
||||
inline const json_char * data() const { return _str -> mystring.data() + offset; }
|
||||
|
||||
inline bool operator != (const json_shared_string & other) const {
|
||||
if ((other._str == _str) && (other.len == len) && (other.offset == offset)) return false;
|
||||
return other.toString() != toString();
|
||||
}
|
||||
|
||||
inline bool operator == (const json_shared_string & other) const {
|
||||
if ((other._str == _str) && (other.len == len) && (other.offset == offset)) return true;
|
||||
return other.toString() == toString();
|
||||
}
|
||||
|
||||
inline bool operator == (const json_string & other) const {
|
||||
return other == toString();
|
||||
}
|
||||
|
||||
json_string & toString(void) const {
|
||||
//gonna have to do a real substring now anyway, so do it completely
|
||||
if (_str -> refCount == 1){
|
||||
if (offset || len != _str -> mystring.length()){
|
||||
_str -> mystring = json_string(std_begin(), std_end());
|
||||
}
|
||||
} else if (offset || len != _str -> mystring.length()){
|
||||
--_str -> refCount; //dont use deref because I know its not going to be deleted
|
||||
_str = new(json_malloc<json_shared_string_internal>(1)) json_shared_string_internal(json_string(std_begin(), std_end()));
|
||||
}
|
||||
offset = 0;
|
||||
return _str -> mystring;
|
||||
}
|
||||
|
||||
|
||||
inline void assign(const json_shared_string & other, size_t _offset, size_t _len){
|
||||
if (other._str != _str){
|
||||
deref();
|
||||
_str = other._str;
|
||||
}
|
||||
++_str -> refCount;
|
||||
offset = other.offset + _offset;
|
||||
len = _len;
|
||||
}
|
||||
|
||||
json_shared_string(const json_shared_string & other) : _str(other._str), offset(other.offset), len(other.len){
|
||||
++_str -> refCount;
|
||||
}
|
||||
|
||||
json_shared_string & operator =(const json_shared_string & other){
|
||||
if (other._str != _str){
|
||||
deref();
|
||||
_str = other._str;
|
||||
++_str -> refCount;
|
||||
}
|
||||
offset = other.offset;
|
||||
len = other.len;
|
||||
return *this;
|
||||
}
|
||||
|
||||
json_shared_string & operator += (const json_char c){
|
||||
toString() += c;
|
||||
++len;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//when doing a plus equal of another string, see if it shares the string and starts where this one left off, in which case just increase len
|
||||
JSON_PRIVATE
|
||||
struct json_shared_string_internal {
|
||||
inline json_shared_string_internal(const json_string & _mystring) : mystring(_mystring), refCount(1) {}
|
||||
json_string mystring;
|
||||
size_t refCount PACKED(20);
|
||||
};
|
||||
inline void deref(void){
|
||||
if (--_str -> refCount == 0){
|
||||
_str -> ~json_shared_string_internal();
|
||||
libjson_free<json_shared_string_internal>(_str);
|
||||
}
|
||||
}
|
||||
mutable json_shared_string_internal * _str;
|
||||
mutable size_t offset PACKED(20);
|
||||
mutable size_t len PACKED(20);
|
||||
};
|
||||
|
||||
#ifdef JSON_LESS_MEMORY
|
||||
#ifdef __GNUC__
|
||||
#pragma pack(pop)
|
||||
#elif _MSC_VER
|
||||
#pragma pack(pop, json_shared_string_pack,)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
23
src/libjson/_internal/Source/JSONSingleton.h
Normal file
23
src/libjson/_internal/Source/JSONSingleton.h
Normal file
|
@ -0,0 +1,23 @@
|
|||
#ifndef JSONSINGLETON_H
|
||||
#define JSONSINGLETON_H
|
||||
|
||||
template <typename T> class JSONSingleton {
|
||||
public:
|
||||
static inline T get(void){
|
||||
return get_singleton() -> ptr;
|
||||
}
|
||||
static inline void set(T p){
|
||||
get_singleton() -> ptr = p;
|
||||
}
|
||||
private:
|
||||
inline JSONSingleton() : ptr(NULL) { }
|
||||
JSONSingleton(const JSONSingleton<T> &);
|
||||
JSONSingleton<T> operator = (const JSONSingleton<T> &);
|
||||
static inline JSONSingleton<T> * get_singleton(void){
|
||||
static JSONSingleton<T> instance;
|
||||
return &instance;
|
||||
}
|
||||
T ptr;
|
||||
};
|
||||
|
||||
#endif
|
83
src/libjson/_internal/Source/JSONStats.h
Normal file
83
src/libjson/_internal/Source/JSONStats.h
Normal file
|
@ -0,0 +1,83 @@
|
|||
#ifndef TestSuite_JSONStats_h
|
||||
#define TestSuite_JSONStats_h
|
||||
|
||||
#include "../../JSONOptions.h"
|
||||
|
||||
#if defined(JSON_UNIT_TEST) || defined(JSON_DEBUG)
|
||||
#define LIBJSON_OBJECT(name)\
|
||||
static size_t & getCtorCounter(void){\
|
||||
static size_t count = 0;\
|
||||
static int i = JSONStats::setCallbacks(getCtorCounter, getCopyCtorCounter, getAssignmentCounter, getDtorCounter, #name);\
|
||||
return count;\
|
||||
}\
|
||||
static size_t & getCopyCtorCounter(void){\
|
||||
static size_t count = 0;\
|
||||
static int i = JSONStats::setCallbacks(getCtorCounter, getCopyCtorCounter, getAssignmentCounter, getDtorCounter, #name);\
|
||||
return count;\
|
||||
}\
|
||||
static size_t & getAssignmentCounter(void){\
|
||||
static size_t count = 0;\
|
||||
static int i = JSONStats::setCallbacks(getCtorCounter, getCopyCtorCounter, getAssignmentCounter, getDtorCounter, #name);\
|
||||
return count;\
|
||||
}\
|
||||
static size_t & getDtorCounter(void){\
|
||||
static size_t count = 0;\
|
||||
static int i = JSONStats::setCallbacks(getCtorCounter, getCopyCtorCounter, getAssignmentCounter, getDtorCounter, #name);\
|
||||
return count;\
|
||||
}
|
||||
#define LIBJSON_CTOR getCtorCounter() += 1
|
||||
#define LIBJSON_COPY_CTOR getCopyCtorCounter() += 1
|
||||
#define LIBJSON_ASSIGNMENT getAssignmentCounter() += 1
|
||||
#define LIBJSON_DTOR getDtorCounter() += 1
|
||||
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
class JSONStats {
|
||||
public:
|
||||
~JSONStats(void){
|
||||
std::map<getCounter_m, objectStructure*> & mymap = getMapper();
|
||||
std::map<getCounter_m, objectStructure*>::iterator b = mymap.begin();
|
||||
std::map<getCounter_m, objectStructure*>::iterator e = mymap.end();
|
||||
std::cout << "Counters for libjson:" << std::endl;
|
||||
for(; b != e; ++b){
|
||||
std::cout << " " << b -> second -> _name << std::endl;
|
||||
std::cout << " Constructor: " << b -> second -> _cTor() << std::endl;
|
||||
std::cout << " Copy Constructor: " << b -> second -> _ccTor() << std::endl;
|
||||
std::cout << " Assignment: " << b -> second -> _assign() << std::endl;
|
||||
std::cout << " Destructor: " << b -> second -> _dTor() << std::endl;
|
||||
delete b -> second;
|
||||
}
|
||||
}
|
||||
|
||||
typedef size_t & (*getCounter_m)(void);
|
||||
struct objectStructure {
|
||||
objectStructure(getCounter_m cTor, getCounter_m ccTor, getCounter_m assign, getCounter_m dTor, const std::string & name):
|
||||
_cTor(cTor), _ccTor(ccTor), _assign(assign), _dTor(dTor), _name(name){}
|
||||
std::string _name;
|
||||
getCounter_m _cTor;
|
||||
getCounter_m _ccTor;
|
||||
getCounter_m _assign;
|
||||
getCounter_m _dTor;
|
||||
};
|
||||
static int setCallbacks(getCounter_m cTor, getCounter_m ccTor, getCounter_m assign, getCounter_m dtor, const std::string & name){
|
||||
getMapper()[cTor] = new objectStructure (cTor, ccTor, assign, dtor, name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static std::map<getCounter_m, objectStructure*> & getMapper(void) {
|
||||
static std::map<getCounter_m, objectStructure*> mymap;
|
||||
return mymap;
|
||||
}
|
||||
};
|
||||
#else
|
||||
#define LIBJSON_OBJECT(name)
|
||||
#define LIBJSON_CTOR (void)0
|
||||
#define LIBJSON_DTOR (void)0
|
||||
#define LIBJSON_COPY_CTOR (void)0
|
||||
#define LIBJSON_ASSIGNMENT (void)0
|
||||
typedef int JSONStats;
|
||||
#endif
|
||||
|
||||
#endif
|
143
src/libjson/_internal/Source/JSONStream.cpp
Normal file
143
src/libjson/_internal/Source/JSONStream.cpp
Normal file
|
@ -0,0 +1,143 @@
|
|||
#include "JSONStream.h"
|
||||
|
||||
#ifdef JSON_STREAM
|
||||
#include "JSONWorker.h"
|
||||
#include "JSONValidator.h"
|
||||
|
||||
|
||||
JSONStream::JSONStream(json_stream_callback_t call_p, json_stream_e_callback_t call_e, void * callbackIdentifier) json_nothrow : state(true), call(call_p), err_call(call_e), buffer(), callback_identifier(callbackIdentifier) {
|
||||
LIBJSON_CTOR;
|
||||
}
|
||||
|
||||
JSONStream::JSONStream(const JSONStream & orig) json_nothrow : state(orig.state), call(orig.call), err_call(orig.err_call), buffer(orig.buffer), callback_identifier(orig.callback_identifier){
|
||||
LIBJSON_COPY_CTOR;
|
||||
}
|
||||
|
||||
JSONStream & JSONStream::operator =(const JSONStream & orig) json_nothrow {
|
||||
LIBJSON_ASSIGNMENT;
|
||||
err_call = orig.err_call;
|
||||
call = orig.call;
|
||||
state = orig.state;
|
||||
buffer = orig.buffer;
|
||||
callback_identifier = orig.callback_identifier;
|
||||
return *this;
|
||||
}
|
||||
|
||||
#ifdef JSON_LIBRARY
|
||||
JSONStream & JSONStream::operator << (const json_char * str) json_nothrow {
|
||||
#else
|
||||
JSONStream & JSONStream::operator << (const json_string & str) json_nothrow {
|
||||
#endif
|
||||
if (state){
|
||||
buffer += str;
|
||||
parse();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
#define QUOTECASE_STREAM()\
|
||||
case JSON_TEXT('\"'):\
|
||||
while (*(++p) != JSON_TEXT('\"')){\
|
||||
if (json_unlikely(*p == JSON_TEXT('\0'))) return json_string::npos;\
|
||||
}\
|
||||
break;
|
||||
|
||||
|
||||
#define NULLCASE_STREAM()\
|
||||
case JSON_TEXT('\0'):\
|
||||
return json_string::npos;\
|
||||
|
||||
|
||||
#define BRACKET_STREAM(left, right)\
|
||||
case left: {\
|
||||
size_t brac = 1;\
|
||||
while (brac){\
|
||||
switch (*(++p)){\
|
||||
case right:\
|
||||
--brac;\
|
||||
break;\
|
||||
case left:\
|
||||
++brac;\
|
||||
break;\
|
||||
QUOTECASE_STREAM()\
|
||||
NULLCASE_STREAM()\
|
||||
}\
|
||||
}\
|
||||
break;}\
|
||||
case right:\
|
||||
return json_string::npos;
|
||||
|
||||
#if (JSON_READ_PRIORITY == HIGH) && (!(defined(JSON_LESS_MEMORY)))
|
||||
#define STREAM_FIND_NEXT_RELEVANT(ch, vt, po) FindNextRelevant<ch>(vt, po)
|
||||
template<json_char ch>
|
||||
size_t JSONStream::FindNextRelevant(const json_string & value_t, const size_t pos) json_nothrow {
|
||||
#else
|
||||
#define STREAM_FIND_NEXT_RELEVANT(ch, vt, po) FindNextRelevant(ch, vt, po)
|
||||
size_t JSONStream::FindNextRelevant(json_char ch, const json_string & value_t, const size_t pos) json_nothrow {
|
||||
#endif
|
||||
const json_char * start = value_t.c_str();
|
||||
for (const json_char * p = start + pos; *p; ++p){
|
||||
if (json_unlikely(*p == ch)) return p - start;
|
||||
switch (*p){
|
||||
BRACKET_STREAM(JSON_TEXT('['), JSON_TEXT(']'))
|
||||
BRACKET_STREAM(JSON_TEXT('{'), JSON_TEXT('}'))
|
||||
QUOTECASE_STREAM()
|
||||
}
|
||||
};
|
||||
return json_string::npos;
|
||||
}
|
||||
|
||||
void JSONStream::parse(void) json_nothrow {
|
||||
#ifdef JSON_SECURITY_MAX_STREAM_OBJECTS
|
||||
size_t objects = 0;
|
||||
#endif
|
||||
for(;;){
|
||||
size_t pos = buffer.find_first_of(JSON_TEXT("{["));
|
||||
if (json_likely(pos != json_string::npos)){
|
||||
size_t end = (buffer[pos] == JSON_TEXT('[')) ? STREAM_FIND_NEXT_RELEVANT(JSON_TEXT(']'), buffer, pos + 1) : STREAM_FIND_NEXT_RELEVANT(JSON_TEXT('}'), buffer, pos + 1);
|
||||
if (end != json_string::npos){
|
||||
#ifdef JSON_SECURITY_MAX_STREAM_OBJECTS
|
||||
if (++objects > JSON_SECURITY_MAX_STREAM_OBJECTS){
|
||||
JSON_FAIL(JSON_TEXT("Maximum number of json objects for a stream at once has been reached"));
|
||||
if (err_call) err_call(getIdentifier());
|
||||
state = false;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
START_MEM_SCOPE
|
||||
JSONNode temp(JSONWorker::parse(buffer.substr(pos, end - pos + 1)));
|
||||
#ifndef JSON_LIBRARY
|
||||
call(temp, getIdentifier());
|
||||
#else
|
||||
call(&temp, getIdentifier());
|
||||
#endif
|
||||
END_MEM_SCOPE
|
||||
json_string::iterator beginning = buffer.begin();
|
||||
buffer.erase(beginning, beginning + end);
|
||||
continue; //parse(); //parse the next object too
|
||||
}
|
||||
#ifdef JSON_SAFE
|
||||
else {
|
||||
//verify that what's in there is at least valid so far
|
||||
#ifndef JSON_VALIDATE
|
||||
#error In order to use safe mode and streams, JSON_VALIDATE needs to be defined
|
||||
#endif
|
||||
|
||||
json_auto<json_char> s;
|
||||
size_t len;
|
||||
s.set(JSONWorker::RemoveWhiteSpace(json_string(buffer.c_str() + pos), len, false));
|
||||
|
||||
|
||||
if (!JSONValidator::isValidPartialRoot(s.ptr)){
|
||||
if (err_call) err_call(getIdentifier());
|
||||
state = false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
93
src/libjson/_internal/Source/JSONStream.h
Normal file
93
src/libjson/_internal/Source/JSONStream.h
Normal file
|
@ -0,0 +1,93 @@
|
|||
#ifndef LIBJSON_GUARD_STREAM_H
|
||||
#define LIBJSON_GUARD_STREAM_H
|
||||
|
||||
#include "JSONDebug.h"
|
||||
|
||||
#ifdef JSON_STREAM
|
||||
|
||||
#ifdef JSON_LESS_MEMORY
|
||||
#ifdef __GNUC__
|
||||
#pragma pack(push, 1)
|
||||
#elif _MSC_VER
|
||||
#pragma pack(push, JSONStream_pack, 1)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef JSON_MEMORY_CALLBACKS
|
||||
#include "JSONMemory.h"
|
||||
#endif
|
||||
|
||||
#ifndef JSON_LIBRARY
|
||||
class JSONNode; //foreward declaration
|
||||
typedef void (*json_stream_callback_t)(JSONNode &, void *);
|
||||
#endif
|
||||
|
||||
class JSONStream {
|
||||
public:
|
||||
LIBJSON_OBJECT(JSONStream);
|
||||
JSONStream(json_stream_callback_t call_p, json_stream_e_callback_t call_e = NULL, void * callbackIdentifier = JSONSTREAM_SELF) json_nothrow;
|
||||
JSONStream(const JSONStream & orig) json_nothrow;
|
||||
JSONStream & operator =(const JSONStream & orig) json_nothrow;
|
||||
~JSONStream(void) json_nothrow { LIBJSON_DTOR; }
|
||||
#ifdef JSON_LIBRARY
|
||||
JSONStream & operator << (const json_char * str) json_nothrow;
|
||||
#else
|
||||
JSONStream & operator << (const json_string & str) json_nothrow;
|
||||
#endif
|
||||
|
||||
static void deleteJSONStream(JSONStream * stream) json_nothrow {
|
||||
#ifdef JSON_MEMORY_CALLBACKS
|
||||
stream -> ~JSONStream();
|
||||
libjson_free<JSONStream>(stream);
|
||||
#else
|
||||
delete stream;
|
||||
#endif
|
||||
}
|
||||
|
||||
static JSONStream * newJSONStream(json_stream_callback_t callback, json_stream_e_callback_t call_e, void * callbackIdentifier) json_nothrow {
|
||||
#ifdef JSON_MEMORY_CALLBACKS
|
||||
return new(json_malloc<JSONStream>(1)) JSONStream(callback, call_e, callbackIdentifier);
|
||||
#else
|
||||
return new JSONStream(callback, call_e, callbackIdentifier);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void reset() json_nothrow {
|
||||
state = true;
|
||||
buffer.clear();
|
||||
}
|
||||
JSON_PRIVATE
|
||||
inline void * getIdentifier(void) json_nothrow {
|
||||
if (callback_identifier == JSONSTREAM_SELF){
|
||||
return (void*)this;
|
||||
}
|
||||
return callback_identifier;
|
||||
}
|
||||
|
||||
#if (JSON_READ_PRIORITY == HIGH) && (!(defined(JSON_LESS_MEMORY)))
|
||||
template<json_char ch>
|
||||
static size_t FindNextRelevant(const json_string & value_t, const size_t pos) json_nothrow json_read_priority;
|
||||
#else
|
||||
static size_t FindNextRelevant(json_char ch, const json_string & value_t, const size_t pos) json_nothrow json_read_priority;
|
||||
#endif
|
||||
|
||||
void parse(void) json_nothrow;
|
||||
json_string buffer;
|
||||
json_stream_callback_t call;
|
||||
json_stream_e_callback_t err_call;
|
||||
void * callback_identifier;
|
||||
bool state BITS(1);
|
||||
};
|
||||
|
||||
#ifdef JSON_LESS_MEMORY
|
||||
#ifdef __GNUC__
|
||||
#pragma pack(pop)
|
||||
#elif _MSC_VER
|
||||
#pragma pack(pop, JSONStream_pack)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
404
src/libjson/_internal/Source/JSONValidator.cpp
Normal file
404
src/libjson/_internal/Source/JSONValidator.cpp
Normal file
|
@ -0,0 +1,404 @@
|
|||
#include "JSONValidator.h"
|
||||
|
||||
#ifdef JSON_VALIDATE
|
||||
|
||||
inline bool isHex(json_char c) json_pure;
|
||||
inline bool isHex(json_char c) json_nothrow {
|
||||
return (((c >= JSON_TEXT('0')) && (c <= JSON_TEXT('9'))) ||
|
||||
((c >= JSON_TEXT('A')) && (c <= JSON_TEXT('F'))) ||
|
||||
((c >= JSON_TEXT('a')) && (c <= JSON_TEXT('f'))));
|
||||
}
|
||||
|
||||
bool JSONValidator::isValidNumber(const json_char * & ptr) json_nothrow {
|
||||
//ptr points at the first character in the number
|
||||
//ptr will end up past the last character
|
||||
bool decimal = false;
|
||||
bool scientific = false;
|
||||
|
||||
//first letter is weird
|
||||
switch(*ptr){
|
||||
#ifndef JSON_STRICT
|
||||
case JSON_TEXT('.'):
|
||||
decimal = true;
|
||||
break;
|
||||
case JSON_TEXT('+'):
|
||||
#endif
|
||||
case JSON_TEXT('-'):
|
||||
#ifdef JSON_STRICT
|
||||
switch(*(ptr + 1)){
|
||||
case '.':
|
||||
case 'e':
|
||||
case 'E':
|
||||
case '\0':
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
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('8'):
|
||||
case JSON_TEXT('9'):
|
||||
break;
|
||||
case JSON_TEXT('0'):
|
||||
++ptr;
|
||||
switch(*ptr){
|
||||
case JSON_TEXT('.'):
|
||||
decimal = true;
|
||||
break;
|
||||
case JSON_TEXT('e'):
|
||||
case JSON_TEXT('E'):
|
||||
scientific = true;
|
||||
++ptr;
|
||||
switch(*ptr){
|
||||
case JSON_TEXT('\0'):
|
||||
return false;
|
||||
case JSON_TEXT('-'):
|
||||
case JSON_TEXT('+'):
|
||||
case JSON_TEXT('0'):
|
||||
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('8'):
|
||||
case JSON_TEXT('9'):
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
#ifndef JSON_STRICT
|
||||
case JSON_TEXT('x'):
|
||||
while(isHex(*++ptr)){};
|
||||
return true;
|
||||
#ifdef JSON_OCTAL
|
||||
#ifdef __GNUC__
|
||||
case JSON_TEXT('0') ... JSON_TEXT('7'): //octal
|
||||
#else
|
||||
case JSON_TEXT('0'):
|
||||
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'):
|
||||
#endif
|
||||
while((*++ptr >= JSON_TEXT('0')) && (*ptr <= JSON_TEXT('7'))){};
|
||||
return ((*ptr != JSON_TEXT('8')) && (*ptr != JSON_TEXT('9')));
|
||||
case JSON_TEXT('8'):
|
||||
case JSON_TEXT('9'):
|
||||
break;
|
||||
#else
|
||||
#ifdef __GNUC__
|
||||
case JSON_TEXT('0') ... JSON_TEXT('9'):
|
||||
#else
|
||||
case JSON_TEXT('0'):
|
||||
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('8'):
|
||||
case JSON_TEXT('9'):
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
#else
|
||||
#ifdef __GNUC__
|
||||
case JSON_TEXT('0') ... JSON_TEXT('9'):
|
||||
#else
|
||||
case JSON_TEXT('0'):
|
||||
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('8'):
|
||||
case JSON_TEXT('9'):
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
default: //just a 0
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
++ptr;
|
||||
|
||||
//next digits
|
||||
while (true){
|
||||
switch(*ptr){
|
||||
case JSON_TEXT('.'):
|
||||
if (json_unlikely(decimal)) return false; //multiple decimals
|
||||
if (json_unlikely(scientific)) return false;
|
||||
decimal = true;
|
||||
break;
|
||||
case JSON_TEXT('e'):
|
||||
case JSON_TEXT('E'):
|
||||
if (json_likely(scientific)) return false;
|
||||
scientific = true;
|
||||
++ptr;
|
||||
switch(*ptr){
|
||||
case JSON_TEXT('-'):
|
||||
case JSON_TEXT('+'):
|
||||
#ifdef __GNUC__
|
||||
case JSON_TEXT('0') ... JSON_TEXT('9'):
|
||||
#else
|
||||
case JSON_TEXT('0'):
|
||||
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('8'):
|
||||
case JSON_TEXT('9'):
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
#ifdef __GNUC__
|
||||
case JSON_TEXT('0') ... JSON_TEXT('9'):
|
||||
#else
|
||||
case JSON_TEXT('0'):
|
||||
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('8'):
|
||||
case JSON_TEXT('9'):
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
++ptr;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifndef JSON_STRICT
|
||||
#define LETTERCASE(x, y)\
|
||||
case JSON_TEXT(x):\
|
||||
case JSON_TEXT(y)
|
||||
#define LETTERCHECK(x, y)\
|
||||
if (json_unlikely((*++ptr != JSON_TEXT(x)) && (*ptr != JSON_TEXT(y)))) return false
|
||||
#else
|
||||
#define LETTERCASE(x, y)\
|
||||
case JSON_TEXT(x)
|
||||
#define LETTERCHECK(x, y)\
|
||||
if (json_unlikely(*++ptr != JSON_TEXT(x))) return false
|
||||
#endif
|
||||
bool JSONValidator::isValidMember(const json_char * & ptr DEPTH_PARAM) json_nothrow {
|
||||
//ptr is on the first character of the member
|
||||
//ptr will end up immediately after the last character in the member
|
||||
switch(*ptr){
|
||||
case JSON_TEXT('\"'):
|
||||
return isValidString(++ptr);
|
||||
case JSON_TEXT('{'):
|
||||
INC_DEPTH();
|
||||
return isValidObject(++ptr DEPTH_ARG(depth_param));
|
||||
case JSON_TEXT('['):
|
||||
INC_DEPTH();
|
||||
return isValidArray(++ptr DEPTH_ARG(depth_param));
|
||||
LETTERCASE('t', 'T'):
|
||||
LETTERCHECK('r', 'R');
|
||||
LETTERCHECK('u', 'U');
|
||||
LETTERCHECK('e', 'E');
|
||||
++ptr;
|
||||
return true;
|
||||
LETTERCASE('f', 'F'):
|
||||
LETTERCHECK('a', 'A');
|
||||
LETTERCHECK('l', 'L');
|
||||
LETTERCHECK('s', 'S');
|
||||
LETTERCHECK('e', 'E');
|
||||
++ptr;
|
||||
return true;
|
||||
LETTERCASE('n', 'N'):
|
||||
LETTERCHECK('u', 'U');
|
||||
LETTERCHECK('l', 'L');
|
||||
LETTERCHECK('l', 'L');
|
||||
++ptr;
|
||||
return true;
|
||||
#ifndef JSON_STRICT
|
||||
case JSON_TEXT('}'): //null in libjson
|
||||
case JSON_TEXT(']'): //null in libjson
|
||||
case JSON_TEXT(','): //null in libjson
|
||||
return true;
|
||||
#endif
|
||||
case JSON_TEXT('\0'):
|
||||
return false;
|
||||
}
|
||||
//a number
|
||||
return isValidNumber(ptr);
|
||||
}
|
||||
|
||||
bool JSONValidator::isValidString(const json_char * & ptr) json_nothrow {
|
||||
//ptr is pointing to the first character after the quote
|
||||
//ptr will end up behind the closing "
|
||||
while(true){
|
||||
switch(*ptr){
|
||||
case JSON_TEXT('\\'):
|
||||
switch(*(++ptr)){
|
||||
case JSON_TEXT('\"'):
|
||||
case JSON_TEXT('\\'):
|
||||
case JSON_TEXT('/'):
|
||||
case JSON_TEXT('b'):
|
||||
case JSON_TEXT('f'):
|
||||
case JSON_TEXT('n'):
|
||||
case JSON_TEXT('r'):
|
||||
case JSON_TEXT('t'):
|
||||
break;
|
||||
case JSON_TEXT('u'):
|
||||
if (json_unlikely(!isHex(*++ptr))) return false;
|
||||
if (json_unlikely(!isHex(*++ptr))) return false;
|
||||
//fallthrough to \x
|
||||
#ifndef JSON_STRICT
|
||||
case JSON_TEXT('x'): //hex
|
||||
#endif
|
||||
if (json_unlikely(!isHex(*++ptr))) return false;
|
||||
if (json_unlikely(!isHex(*++ptr))) return false;
|
||||
break;
|
||||
#ifdef JSON_OCTAL
|
||||
#ifdef __GNUC__
|
||||
case JSON_TEXT('0') ... JSON_TEXT('7'): //octal
|
||||
#else
|
||||
case JSON_TEXT('0'):
|
||||
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'):
|
||||
#endif
|
||||
if (json_unlikely((*++ptr < JSON_TEXT('0')) || (*ptr > JSON_TEXT('7')))) return false;
|
||||
if (json_unlikely((*++ptr < JSON_TEXT('0')) || (*ptr > JSON_TEXT('7')))) return false;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case JSON_TEXT('\"'):
|
||||
++ptr;
|
||||
return true;
|
||||
case JSON_TEXT('\0'):
|
||||
return false;
|
||||
}
|
||||
++ptr;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool JSONValidator::isValidNamedObject(const json_char * &ptr DEPTH_PARAM) json_nothrow {
|
||||
if (json_unlikely(!isValidString(++ptr))) return false;
|
||||
if (json_unlikely(*ptr++ != JSON_TEXT(':'))) return false;
|
||||
if (json_unlikely(!isValidMember(ptr DEPTH_ARG(depth_param)))) return false;
|
||||
switch(*ptr){
|
||||
case JSON_TEXT(','):
|
||||
return isValidNamedObject(++ptr DEPTH_ARG(depth_param));
|
||||
case JSON_TEXT('}'):
|
||||
++ptr;
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool JSONValidator::isValidObject(const json_char * & ptr DEPTH_PARAM) json_nothrow {
|
||||
//ptr should currently be pointing past the {, so this must be the start of a name, or the closing }
|
||||
//ptr will end up past the last }
|
||||
do{
|
||||
switch(*ptr){
|
||||
case JSON_TEXT('\"'):
|
||||
return isValidNamedObject(ptr DEPTH_ARG(depth_param));
|
||||
case JSON_TEXT('}'):
|
||||
++ptr;
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
} while (*++ptr);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool JSONValidator::isValidArray(const json_char * & ptr DEPTH_PARAM) json_nothrow {
|
||||
//ptr should currently be pointing past the [, so this must be the start of a member, or the closing ]
|
||||
//ptr will end up past the last ]
|
||||
do{
|
||||
switch(*ptr){
|
||||
case JSON_TEXT(']'):
|
||||
++ptr;
|
||||
return true;
|
||||
default:
|
||||
if (json_unlikely(!isValidMember(ptr DEPTH_ARG(depth_param)))) return false;
|
||||
switch(*ptr){
|
||||
case JSON_TEXT(','):
|
||||
break;
|
||||
case JSON_TEXT(']'):
|
||||
++ptr;
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} while (*++ptr);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool JSONValidator::isValidRoot(const json_char * json) json_nothrow {
|
||||
const json_char * ptr = json;
|
||||
switch(*ptr){
|
||||
case JSON_TEXT('{'):
|
||||
if (json_likely(isValidObject(++ptr DEPTH_ARG(1)))){
|
||||
return *ptr == JSON_TEXT('\0');
|
||||
}
|
||||
return false;
|
||||
case JSON_TEXT('['):
|
||||
if (json_likely(isValidArray(++ptr DEPTH_ARG(1)))){
|
||||
return *ptr == JSON_TEXT('\0');
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef JSON_STREAM
|
||||
//It has already been checked for a complete structure, so we know it's not complete
|
||||
bool JSONValidator::isValidPartialRoot(const json_char * json) json_nothrow {
|
||||
const json_char * ptr = json;
|
||||
switch(*ptr){
|
||||
case JSON_TEXT('{'):
|
||||
JSON_ASSERT_SAFE(!isValidObject(++ptr DEPTH_ARG(1)), JSON_TEXT("Partial Object seems to be valid"), );
|
||||
return *ptr == JSON_TEXT('\0');
|
||||
case JSON_TEXT('['):
|
||||
JSON_ASSERT_SAFE(!isValidArray(++ptr DEPTH_ARG(1)), JSON_TEXT("Partial Object seems to be valid"), );
|
||||
return *ptr == JSON_TEXT('\0');
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
40
src/libjson/_internal/Source/JSONValidator.h
Normal file
40
src/libjson/_internal/Source/JSONValidator.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
#ifndef JSON_VALIDATOR_H
|
||||
#define JSON_VALIDATOR_H
|
||||
|
||||
#include "JSONDebug.h"
|
||||
|
||||
#ifdef JSON_VALIDATE
|
||||
|
||||
#ifdef JSON_SECURITY_MAX_NEST_LEVEL
|
||||
#define DEPTH_PARAM ,size_t depth_param
|
||||
#define DEPTH_ARG(arg) ,arg
|
||||
#define INC_DEPTH()\
|
||||
if (++depth_param > JSON_SECURITY_MAX_NEST_LEVEL){\
|
||||
JSON_FAIL(JSON_TEXT("Exceeded JSON_SECURITY_MAX_NEST_LEVEL"));\
|
||||
return false;\
|
||||
}
|
||||
#else
|
||||
#define DEPTH_PARAM
|
||||
#define DEPTH_ARG(arg)
|
||||
#define INC_DEPTH() (void)0
|
||||
#endif
|
||||
|
||||
class JSONValidator {
|
||||
public:
|
||||
static bool isValidNumber(const json_char * & ptr) json_nothrow json_read_priority;
|
||||
static bool isValidMember(const json_char * & ptr DEPTH_PARAM) json_nothrow json_read_priority;
|
||||
static bool isValidString(const json_char * & ptr) json_nothrow json_read_priority;
|
||||
static bool isValidNamedObject(const json_char * & ptr DEPTH_PARAM) json_nothrow json_read_priority;
|
||||
static bool isValidObject(const json_char * & ptr DEPTH_PARAM) json_nothrow json_read_priority;
|
||||
static bool isValidArray(const json_char * & ptr DEPTH_PARAM) json_nothrow json_read_priority;
|
||||
static bool isValidRoot(const json_char * json) json_nothrow json_read_priority;
|
||||
#ifdef JSON_STREAM
|
||||
static bool isValidPartialRoot(const json_char * json) json_nothrow json_read_priority;
|
||||
#endif
|
||||
private:
|
||||
JSONValidator(void);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
674
src/libjson/_internal/Source/JSONWorker.cpp
Normal file
674
src/libjson/_internal/Source/JSONWorker.cpp
Normal file
|
@ -0,0 +1,674 @@
|
|||
#include "JSONWorker.h"
|
||||
|
||||
bool used_ascii_one = false; //used to know whether or not to check for intermediates when writing, once flipped, can't be unflipped
|
||||
inline json_char ascii_one(void) json_nothrow {
|
||||
used_ascii_one = true;
|
||||
return JSON_TEXT('\1');
|
||||
}
|
||||
|
||||
#ifdef JSON_READ_PRIORITY
|
||||
|
||||
JSONNode JSONWorker::parse(const json_string & json) json_throws(std::invalid_argument) {
|
||||
json_auto<json_char> s;
|
||||
size_t len;
|
||||
s.set(RemoveWhiteSpace(json, len, true));
|
||||
return _parse_unformatted(s.ptr, s.ptr + len);
|
||||
}
|
||||
|
||||
JSONNode JSONWorker::parse_unformatted(const json_string & json) json_throws(std::invalid_argument) {
|
||||
#if defined JSON_DEBUG || defined JSON_SAFE
|
||||
#ifndef JSON_NO_EXCEPTIONS
|
||||
JSON_ASSERT_SAFE((json[0] == JSON_TEXT('{')) || (json[0] == JSON_TEXT('[')), JSON_TEXT("Not JSON!"), throw std::invalid_argument(json_global(EMPTY_STD_STRING)););
|
||||
#else
|
||||
JSON_ASSERT_SAFE((json[0] == JSON_TEXT('{')) || (json[0] == JSON_TEXT('[')), JSON_TEXT("Not JSON!"), return JSONNode(JSON_NULL););
|
||||
#endif
|
||||
#endif
|
||||
return _parse_unformatted(json.data(), json.data() + json.length());
|
||||
}
|
||||
|
||||
JSONNode JSONWorker::_parse_unformatted(const json_char * json, const json_char * const end) json_throws(std::invalid_argument) {
|
||||
#ifdef JSON_COMMENTS
|
||||
json_char firstchar = *json;
|
||||
json_string _comment;
|
||||
json_char * runner = (json_char*)json;
|
||||
if (json_unlikely(firstchar == JSON_TEMP_COMMENT_IDENTIFIER)){ //multiple comments will be consolidated into one
|
||||
newcomment:
|
||||
while(*(++runner) != JSON_TEMP_COMMENT_IDENTIFIER){
|
||||
JSON_ASSERT(runner != end, JSON_TEXT("Removing white space failed"));
|
||||
_comment += *runner;
|
||||
}
|
||||
firstchar = *(++runner); //step past the trailing tag
|
||||
if (json_unlikely(firstchar == JSON_TEMP_COMMENT_IDENTIFIER)){
|
||||
_comment += JSON_TEXT('\n');
|
||||
goto newcomment;
|
||||
}
|
||||
}
|
||||
#else
|
||||
const json_char firstchar = *json;
|
||||
#endif
|
||||
|
||||
switch (firstchar){
|
||||
case JSON_TEXT('{'):
|
||||
case JSON_TEXT('['):
|
||||
#if defined JSON_DEBUG || defined JSON_SAFE
|
||||
if (firstchar == JSON_TEXT('[')){
|
||||
if (json_unlikely(*(end - 1) != JSON_TEXT(']'))){
|
||||
JSON_FAIL(JSON_TEXT("Missing final ]"));
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (json_unlikely(*(end - 1) != JSON_TEXT('}'))){
|
||||
JSON_FAIL(JSON_TEXT("Missing final }"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef JSON_COMMENTS
|
||||
JSONNode foo(json_string(runner, end - 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(json_string(json, end - json));
|
||||
#endif
|
||||
}
|
||||
|
||||
JSON_FAIL(JSON_TEXT("Not JSON!"));
|
||||
#ifndef JSON_NO_EXCEPTIONS
|
||||
throw std::invalid_argument(json_global(EMPTY_STD_STRING));
|
||||
#else
|
||||
return JSONNode(JSON_NULL);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#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;
|
||||
|
||||
#if defined(JSON_DEBUG) || defined(JSON_SAFE)
|
||||
#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;
|
||||
|
||||
|
||||
|
||||
#if defined(JSON_READ_PRIORITY) || defined(JSON_STREAM)
|
||||
#if (JSON_READ_PRIORITY == HIGH) && (!(defined(JSON_LESS_MEMORY)))
|
||||
#define FIND_NEXT_RELEVANT(ch, vt, po) JSONWorker::FindNextRelevant<ch>(vt, po)
|
||||
template<json_char ch>
|
||||
size_t JSONWorker::FindNextRelevant(const json_string & value_t, const size_t pos) json_nothrow {
|
||||
#else
|
||||
#define FIND_NEXT_RELEVANT(ch, vt, po) JSONWorker::FindNextRelevant(ch, vt, po)
|
||||
size_t JSONWorker::FindNextRelevant(json_char ch, const json_string & value_t, const size_t pos) json_nothrow {
|
||||
#endif
|
||||
json_string::const_iterator start = value_t.begin();
|
||||
json_string::const_iterator e = value_t.end();
|
||||
for (json_string::const_iterator p = value_t.begin() + pos; p != e; ++p){
|
||||
if (json_unlikely(*p == ch)) return p - start;
|
||||
switch (*p){
|
||||
BRACKET(JSON_TEXT('['), JSON_TEXT(']'))
|
||||
BRACKET(JSON_TEXT('{'), JSON_TEXT('}'))
|
||||
QUOTECASE()
|
||||
}
|
||||
};
|
||||
return json_string::npos;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef JSON_COMMENTS
|
||||
#define COMMENT_DELIMITER() *runner++ = JSON_TEMP_COMMENT_IDENTIFIER
|
||||
#define AND_RUNNER ,runner
|
||||
inline void SingleLineComment(const json_char * & p, const json_char * const end, json_char * & runner) json_nothrow {
|
||||
//It is okay to add two '\5' characters here because at minimun the # and '\n' are replaced, so it's at most the same size
|
||||
COMMENT_DELIMITER();
|
||||
while((++p != end) && (*p != JSON_TEXT('\n'))){
|
||||
*runner++ = *p;
|
||||
}
|
||||
COMMENT_DELIMITER();
|
||||
}
|
||||
#else
|
||||
#define COMMENT_DELIMITER() (void)0
|
||||
#define AND_RUNNER
|
||||
#endif
|
||||
|
||||
#ifndef JSON_STRICT
|
||||
inline void SingleLineComment(const json_char * & p, const json_char * const end) json_nothrow {
|
||||
while((++p != end) && (*p != JSON_TEXT('\n')));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(JSON_LESS_MEMORY) && defined(JSON_READ_PRIORITY)
|
||||
#define PRIVATE_REMOVEWHITESPACE(T, value_t, escapeQuotes, len) private_RemoveWhiteSpace(T, value_t, escapeQuotes, len)
|
||||
json_char * private_RemoveWhiteSpace(bool T, const json_string & value_t, bool escapeQuotes, size_t & len) json_nothrow {
|
||||
#else
|
||||
#define PRIVATE_REMOVEWHITESPACE(T, value_t, escapeQuotes, len) private_RemoveWhiteSpace<T>(value_t, escapeQuotes, len)
|
||||
template<bool T>
|
||||
json_char * private_RemoveWhiteSpace(const json_string & value_t, bool escapeQuotes, size_t & len) json_nothrow {
|
||||
#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 != 0, json_global(ERROR_OUT_OF_MEMORY));
|
||||
const json_char * const end = value_t.data() + value_t.length();
|
||||
for(const json_char * p = value_t.data(); p != end; ++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;
|
||||
#ifndef JSON_STRICT
|
||||
case JSON_TEXT('/'): //a C comment
|
||||
if (*(++p) == JSON_TEXT('*')){ //a multiline comment
|
||||
if (T) COMMENT_DELIMITER();
|
||||
while ((*(++p) != JSON_TEXT('*')) || (*(p + 1) != JSON_TEXT('/'))){
|
||||
if(p == end){
|
||||
COMMENT_DELIMITER();
|
||||
goto endofrunner;
|
||||
}
|
||||
if (T) *runner++ = *p;
|
||||
}
|
||||
++p;
|
||||
if (T) 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 endofrunner;);
|
||||
case JSON_TEXT('#'): //a bash comment
|
||||
if (T){
|
||||
SingleLineComment(p, end AND_RUNNER);
|
||||
} else {
|
||||
SingleLineComment(p, end);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
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
|
||||
if(p == end) goto endofrunner;
|
||||
switch(*p){
|
||||
case JSON_TEXT('\\'):
|
||||
*runner++ = JSON_TEXT('\\');
|
||||
if (escapeQuotes){
|
||||
*runner++ = (*++p == JSON_TEXT('\"')) ? ascii_one() : *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
|
||||
} else {
|
||||
*runner++ = *++p;
|
||||
}
|
||||
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 endofrunner;);
|
||||
JSON_ASSERT_SAFE((json_uchar)*p <= 126, JSON_TEXT("Invalid JSON character detected (hi)"), goto endofrunner;);
|
||||
*runner++ = *p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
endofrunner:
|
||||
len = runner - result;
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifdef JSON_READ_PRIORITY
|
||||
json_char * JSONWorker::RemoveWhiteSpace(const json_string & value_t, size_t & len, bool escapeQuotes) json_nothrow {
|
||||
json_char * result = PRIVATE_REMOVEWHITESPACE(true, value_t, escapeQuotes, len);
|
||||
result[len] = JSON_TEXT('\0');
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
json_char * JSONWorker::RemoveWhiteSpaceAndCommentsC(const json_string & value_t, bool escapeQuotes) json_nothrow {
|
||||
size_t len;
|
||||
json_char * result = PRIVATE_REMOVEWHITESPACE(false, value_t, escapeQuotes, len);
|
||||
result[len] = JSON_TEXT('\0');
|
||||
return result;
|
||||
}
|
||||
|
||||
json_string JSONWorker::RemoveWhiteSpaceAndComments(const json_string & value_t, bool escapeQuotes) json_nothrow {
|
||||
json_auto<json_char> s;
|
||||
size_t len;
|
||||
s.set(PRIVATE_REMOVEWHITESPACE(false, value_t, escapeQuotes, len));
|
||||
return json_string(s.ptr, len);
|
||||
}
|
||||
|
||||
#ifdef JSON_READ_PRIORITY
|
||||
/*
|
||||
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_pure;
|
||||
inline json_uchar SurrogatePair(const json_uchar hi, const json_uchar lo) json_nothrow {
|
||||
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;
|
||||
}
|
||||
|
||||
void JSONWorker::UTF(const json_char * & pos, json_string & result, const json_char * const end) json_nothrow {
|
||||
JSON_ASSERT_SAFE(((long)end - (long)pos) > 4, JSON_TEXT("UTF will go out of bounds"), return;);
|
||||
json_uchar first = UTF8(pos, end);
|
||||
if (json_unlikely((first > 0xD800) && (first < 0xDBFF) &&
|
||||
(*(pos + 1) == '\\') && (*(pos + 2) == 'u'))){
|
||||
const json_char * original_pos = pos; //if the 2nd character is not correct I need to roll back the iterator
|
||||
pos += 2;
|
||||
json_uchar second = UTF8(pos, end);
|
||||
//surrogate pair, not two characters
|
||||
if (json_unlikely((second > 0xDC00) && (second < 0xDFFF))){
|
||||
result += SurrogatePair(first, second);
|
||||
} else {
|
||||
pos = original_pos;
|
||||
}
|
||||
} else {
|
||||
result += first;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
json_uchar JSONWorker::UTF8(const json_char * & pos, const json_char * const end) json_nothrow {
|
||||
JSON_ASSERT_SAFE(((long)end - (long)pos) > 4, JSON_TEXT("UTF will go out of bounds"), return JSON_TEXT('\0'););
|
||||
#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
|
||||
}
|
||||
|
||||
|
||||
json_char JSONWorker::Hex(const json_char * & pos) json_nothrow {
|
||||
/*
|
||||
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);
|
||||
}
|
||||
|
||||
#ifndef JSON_STRICT
|
||||
inline json_char FromOctal(const json_char * & str, const json_char * const end) json_nothrow {
|
||||
JSON_ASSERT_SAFE(((long)end - (long)str) > 3, JSON_TEXT("Octal will go out of bounds"), return JSON_TEXT('\0'););
|
||||
str += 2;
|
||||
return (json_char)(((((json_uchar)(*(str - 2) - 48))) << 6) | (((json_uchar)(*(str - 1) - 48)) << 3) | ((json_uchar)(*str - 48)));
|
||||
}
|
||||
#endif
|
||||
|
||||
void JSONWorker::SpecialChar(const json_char * & pos, const json_char * const end, json_string & res) json_nothrow {
|
||||
JSON_ASSERT_SAFE(pos != end, JSON_TEXT("Special char termantion"), return;);
|
||||
/*
|
||||
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('u'): //utf character
|
||||
#ifdef JSON_UNICODE
|
||||
UTF(pos, res, end);
|
||||
#else
|
||||
res += UTF8(pos, end);
|
||||
#endif
|
||||
break;
|
||||
#ifndef JSON_STRICT
|
||||
case JSON_TEXT('x'): //hexidecimal ascii code
|
||||
JSON_ASSERT_SAFE(((long)end - (long)pos) > 3, JSON_TEXT("Hex will go out of bounds"), res += JSON_TEXT('\0'); return;);
|
||||
res += Hex(++pos);
|
||||
break;
|
||||
|
||||
#ifdef __GNUC__
|
||||
case JSON_TEXT('0') ... JSON_TEXT('7'):
|
||||
#else
|
||||
//octal encoding
|
||||
case JSON_TEXT('0'):
|
||||
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'):
|
||||
#endif
|
||||
res += FromOctal(pos, end);
|
||||
break;
|
||||
default:
|
||||
res += *pos;
|
||||
break;
|
||||
#elif defined(JSON_DEBUG)
|
||||
default:
|
||||
JSON_FAIL(JSON_TEXT("Unsupported escaped character"));
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef JSON_LESS_MEMORY
|
||||
inline void doflag(const internalJSONNode * flag, bool which, bool x) json_nothrow {
|
||||
if (json_likely(which)){
|
||||
flag -> _name_encoded = x;
|
||||
} else {
|
||||
flag -> _string_encoded = x;
|
||||
}
|
||||
}
|
||||
|
||||
json_string JSONWorker::FixString(const json_string & value_t, const internalJSONNode * flag, bool which) json_nothrow {
|
||||
#define setflag(x) doflag(flag, which, x)
|
||||
#else
|
||||
json_string JSONWorker::FixString(const json_string & value_t, bool & flag) json_nothrow {
|
||||
#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 * const end = value_t.data() + value_t.length();
|
||||
for(const json_char * p = value_t.data(); p != end; ++p){
|
||||
switch (*p){
|
||||
case JSON_TEXT('\\'):
|
||||
setflag(true);
|
||||
SpecialChar(++p, end, res);
|
||||
break;
|
||||
default:
|
||||
res += *p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
shrinkString(res); //because this is actually setting something to be stored, shrink it it need be
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef JSON_UNICODE
|
||||
#ifdef JSON_ESCAPE_WRITES
|
||||
json_string JSONWorker::toSurrogatePair(json_uchar C) json_nothrow {
|
||||
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
|
||||
unsigned short HiSurrogate = 0xD800 | (((unsigned short)((unsigned int)((C >> 16) & 31)) - 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
|
||||
#endif
|
||||
|
||||
#ifdef JSON_ESCAPE_WRITES
|
||||
json_string JSONWorker::toUTF8(json_uchar p) json_nothrow {
|
||||
#ifdef JSON_UNICODE
|
||||
if (json_unlikely(p > 0xFFFF)) return toSurrogatePair(p);
|
||||
#endif
|
||||
json_string res(JSON_TEXT("\\u"));
|
||||
#ifdef JSON_UNICODE
|
||||
START_MEM_SCOPE
|
||||
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;
|
||||
END_MEM_SCOPE
|
||||
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;
|
||||
}
|
||||
#endif
|
||||
|
||||
void JSONWorker::UnfixString(const json_string & value_t, bool flag, json_string & res) json_nothrow {
|
||||
if (!flag){
|
||||
res += value_t;
|
||||
return;
|
||||
}
|
||||
//Re-escapes a json_string so that it can be written out into a JSON file
|
||||
const json_char * const end = value_t.data() + value_t.length();
|
||||
for(const json_char * p = value_t.data(); p != end; ++p){
|
||||
switch(*p){
|
||||
case JSON_TEXT('\"'): //quote character
|
||||
res += JSON_TEXT("\\\"");
|
||||
break;
|
||||
case JSON_TEXT('\\'): //backslash
|
||||
res += JSON_TEXT("\\\\");
|
||||
break;
|
||||
#ifdef JSON_ESCAPE_WRITES
|
||||
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('/'): //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;
|
||||
default:
|
||||
{
|
||||
if (json_unlikely(((json_uchar)(*p) < 32) || ((json_uchar)(*p) > 126))){
|
||||
res += toUTF8((json_uchar)(*p));
|
||||
} else {
|
||||
res += *p;
|
||||
}
|
||||
}
|
||||
break;
|
||||
#else
|
||||
default:
|
||||
res += *p;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef JSON_READ_PRIORITY
|
||||
//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) json_nothrow {
|
||||
#ifdef JSON_COMMENTS
|
||||
JSONNode * child;
|
||||
START_MEM_SCOPE
|
||||
json_string _comment;
|
||||
START_MEM_SCOPE
|
||||
const json_char * runner = ((array) ? value.data() : name.data());
|
||||
#ifdef JSON_DEBUG
|
||||
const json_char * const end = runner + value.length();
|
||||
#endif
|
||||
if (json_unlikely(*runner == JSON_TEMP_COMMENT_IDENTIFIER)){ //multiple comments will be consolidated into one
|
||||
size_t count;
|
||||
const json_char * start;
|
||||
newcomment:
|
||||
count = 0;
|
||||
start = runner + 1;
|
||||
while(*(++runner) != JSON_TEMP_COMMENT_IDENTIFIER){
|
||||
JSON_ASSERT(runner != end, JSON_TEXT("Removing white space failed"));
|
||||
++count;
|
||||
}
|
||||
if (count) _comment += json_string(start, count);
|
||||
if (json_unlikely(*(++runner) == JSON_TEMP_COMMENT_IDENTIFIER)){ //step past the trailing tag
|
||||
_comment += JSON_TEXT('\n');
|
||||
goto newcomment;
|
||||
}
|
||||
}
|
||||
internalJSONNode * myinternal;
|
||||
if (array){
|
||||
myinternal = internalJSONNode::newInternal(name, runner);
|
||||
} else {
|
||||
myinternal = internalJSONNode::newInternal(++runner, value);
|
||||
}
|
||||
child = JSONNode::newJSONNode(myinternal);
|
||||
END_MEM_SCOPE
|
||||
child -> set_comment(_comment);
|
||||
END_MEM_SCOPE
|
||||
const_cast<internalJSONNode*>(parent) -> CHILDREN -> push_back(child); //attach it to the parent node
|
||||
#else
|
||||
if (name.empty()){
|
||||
const_cast<internalJSONNode*>(parent) -> CHILDREN -> push_back(JSONNode::newJSONNode(internalJSONNode::newInternal(name, value))); //attach it to the parent node
|
||||
} else {
|
||||
const_cast<internalJSONNode*>(parent) -> CHILDREN -> push_back(JSONNode::newJSONNode(internalJSONNode::newInternal(json_string(name.begin() + 1, name.end()), value))); //attach it to the parent node
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//Create a subarray
|
||||
void JSONWorker::DoArray(const internalJSONNode * parent, const json_string & value_t) json_nothrow {
|
||||
//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;);
|
||||
if (json_unlikely(value_t.length() <= 2)) return; // just a [] (blank array)
|
||||
|
||||
#ifdef JSON_SAFE
|
||||
json_string newValue; //share this so it has a reserved buffer
|
||||
#endif
|
||||
size_t starting = 1; //ignore the [
|
||||
|
||||
//Not sure what's in the array, so we have to use commas
|
||||
for(size_t ending = FIND_NEXT_RELEVANT(JSON_TEXT(','), value_t, 1);
|
||||
ending != json_string::npos;
|
||||
ending = FIND_NEXT_RELEVANT(JSON_TEXT(','), value_t, starting)){
|
||||
|
||||
#ifdef JSON_SAFE
|
||||
newValue.assign(value_t.begin() + starting, value_t.begin() + ending);
|
||||
JSON_ASSERT_SAFE(FIND_NEXT_RELEVANT(JSON_TEXT(':'), newValue, 0) == json_string::npos, JSON_TEXT("Key/Value pairs are not allowed in arrays"), parent -> Nullify(); return;);
|
||||
NewNode(parent, json_global(EMPTY_JSON_STRING), newValue, true);
|
||||
#else
|
||||
NewNode(parent, json_global(EMPTY_JSON_STRING), json_string(value_t.begin() + starting, value_t.begin() + ending), true);
|
||||
#endif
|
||||
starting = ending + 1;
|
||||
}
|
||||
//since the last one will not find the comma, we have to add it here, but ignore the final ]
|
||||
|
||||
#ifdef JSON_SAFE
|
||||
newValue.assign(value_t.begin() + starting, value_t.end() - 1);
|
||||
JSON_ASSERT_SAFE(FIND_NEXT_RELEVANT(JSON_TEXT(':'), newValue, 0) == json_string::npos, JSON_TEXT("Key/Value pairs are not allowed in arrays"), parent -> Nullify(); return;);
|
||||
NewNode(parent, json_global(EMPTY_JSON_STRING), newValue, true);
|
||||
#else
|
||||
NewNode(parent, json_global(EMPTY_JSON_STRING), json_string(value_t.begin() + starting, value_t.end() - 1), true);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//Create all child nodes
|
||||
void JSONWorker::DoNode(const internalJSONNode * parent, const json_string & value_t) json_nothrow {
|
||||
//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;);
|
||||
if (json_unlikely(value_t.length() <= 2)) return; // just a {} (blank node)
|
||||
|
||||
size_t name_ending = FIND_NEXT_RELEVANT(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.begin() + 1, value_t.begin() + name_ending - 1); //pull the name out
|
||||
for (size_t value_ending = FIND_NEXT_RELEVANT(JSON_TEXT(','), value_t, name_ending), //find the end of the value
|
||||
name_starting = 1; //ignore the {
|
||||
value_ending != json_string::npos;
|
||||
value_ending = FIND_NEXT_RELEVANT(JSON_TEXT(','), value_t, name_ending)){
|
||||
|
||||
NewNode(parent, name, json_string(value_t.begin() + name_ending + 1, value_t.begin() + value_ending), false);
|
||||
name_starting = value_ending + 1;
|
||||
name_ending = FIND_NEXT_RELEVANT(JSON_TEXT(':'), value_t, name_starting);
|
||||
JSON_ASSERT_SAFE(name_ending != json_string::npos, JSON_TEXT("Missing :"), parent -> Nullify(); return;);
|
||||
name.assign(value_t.begin() + name_starting, value_t.begin() + name_ending - 1);
|
||||
}
|
||||
//since the last one will not find the comma, we have to add it here
|
||||
NewNode(parent, name, json_string(value_t.begin() + name_ending + 1, value_t.end() - 1), false);
|
||||
}
|
||||
#endif
|
65
src/libjson/_internal/Source/JSONWorker.h
Normal file
65
src/libjson/_internal/Source/JSONWorker.h
Normal file
|
@ -0,0 +1,65 @@
|
|||
#ifndef JSON_WORKER_H
|
||||
#define JSON_WORKER_H
|
||||
|
||||
#include "JSONNode.h"
|
||||
#include "JSONSharedString.h"
|
||||
|
||||
class JSONWorker {
|
||||
public:
|
||||
static json_string RemoveWhiteSpaceAndComments(const json_string & value_t, bool escapeQuotes) json_nothrow json_read_priority;
|
||||
static json_char * RemoveWhiteSpaceAndCommentsC(const json_string & value_t, bool escapeQuotes) json_nothrow json_read_priority;
|
||||
|
||||
#ifdef JSON_READ_PRIORITY
|
||||
static JSONNode parse(const json_string & json) json_throws(std::invalid_argument) json_read_priority;
|
||||
static JSONNode parse_unformatted(const json_string & json) json_throws(std::invalid_argument) json_read_priority;
|
||||
|
||||
static JSONNode _parse_unformatted(const json_char * json, const json_char * const end) json_throws(std::invalid_argument) json_read_priority;
|
||||
|
||||
static json_char * RemoveWhiteSpace(const json_string & value_t, size_t & len, bool escapeQuotes) json_nothrow json_read_priority;
|
||||
|
||||
static void DoArray(const internalJSONNode * parent, const json_string & value_t) json_nothrow json_read_priority;
|
||||
static void DoNode(const internalJSONNode * parent, const json_string & value_t) json_nothrow json_read_priority;
|
||||
|
||||
#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) json_nothrow json_read_priority;
|
||||
#else
|
||||
#define NAME_ENCODED _name_encoded
|
||||
#define STRING_ENCODED _string_encoded
|
||||
static json_string FixString(const json_string & value_t, bool & flag) json_nothrow json_read_priority;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(JSON_READ_PRIORITY) || defined(JSON_STREAM)
|
||||
#if (JSON_READ_PRIORITY == HIGH) && (!(defined(JSON_LESS_MEMORY)))
|
||||
template<json_char ch>
|
||||
static size_t FindNextRelevant(const json_string & value_t, const size_t pos) json_nothrow json_read_priority;
|
||||
#else
|
||||
static size_t FindNextRelevant(json_char ch, const json_string & value_t, const size_t pos) json_nothrow json_read_priority;
|
||||
#endif
|
||||
#endif
|
||||
static void UnfixString(const json_string & value_t, bool flag, json_string & res) json_nothrow;
|
||||
JSON_PRIVATE
|
||||
#ifdef JSON_READ_PRIORITY
|
||||
static json_char Hex(const json_char * & pos) json_nothrow;
|
||||
static json_uchar UTF8(const json_char * & pos, const json_char * const end) json_nothrow;
|
||||
#endif
|
||||
#ifdef JSON_ESCAPE_WRITES
|
||||
static json_string toUTF8(json_uchar p) json_nothrow;
|
||||
#endif
|
||||
#ifdef JSON_UNICODE
|
||||
static void UTF(const json_char * & pos, json_string & result, const json_char * const end) json_nothrow;
|
||||
#ifdef JSON_ESCAPE_WRITES
|
||||
static json_string toSurrogatePair(json_uchar pos) json_nothrow;
|
||||
#endif
|
||||
#endif
|
||||
#ifdef JSON_READ_PRIORITY
|
||||
static void SpecialChar(const json_char * & pos, const json_char * const end, json_string & res) json_nothrow;
|
||||
static void NewNode(const internalJSONNode * parent, const json_string & name, const json_string & value, bool array) json_nothrow;
|
||||
#endif
|
||||
private:
|
||||
JSONWorker(void);
|
||||
};
|
||||
|
||||
#endif
|
252
src/libjson/_internal/Source/JSONWriter.cpp
Normal file
252
src/libjson/_internal/Source/JSONWriter.cpp
Normal file
|
@ -0,0 +1,252 @@
|
|||
#include "JSONNode.h"
|
||||
#ifdef JSON_WRITE_PRIORITY
|
||||
#include "JSONWorker.h"
|
||||
#include "JSONGlobals.h"
|
||||
|
||||
extern bool used_ascii_one;
|
||||
|
||||
#ifdef JSON_INDENT
|
||||
inline json_string makeIndent(unsigned int amount) json_nothrow json_write_priority;
|
||||
inline json_string makeIndent(unsigned int amount) json_nothrow {
|
||||
if (amount == 0xFFFFFFFF) return json_global(EMPTY_JSON_STRING);
|
||||
json_string result;
|
||||
result.reserve(amount * json_global(INDENT).length());
|
||||
for(unsigned int i = 0; i < amount; ++i){
|
||||
result += json_global(INDENT);
|
||||
}
|
||||
JSON_ASSERT(result.capacity() == amount * json_global(INDENT).length(), JSON_TEXT("makeIndent made a string too big"));
|
||||
return result;
|
||||
}
|
||||
#else
|
||||
inline json_string makeIndent(unsigned int amount) json_nothrow {
|
||||
if (amount == 0xFFFFFFFF) return json_global(EMPTY_JSON_STRING);
|
||||
if (json_likely(amount < 8)){
|
||||
static const json_string cache[] = {
|
||||
json_string(),
|
||||
json_string(JSON_TEXT("\t")),
|
||||
json_string(JSON_TEXT("\t\t")),
|
||||
json_string(JSON_TEXT("\t\t\t")),
|
||||
json_string(JSON_TEXT("\t\t\t\t")),
|
||||
json_string(JSON_TEXT("\t\t\t\t\t")),
|
||||
json_string(JSON_TEXT("\t\t\t\t\t\t")),
|
||||
json_string(JSON_TEXT("\t\t\t\t\t\t\t"))
|
||||
};
|
||||
return cache[amount];
|
||||
}
|
||||
#ifndef JSON_LESS_MEMORY
|
||||
if (json_likely(amount < 16)){
|
||||
static const json_string cache[] = {
|
||||
json_string(JSON_TEXT("\t\t\t\t\t\t\t\t")),
|
||||
json_string(JSON_TEXT("\t\t\t\t\t\t\t\t\t")),
|
||||
json_string(JSON_TEXT("\t\t\t\t\t\t\t\t\t\t")),
|
||||
json_string(JSON_TEXT("\t\t\t\t\t\t\t\t\t\t\t")),
|
||||
json_string(JSON_TEXT("\t\t\t\t\t\t\t\t\t\t\t\t")),
|
||||
json_string(JSON_TEXT("\t\t\t\t\t\t\t\t\t\t\t\t\t")),
|
||||
json_string(JSON_TEXT("\t\t\t\t\t\t\t\t\t\t\t\t\t\t")),
|
||||
json_string(JSON_TEXT("\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"))
|
||||
};
|
||||
return cache[amount - 8];
|
||||
}
|
||||
#if JSON_WRITE_PRIORITY == HIGH
|
||||
if (json_likely(amount < 24)){
|
||||
static const json_string cache[] = {
|
||||
json_string(JSON_TEXT("\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t")),
|
||||
json_string(JSON_TEXT("\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t")),
|
||||
json_string(JSON_TEXT("\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t")),
|
||||
json_string(JSON_TEXT("\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t")),
|
||||
json_string(JSON_TEXT("\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t")),
|
||||
json_string(JSON_TEXT("\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t")),
|
||||
json_string(JSON_TEXT("\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t")),
|
||||
json_string(JSON_TEXT("\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"))
|
||||
};
|
||||
return cache[amount - 16];
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
return json_string(amount, JSON_TEXT('\t'));
|
||||
}
|
||||
#endif
|
||||
|
||||
void internalJSONNode::WriteName(bool formatted, bool arrayChild, json_string & output) const json_nothrow {
|
||||
if (!arrayChild){
|
||||
output += JSON_TEXT("\"");
|
||||
JSONWorker::UnfixString(_name, _name_encoded, output);
|
||||
output += ((formatted) ? JSON_TEXT("\" : ") : JSON_TEXT("\":"));
|
||||
}
|
||||
}
|
||||
|
||||
void internalJSONNode::WriteChildren(unsigned int indent, json_string & output) const json_nothrow {
|
||||
//Iterate through the children and write them
|
||||
if (json_likely(CHILDREN -> empty())) return;
|
||||
|
||||
json_string indent_plus_one;
|
||||
//handle whether or not it's formatted JSON
|
||||
if (indent != 0xFFFFFFFF){ //it's formatted, make the indentation strings
|
||||
indent_plus_one = json_global(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;
|
||||
JSONNode ** it = CHILDREN -> begin();
|
||||
for(JSONNode ** it_end = CHILDREN -> end(); it != it_end; ++it, ++i){
|
||||
|
||||
output += indent_plus_one;
|
||||
(*it) -> internal -> Write(indent, type() == JSON_ARRAY, output);
|
||||
if (json_likely(i < size_minus_one)) output += JSON_TEXT(','); //the last one does not get a comma, but all of the others do
|
||||
}
|
||||
if (indent != 0xFFFFFFFF){
|
||||
output += json_global(NEW_LINE);
|
||||
output += makeIndent(indent - 1);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef JSON_ARRAY_SIZE_ON_ONE_LINE
|
||||
void internalJSONNode::WriteChildrenOneLine(unsigned int indent, json_string & output) const json_nothrow {
|
||||
//Iterate through the children and write them
|
||||
if (json_likely(CHILDREN -> empty())) return;
|
||||
if ((*CHILDREN -> begin()) -> internal -> isContainer()) return WriteChildren(indent, output);
|
||||
|
||||
json_string comma(JSON_TEXT(","));
|
||||
if (indent != 0xFFFFFFFF){
|
||||
comma += JSON_TEXT(' ');
|
||||
}
|
||||
|
||||
//else it's not formatted, leave the indentation strings empty
|
||||
const size_t size_minus_one = CHILDREN -> size() - 1;
|
||||
size_t i = 0;
|
||||
JSONNode ** it = CHILDREN -> begin();
|
||||
for(JSONNode ** it_end = CHILDREN -> end(); it != it_end; ++it, ++i){
|
||||
(*it) -> internal -> Write(indent, type() == JSON_ARRAY, output);
|
||||
if (json_likely(i < size_minus_one)) output += comma; //the last one does not get a comma, but all of the others do
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef JSON_COMMENTS
|
||||
void internalJSONNode::WriteComment(unsigned int indent, json_string & output) const json_nothrow {
|
||||
if (indent == 0xFFFFFFFF) return;
|
||||
if (json_likely(_comment.empty())) return;
|
||||
size_t pos = _comment.find(JSON_TEXT('\n'));
|
||||
|
||||
const json_string current_indent(json_global(NEW_LINE) + makeIndent(indent));
|
||||
|
||||
if (json_likely(pos == json_string::npos)){ //Single line comment
|
||||
output += current_indent;
|
||||
output += json_global(SINGLELINE_COMMENT);
|
||||
output.append(_comment.begin(), _comment.end());
|
||||
output += current_indent;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
Multiline comments
|
||||
*/
|
||||
output += current_indent;
|
||||
#if !(defined(JSON_WRITE_BASH_COMMENTS) || defined(JSON_WRITE_SINGLE_LINE_COMMENTS))
|
||||
const json_string current_indent_plus_one(json_global(NEW_LINE) + makeIndent(indent + 1));
|
||||
output += JSON_TEXT("/*");
|
||||
output += current_indent_plus_one;
|
||||
#endif
|
||||
size_t old = 0;
|
||||
while(pos != json_string::npos){
|
||||
if (json_unlikely(pos && _comment[pos - 1] == JSON_TEXT('\r'))) --pos;
|
||||
#if defined(JSON_WRITE_BASH_COMMENTS) || defined(JSON_WRITE_SINGLE_LINE_COMMENTS)
|
||||
output += json_global(SINGLELINE_COMMENT);
|
||||
#endif
|
||||
output.append(_comment.begin() + old, _comment.begin() + pos);
|
||||
|
||||
#if defined(JSON_WRITE_BASH_COMMENTS) || defined(JSON_WRITE_SINGLE_LINE_COMMENTS)
|
||||
output += current_indent;
|
||||
#else
|
||||
output += current_indent_plus_one;
|
||||
#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)
|
||||
output += json_global(SINGLELINE_COMMENT);
|
||||
#endif
|
||||
output.append(_comment.begin() + old, _comment.end());
|
||||
output += current_indent;
|
||||
#if !(defined(JSON_WRITE_BASH_COMMENTS) || defined(JSON_WRITE_SINGLE_LINE_COMMENTS))
|
||||
output += JSON_TEXT("*/");
|
||||
output += current_indent;
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
inline void internalJSONNode::WriteComment(unsigned int, json_string &) const json_nothrow {}
|
||||
#endif
|
||||
|
||||
void internalJSONNode::DumpRawString(json_string & output) const json_nothrow {
|
||||
//first remove the \1 characters
|
||||
if (used_ascii_one){ //if it hasn't been used yet, don't bother checking
|
||||
json_string result(_string.begin(), _string.end());
|
||||
for(json_string::iterator beg = result.begin(), en = result.end(); beg != en; ++beg){
|
||||
if (*beg == JSON_TEXT('\1')) *beg = JSON_TEXT('\"');
|
||||
}
|
||||
output += result;
|
||||
return;
|
||||
} else {
|
||||
output.append(_string.begin(), _string.end());
|
||||
}
|
||||
}
|
||||
|
||||
void internalJSONNode::Write(unsigned int indent, bool arrayChild, json_string & output) const json_nothrow {
|
||||
const bool formatted = indent != 0xFFFFFFFF;
|
||||
WriteComment(indent, output);
|
||||
|
||||
#if !defined(JSON_PREPARSE) && defined(JSON_READ_PRIORITY)
|
||||
if (!(formatted || fetched)){ //It's not formatted or fetched, just do a raw dump
|
||||
WriteName(false, arrayChild, output);
|
||||
//first remove the \1 characters
|
||||
DumpRawString(output);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
WriteName(formatted, arrayChild, output);
|
||||
//It's either formatted or fetched
|
||||
switch (_type){
|
||||
case JSON_NODE: //got members, write the members
|
||||
Fetch();
|
||||
output += JSON_TEXT("{");
|
||||
WriteChildren(indent, output);
|
||||
output += JSON_TEXT("}");
|
||||
return;
|
||||
case JSON_ARRAY: //write out the child nodes int he array
|
||||
Fetch();
|
||||
output += JSON_TEXT("[");
|
||||
#ifdef JSON_ARRAY_SIZE_ON_ONE_LINE
|
||||
if (size() <= JSON_ARRAY_SIZE_ON_ONE_LINE){
|
||||
WriteChildrenOneLine(indent, output);
|
||||
} else {
|
||||
#endif
|
||||
WriteChildren(indent, output);
|
||||
#ifdef JSON_ARRAY_SIZE_ON_ONE_LINE
|
||||
}
|
||||
#endif
|
||||
output += JSON_TEXT("]");
|
||||
return;
|
||||
case JSON_NUMBER: //write out a literal, without quotes
|
||||
case JSON_NULL:
|
||||
case JSON_BOOL:
|
||||
output.append(_string.begin(), _string.end());
|
||||
return;
|
||||
}
|
||||
|
||||
JSON_ASSERT(_type == JSON_STRING, JSON_TEXT("Unknown json node type"));
|
||||
//If it go here, then it's a json_string
|
||||
#if !defined(JSON_PREPARSE) && defined(JSON_READ_PRIORITY)
|
||||
if (json_likely(fetched)){
|
||||
#endif
|
||||
output += JSON_TEXT("\"");
|
||||
JSONWorker::UnfixString(_string, _string_encoded, output); //It's already been fetched, meaning that it's unescaped
|
||||
output += JSON_TEXT("\"");
|
||||
#if !defined(JSON_PREPARSE) && defined(JSON_READ_PRIORITY)
|
||||
} else {
|
||||
DumpRawString(output); //it hasn't yet been fetched, so it's already unescaped, just do a dump
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
35
src/libjson/_internal/Source/JSON_Base64.h
Normal file
35
src/libjson/_internal/Source/JSON_Base64.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
#ifndef LIBJSON_GUARD_BASE64_H
|
||||
#define LIBJSON_GUARD_BASE64_H
|
||||
|
||||
#include "JSONDebug.h"
|
||||
#if defined(JSON_BINARY) || defined(JSON_EXPOSE_BASE64) //if this is not needed, don't waste space compiling it
|
||||
|
||||
#include "../Dependencies/libbase64++/libbase64++.h"
|
||||
|
||||
class JSONBase64 {
|
||||
public:
|
||||
inline static json_string json_encode64(const unsigned char * binary, size_t bytes) json_nothrow json_cold;
|
||||
inline static std::string json_decode64(const json_string & encoded) json_nothrow json_cold;
|
||||
private:
|
||||
JSONBase64(void);
|
||||
};
|
||||
|
||||
json_string JSONBase64::json_encode64(const unsigned char * binary, size_t bytes) json_nothrow {
|
||||
#if defined JSON_DEBUG || defined JSON_SAFE
|
||||
return libbase64::encode<json_string, json_char, json_uchar, true>(binary, bytes);
|
||||
#else
|
||||
return libbase64::encode<json_string, json_char, json_uchar, false>(binary, bytes);
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string JSONBase64::json_decode64(const json_string & encoded) json_nothrow {
|
||||
#if defined JSON_DEBUG || defined JSON_SAFE
|
||||
return libbase64::decode<json_string, json_char, json_uchar, true>(encoded);
|
||||
#else
|
||||
return libbase64::decode<json_string, json_char, json_uchar, false>(encoded);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
#endif
|
450
src/libjson/_internal/Source/NumberToString.h
Normal file
450
src/libjson/_internal/Source/NumberToString.h
Normal file
|
@ -0,0 +1,450 @@
|
|||
#ifndef NUMBERTOSTRING_H
|
||||
#define NUMBERTOSTRING_H
|
||||
|
||||
#include <limits>
|
||||
#include "JSONDebug.h"
|
||||
#ifdef JSON_LESS_MEMORY
|
||||
#include "JSONMemory.h"
|
||||
#endif
|
||||
#include "JSONSharedString.h"
|
||||
#include <cstdio>
|
||||
#ifdef JSON_STRICT
|
||||
#include <cmath>
|
||||
#endif
|
||||
template <unsigned int GETLENSIZE>
|
||||
struct getLenSize{
|
||||
char tmp[GETLENSIZE == 16]; // compile time assertion
|
||||
enum {GETLEN = 41};
|
||||
};
|
||||
|
||||
template<>
|
||||
struct getLenSize<1>{
|
||||
enum {GETLEN = 5};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct getLenSize<2>{
|
||||
enum {GETLEN = 7};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct getLenSize<4>{
|
||||
enum {GETLEN = 12};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct getLenSize<8>{
|
||||
enum {GETLEN = 22};
|
||||
};
|
||||
|
||||
static inline bool _floatsAreEqual(const json_number & one, const json_number & two) json_pure;
|
||||
static inline bool _floatsAreEqual(const json_number & one, const json_number & two) json_nothrow {
|
||||
return (one > two) ? (one - two) < JSON_FLOAT_THRESHHOLD : (one - two) > -JSON_FLOAT_THRESHHOLD;
|
||||
}
|
||||
|
||||
#ifdef JSON_LESS_MEMORY
|
||||
#define num_str_result s.ptr
|
||||
#endif
|
||||
|
||||
class NumberToString {
|
||||
public:
|
||||
template<typename T>
|
||||
static json_string _itoa(T val) json_nothrow {
|
||||
#ifdef JSON_LESS_MEMORY
|
||||
json_auto<json_char> s(getLenSize<sizeof(T)>::GETLEN);
|
||||
#else
|
||||
json_char num_str_result[getLenSize<sizeof(T)>::GETLEN];
|
||||
#endif
|
||||
num_str_result[getLenSize<sizeof(T)>::GETLEN - 1] = JSON_TEXT('\0'); //null terminator
|
||||
json_char * runner = &num_str_result[getLenSize<sizeof(T)>::GETLEN - 2];
|
||||
bool negative;
|
||||
|
||||
START_MEM_SCOPE
|
||||
long value = (long)val;
|
||||
//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);
|
||||
END_MEM_SCOPE
|
||||
|
||||
//if it's negative, add the negation
|
||||
if (negative){
|
||||
*runner = JSON_TEXT('-');
|
||||
return json_string(runner);
|
||||
}
|
||||
return json_string(runner + 1);
|
||||
}
|
||||
|
||||
#ifndef JSON_LIBRARY
|
||||
template<typename T>
|
||||
static json_string _uitoa(T val) json_nothrow {
|
||||
#ifdef JSON_LESS_MEMORY
|
||||
json_auto<json_char> s(getLenSize<sizeof(T)>::GETLEN);
|
||||
#else
|
||||
json_char num_str_result[getLenSize<sizeof(T)>::GETLEN];
|
||||
#endif
|
||||
num_str_result[getLenSize<sizeof(T)>::GETLEN - 1] = JSON_TEXT('\0'); //null terminator
|
||||
json_char * runner = &num_str_result[getLenSize<sizeof(T)>::GETLEN - 2];
|
||||
|
||||
//create the string
|
||||
START_MEM_SCOPE
|
||||
unsigned long value = (unsigned long)val;
|
||||
do {
|
||||
*runner-- = (json_char)(value % 10) + JSON_TEXT('0');
|
||||
} while(value /= 10);
|
||||
END_MEM_SCOPE
|
||||
|
||||
return json_string(runner + 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef JSON_ISO_STRICT
|
||||
#define EXTRA_LONG
|
||||
#define FLOAT_STRING "%f"
|
||||
#define LFLOAT_STRING L"%f"
|
||||
#else
|
||||
#define EXTRA_LONG long
|
||||
#define FLOAT_STRING "%Lf"
|
||||
#define LFLOAT_STRING L"%Lf"
|
||||
#endif
|
||||
|
||||
static json_string _ftoa(json_number value) json_nothrow {
|
||||
#ifndef JSON_LIBRARY
|
||||
//ScopeCoverage(_ftoa_coverage, 6);
|
||||
if (json_unlikely(value >= 0.0 && _floatsAreEqual(value, (json_number)((unsigned EXTRA_LONG long)value)))){
|
||||
return _uitoa<unsigned EXTRA_LONG long>((unsigned EXTRA_LONG long)value);
|
||||
} else
|
||||
#else
|
||||
//ScopeCoverage(_ftoa_coverage, 5);
|
||||
#endif
|
||||
if (json_unlikely(_floatsAreEqual(value, (json_number)((long EXTRA_LONG)value)))){
|
||||
return _itoa<long EXTRA_LONG>((long EXTRA_LONG)value);
|
||||
}
|
||||
|
||||
#ifdef JSON_LESS_MEMORY
|
||||
json_auto<json_char> s(64);
|
||||
#else
|
||||
json_char num_str_result[64];
|
||||
#endif
|
||||
#ifdef JSON_UNICODE
|
||||
std::swprintf(num_str_result, 63, LFLOAT_STRING, (EXTRA_LONG double)value);
|
||||
#else
|
||||
//Thanks to Salvor Hardin for this Visual C++ fix
|
||||
#ifdef _MSC_VER
|
||||
_snprintf_s(num_str_result, 63, 63, FLOAT_STRING, (EXTRA_LONG double)value); //yes, 63 appears twice using _snprintf_s()
|
||||
#else
|
||||
snprintf(num_str_result, 63, FLOAT_STRING, (EXTRA_LONG double)value);
|
||||
#endif
|
||||
#endif
|
||||
//strip the trailing zeros
|
||||
for(json_char * pos = &num_str_result[0]; *pos; ++pos){
|
||||
if (json_unlikely(*pos == '.')){ //only care about after the decimal
|
||||
for(json_char * runner = pos + 1; *runner; ++runner){
|
||||
if (json_likely(*runner != JSON_TEXT('0'))){
|
||||
pos = runner + 1; //have to go to the end 1.0001
|
||||
}
|
||||
}
|
||||
*pos = JSON_TEXT('\0');
|
||||
break;
|
||||
}
|
||||
}
|
||||
return json_string(num_str_result);
|
||||
}
|
||||
|
||||
#if defined(JSON_SAFE) || defined(JSON_DEBUG)
|
||||
static bool isNumeric(const json_string & str) json_nothrow {
|
||||
const json_char * p = str.c_str();
|
||||
bool decimal = false;
|
||||
bool scientific = false;
|
||||
|
||||
#ifdef JSON_STRICT
|
||||
bool leadingzero = false;
|
||||
#endif
|
||||
|
||||
//first letter is weird
|
||||
switch(*p){
|
||||
case JSON_TEXT('\0'):
|
||||
return false;
|
||||
#ifndef JSON_STRICT
|
||||
case JSON_TEXT('.'):
|
||||
decimal = true;
|
||||
break;
|
||||
case JSON_TEXT('+'):
|
||||
#endif
|
||||
case JSON_TEXT('-'):
|
||||
switch (*(p + 1)){
|
||||
case JSON_TEXT('.'):
|
||||
case JSON_TEXT('e'):
|
||||
case JSON_TEXT('E'):
|
||||
case JSON_TEXT('\0'):
|
||||
return false;
|
||||
case JSON_TEXT('0'):
|
||||
#ifdef JSON_STRICT
|
||||
switch(*(p + 2)){
|
||||
case JSON_TEXT('.'):
|
||||
case JSON_TEXT('e'):
|
||||
case JSON_TEXT('E'):
|
||||
leadingzero = false;
|
||||
break;
|
||||
case JSON_TEXT('\0'):
|
||||
return true;
|
||||
default:
|
||||
leadingzero = true;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
++p;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
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('8'):
|
||||
case JSON_TEXT('9'):
|
||||
break;
|
||||
case JSON_TEXT('0'):
|
||||
++p;
|
||||
#ifdef JSON_STRICT
|
||||
leadingzero = true;
|
||||
#endif
|
||||
switch(*p){
|
||||
case JSON_TEXT('.'):
|
||||
decimal = true;
|
||||
break;
|
||||
case JSON_TEXT('e'):
|
||||
case JSON_TEXT('E'):
|
||||
#ifdef JSON_STRICT
|
||||
leadingzero = false; //not leading, just a zero
|
||||
#endif
|
||||
scientific = true;
|
||||
++p;
|
||||
switch(*p){
|
||||
case JSON_TEXT('\0'):
|
||||
return false;
|
||||
case JSON_TEXT('-'):
|
||||
case JSON_TEXT('+'):
|
||||
#ifndef JSON_STRICT
|
||||
case JSON_TEXT('0'): //cant have a leading zero in scrict
|
||||
#endif
|
||||
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('8'):
|
||||
case JSON_TEXT('9'):
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
#ifndef JSON_STRICT
|
||||
case JSON_TEXT('x'):
|
||||
return (str.find_first_not_of(JSON_TEXT("0123456789ABCDEFabcdef"), 2) == json_string::npos);
|
||||
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'):
|
||||
return (str.find_first_not_of(JSON_TEXT("01234567"), 1) == json_string::npos);
|
||||
#endif
|
||||
case JSON_TEXT('\0'): //just 0
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
++p;
|
||||
|
||||
//next digits
|
||||
while (*p){
|
||||
switch(*p){
|
||||
case JSON_TEXT('.'):
|
||||
if (json_unlikely(decimal)){
|
||||
return false; //multiple decimals
|
||||
}
|
||||
|
||||
if (json_unlikely(scientific)){
|
||||
return false;
|
||||
}
|
||||
decimal = true;
|
||||
break;
|
||||
case JSON_TEXT('e'):
|
||||
case JSON_TEXT('E'):
|
||||
if (json_unlikely(scientific)){
|
||||
return false;
|
||||
}
|
||||
scientific = true;
|
||||
++p;
|
||||
switch(*p){
|
||||
case JSON_TEXT('\0'):
|
||||
return false;
|
||||
case JSON_TEXT('-'):
|
||||
case JSON_TEXT('+'):
|
||||
if (!isdigit(*(p + 1))){
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef JSON_STRICT
|
||||
if (*(p + 1) == JSON_TEXT('0')){ //no leading zeros on scientific notations
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
#ifndef JSON_STRICT
|
||||
case JSON_TEXT('0'): //cant have a leading zero in scrict
|
||||
#endif
|
||||
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('8'):
|
||||
case JSON_TEXT('9'):
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case JSON_TEXT('0'):
|
||||
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('8'):
|
||||
case JSON_TEXT('9'):
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
++p;
|
||||
}
|
||||
#ifdef JSON_STRICT
|
||||
if (leadingzero && !decimal){
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef JSON_STRICT
|
||||
//much faster because no octal or hex support
|
||||
static json_number _atof (const json_char * num){
|
||||
json_number sign = (json_number)1.0;
|
||||
|
||||
//sign
|
||||
if (*num==JSON_TEXT('-')){
|
||||
sign = -1.0;
|
||||
++num;
|
||||
} else {
|
||||
}
|
||||
|
||||
//skip leading zero if one
|
||||
#if defined(JSON_SAFE) || defined(JSON_DEBUG)
|
||||
bool _leadingzeros = *num == JSON_TEXT('0');
|
||||
bool _leadingdigits = false;
|
||||
#endif
|
||||
if (*num == JSON_TEXT('0')){
|
||||
++num;
|
||||
}
|
||||
#ifdef JSON_STRICT
|
||||
else if (json_likely(*num < JSON_TEXT('1') || *num > JSON_TEXT('9'))){
|
||||
return std::numeric_limits<json_number>::signaling_NaN();
|
||||
}
|
||||
#endif
|
||||
|
||||
JSON_ASSERT_SAFE(*num != JSON_TEXT('0'), JSON_TEXT("multiple leading zeros"), return std::numeric_limits<json_number>::signaling_NaN(); );
|
||||
|
||||
// Number
|
||||
json_number n = (json_number)0.0;
|
||||
if (json_likely(*num >= JSON_TEXT('1') && *num <= JSON_TEXT('9'))){
|
||||
#if defined(JSON_SAFE) || defined(JSON_DEBUG)
|
||||
_leadingdigits = true;
|
||||
#endif
|
||||
do {
|
||||
n = (n * 10.0) + (*num++ - JSON_TEXT('0'));
|
||||
} while (*num >= JSON_TEXT('0') && *num <= JSON_TEXT('9'));
|
||||
} else {
|
||||
JSON_ASSERT_SAFE(
|
||||
(*num) == JSON_TEXT('.') || //.xxx
|
||||
(*num) == JSON_TEXT('e') || //0Exxx
|
||||
(*num) == JSON_TEXT('E') || //0exxx
|
||||
(*num) == JSON_TEXT('\0') //end of the number, just zero
|
||||
, JSON_TEXT("first digit not a number, e, period, or terminator"), return std::numeric_limits<json_number>::signaling_NaN(); );
|
||||
}
|
||||
|
||||
// Fractional part
|
||||
json_number scale = (json_number)0.0;
|
||||
if (*num == JSON_TEXT('.')) {
|
||||
JSON_ASSERT_SAFE(_leadingzeros || _leadingdigits, JSON_TEXT("period without leading anything"), return std::numeric_limits<json_number>::signaling_NaN(); );
|
||||
++num;
|
||||
for(; *num >= JSON_TEXT('0') && *num <= JSON_TEXT('9');){
|
||||
n = (n * 10.0) + (*num++ - JSON_TEXT('0'));
|
||||
--scale;
|
||||
};
|
||||
} else {
|
||||
JSON_ASSERT_SAFE(!_leadingzeros || n == 0, JSON_TEXT("leading zero on an int"), return std::numeric_limits<json_number>::signaling_NaN(); );
|
||||
JSON_ASSERT_SAFE(
|
||||
(*num) == JSON_TEXT('e') || //0Exxx
|
||||
(*num) == JSON_TEXT('E') || //0exxx
|
||||
(*num) == JSON_TEXT('\0') //end of the number, just zero
|
||||
, JSON_TEXT("next char not an e or terminator"), return std::numeric_limits<json_number>::signaling_NaN(); );
|
||||
}
|
||||
|
||||
// Exponent
|
||||
int subscale = 0, signsubscale = 1;
|
||||
if (json_unlikely(*num == JSON_TEXT('e') || *num == JSON_TEXT('E'))){
|
||||
++num;
|
||||
switch(*num){
|
||||
case JSON_TEXT('+'):
|
||||
++num;
|
||||
break;
|
||||
case JSON_TEXT('-'):
|
||||
signsubscale = -1;
|
||||
++num;
|
||||
JSON_ASSERT_SAFE(*num != JSON_TEXT('0'), JSON_TEXT("negative cant be followed by leading zero even after E"), return std::numeric_limits<json_number>::signaling_NaN(); );
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
JSON_ASSERT_SAFE(*num != JSON_TEXT('\0'), JSON_TEXT("no exponent for scientific notation"), return std::numeric_limits<json_number>::signaling_NaN(); );
|
||||
while (*num >= JSON_TEXT('0') && *num <= JSON_TEXT('9')){
|
||||
subscale=(subscale * 10) + (*num++ - JSON_TEXT('0'));
|
||||
}
|
||||
}
|
||||
|
||||
JSON_ASSERT_SAFE(*num == JSON_TEXT('\0'), JSON_TEXT("done with number, not at terminator"), return std::numeric_limits<json_number>::signaling_NaN(); );
|
||||
return sign * n * pow((json_number)10.0, scale + subscale * signsubscale); // number = +/- number.fraction * 10^+/- exponent
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
450
src/libjson/_internal/Source/NumberToString.h~
Normal file
450
src/libjson/_internal/Source/NumberToString.h~
Normal file
|
@ -0,0 +1,450 @@
|
|||
#ifndef NUMBERTOSTRING_H
|
||||
#define NUMBERTOSTRING_H
|
||||
|
||||
#include <limits>
|
||||
#include "JSONDebug.h"
|
||||
#ifdef JSON_LESS_MEMORY
|
||||
#include "JSONMemory.h"
|
||||
#endif
|
||||
#include "JSONSharedString.h"
|
||||
#include <cstdio>
|
||||
#ifdef JSON_STRICT
|
||||
#include <cmath>
|
||||
#endif
|
||||
template <unsigned int GETLENSIZE>
|
||||
struct getLenSize{
|
||||
char tmp[GETLENSIZE == 16]; // compile time assertion
|
||||
enum {GETLEN = 41};
|
||||
};
|
||||
|
||||
template<>
|
||||
struct getLenSize<1>{
|
||||
enum {GETLEN = 5};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct getLenSize<2>{
|
||||
enum {GETLEN = 7};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct getLenSize<4>{
|
||||
enum {GETLEN = 12};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct getLenSize<8>{
|
||||
enum {GETLEN = 22};
|
||||
};
|
||||
|
||||
static inline bool _floatsAreEqual(const json_number & one, const json_number & two) json_pure;
|
||||
static inline bool _floatsAreEqual(const json_number & one, const json_number & two) json_nothrow {
|
||||
return (one > two) ? (one - two) < JSON_FLOAT_THRESHHOLD : (one - two) > -JSON_FLOAT_THRESHHOLD;
|
||||
}
|
||||
|
||||
#ifdef JSON_LESS_MEMORY
|
||||
#define num_str_result s.ptr
|
||||
#endif
|
||||
|
||||
class NumberToString {
|
||||
public:
|
||||
template<typename T>
|
||||
static json_string _itoa(T val) json_nothrow {
|
||||
#ifdef JSON_LESS_MEMORY
|
||||
json_auto<json_char> s(getLenSize<sizeof(T)>::GETLEN);
|
||||
#else
|
||||
json_char num_str_result[getLenSize<sizeof(T)>::GETLEN];
|
||||
#endif
|
||||
num_str_result[getLenSize<sizeof(T)>::GETLEN - 1] = JSON_TEXT('\0'); //null terminator
|
||||
json_char * runner = &num_str_result[getLenSize<sizeof(T)>::GETLEN - 2];
|
||||
bool negative;
|
||||
|
||||
START_MEM_SCOPE
|
||||
long value = (long)val;
|
||||
//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);
|
||||
END_MEM_SCOPE
|
||||
|
||||
//if it's negative, add the negation
|
||||
if (negative){
|
||||
*runner = JSON_TEXT('-');
|
||||
return json_string(runner);
|
||||
}
|
||||
return json_string(runner + 1);
|
||||
}
|
||||
|
||||
#ifndef JSON_LIBRARY
|
||||
template<typename T>
|
||||
static json_string _uitoa(T val) json_nothrow {
|
||||
#ifdef JSON_LESS_MEMORY
|
||||
json_auto<json_char> s(getLenSize<sizeof(T)>::GETLEN);
|
||||
#else
|
||||
json_char num_str_result[getLenSize<sizeof(T)>::GETLEN];
|
||||
#endif
|
||||
num_str_result[getLenSize<sizeof(T)>::GETLEN - 1] = JSON_TEXT('\0'); //null terminator
|
||||
json_char * runner = &num_str_result[getLenSize<sizeof(T)>::GETLEN - 2];
|
||||
|
||||
//create the string
|
||||
START_MEM_SCOPE
|
||||
unsigned long value = (unsigned long)val;
|
||||
do {
|
||||
*runner-- = (json_char)(value % 10) + JSON_TEXT('0');
|
||||
} while(value /= 10);
|
||||
END_MEM_SCOPE
|
||||
|
||||
return json_string(runner + 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef JSON_ISO_STRICT
|
||||
#define EXTRA_LONG
|
||||
#define FLOAT_STRING "%f"
|
||||
#define LFLOAT_STRING L"%f"
|
||||
#else
|
||||
#define EXTRA_LONG long
|
||||
#define FLOAT_STRING "%Lf"
|
||||
#define LFLOAT_STRING L"%Lf"
|
||||
#endif
|
||||
|
||||
static json_string _ftoa(json_number value) json_nothrow {
|
||||
#ifndef JSON_LIBRARY
|
||||
//ScopeCoverage(_ftoa_coverage, 6);
|
||||
if (json_unlikely(value >= 0.0 && _floatsAreEqual(value, (json_number)((unsigned EXTRA_LONG long)value)))){
|
||||
return _uitoa<unsigned EXTRA_LONG long>((unsigned EXTRA_LONG long)value);
|
||||
} else
|
||||
#else
|
||||
//ScopeCoverage(_ftoa_coverage, 5);
|
||||
#endif
|
||||
if (json_unlikely(_floatsAreEqual(value, (json_number)((long EXTRA_LONG)value)))){
|
||||
return _itoa<long EXTRA_LONG>((long EXTRA_LONG)value);
|
||||
}
|
||||
|
||||
#ifdef JSON_LESS_MEMORY
|
||||
json_auto<json_char> s(64);
|
||||
#else
|
||||
json_char num_str_result[64];
|
||||
#endif
|
||||
#ifdef JSON_UNICODE
|
||||
std::swprintf(num_str_result, 63, LFLOAT_STRING, (EXTRA_LONG double)value);
|
||||
#else
|
||||
//Thanks to Salvor Hardin for this Visual C++ fix
|
||||
#ifdef _MSC_VER
|
||||
_snprintf_s(num_str_result, 63, 63, FLOAT_STRING, (EXTRA_LONG double)value); //yes, 63 appears twice using _snprintf_s()
|
||||
#else
|
||||
std::snprintf(num_str_result, 63, FLOAT_STRING, (EXTRA_LONG double)value);
|
||||
#endif
|
||||
#endif
|
||||
//strip the trailing zeros
|
||||
for(json_char * pos = &num_str_result[0]; *pos; ++pos){
|
||||
if (json_unlikely(*pos == '.')){ //only care about after the decimal
|
||||
for(json_char * runner = pos + 1; *runner; ++runner){
|
||||
if (json_likely(*runner != JSON_TEXT('0'))){
|
||||
pos = runner + 1; //have to go to the end 1.0001
|
||||
}
|
||||
}
|
||||
*pos = JSON_TEXT('\0');
|
||||
break;
|
||||
}
|
||||
}
|
||||
return json_string(num_str_result);
|
||||
}
|
||||
|
||||
#if defined(JSON_SAFE) || defined(JSON_DEBUG)
|
||||
static bool isNumeric(const json_string & str) json_nothrow {
|
||||
const json_char * p = str.c_str();
|
||||
bool decimal = false;
|
||||
bool scientific = false;
|
||||
|
||||
#ifdef JSON_STRICT
|
||||
bool leadingzero = false;
|
||||
#endif
|
||||
|
||||
//first letter is weird
|
||||
switch(*p){
|
||||
case JSON_TEXT('\0'):
|
||||
return false;
|
||||
#ifndef JSON_STRICT
|
||||
case JSON_TEXT('.'):
|
||||
decimal = true;
|
||||
break;
|
||||
case JSON_TEXT('+'):
|
||||
#endif
|
||||
case JSON_TEXT('-'):
|
||||
switch (*(p + 1)){
|
||||
case JSON_TEXT('.'):
|
||||
case JSON_TEXT('e'):
|
||||
case JSON_TEXT('E'):
|
||||
case JSON_TEXT('\0'):
|
||||
return false;
|
||||
case JSON_TEXT('0'):
|
||||
#ifdef JSON_STRICT
|
||||
switch(*(p + 2)){
|
||||
case JSON_TEXT('.'):
|
||||
case JSON_TEXT('e'):
|
||||
case JSON_TEXT('E'):
|
||||
leadingzero = false;
|
||||
break;
|
||||
case JSON_TEXT('\0'):
|
||||
return true;
|
||||
default:
|
||||
leadingzero = true;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
++p;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
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('8'):
|
||||
case JSON_TEXT('9'):
|
||||
break;
|
||||
case JSON_TEXT('0'):
|
||||
++p;
|
||||
#ifdef JSON_STRICT
|
||||
leadingzero = true;
|
||||
#endif
|
||||
switch(*p){
|
||||
case JSON_TEXT('.'):
|
||||
decimal = true;
|
||||
break;
|
||||
case JSON_TEXT('e'):
|
||||
case JSON_TEXT('E'):
|
||||
#ifdef JSON_STRICT
|
||||
leadingzero = false; //not leading, just a zero
|
||||
#endif
|
||||
scientific = true;
|
||||
++p;
|
||||
switch(*p){
|
||||
case JSON_TEXT('\0'):
|
||||
return false;
|
||||
case JSON_TEXT('-'):
|
||||
case JSON_TEXT('+'):
|
||||
#ifndef JSON_STRICT
|
||||
case JSON_TEXT('0'): //cant have a leading zero in scrict
|
||||
#endif
|
||||
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('8'):
|
||||
case JSON_TEXT('9'):
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
#ifndef JSON_STRICT
|
||||
case JSON_TEXT('x'):
|
||||
return (str.find_first_not_of(JSON_TEXT("0123456789ABCDEFabcdef"), 2) == json_string::npos);
|
||||
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'):
|
||||
return (str.find_first_not_of(JSON_TEXT("01234567"), 1) == json_string::npos);
|
||||
#endif
|
||||
case JSON_TEXT('\0'): //just 0
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
++p;
|
||||
|
||||
//next digits
|
||||
while (*p){
|
||||
switch(*p){
|
||||
case JSON_TEXT('.'):
|
||||
if (json_unlikely(decimal)){
|
||||
return false; //multiple decimals
|
||||
}
|
||||
|
||||
if (json_unlikely(scientific)){
|
||||
return false;
|
||||
}
|
||||
decimal = true;
|
||||
break;
|
||||
case JSON_TEXT('e'):
|
||||
case JSON_TEXT('E'):
|
||||
if (json_unlikely(scientific)){
|
||||
return false;
|
||||
}
|
||||
scientific = true;
|
||||
++p;
|
||||
switch(*p){
|
||||
case JSON_TEXT('\0'):
|
||||
return false;
|
||||
case JSON_TEXT('-'):
|
||||
case JSON_TEXT('+'):
|
||||
if (!isdigit(*(p + 1))){
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef JSON_STRICT
|
||||
if (*(p + 1) == JSON_TEXT('0')){ //no leading zeros on scientific notations
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
#ifndef JSON_STRICT
|
||||
case JSON_TEXT('0'): //cant have a leading zero in scrict
|
||||
#endif
|
||||
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('8'):
|
||||
case JSON_TEXT('9'):
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case JSON_TEXT('0'):
|
||||
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('8'):
|
||||
case JSON_TEXT('9'):
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
++p;
|
||||
}
|
||||
#ifdef JSON_STRICT
|
||||
if (leadingzero && !decimal){
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef JSON_STRICT
|
||||
//much faster because no octal or hex support
|
||||
static json_number _atof (const json_char * num){
|
||||
json_number sign = (json_number)1.0;
|
||||
|
||||
//sign
|
||||
if (*num==JSON_TEXT('-')){
|
||||
sign = -1.0;
|
||||
++num;
|
||||
} else {
|
||||
}
|
||||
|
||||
//skip leading zero if one
|
||||
#if defined(JSON_SAFE) || defined(JSON_DEBUG)
|
||||
bool _leadingzeros = *num == JSON_TEXT('0');
|
||||
bool _leadingdigits = false;
|
||||
#endif
|
||||
if (*num == JSON_TEXT('0')){
|
||||
++num;
|
||||
}
|
||||
#ifdef JSON_STRICT
|
||||
else if (json_likely(*num < JSON_TEXT('1') || *num > JSON_TEXT('9'))){
|
||||
return std::numeric_limits<json_number>::signaling_NaN();
|
||||
}
|
||||
#endif
|
||||
|
||||
JSON_ASSERT_SAFE(*num != JSON_TEXT('0'), JSON_TEXT("multiple leading zeros"), return std::numeric_limits<json_number>::signaling_NaN(); );
|
||||
|
||||
// Number
|
||||
json_number n = (json_number)0.0;
|
||||
if (json_likely(*num >= JSON_TEXT('1') && *num <= JSON_TEXT('9'))){
|
||||
#if defined(JSON_SAFE) || defined(JSON_DEBUG)
|
||||
_leadingdigits = true;
|
||||
#endif
|
||||
do {
|
||||
n = (n * 10.0) + (*num++ - JSON_TEXT('0'));
|
||||
} while (*num >= JSON_TEXT('0') && *num <= JSON_TEXT('9'));
|
||||
} else {
|
||||
JSON_ASSERT_SAFE(
|
||||
(*num) == JSON_TEXT('.') || //.xxx
|
||||
(*num) == JSON_TEXT('e') || //0Exxx
|
||||
(*num) == JSON_TEXT('E') || //0exxx
|
||||
(*num) == JSON_TEXT('\0') //end of the number, just zero
|
||||
, JSON_TEXT("first digit not a number, e, period, or terminator"), return std::numeric_limits<json_number>::signaling_NaN(); );
|
||||
}
|
||||
|
||||
// Fractional part
|
||||
json_number scale = (json_number)0.0;
|
||||
if (*num == JSON_TEXT('.')) {
|
||||
JSON_ASSERT_SAFE(_leadingzeros || _leadingdigits, JSON_TEXT("period without leading anything"), return std::numeric_limits<json_number>::signaling_NaN(); );
|
||||
++num;
|
||||
for(; *num >= JSON_TEXT('0') && *num <= JSON_TEXT('9');){
|
||||
n = (n * 10.0) + (*num++ - JSON_TEXT('0'));
|
||||
--scale;
|
||||
};
|
||||
} else {
|
||||
JSON_ASSERT_SAFE(!_leadingzeros || n == 0, JSON_TEXT("leading zero on an int"), return std::numeric_limits<json_number>::signaling_NaN(); );
|
||||
JSON_ASSERT_SAFE(
|
||||
(*num) == JSON_TEXT('e') || //0Exxx
|
||||
(*num) == JSON_TEXT('E') || //0exxx
|
||||
(*num) == JSON_TEXT('\0') //end of the number, just zero
|
||||
, JSON_TEXT("next char not an e or terminator"), return std::numeric_limits<json_number>::signaling_NaN(); );
|
||||
}
|
||||
|
||||
// Exponent
|
||||
int subscale = 0, signsubscale = 1;
|
||||
if (json_unlikely(*num == JSON_TEXT('e') || *num == JSON_TEXT('E'))){
|
||||
++num;
|
||||
switch(*num){
|
||||
case JSON_TEXT('+'):
|
||||
++num;
|
||||
break;
|
||||
case JSON_TEXT('-'):
|
||||
signsubscale = -1;
|
||||
++num;
|
||||
JSON_ASSERT_SAFE(*num != JSON_TEXT('0'), JSON_TEXT("negative cant be followed by leading zero even after E"), return std::numeric_limits<json_number>::signaling_NaN(); );
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
JSON_ASSERT_SAFE(*num != JSON_TEXT('\0'), JSON_TEXT("no exponent for scientific notation"), return std::numeric_limits<json_number>::signaling_NaN(); );
|
||||
while (*num >= JSON_TEXT('0') && *num <= JSON_TEXT('9')){
|
||||
subscale=(subscale * 10) + (*num++ - JSON_TEXT('0'));
|
||||
}
|
||||
}
|
||||
|
||||
JSON_ASSERT_SAFE(*num == JSON_TEXT('\0'), JSON_TEXT("done with number, not at terminator"), return std::numeric_limits<json_number>::signaling_NaN(); );
|
||||
return sign * n * pow((json_number)10.0, scale + subscale * signsubscale); // number = +/- number.fraction * 10^+/- exponent
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
828
src/libjson/_internal/Source/internalJSONNode.cpp
Normal file
828
src/libjson/_internal/Source/internalJSONNode.cpp
Normal file
|
@ -0,0 +1,828 @@
|
|||
#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
|
||||
#include "JSONGlobals.h"
|
||||
|
||||
internalJSONNode::internalJSONNode(const internalJSONNode & orig) json_nothrow :
|
||||
_type(orig._type), _name(orig._name), _name_encoded(orig._name_encoded),
|
||||
_string(orig._string), _string_encoded(orig._string_encoded), _value(orig._value)
|
||||
initializeMutex(0)
|
||||
initializeRefCount(1)
|
||||
initializeFetch(orig.fetched)
|
||||
initializeComment(orig._comment)
|
||||
initializeChildren(0){
|
||||
|
||||
|
||||
LIBJSON_COPY_CTOR;
|
||||
if (isContainer()){
|
||||
CHILDREN = jsonChildren::newChildren();
|
||||
if (json_likely(!orig.CHILDREN -> empty())){
|
||||
CHILDREN -> reserve(orig.CHILDREN -> size());
|
||||
json_foreach(orig.CHILDREN, myrunner){
|
||||
CHILDREN -> push_back(JSONNode::newJSONNode((*myrunner) -> duplicate()));
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef JSON_MUTEX_CALLBACKS /*-> JSON_MUTEX_CALLBACKS */
|
||||
_set_mutex(orig.mylock, false);
|
||||
#endif /*<- */
|
||||
}
|
||||
|
||||
#ifdef JSON_PREPARSE /*-> JSON_PREPARSE */
|
||||
#define SetFetchedFalseOrDo(code) code
|
||||
#else /*<- else */
|
||||
#define SetFetchedFalseOrDo(code) SetFetched(false)
|
||||
#endif /*<- */
|
||||
|
||||
//this one is specialized because the root can only be array or node
|
||||
#ifdef JSON_READ_PRIORITY /*-> JSON_READ_PRIORITY */
|
||||
internalJSONNode::internalJSONNode(const json_string & unparsed) json_nothrow : _type(), _name(),_name_encoded(false), _string(unparsed), _string_encoded(), _value()
|
||||
initializeMutex(0)
|
||||
initializeRefCount(1)
|
||||
initializeFetch(false)
|
||||
initializeComment(json_global(EMPTY_JSON_STRING))
|
||||
initializeChildren(0){
|
||||
|
||||
LIBJSON_CTOR;
|
||||
switch (unparsed[0]){
|
||||
case JSON_TEXT('{'): //node
|
||||
_type = JSON_NODE;
|
||||
CHILDREN = jsonChildren::newChildren();
|
||||
#ifdef JSON_PREPARSE
|
||||
FetchNode();
|
||||
#endif
|
||||
break;
|
||||
case JSON_TEXT('['): //array
|
||||
_type = JSON_ARRAY;
|
||||
CHILDREN = jsonChildren::newChildren();
|
||||
#ifdef JSON_PREPARSE
|
||||
FetchArray();
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
JSON_FAIL_SAFE(JSON_TEXT("root not starting with either { or ["), Nullify(););
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef JSON_STRICT
|
||||
#define LETTERCASE(x, y)\
|
||||
case JSON_TEXT(x):\
|
||||
case JSON_TEXT(y)
|
||||
#else
|
||||
#define LETTERCASE(x, y)\
|
||||
case JSON_TEXT(x)
|
||||
#endif
|
||||
|
||||
internalJSONNode::internalJSONNode(const json_string & name_t, const json_string & value_t) json_nothrow : _type(), _name_encoded(), _name(JSONWorker::FixString(name_t, NAME_ENCODED)), _string(), _string_encoded(), _value()
|
||||
initializeMutex(0)
|
||||
initializeRefCount(1)
|
||||
initializeFetch(false)
|
||||
initializeComment(json_global(EMPTY_JSON_STRING))
|
||||
initializeChildren(0){
|
||||
|
||||
LIBJSON_CTOR;
|
||||
|
||||
#ifdef JSON_STRICT
|
||||
JSON_ASSERT_SAFE(!value_t.empty(), JSON_TEXT("empty node"), Nullify(); return;);
|
||||
#else
|
||||
if (json_unlikely(value_t.empty())){
|
||||
_type = JSON_NULL;
|
||||
SetFetched(true);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
_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(); 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(); return;);
|
||||
_type = JSON_NODE;
|
||||
CHILDREN = jsonChildren::newChildren();
|
||||
SetFetchedFalseOrDo(FetchNode());
|
||||
break;
|
||||
case JSON_TEXT('['): //an array
|
||||
JSON_ASSERT_SAFE(lastchar == JSON_TEXT(']'), JSON_TEXT("Missing ]"), Nullify(); return;);
|
||||
_type = JSON_ARRAY;
|
||||
CHILDREN = jsonChildren::newChildren();
|
||||
SetFetchedFalseOrDo(FetchArray());
|
||||
break;
|
||||
LETTERCASE('t', 'T'):
|
||||
JSON_ASSERT_SAFE(value_t == json_global(CONST_TRUE), json_string(json_global(ERROR_UNKNOWN_LITERAL) + value_t).c_str(), Nullify(); return;);
|
||||
_value._bool = true;
|
||||
_type = JSON_BOOL;
|
||||
SetFetched(true);
|
||||
break;
|
||||
LETTERCASE('f', 'F'):
|
||||
JSON_ASSERT_SAFE(value_t == json_global(CONST_FALSE), json_string(json_global(ERROR_UNKNOWN_LITERAL) + value_t).c_str(), Nullify(); return;);
|
||||
_value._bool = false;
|
||||
_type = JSON_BOOL;
|
||||
SetFetched(true);
|
||||
break;
|
||||
LETTERCASE('n', 'N'):
|
||||
JSON_ASSERT_SAFE(value_t == json_global(CONST_NULL), json_string(json_global(ERROR_UNKNOWN_LITERAL) + value_t).c_str(), Nullify(); return;);
|
||||
_type = JSON_NULL;
|
||||
SetFetched(true);
|
||||
break;
|
||||
default:
|
||||
JSON_ASSERT_SAFE(NumberToString::isNumeric(value_t), json_string(json_global(ERROR_UNKNOWN_LITERAL) + value_t).c_str(), Nullify(); return;);
|
||||
_type = JSON_NUMBER;
|
||||
SetFetchedFalseOrDo(FetchNumber());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /*<- */
|
||||
|
||||
|
||||
internalJSONNode::~internalJSONNode(void) json_nothrow {
|
||||
LIBJSON_DTOR;
|
||||
#ifdef JSON_MUTEX_CALLBACKS
|
||||
_unset_mutex();
|
||||
#endif /*<- */
|
||||
DELETE_CHILDREN();
|
||||
}
|
||||
|
||||
#ifdef JSON_READ_PRIORITY
|
||||
void internalJSONNode::FetchString(void) const json_nothrow {
|
||||
JSON_ASSERT_SAFE(!_string.empty(), JSON_TEXT("JSON json_string type is empty?"), Nullify(); return;);
|
||||
JSON_ASSERT_SAFE(_string[0] == JSON_TEXT('\"'), JSON_TEXT("JSON json_string type doesn't start with a quotation?"), Nullify(); return;);
|
||||
JSON_ASSERT_SAFE(_string[_string.length() - 1] == JSON_TEXT('\"'), JSON_TEXT("JSON json_string type doesn't end with a quotation?"), Nullify(); return;);
|
||||
_string = JSONWorker::FixString(json_string(_string.begin() + 1, _string.end() - 1), STRING_ENCODED);
|
||||
#ifdef JSON_LESS_MEMORY
|
||||
JSON_ASSERT(_string.capacity() == _string.length(), JSON_TEXT("_string object too large 2"));
|
||||
#endif
|
||||
}
|
||||
|
||||
void internalJSONNode::FetchNode(void) const json_nothrow {
|
||||
JSON_ASSERT_SAFE(!_string.empty(), JSON_TEXT("JSON node type is empty?"), Nullify(); return;);
|
||||
JSON_ASSERT_SAFE(_string[0] == JSON_TEXT('{'), JSON_TEXT("JSON node type doesn't start with a bracket?"), Nullify(); return;);
|
||||
JSON_ASSERT_SAFE(_string[_string.length() - 1] == JSON_TEXT('}'), JSON_TEXT("JSON node type doesn't end with a bracket?"), Nullify(); return;);
|
||||
JSONWorker::DoNode(this, _string);
|
||||
clearString(_string);
|
||||
}
|
||||
|
||||
void internalJSONNode::FetchArray(void) const json_nothrow {
|
||||
JSON_ASSERT_SAFE(!_string.empty(), JSON_TEXT("JSON node type is empty?"), Nullify(); return;);
|
||||
JSON_ASSERT_SAFE(_string[0] == JSON_TEXT('['), JSON_TEXT("JSON node type doesn't start with a square bracket?"), Nullify(); return;);
|
||||
JSON_ASSERT_SAFE(_string[_string.length() - 1] == JSON_TEXT(']'), JSON_TEXT("JSON node type doesn't end with a square bracket?"), Nullify(); return;);
|
||||
JSONWorker::DoArray(this, _string);
|
||||
clearString(_string);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//This one is used by as_int and as_float, so even non-readers need it
|
||||
void internalJSONNode::FetchNumber(void) const json_nothrow {
|
||||
#ifdef JSON_STRICT
|
||||
_value._number = NumberToString::_atof(_string.c_str());
|
||||
#else
|
||||
#ifdef JSON_UNICODE
|
||||
const size_t len = _string.length();
|
||||
#if defined(_MSC_VER) && defined(JSON_SAFE)
|
||||
const size_t bytes = (len * (sizeof(json_char) / sizeof(char))) + 1;
|
||||
json_auto<char> temp(bytes);
|
||||
size_t res;
|
||||
errno_t err = wcstombs_s(&res, temp.ptr, bytes, _string.c_str(), len);
|
||||
if (err != 0){
|
||||
_value._number = (json_number)0.0;
|
||||
return;
|
||||
}
|
||||
#elif defined(JSON_SAFE)
|
||||
const size_t bytes = (len * (sizeof(json_char) / sizeof(char))) + 1;
|
||||
json_auto<char> temp(bytes);
|
||||
size_t res = std::wcstombs(temp.ptr, _string.c_str(), len);
|
||||
if (res == (size_t)-1){
|
||||
_value._number = (json_number)0.0;
|
||||
return;
|
||||
}
|
||||
#else
|
||||
json_auto<char> temp(len + 1);
|
||||
size_t res = std::wcstombs(temp.ptr, _string.c_str(), len);
|
||||
#endif
|
||||
temp.ptr[res] = '\0';
|
||||
_value._number = (json_number)std::atof(temp.ptr);
|
||||
#else
|
||||
_value._number = (json_number)std::atof(_string.c_str());
|
||||
#endif
|
||||
#endif
|
||||
#if((!defined(JSON_CASTABLE) && defined(JSON_LESS_MEMORY)) && !defined(JSON_WRITE_PRIORITY))
|
||||
clearString(_string);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !defined(JSON_PREPARSE) && defined(JSON_READ_PRIORITY)
|
||||
void internalJSONNode::Fetch(void) const json_nothrow {
|
||||
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();
|
||||
#endif
|
||||
}
|
||||
fetched = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
void internalJSONNode::Set(const json_string & val) json_nothrow {
|
||||
makeNotContainer();
|
||||
_type = JSON_STRING;
|
||||
_string = val;
|
||||
shrinkString(_string);
|
||||
_string_encoded = true;
|
||||
SetFetched(true);
|
||||
}
|
||||
|
||||
#ifdef JSON_LIBRARY
|
||||
void internalJSONNode::Set(json_int_t val) json_nothrow {
|
||||
makeNotContainer();
|
||||
_type = JSON_NUMBER;
|
||||
_value._number = (json_number)val;
|
||||
#if(defined(JSON_CASTABLE) || !defined(JSON_LESS_MEMORY) || defined(JSON_WRITE_PRIORITY))
|
||||
_string = NumberToString::_itoa<json_int_t>(val);
|
||||
#else
|
||||
clearString(_string);
|
||||
#endif
|
||||
SetFetched(true);
|
||||
}
|
||||
|
||||
void internalJSONNode::Set(json_number val) json_nothrow {
|
||||
makeNotContainer();
|
||||
_type = JSON_NUMBER;
|
||||
_value._number = val;
|
||||
#if(defined(JSON_CASTABLE) || !defined(JSON_LESS_MEMORY) || defined(JSON_WRITE_PRIORITY))
|
||||
_string = NumberToString::_ftoa(val);
|
||||
#else
|
||||
clearString(_string);
|
||||
#endif
|
||||
SetFetched(true);
|
||||
}
|
||||
#else
|
||||
#if(defined(JSON_CASTABLE) || !defined(JSON_LESS_MEMORY) || defined(JSON_WRITE_PRIORITY))
|
||||
#define SET(converter, type)\
|
||||
void internalJSONNode::Set(type val) json_nothrow {\
|
||||
makeNotContainer();\
|
||||
_type = JSON_NUMBER;\
|
||||
_value._number = (json_number)val;\
|
||||
_string = NumberToString::converter<type>(val);\
|
||||
SetFetched(true);\
|
||||
}
|
||||
#define SET_FLOAT(type) \
|
||||
void internalJSONNode::Set(type val) json_nothrow {\
|
||||
makeNotContainer();\
|
||||
_type = JSON_NUMBER;\
|
||||
_value._number = (json_number)val;\
|
||||
_string = NumberToString::_ftoa(_value._number);\
|
||||
SetFetched(true);\
|
||||
}
|
||||
#else /*<- else */
|
||||
#define SET(converter, type)\
|
||||
void internalJSONNode::Set(type val) json_nothrow {\
|
||||
makeNotContainer();\
|
||||
_type = JSON_NUMBER;\
|
||||
_value._number = (json_number)val;\
|
||||
clearString(_string);\
|
||||
SetFetched(true);\
|
||||
}
|
||||
#define SET_FLOAT(type) \
|
||||
void internalJSONNode::Set(type val) json_nothrow {\
|
||||
makeNotContainer();\
|
||||
_type = JSON_NUMBER;\
|
||||
_value._number = (json_number)val;\
|
||||
clearString(_string);\
|
||||
SetFetched(true);\
|
||||
}
|
||||
#endif
|
||||
#define SET_INTEGER(type) SET(_itoa, type) SET(_uitoa, unsigned type)
|
||||
|
||||
SET_INTEGER(char)
|
||||
SET_INTEGER(short)
|
||||
SET_INTEGER(int)
|
||||
SET_INTEGER(long)
|
||||
#ifndef JSON_ISO_STRICT
|
||||
SET_INTEGER(long long)
|
||||
SET_FLOAT(long double)
|
||||
#endif
|
||||
|
||||
SET_FLOAT(float)
|
||||
SET_FLOAT(double)
|
||||
#endif
|
||||
|
||||
void internalJSONNode::Set(bool val) json_nothrow {
|
||||
makeNotContainer();
|
||||
_type = JSON_BOOL;
|
||||
_value._bool = val;
|
||||
#if(defined(JSON_CASTABLE) || !defined(JSON_LESS_MEMORY) || defined(JSON_WRITE_PRIORITY))
|
||||
_string = val ? json_global(CONST_TRUE) : json_global(CONST_FALSE);
|
||||
#endif
|
||||
SetFetched(true);
|
||||
}
|
||||
|
||||
bool internalJSONNode::IsEqualTo(const internalJSONNode * val) const json_nothrow {
|
||||
if (this == val) return true; //same internal object, so they must be equal (not only for ref counting)
|
||||
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
|
||||
#if !defined(JSON_PREPARSE) && defined(JSON_READ_PRIORITY)
|
||||
Fetch();
|
||||
val -> Fetch();
|
||||
#endif
|
||||
switch (type()){
|
||||
case JSON_STRING:
|
||||
return val -> _string == _string;
|
||||
case JSON_NUMBER:
|
||||
return _floatsAreEqual(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 != NULL, json_global(ERROR_NULL_IN_CHILDREN));
|
||||
JSON_ASSERT(*valrunner != NULL, json_global(ERROR_NULL_IN_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;
|
||||
}
|
||||
|
||||
void internalJSONNode::Nullify(void) const json_nothrow {
|
||||
_type = JSON_NULL;
|
||||
#if(defined(JSON_CASTABLE) || !defined(JSON_LESS_MEMORY) || defined(JSON_WRITE_PRIORITY)) /*-> JSON_CASTABLE || !JSON_LESS_MEMORY || JSON_WRITE_PRIORITY */
|
||||
_string = json_global(CONST_NULL);
|
||||
#else /*<- else */
|
||||
clearString(_string);
|
||||
#endif /*<- */
|
||||
SetFetched(true);
|
||||
}
|
||||
|
||||
#ifdef JSON_MUTEX_CALLBACKS /*-> JSON_MUTEX_CALLBACKS */
|
||||
#define JSON_MUTEX_COPY ,mylock
|
||||
#else /*<- else */
|
||||
#define JSON_MUTEX_COPY
|
||||
#endif /*<- */
|
||||
|
||||
#ifdef JSON_LIBRARY /*-> JSON_LIBRARY */
|
||||
void internalJSONNode::push_back(JSONNode * node) json_nothrow {
|
||||
#else /*<- else */
|
||||
void internalJSONNode::push_back(const JSONNode & node) json_nothrow {
|
||||
#endif /*<- */
|
||||
JSON_ASSERT_SAFE(isContainer(), json_global(ERROR_NON_CONTAINER) + JSON_TEXT("push_back"), return;);
|
||||
#ifdef JSON_LIBRARY /*-> JSON_LIBRARY */
|
||||
#ifdef JSON_MUTEX_CALLBACKS /*-> JSON_MUTEX_CALLBACKS */
|
||||
if (mylock != 0) node -> set_mutex(mylock);
|
||||
#endif /*<- */
|
||||
CHILDREN -> push_back(node);
|
||||
#else /*<- else */
|
||||
CHILDREN -> push_back(JSONNode::newJSONNode(node JSON_MUTEX_COPY));
|
||||
#endif /*<- */
|
||||
}
|
||||
|
||||
void internalJSONNode::push_front(const JSONNode & node) json_nothrow {
|
||||
JSON_ASSERT_SAFE(isContainer(), json_global(ERROR_NON_CONTAINER) + JSON_TEXT("push_front"), return;);
|
||||
CHILDREN -> push_front(JSONNode::newJSONNode(node JSON_MUTEX_COPY));
|
||||
}
|
||||
|
||||
JSONNode * internalJSONNode::pop_back(json_index_t pos) json_nothrow {
|
||||
JSON_ASSERT_SAFE(isContainer(), json_global(ERROR_NON_CONTAINER) + JSON_TEXT("pop_back"), return 0;);
|
||||
JSONNode * result = (*CHILDREN)[pos];
|
||||
JSONNode ** temp = CHILDREN -> begin() + pos;
|
||||
CHILDREN -> erase(temp);
|
||||
return result;
|
||||
}
|
||||
|
||||
JSONNode * internalJSONNode::pop_back(const json_string & name_t) json_nothrow {
|
||||
JSON_ASSERT_SAFE(isContainer(), json_global(ERROR_NON_CONTAINER) + JSON_TEXT("pop_back(str)"), return 0;);
|
||||
if (JSONNode ** res = at(name_t)){
|
||||
JSONNode * result = *res;
|
||||
CHILDREN -> erase(res);
|
||||
return result;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef JSON_CASE_INSENSITIVE_FUNCTIONS /*-> JSON_CASE_INSENSITIVE_FUNCTIONS */
|
||||
JSONNode * internalJSONNode::pop_back_nocase(const json_string & name_t) json_nothrow {
|
||||
JSON_ASSERT_SAFE(isContainer(), json_global(ERROR_NON_CONTAINER) + JSON_TEXT("pop_back_nocase"), return 0;);
|
||||
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) json_nothrow {
|
||||
JSON_ASSERT_SAFE(isContainer(), json_global(ERROR_NON_CONTAINER) + JSON_TEXT("at"), return 0;);
|
||||
Fetch();
|
||||
json_foreach(CHILDREN, myrunner){
|
||||
JSON_ASSERT(*myrunner != NULL, json_global(ERROR_NULL_IN_CHILDREN));
|
||||
if (json_unlikely((*myrunner) -> name() == name_t)) return myrunner;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef JSON_CASE_INSENSITIVE_FUNCTIONS /*-> JSON_CASE_INSENSITIVE_FUNCTIONS */
|
||||
bool internalJSONNode::AreEqualNoCase(const json_char * ch_one, const json_char * ch_two) json_nothrow {
|
||||
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) json_nothrow {
|
||||
JSON_ASSERT_SAFE(isContainer(), json_global(ERROR_NON_CONTAINER) + JSON_TEXT("at_nocase"), return 0;);
|
||||
Fetch();
|
||||
json_foreach(CHILDREN, myrunner){
|
||||
JSON_ASSERT(*myrunner, json_global(ERROR_NULL_IN_CHILDREN));
|
||||
if (json_unlikely(AreEqualNoCase((*myrunner) -> name().c_str(), name_t.c_str()))) return myrunner;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif /*<- */
|
||||
|
||||
#if !defined(JSON_PREPARSE) && defined(JSON_READ_PRIORITY) /*-> JSON_PREPARSE && JSON_READ_PRIORITY */
|
||||
void internalJSONNode::preparse(void) json_nothrow {
|
||||
Fetch();
|
||||
if (isContainer()){
|
||||
json_foreach(CHILDREN, myrunner){
|
||||
(*myrunner) -> preparse();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /*<- */
|
||||
|
||||
internalJSONNode::operator bool() const json_nothrow {
|
||||
Fetch();
|
||||
#ifdef JSON_CASTABLE /*-> JSON_CASTABLE */
|
||||
switch(type()){
|
||||
case JSON_NUMBER:
|
||||
return !_floatsAreEqual(_value._number, (json_number)0.0);
|
||||
case JSON_NULL:
|
||||
return false;
|
||||
}
|
||||
#endif /*<- */
|
||||
JSON_ASSERT(type() == JSON_BOOL, json_global(ERROR_UNDEFINED) + JSON_TEXT("(bool)"));
|
||||
return _value._bool;
|
||||
}
|
||||
|
||||
#ifdef JSON_LIBRARY /*-> JSON_LIBRARY */
|
||||
internalJSONNode::operator json_number() const json_nothrow {
|
||||
Fetch();
|
||||
#ifdef JSON_CASTABLE /*-> JSON_CASTABLE */
|
||||
switch(type()){
|
||||
case JSON_NULL:
|
||||
return (json_number)0.0;
|
||||
case JSON_BOOL:
|
||||
return (json_number)(_value._bool ? 1.0 : 0.0);
|
||||
case JSON_STRING:
|
||||
FetchNumber();
|
||||
}
|
||||
#endif /*<- */
|
||||
JSON_ASSERT(type() == JSON_NUMBER, json_global(ERROR_UNDEFINED) + JSON_TEXT("as_float"));
|
||||
return (json_number)_value._number;
|
||||
}
|
||||
|
||||
internalJSONNode::operator json_int_t() const json_nothrow {
|
||||
Fetch();
|
||||
#ifdef JSON_CASTABLE /*-> JSON_CASTABLE */
|
||||
switch(type()){
|
||||
case JSON_NULL:
|
||||
return 0;
|
||||
case JSON_BOOL:
|
||||
return _value._bool ? 1 : 0;
|
||||
case JSON_STRING:
|
||||
FetchNumber();
|
||||
}
|
||||
#endif /*<- */
|
||||
JSON_ASSERT(type() == JSON_NUMBER, json_global(ERROR_UNDEFINED) + JSON_TEXT("as_int"));
|
||||
JSON_ASSERT(_value._number == (json_number)((json_int_t)_value._number), json_string(JSON_TEXT("as_int will truncate ")) + _string);
|
||||
return (json_int_t)_value._number;
|
||||
}
|
||||
#else /*<- else */
|
||||
#ifndef JSON_ISO_STRICT /*-> !JSON_ISO_STRICT */
|
||||
internalJSONNode::operator long double() const json_nothrow {
|
||||
Fetch();
|
||||
#ifdef JSON_CASTABLE /*-> JSON_CASTABLE */
|
||||
switch(type()){
|
||||
case JSON_NULL:
|
||||
return (long double)0.0;
|
||||
case JSON_BOOL:
|
||||
return (long double)(_value._bool ? 1.0 : 0.0);
|
||||
case JSON_STRING:
|
||||
FetchNumber();
|
||||
}
|
||||
#endif /*<- */
|
||||
JSON_ASSERT(type() == JSON_NUMBER, json_global(ERROR_UNDEFINED) + JSON_TEXT("(long double)"));
|
||||
return (long double)_value._number;
|
||||
}
|
||||
#else /*<- else */
|
||||
internalJSONNode::operator double() const json_nothrow {
|
||||
Fetch();
|
||||
#ifdef JSON_CASTABLE /*-> JSON_CASTABLE */
|
||||
switch(type()){
|
||||
case JSON_NULL:
|
||||
return (double)0.0;
|
||||
case JSON_BOOL:
|
||||
return (double)(_value._bool ? 1.0 : 0.0);
|
||||
case JSON_STRING:
|
||||
FetchNumber();
|
||||
}
|
||||
#endif /*<- */
|
||||
JSON_ASSERT(type() == JSON_NUMBER, json_global(ERROR_UNDEFINED) + JSON_TEXT("(double)"));
|
||||
return (double)_value._number;
|
||||
}
|
||||
#endif /*<- */
|
||||
|
||||
//do whichever one is longer, because it's easy to cast down
|
||||
#ifdef JSON_ISO_STRICT /*-> JSON_ISO_STRICT */
|
||||
internalJSONNode::operator long() const json_nothrow
|
||||
#else /*<- else */
|
||||
internalJSONNode::operator long long() const json_nothrow
|
||||
#endif /*<- */
|
||||
{
|
||||
Fetch();
|
||||
#ifdef JSON_CASTABLE /*-> JSON_CASTABLE */
|
||||
switch(type()){
|
||||
case JSON_NULL:
|
||||
return 0;
|
||||
case JSON_BOOL:
|
||||
return _value._bool ? 1 : 0;
|
||||
case JSON_STRING:
|
||||
FetchNumber();
|
||||
}
|
||||
#endif /*<- */
|
||||
#ifdef JSON_ISO_STRICT /*-> JSON_ISO_STRICT */
|
||||
JSON_ASSERT(type() == JSON_NUMBER, json_global(ERROR_UNDEFINED) + JSON_TEXT("(long)"));
|
||||
JSON_ASSERT(_value._number > LONG_MIN, _string + json_global(ERROR_LOWER_RANGE) + JSON_TEXT("long"));
|
||||
JSON_ASSERT(_value._number < LONG_MAX, _string + json_global(ERROR_UPPER_RANGE) + JSON_TEXT("long"));
|
||||
JSON_ASSERT(_value._number == (json_number)((long)_value._number), json_string(JSON_TEXT("(long) will truncate ")) + _string);
|
||||
return (long)_value._number;
|
||||
#else /*<- else */
|
||||
JSON_ASSERT(type() == JSON_NUMBER, json_global(ERROR_UNDEFINED) + JSON_TEXT("(long long)"));
|
||||
#ifdef LONG_LONG_MAX
|
||||
JSON_ASSERT(_value._number < LONG_LONG_MAX, _string + json_global(ERROR_UPPER_RANGE) + JSON_TEXT("long long"));
|
||||
#elif defined(LLONG_MAX)
|
||||
JSON_ASSERT(_value._number < LLONG_MAX, _string + json_global(ERROR_UPPER_RANGE) + JSON_TEXT("long long"));
|
||||
#endif
|
||||
#ifdef LONG_LONG_MIN
|
||||
JSON_ASSERT(_value._number > LONG_LONG_MIN, _string + json_global(ERROR_LOWER_RANGE) + JSON_TEXT("long long"));
|
||||
#elif defined(LLONG_MAX)
|
||||
JSON_ASSERT(_value._number > LLONG_MIN, _string + json_global(ERROR_LOWER_RANGE) + JSON_TEXT("long long"));
|
||||
#endif
|
||||
|
||||
JSON_ASSERT(_value._number == (json_number)((long long)_value._number), json_string(JSON_TEXT("(long long) will truncate ")) + _string);
|
||||
return (long long)_value._number;
|
||||
#endif /*<- */
|
||||
}
|
||||
|
||||
#ifdef JSON_ISO_STRICT /*-> JSON_ISO_STRICT */
|
||||
internalJSONNode::operator unsigned long() const json_nothrow
|
||||
#else /*<- else */
|
||||
internalJSONNode::operator unsigned long long() const json_nothrow
|
||||
#endif /*<- */
|
||||
{
|
||||
Fetch();
|
||||
#ifdef JSON_CASTABLE /*-> JSON_CASTABLE */
|
||||
switch(type()){
|
||||
case JSON_NULL:
|
||||
return 0;
|
||||
case JSON_BOOL:
|
||||
return _value._bool ? 1 : 0;
|
||||
case JSON_STRING:
|
||||
FetchNumber();
|
||||
}
|
||||
#endif /*<- */
|
||||
#ifdef JSON_ISO_STRICT /*-> JSON_ISO_STRICT */
|
||||
JSON_ASSERT(type() == JSON_NUMBER, json_global(ERROR_UNDEFINED) + JSON_TEXT("(unsigned long)"));
|
||||
JSON_ASSERT(_value._number > 0, _string + json_global(ERROR_LOWER_RANGE) + JSON_TEXT("unsigned long"));
|
||||
JSON_ASSERT(_value._number < ULONG_MAX, _string + json_global(ERROR_UPPER_RANGE) + JSON_TEXT("unsigned long"));
|
||||
JSON_ASSERT(_value._number == (json_number)((unsigned long)_value._number), json_string(JSON_TEXT("(unsigend long) will truncate ")) + _string);
|
||||
return (unsigned long)_value._number;
|
||||
#else /*<- else */
|
||||
JSON_ASSERT(type() == JSON_NUMBER, json_global(ERROR_UNDEFINED) + JSON_TEXT("(unsigned long long)"));
|
||||
JSON_ASSERT(_value._number > 0, _string + json_global(ERROR_LOWER_RANGE) + JSON_TEXT("unsigned long long"));
|
||||
#ifdef ULONG_LONG_MAX
|
||||
JSON_ASSERT(_value._number < ULONG_LONG_MAX, _string + json_global(ERROR_UPPER_RANGE) + JSON_TEXT("unsigned long long"));
|
||||
#elif defined(ULLONG_MAX)
|
||||
JSON_ASSERT(_value._number < ULLONG_MAX, _string + json_global(ERROR_UPPER_RANGE) + JSON_TEXT("unsigned long long"));
|
||||
#endif
|
||||
JSON_ASSERT(_value._number == (json_number)((unsigned long long)_value._number), json_string(JSON_TEXT("(unsigned long long) will truncate ")) + _string);
|
||||
return (unsigned long long)_value._number;
|
||||
#endif /*<- */
|
||||
}
|
||||
#endif /*<- */
|
||||
|
||||
/*
|
||||
These functions are to allow allocation to be completely controlled by the callbacks
|
||||
*/
|
||||
|
||||
#ifdef JSON_MEMORY_POOL /*-> JSON_MEMORY_POOL */
|
||||
#include "JSONMemoryPool.h"
|
||||
static memory_pool<INTERNALNODEPOOL> json_internal_mempool;
|
||||
#endif /*<- */
|
||||
|
||||
void internalJSONNode::deleteInternal(internalJSONNode * ptr) json_nothrow {
|
||||
#ifdef JSON_MEMORY_POOL /*-> JSON_MEMORY_POOL */
|
||||
ptr -> ~internalJSONNode();
|
||||
json_internal_mempool.deallocate((void*)ptr);
|
||||
#elif defined(JSON_MEMORY_CALLBACKS) /*<- else JSON_MEMORY_CALLBACKS */
|
||||
ptr -> ~internalJSONNode();
|
||||
libjson_free<internalJSONNode>(ptr);
|
||||
#else /*<- else */
|
||||
delete ptr;
|
||||
#endif /*<- */
|
||||
}
|
||||
|
||||
internalJSONNode * internalJSONNode::newInternal(char mytype) {
|
||||
#ifdef JSON_MEMORY_POOL /*-> JSON_MEMORY_POOL */
|
||||
return new((internalJSONNode*)json_internal_mempool.allocate()) internalJSONNode(mytype);
|
||||
#elif defined(JSON_MEMORY_CALLBACKS) /*<- else JSON_MEMORY_CALLBACKS */
|
||||
return new(json_malloc<internalJSONNode>(1)) internalJSONNode(mytype);
|
||||
#else /*<- else */
|
||||
return new internalJSONNode(mytype);
|
||||
#endif /*<- */
|
||||
}
|
||||
|
||||
#ifdef JSON_READ_PRIORITY /*-> JSON_READ_PRIORITY */
|
||||
internalJSONNode * internalJSONNode::newInternal(const json_string & unparsed) {
|
||||
#ifdef JSON_MEMORY_POOL /*-> JSON_MEMORY_POOL */
|
||||
return new((internalJSONNode*)json_internal_mempool.allocate()) internalJSONNode(unparsed);
|
||||
#elif defined(JSON_MEMORY_CALLBACKS) /*<- else JSON_MEMORY_CALLBACKS */
|
||||
return new(json_malloc<internalJSONNode>(1)) internalJSONNode(unparsed);
|
||||
#else /*<- else */
|
||||
return new internalJSONNode(unparsed);
|
||||
#endif /*<- */
|
||||
}
|
||||
|
||||
internalJSONNode * internalJSONNode::newInternal(const json_string & name_t, const json_string & value_t) {
|
||||
#ifdef JSON_MEMORY_POOL /*-> JSON_MEMORY_POOL */
|
||||
return new((internalJSONNode*)json_internal_mempool.allocate()) internalJSONNode(name_t, value_t);
|
||||
#elif defined(JSON_MEMORY_CALLBACKS) /*<- else JSON_MEMORY_CALLBACKS */
|
||||
return new(json_malloc<internalJSONNode>(1)) internalJSONNode(name_t, value_t);
|
||||
#else /*<- else */
|
||||
return new internalJSONNode(name_t, value_t);
|
||||
#endif /*<- */
|
||||
}
|
||||
|
||||
#endif /*<- */
|
||||
|
||||
internalJSONNode * internalJSONNode::newInternal(const internalJSONNode & orig) {
|
||||
#ifdef JSON_MEMORY_POOL /*-> JSON_MEMORY_POOL */
|
||||
return new((internalJSONNode*)json_internal_mempool.allocate()) internalJSONNode(orig);
|
||||
#elif defined(JSON_MEMORY_CALLBACKS) /*<- else JSON_MEMORY_CALLBACKS */
|
||||
return new(json_malloc<internalJSONNode>(1)) internalJSONNode(orig);
|
||||
#else /*<- else */
|
||||
return new internalJSONNode(orig);
|
||||
#endif /*<- */
|
||||
}
|
||||
|
||||
#ifdef JSON_DEBUG /*-> JSON_MEMORY_POOL */
|
||||
#ifndef JSON_LIBRARY /*-> JSON_MEMORY_POOL */
|
||||
JSONNode internalJSONNode::Dump(size_t & totalbytes) const json_nothrow {
|
||||
JSONNode dumpage(JSON_NODE);
|
||||
dumpage.set_name(JSON_TEXT("internalJSONNode"));
|
||||
dumpage.push_back(JSON_NEW(JSONNode(JSON_TEXT("this"), (long)this)));
|
||||
|
||||
START_MEM_SCOPE
|
||||
size_t memory = sizeof(internalJSONNode);
|
||||
memory += _name.capacity() * sizeof(json_char);
|
||||
memory += _string.capacity() * sizeof(json_char);
|
||||
if (isContainer()){
|
||||
memory += sizeof(jsonChildren);
|
||||
memory += CHILDREN -> capacity() * sizeof(JSONNode*);
|
||||
}
|
||||
#ifdef JSON_COMMENTS /*-> JSON_COMMENTS */
|
||||
memory += _comment.capacity() * sizeof(json_char);
|
||||
#endif /*<- */
|
||||
totalbytes += memory;
|
||||
dumpage.push_back(JSON_NEW(JSONNode(JSON_TEXT("bytes used"), memory)));
|
||||
END_MEM_SCOPE
|
||||
|
||||
|
||||
#ifdef JSON_REF_COUNT /*-> JSON_REF_COUNT */
|
||||
dumpage.push_back(JSON_NEW(JSONNode(JSON_TEXT("refcount"), refcount)));
|
||||
#endif /*<- */
|
||||
#ifdef JSON_MUTEX_CALLBACKS /*-> 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())));
|
||||
|
||||
dumpage.push_back(JSON_NEW(JSONNode(JSON_TEXT("_name_encoded"), _name_encoded)));
|
||||
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));
|
||||
|
||||
if ((type() == JSON_BOOL) || (type() == JSON_NUMBER)){
|
||||
JSONNode unio(JSON_NODE);
|
||||
unio.set_name(JSON_TEXT("_value"));
|
||||
if (type() == JSON_BOOL){
|
||||
unio.push_back(JSON_NEW(JSONNode(JSON_TEXT("_bool"), _value._bool)));
|
||||
} else if (type() == JSON_NUMBER){
|
||||
unio.push_back(JSON_NEW(JSONNode(JSON_TEXT("_number"), _value._number)));
|
||||
}
|
||||
dumpage.push_back(JSON_NEW(unio));
|
||||
}
|
||||
|
||||
#if !defined(JSON_PREPARSE) && defined(JSON_READ_PRIORITY) /*-> !JSON_PREPARSE && JSON_READ_PRIORITY */
|
||||
dumpage.push_back(JSON_NEW(JSONNode(JSON_TEXT("fetched"), fetched)));
|
||||
#endif /*<- */
|
||||
|
||||
#ifdef JSON_COMMENTS /*-> 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 /*<- */
|
||||
|
||||
if (isContainer()){
|
||||
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 /*<- */
|
504
src/libjson/_internal/Source/internalJSONNode.h
Normal file
504
src/libjson/_internal/Source/internalJSONNode.h
Normal file
|
@ -0,0 +1,504 @@
|
|||
#ifndef INTERNAL_JSONNODE_H
|
||||
#define INTERNAL_JSONNODE_H
|
||||
|
||||
#include "JSONDebug.h"
|
||||
#include "JSONChildren.h"
|
||||
#include "JSONMemory.h"
|
||||
#include "JSONGlobals.h"
|
||||
#ifdef JSON_DEBUG
|
||||
#include <climits> //to check int value
|
||||
#endif
|
||||
#include "JSONSharedString.h"
|
||||
|
||||
#ifdef JSON_LESS_MEMORY
|
||||
#ifdef __GNUC__
|
||||
#pragma pack(push, 1)
|
||||
#elif _MSC_VER
|
||||
#pragma pack(push, internalJSONNode_pack, 1)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
This class is the work horse of libjson, it handles all of the
|
||||
functinality of JSONNode. This object is reference counted for
|
||||
speed and memory reasons.
|
||||
|
||||
If JSON_REF_COUNT is not on, this internal structure still has an important
|
||||
purpose, as it can be passed around by JSONNoders that are flagged as temporary
|
||||
*/
|
||||
|
||||
class JSONNode; //forward declaration
|
||||
|
||||
#ifndef JSON_LIBRARY
|
||||
#define DECL_SET_INTEGER(type) void Set(type) json_nothrow json_write_priority; void Set(unsigned type) json_nothrow json_write_priority;
|
||||
#define DECL_CAST_OP(type) operator type() const json_nothrow; operator unsigned type() const json_nothrow;
|
||||
#endif
|
||||
|
||||
#ifdef JSON_MUTEX_CALLBACKS
|
||||
#define initializeMutex(x) ,mylock(x)
|
||||
#else
|
||||
#define initializeMutex(x)
|
||||
#endif
|
||||
|
||||
#if defined(JSON_PREPARSE) || !defined(JSON_READ_PRIORITY)
|
||||
#define SetFetched(b) (void)0
|
||||
#define Fetch() (void)0
|
||||
#define initializeFetch(x)
|
||||
#else
|
||||
#define initializeFetch(x) ,fetched(x)
|
||||
#endif
|
||||
|
||||
#ifdef JSON_REF_COUNT
|
||||
#define initializeRefCount(x) ,refcount(x)
|
||||
#else
|
||||
#define initializeRefCount(x)
|
||||
#endif
|
||||
|
||||
#ifdef JSON_COMMENTS
|
||||
#define initializeComment(x) ,_comment(x)
|
||||
#else
|
||||
#define initializeComment(x)
|
||||
#endif
|
||||
|
||||
#ifdef JSON_LESS_MEMORY
|
||||
#define CHILDREN _value.Children
|
||||
#define DELETE_CHILDREN()\
|
||||
if (isContainer()){\
|
||||
jsonChildren::deleteChildren(CHILDREN);\
|
||||
}
|
||||
#define CHILDREN_TO_NULL() (void)0
|
||||
#define initializeChildren(x)
|
||||
#else
|
||||
#define CHILDREN Children
|
||||
#define DELETE_CHILDREN()\
|
||||
if (CHILDREN != 0) jsonChildren::deleteChildren(CHILDREN);
|
||||
#define CHILDREN_TO_NULL() CHILDREN = 0
|
||||
#define makeNotContainer() (void)0
|
||||
#define makeContainer() if (!CHILDREN) CHILDREN = jsonChildren::newChildren()
|
||||
#define initializeChildren(x) ,CHILDREN(x)
|
||||
#endif
|
||||
|
||||
class internalJSONNode {
|
||||
public:
|
||||
LIBJSON_OBJECT(internalJSONNode);
|
||||
internalJSONNode(char mytype = JSON_NULL) json_nothrow json_hot;
|
||||
#ifdef JSON_READ_PRIORITY
|
||||
internalJSONNode(const json_string & unparsed) json_nothrow json_hot;
|
||||
internalJSONNode(const json_string & name_t, const json_string & value_t) json_nothrow json_read_priority;
|
||||
#endif
|
||||
internalJSONNode(const internalJSONNode & orig) json_nothrow json_hot;
|
||||
internalJSONNode & operator = (const internalJSONNode &) json_nothrow json_hot;
|
||||
~internalJSONNode(void) json_nothrow json_hot;
|
||||
|
||||
static internalJSONNode * newInternal(char mytype = JSON_NULL) json_hot;
|
||||
#ifdef JSON_READ_PRIORITY
|
||||
static internalJSONNode * newInternal(const json_string & unparsed) json_hot;
|
||||
static internalJSONNode * newInternal(const json_string & name_t, const json_string & value_t) json_hot;
|
||||
#endif
|
||||
static internalJSONNode * newInternal(const internalJSONNode & orig) json_hot; //not copyable, only by this class
|
||||
static void deleteInternal(internalJSONNode * ptr) json_nothrow json_hot;
|
||||
|
||||
json_index_t size(void) const json_nothrow json_read_priority;
|
||||
bool empty(void) const json_nothrow;
|
||||
unsigned char type(void) const json_nothrow json_read_priority;
|
||||
|
||||
json_string name(void) const json_nothrow json_read_priority;
|
||||
void setname(const json_string & newname) json_nothrow json_write_priority;
|
||||
#ifdef JSON_COMMENTS
|
||||
void setcomment(const json_string & comment) json_nothrow;
|
||||
json_string getcomment(void) const json_nothrow;
|
||||
#endif
|
||||
|
||||
#if !defined(JSON_PREPARSE) && defined(JSON_READ_PRIORITY)
|
||||
void preparse(void) json_nothrow;
|
||||
#endif
|
||||
|
||||
#ifdef JSON_LIBRARY
|
||||
void push_back(JSONNode * node) json_nothrow;
|
||||
#else
|
||||
void push_back(const JSONNode & node) json_nothrow;
|
||||
#endif
|
||||
void reserve(json_index_t siz) json_nothrow;
|
||||
void push_front(const JSONNode & node) json_nothrow;
|
||||
JSONNode * pop_back(json_index_t pos) json_nothrow;
|
||||
JSONNode * pop_back(const json_string & name_t) json_nothrow;
|
||||
#ifdef JSON_CASE_INSENSITIVE_FUNCTIONS
|
||||
JSONNode * pop_back_nocase(const json_string & name_t) json_nothrow;
|
||||
#endif
|
||||
|
||||
JSONNode * at(json_index_t pos) json_nothrow;
|
||||
//These return ** because pop_back needs them
|
||||
JSONNode ** at(const json_string & name_t) json_nothrow;
|
||||
#ifdef JSON_CASE_INSENSITIVE_FUNCTIONS
|
||||
JSONNode ** at_nocase(const json_string & name_t) json_nothrow;
|
||||
#endif
|
||||
|
||||
void Set(const json_string & val) json_nothrow json_write_priority;
|
||||
#ifdef JSON_LIBRARY
|
||||
void Set(json_number val) json_nothrow json_write_priority;
|
||||
void Set(json_int_t val) json_nothrow json_write_priority;
|
||||
operator json_int_t() const json_nothrow;
|
||||
operator json_number() const json_nothrow;
|
||||
#else
|
||||
DECL_SET_INTEGER(char)
|
||||
DECL_SET_INTEGER(short)
|
||||
DECL_SET_INTEGER(int)
|
||||
DECL_SET_INTEGER(long)
|
||||
#ifndef JSON_ISO_STRICT
|
||||
DECL_SET_INTEGER(long long)
|
||||
void Set(long double val) json_nothrow json_write_priority;
|
||||
#endif
|
||||
void Set(float val) json_nothrow json_write_priority;
|
||||
void Set(double val) json_nothrow json_write_priority;
|
||||
|
||||
|
||||
DECL_CAST_OP(char)
|
||||
DECL_CAST_OP(short)
|
||||
DECL_CAST_OP(int)
|
||||
DECL_CAST_OP(long)
|
||||
#ifndef JSON_ISO_STRICT
|
||||
DECL_CAST_OP(long long)
|
||||
operator long double() const json_nothrow;
|
||||
#endif
|
||||
operator float() const json_nothrow;
|
||||
operator double() const json_nothrow;
|
||||
#endif
|
||||
operator json_string()const json_nothrow;
|
||||
operator bool() const json_nothrow;
|
||||
void Set(bool val) json_nothrow;
|
||||
|
||||
bool IsEqualTo(const json_string & val) const json_nothrow;
|
||||
bool IsEqualTo(bool val) const json_nothrow;
|
||||
bool IsEqualTo(const internalJSONNode * val) const json_nothrow;
|
||||
|
||||
template<typename T>
|
||||
bool IsEqualToNum(T val) const json_nothrow;
|
||||
|
||||
internalJSONNode * incRef(void) json_nothrow;
|
||||
#ifdef JSON_REF_COUNT
|
||||
void decRef(void) json_nothrow json_hot;
|
||||
bool hasNoReferences(void) json_nothrow json_hot;
|
||||
#endif
|
||||
internalJSONNode * makeUnique(void) json_nothrow json_hot;
|
||||
|
||||
JSONNode ** begin(void) const json_nothrow;
|
||||
JSONNode ** end(void) const json_nothrow;
|
||||
bool Fetched(void) const json_nothrow json_hot;
|
||||
#ifdef JSON_MUTEX_CALLBACKS
|
||||
void _set_mutex(void * mutex, bool unset = true) json_nothrow json_cold;
|
||||
void _unset_mutex(void) json_nothrow json_cold;
|
||||
#endif
|
||||
|
||||
#ifdef JSON_WRITE_PRIORITY
|
||||
void DumpRawString(json_string & output) const json_nothrow json_write_priority;
|
||||
void WriteName(bool formatted, bool arrayChild, json_string & output) const json_nothrow json_write_priority;
|
||||
#ifdef JSON_ARRAY_SIZE_ON_ONE_LINE
|
||||
void WriteChildrenOneLine(unsigned int indent, json_string & output) const json_nothrow json_write_priority;
|
||||
#endif
|
||||
void WriteChildren(unsigned int indent, json_string & output) const json_nothrow json_write_priority;
|
||||
void WriteComment(unsigned int indent, json_string & output) const json_nothrow json_write_priority;
|
||||
void Write(unsigned int indent, bool arrayChild, json_string & output) const json_nothrow json_write_priority;
|
||||
#endif
|
||||
|
||||
|
||||
inline bool isContainer(void) const json_nothrow {
|
||||
return (_type == JSON_NODE || _type == JSON_ARRAY);
|
||||
}
|
||||
inline bool isNotContainer(void) const json_nothrow {
|
||||
return (_type != JSON_NODE && _type != JSON_ARRAY);
|
||||
}
|
||||
|
||||
#ifdef JSON_LESS_MEMORY
|
||||
inline void makeNotContainer(void){
|
||||
if (isContainer()){
|
||||
jsonChildren::deleteChildren(CHILDREN);
|
||||
}
|
||||
}
|
||||
inline void makeContainer(void){
|
||||
if (isNotContainer()){
|
||||
CHILDREN = jsonChildren::newChildren();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void Nullify(void) const json_nothrow;
|
||||
|
||||
#if !defined(JSON_PREPARSE) && defined(JSON_READ_PRIORITY)
|
||||
void SetFetched(bool val) const json_nothrow json_hot;
|
||||
void Fetch(void) const json_nothrow json_hot; //it's const because it doesn't change the VALUE of the function
|
||||
#endif
|
||||
|
||||
#ifdef JSON_READ_PRIORITY
|
||||
void FetchString(void) const json_nothrow json_read_priority;
|
||||
void FetchNode(void) const json_nothrow json_read_priority;
|
||||
void FetchArray(void) const json_nothrow json_read_priority;
|
||||
#endif
|
||||
void FetchNumber(void) const json_nothrow json_read_priority;
|
||||
|
||||
#ifdef JSON_CASE_INSENSITIVE_FUNCTIONS
|
||||
static bool AreEqualNoCase(const json_char * ch_one, const json_char * ch_two) json_nothrow json_read_priority;
|
||||
#endif
|
||||
|
||||
inline void clearname(void) json_nothrow {
|
||||
clearString(_name);
|
||||
}
|
||||
|
||||
#ifdef JSON_DEBUG
|
||||
#ifndef JSON_LIBRARY
|
||||
JSONNode Dump(size_t & totalmemory) const json_nothrow;
|
||||
JSONNode DumpMutex(void) const json_nothrow;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
mutable unsigned char _type BITS(3);
|
||||
|
||||
json_string _name;
|
||||
mutable bool _name_encoded BITS(1); //must be above name due to initialization list order
|
||||
|
||||
mutable json_string _string; //these are both mutable because the string can change when it's fetched
|
||||
mutable bool _string_encoded BITS(1);
|
||||
|
||||
//the value of the json
|
||||
union value_union_t {
|
||||
bool _bool BITS(1);
|
||||
json_number _number;
|
||||
#ifdef JSON_LESS_MEMORY
|
||||
jsonChildren * Children;
|
||||
#endif
|
||||
};
|
||||
mutable value_union_t _value; //internal structure changes depending on type
|
||||
|
||||
#ifdef JSON_MUTEX_CALLBACKS
|
||||
void * mylock;
|
||||
#endif
|
||||
|
||||
#ifdef JSON_REF_COUNT
|
||||
size_t refcount PACKED(20);
|
||||
#endif
|
||||
|
||||
#if !defined(JSON_PREPARSE) && defined(JSON_READ_PRIORITY)
|
||||
mutable bool fetched BITS(1);
|
||||
#endif
|
||||
|
||||
#ifdef JSON_COMMENTS
|
||||
json_string _comment;
|
||||
#endif
|
||||
|
||||
#ifndef JSON_LESS_MEMORY
|
||||
jsonChildren * CHILDREN;
|
||||
#endif
|
||||
};
|
||||
|
||||
inline internalJSONNode::internalJSONNode(char mytype) json_nothrow : _type(mytype), _name(), _name_encoded(), _string(), _string_encoded(), _value()
|
||||
initializeMutex(0)
|
||||
initializeRefCount(1)
|
||||
initializeFetch(true)
|
||||
initializeComment(json_global(EMPTY_JSON_STRING))
|
||||
initializeChildren((_type == JSON_NODE || _type == JSON_ARRAY) ? jsonChildren::newChildren() : 0){
|
||||
|
||||
LIBJSON_CTOR;
|
||||
|
||||
#ifdef JSON_LESS_MEMORY
|
||||
//if not less memory, its in the initialization list
|
||||
if (isContainer()){
|
||||
CHILDREN = jsonChildren::newChildren();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
inline internalJSONNode * internalJSONNode::incRef(void) json_nothrow {
|
||||
#ifdef JSON_REF_COUNT
|
||||
++refcount;
|
||||
return this;
|
||||
#else
|
||||
return makeUnique();
|
||||
#endif
|
||||
}
|
||||
|
||||
inline json_index_t internalJSONNode::size(void) const json_nothrow {
|
||||
if (isNotContainer()) return 0;
|
||||
Fetch();
|
||||
return CHILDREN -> size();
|
||||
}
|
||||
|
||||
inline bool internalJSONNode::empty(void) const json_nothrow {
|
||||
if (isNotContainer()) return true;
|
||||
Fetch();
|
||||
return CHILDREN -> empty();
|
||||
}
|
||||
|
||||
inline unsigned char internalJSONNode::type(void) const json_nothrow {
|
||||
return _type;
|
||||
}
|
||||
|
||||
inline json_string internalJSONNode::name(void) const json_nothrow {
|
||||
return _name;
|
||||
}
|
||||
|
||||
inline void internalJSONNode::setname(const json_string & newname) json_nothrow {
|
||||
#ifdef JSON_LESS_MEMORY
|
||||
JSON_ASSERT(newname.capacity() == newname.length(), JSON_TEXT("name object too large"));
|
||||
#endif
|
||||
_name = newname;
|
||||
_name_encoded = true;
|
||||
}
|
||||
|
||||
#ifdef JSON_COMMENTS
|
||||
inline void internalJSONNode::setcomment(const json_string & comment) json_nothrow {
|
||||
_comment = comment;
|
||||
}
|
||||
|
||||
inline json_string internalJSONNode::getcomment(void) const json_nothrow {
|
||||
return _comment;
|
||||
}
|
||||
#endif
|
||||
|
||||
inline bool internalJSONNode::IsEqualTo(const json_string & val) const json_nothrow {
|
||||
if (type() != JSON_STRING) return false;
|
||||
Fetch();
|
||||
return _string == val;
|
||||
}
|
||||
|
||||
inline bool internalJSONNode::IsEqualTo(bool val) const json_nothrow {
|
||||
if (type() != JSON_BOOL) return false;
|
||||
Fetch();
|
||||
return val == _value._bool;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline bool internalJSONNode::IsEqualToNum(T val) const json_nothrow {
|
||||
if (type() != JSON_NUMBER) return false;
|
||||
Fetch();
|
||||
return (json_number)val == _value._number;
|
||||
}
|
||||
|
||||
#ifdef JSON_REF_COUNT
|
||||
inline void internalJSONNode::decRef(void) json_nothrow {
|
||||
JSON_ASSERT(refcount != 0, JSON_TEXT("decRef on a 0 refcount internal"));
|
||||
--refcount;
|
||||
}
|
||||
|
||||
inline bool internalJSONNode::hasNoReferences(void) json_nothrow {
|
||||
return refcount == 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
inline internalJSONNode * internalJSONNode::makeUnique(void) json_nothrow {
|
||||
#ifdef JSON_REF_COUNT
|
||||
if (refcount > 1){
|
||||
decRef();
|
||||
return newInternal(*this);
|
||||
}
|
||||
JSON_ASSERT(refcount == 1, JSON_TEXT("makeUnique on a 0 refcount internal"));
|
||||
return this;
|
||||
#else
|
||||
return newInternal(*this);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !defined(JSON_PREPARSE) && defined(JSON_READ_PRIORITY)
|
||||
inline void internalJSONNode::SetFetched(bool val) const json_nothrow {
|
||||
fetched = val;
|
||||
}
|
||||
#endif
|
||||
|
||||
inline bool internalJSONNode::Fetched(void) const json_nothrow {
|
||||
#if !defined(JSON_PREPARSE) && defined(JSON_READ_PRIORITY)
|
||||
return fetched;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline JSONNode ** internalJSONNode::begin(void) const json_nothrow {
|
||||
JSON_ASSERT_SAFE(isContainer(), json_global(ERROR_NON_CONTAINER) + JSON_TEXT("begin"), return 0;);
|
||||
Fetch();
|
||||
return CHILDREN -> begin();
|
||||
}
|
||||
|
||||
inline JSONNode ** internalJSONNode::end(void) const json_nothrow {
|
||||
JSON_ASSERT_SAFE(isContainer(), json_global(ERROR_NON_CONTAINER) + JSON_TEXT("end"), return 0;);
|
||||
Fetch();
|
||||
return CHILDREN -> end();
|
||||
}
|
||||
|
||||
inline JSONNode * internalJSONNode::at(json_index_t pos) json_nothrow {
|
||||
JSON_ASSERT_SAFE(isContainer(), JSON_TEXT("calling at on non-container type"), return 0;);
|
||||
Fetch();
|
||||
return (*CHILDREN)[pos];
|
||||
}
|
||||
|
||||
#if defined(JSON_LESS_MEMORY) && defined(__GNUC__)
|
||||
inline void internalJSONNode::reserve(json_index_t __attribute__((unused)) siz) json_nothrow
|
||||
#else
|
||||
inline void internalJSONNode::reserve(json_index_t siz) json_nothrow
|
||||
#endif
|
||||
{
|
||||
JSON_ASSERT_SAFE(isContainer(), json_global(ERROR_NON_CONTAINER) + JSON_TEXT("reserve"), return;);
|
||||
Fetch();
|
||||
jsonChildren::reserve2(CHILDREN, siz);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
cast operators
|
||||
*/
|
||||
#ifndef JSON_LIBRARY
|
||||
#ifdef JSON_ISO_STRICT
|
||||
#define BASE_CONVERT_TYPE long
|
||||
#else
|
||||
#define BASE_CONVERT_TYPE long long
|
||||
#endif
|
||||
|
||||
#define IMP_SMALLER_INT_CAST_OP(_type, type_max, type_min)\
|
||||
inline internalJSONNode::operator _type() const json_nothrow {\
|
||||
JSON_ASSERT(_value._number > type_min, _string + json_global(ERROR_LOWER_RANGE) + JSON_TEXT(#_type));\
|
||||
JSON_ASSERT(_value._number < type_max, _string + json_global(ERROR_UPPER_RANGE) + JSON_TEXT(#_type));\
|
||||
JSON_ASSERT(_value._number == (json_number)((_type)(_value._number)), json_string(JSON_TEXT("(")) + json_string(JSON_TEXT(#_type)) + json_string(JSON_TEXT(") will truncate ")) + _string);\
|
||||
return (_type)static_cast<BASE_CONVERT_TYPE>(*this);\
|
||||
}
|
||||
|
||||
IMP_SMALLER_INT_CAST_OP(char, CHAR_MAX, CHAR_MIN)
|
||||
IMP_SMALLER_INT_CAST_OP(unsigned char, UCHAR_MAX, 0)
|
||||
IMP_SMALLER_INT_CAST_OP(short, SHRT_MAX, SHRT_MIN)
|
||||
IMP_SMALLER_INT_CAST_OP(unsigned short, USHRT_MAX, 0)
|
||||
IMP_SMALLER_INT_CAST_OP(int, INT_MAX, INT_MIN)
|
||||
IMP_SMALLER_INT_CAST_OP(unsigned int, UINT_MAX, 0)
|
||||
|
||||
#ifndef JSON_ISO_STRICT
|
||||
IMP_SMALLER_INT_CAST_OP(long, LONG_MAX, LONG_MIN)
|
||||
IMP_SMALLER_INT_CAST_OP(unsigned long, ULONG_MAX, 0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
inline internalJSONNode::operator json_string() const json_nothrow {
|
||||
Fetch();
|
||||
return _string;
|
||||
}
|
||||
|
||||
|
||||
#ifndef JSON_LIBRARY
|
||||
#ifndef JSON_ISO_STRICT
|
||||
inline internalJSONNode::operator float() const json_nothrow {
|
||||
return static_cast<float>(static_cast<long double>(*this));
|
||||
}
|
||||
inline internalJSONNode::operator double() const json_nothrow {
|
||||
return static_cast<double>(static_cast<long double>(*this));
|
||||
}
|
||||
#else
|
||||
inline internalJSONNode::operator float() const json_nothrow {
|
||||
return static_cast<float>(static_cast<double>(*this));
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef JSON_LESS_MEMORY
|
||||
#ifdef __GNUC__
|
||||
#pragma pack(pop)
|
||||
#elif _MSC_VER
|
||||
#pragma pack(pop, internalJSONNode_pack,)
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
605
src/libjson/_internal/Source/libjson.cpp
Normal file
605
src/libjson/_internal/Source/libjson.cpp
Normal file
|
@ -0,0 +1,605 @@
|
|||
/*
|
||||
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
|
||||
*/
|
||||
#include "../../libjson.h"
|
||||
#ifdef JSON_LIBRARY
|
||||
|
||||
#include "JSONNode.h"
|
||||
#include "JSONWorker.h"
|
||||
#include "JSONValidator.h"
|
||||
#include "JSONStream.h"
|
||||
#include "JSONGlobals.h"
|
||||
#include <stdexcept> //some methods throw exceptions
|
||||
#ifdef JSON_MEMORY_MANAGE
|
||||
#define MANAGER_INSERT(x) json_global(NODE_HANDLER).insert(x)
|
||||
#define MANAGER_STREAM_INSERT(x) json_global(STREAM_HANDLER).insert(x)
|
||||
#else
|
||||
#define MANAGER_INSERT(x) x
|
||||
#define MANAGER_STREAM_INSERT(x) x
|
||||
#endif
|
||||
|
||||
static const json_char * EMPTY_CSTRING(JSON_TEXT(""));
|
||||
|
||||
#ifdef JSON_MEMORY_POOL
|
||||
#include "JSONMemoryPool.h"
|
||||
extern memory_pool<NODEPOOL> json_node_mempool;
|
||||
#endif
|
||||
|
||||
inline json_char * toCString(const json_string & str) json_nothrow {
|
||||
const size_t len = (str.length() + 1) * sizeof(json_char);
|
||||
#ifdef JSON_MEMORY_MANAGE
|
||||
return (json_char *)json_global(STRING_HANDLER).insert(std::memcpy(json_malloc<json_char>(len), str.c_str(), len));
|
||||
#else
|
||||
return (json_char *)std::memcpy(json_malloc<json_char>(len), str.c_str(), len);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline json_char * alreadyCString(json_char * str) json_nothrow {
|
||||
#ifdef JSON_MEMORY_MANAGE
|
||||
return (json_char *)json_global(STRING_HANDLER).insert(str);
|
||||
#else
|
||||
return str;
|
||||
#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
|
||||
json_global(STRING_HANDLER).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
|
||||
json_global(NODE_HANDLER).remove(node);
|
||||
#endif
|
||||
JSONNode::deleteJSONNode((JSONNode *)node);
|
||||
}
|
||||
|
||||
#ifdef JSON_MEMORY_MANAGE
|
||||
void json_free_all(void){
|
||||
json_global(STRING_HANDLER).clear();
|
||||
}
|
||||
|
||||
void json_delete_all(void){
|
||||
json_global(NODE_HANDLER).clear();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef JSON_READ_PRIORITY
|
||||
JSONNODE * json_parse(json_const json_char * json){
|
||||
JSON_ASSERT_SAFE(json, JSON_TEXT("null ptr to json_parse"), return 0;);
|
||||
json_try {
|
||||
//use this constructor to simply copy reference instead of copying the temp
|
||||
return MANAGER_INSERT(JSONNode::newJSONNode_Shallow(JSONWorker::parse(TOCONST_CSTR(json))));
|
||||
} json_catch (std::invalid_argument, (void)0; )
|
||||
#ifndef JSON_NO_EXCEPTIONS
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
JSONNODE * json_parse_unformatted(json_const json_char * json){
|
||||
JSON_ASSERT_SAFE(json, JSON_TEXT("null ptr to json_parse"), return 0;);
|
||||
json_try {
|
||||
//use this constructor to simply copy reference instead of copying the temp
|
||||
return MANAGER_INSERT(JSONNode::newJSONNode_Shallow(JSONWorker::parse_unformatted(TOCONST_CSTR(json))));
|
||||
} json_catch(std::invalid_argument, (void)0; )
|
||||
#ifndef JSON_NO_EXCEPTIONS
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
json_char * json_strip_white_space(json_const json_char * json){
|
||||
JSON_ASSERT_SAFE(json, JSON_TEXT("null ptr to json_strip_white_space"), return 0;);
|
||||
return alreadyCString(JSONWorker::RemoveWhiteSpaceAndCommentsC(TOCONST_CSTR(json), false));
|
||||
}
|
||||
|
||||
#ifdef JSON_VALIDATE
|
||||
#ifdef JSON_DEPRECATED_FUNCTIONS
|
||||
JSONNODE * json_validate(json_const json_char * json){
|
||||
JSON_ASSERT_SAFE(json, JSON_TEXT("null ptr to json_validate"), return 0;);
|
||||
if (json_is_valid(json)){
|
||||
return json_parse(json);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
json_bool_t json_is_valid(json_const json_char * json){
|
||||
JSON_ASSERT_SAFE(json, JSON_TEXT("null ptr to json_is_valid"), return (json_bool_t)false;);
|
||||
#ifdef JSON_SECURITY_MAX_STRING_LENGTH
|
||||
if (json_unlikely(json_strlen(json) > JSON_SECURITY_MAX_STRING_LENGTH)){
|
||||
JSON_FAIL(JSON_TEXT("Exceeding JSON_SECURITY_MAX_STRING_LENGTH"));
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
json_auto<json_char> s;
|
||||
s.set(JSONWorker::RemoveWhiteSpaceAndCommentsC(json, false));
|
||||
return (json_bool_t)JSONValidator::isValidRoot(s.ptr);
|
||||
}
|
||||
|
||||
json_bool_t json_is_valid_unformatted(json_const json_char * json){
|
||||
JSON_ASSERT_SAFE(json, JSON_TEXT("null ptr to json_is_valid_unformatted"), return (json_bool_t)true;);
|
||||
#ifdef JSON_SECURITY_MAX_STRING_LENGTH
|
||||
if (json_unlikely(json_strlen(json) > JSON_SECURITY_MAX_STRING_LENGTH)){
|
||||
JSON_FAIL(JSON_TEXT("Exceeding JSON_SECURITY_MAX_STRING_LENGTH"));
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return (json_bool_t)JSONValidator::isValidRoot(json);
|
||||
}
|
||||
#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
|
||||
|
||||
#ifdef JSON_STREAM
|
||||
void json_stream_push(JSONSTREAM * stream, json_const json_char * addendum){
|
||||
(*((JSONStream*)stream)) << addendum;
|
||||
}
|
||||
|
||||
void json_delete_stream(JSONSTREAM * stream){
|
||||
JSON_ASSERT_SAFE(stream, JSON_TEXT("deleting null ptr"), return;);
|
||||
#ifdef JSON_MEMORY_MANAGE
|
||||
json_global(STREAM_HANDLER).remove(stream);
|
||||
#endif
|
||||
JSONStream::deleteJSONStream((JSONStream *)stream);
|
||||
}
|
||||
|
||||
JSONSTREAM * json_new_stream(json_stream_callback_t callback, json_stream_e_callback_t e_callback, void * identifier){
|
||||
return MANAGER_STREAM_INSERT(JSONStream::newJSONStream(callback, e_callback, identifier));
|
||||
}
|
||||
|
||||
void json_stream_reset(JSONSTREAM * stream){
|
||||
JSON_ASSERT_SAFE(stream, JSON_TEXT("resetting null ptr"), return;);
|
||||
((JSONStream*)stream) -> reset();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
stuff that's in class JSONNode
|
||||
*/
|
||||
//ctors
|
||||
JSONNODE * json_new_a(json_const json_char * name, json_const json_char * value){
|
||||
if (!name) name = EMPTY_CSTRING;
|
||||
JSON_ASSERT_SAFE(value, JSON_TEXT("null value to json_new_a"), value = EMPTY_CSTRING;);
|
||||
#ifdef JSON_MEMORY_POOL
|
||||
return MANAGER_INSERT(new((JSONNode*)json_node_mempool.allocate()) JSONNode(TOCONST_CSTR(name), json_string(TOCONST_CSTR(value))));
|
||||
#elif defined(JSON_MEMORY_CALLBACKS)
|
||||
return MANAGER_INSERT(new(json_malloc<JSONNode>(1)) JSONNode(TOCONST_CSTR(name), json_string(TOCONST_CSTR(value))));
|
||||
#else
|
||||
return MANAGER_INSERT(new JSONNode(TOCONST_CSTR(name), json_string(TOCONST_CSTR(value))));
|
||||
#endif
|
||||
}
|
||||
|
||||
JSONNODE * json_new_i(json_const json_char * name, json_int_t value){
|
||||
if (!name) name = EMPTY_CSTRING;
|
||||
#ifdef JSON_MEMORY_POOL
|
||||
return MANAGER_INSERT(new((JSONNode*)json_node_mempool.allocate()) JSONNode(TOCONST_CSTR(name), value));
|
||||
#elif defined(JSON_MEMORY_CALLBACKS)
|
||||
return MANAGER_INSERT(new(json_malloc<JSONNode>(1)) JSONNode(TOCONST_CSTR(name), value));
|
||||
#else
|
||||
return MANAGER_INSERT(new JSONNode(TOCONST_CSTR(name), value));
|
||||
#endif
|
||||
}
|
||||
|
||||
JSONNODE * json_new_f(json_const json_char * name, json_number value){
|
||||
if (!name) name = EMPTY_CSTRING;
|
||||
#ifdef JSON_MEMORY_POOL
|
||||
return MANAGER_INSERT(new((JSONNode*)json_node_mempool.allocate()) JSONNode(TOCONST_CSTR(name), value));
|
||||
#elif defined(JSON_MEMORY_CALLBACKS)
|
||||
return MANAGER_INSERT(new(json_malloc<JSONNode>(1)) JSONNode(TOCONST_CSTR(name), value));
|
||||
#else
|
||||
return MANAGER_INSERT(new JSONNode(TOCONST_CSTR(name), value));
|
||||
#endif
|
||||
}
|
||||
|
||||
JSONNODE * json_new_b(json_const json_char * name, json_bool_t value){
|
||||
if (!name) name = EMPTY_CSTRING;
|
||||
#ifdef JSON_MEMORY_POOL
|
||||
return MANAGER_INSERT(new((JSONNode*)json_node_mempool.allocate()) JSONNode(TOCONST_CSTR(name), static_cast<bool>(value)));
|
||||
#elif defined(JSON_MEMORY_CALLBACKS)
|
||||
return MANAGER_INSERT(new(json_malloc<JSONNode>(1)) JSONNode(TOCONST_CSTR(name), static_cast<bool>(value)));
|
||||
#else
|
||||
return MANAGER_INSERT(new JSONNode(TOCONST_CSTR(name), static_cast<bool>(value)));
|
||||
#endif
|
||||
}
|
||||
|
||||
JSONNODE * json_new(char type){
|
||||
#ifdef JSON_MEMORY_POOL
|
||||
return MANAGER_INSERT(new((JSONNode*)json_node_mempool.allocate()) JSONNode(type));
|
||||
#elif defined(JSON_MEMORY_CALLBACKS)
|
||||
return MANAGER_INSERT(new(json_malloc<JSONNode>(1)) JSONNode(type));
|
||||
#else
|
||||
return MANAGER_INSERT(new JSONNode(type));
|
||||
#endif
|
||||
}
|
||||
|
||||
JSONNODE * json_copy(json_const JSONNODE * orig){
|
||||
JSON_ASSERT_SAFE(orig, JSON_TEXT("null orig to json_copy"), return 0;);
|
||||
#ifdef JSON_MEMORY_POOL
|
||||
return MANAGER_INSERT(new((JSONNode*)json_node_mempool.allocate()) JSONNode(*((JSONNode*)orig)));
|
||||
#elif defined(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(json_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, json_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(TOCONST_CSTR(value));
|
||||
}
|
||||
|
||||
void json_set_i(JSONNODE * node, json_int_t 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, json_bool_t value){
|
||||
JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_set_b"), return;);
|
||||
*((JSONNode*)node) = static_cast<bool>(value);
|
||||
}
|
||||
|
||||
void json_set_n(JSONNODE * node, json_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(json_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(json_const JSONNODE * node){
|
||||
JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_size"), return 0;);
|
||||
return ((JSONNode*)node) -> size();
|
||||
}
|
||||
|
||||
json_bool_t json_empty(json_const JSONNODE * node){
|
||||
JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_empty"), return true;);
|
||||
return (json_bool_t)(((JSONNode*)node) -> empty());
|
||||
}
|
||||
|
||||
json_char * json_name(json_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(json_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(json_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());
|
||||
//return toCString(static_cast<json_string>(*((JSONNode*)node)));
|
||||
}
|
||||
|
||||
json_int_t json_as_int(json_const JSONNODE * node){
|
||||
JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_as_int"), return 0;);
|
||||
return ((JSONNode*)node) -> as_int();
|
||||
//return static_cast<json_int_t>(*((JSONNode*)node));
|
||||
}
|
||||
|
||||
json_number json_as_float(json_const JSONNODE * node){
|
||||
JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_as_float"), return 0.0f;);
|
||||
return ((JSONNode*)node) -> as_float();
|
||||
//return static_cast<json_number>(*((JSONNode*)node));
|
||||
}
|
||||
|
||||
json_bool_t json_as_bool(json_const JSONNODE * node){
|
||||
JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_as_bool"), return false;);
|
||||
return ((JSONNode*)node) -> as_bool();
|
||||
//return (json_bool_t)static_cast<bool>(*((JSONNode*)node));
|
||||
}
|
||||
|
||||
#ifdef JSON_CASTABLE
|
||||
JSONNODE * json_as_node(json_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(json_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()));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(JSON_BINARY) || defined(JSON_EXPOSE_BASE64)
|
||||
static void * returnDecode64(const std::string & result, unsigned long * size) json_nothrow json_cold;
|
||||
static void * returnDecode64(const std::string & result, unsigned long * size) json_nothrow {
|
||||
const size_t len = result.length();
|
||||
if (json_likely(size)) *size = (json_index_t)len;
|
||||
#ifdef JSON_SAFE
|
||||
if (json_unlikely(result.empty())) return 0;
|
||||
#endif
|
||||
#ifdef JSON_MEMORY_MANAGE
|
||||
return json_global(STRING_HANDLER).insert(std::memcpy(json_malloc<char>(len), result.data(), len));
|
||||
#else
|
||||
return std::memcpy(json_malloc<char>(len), result.data(), len);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef JSON_BINARY
|
||||
void * json_as_binary(json_const JSONNODE * node, unsigned long * size){
|
||||
JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_as_binary"), if (size){*size = 0;} return 0;);
|
||||
return returnDecode64(((JSONNode*)node) -> as_binary(), size);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef JSON_EXPOSE_BASE64
|
||||
#include "JSON_Base64.h"
|
||||
json_char * json_encode64(json_const void * binary, json_index_t bytes){
|
||||
const json_string result(JSONBase64::json_encode64((const unsigned char *)binary, (size_t)bytes));
|
||||
#ifdef JSON_MEMORY_MANAGE
|
||||
return (json_char*)json_global(STRING_HANDLER).insert((json_char*)std::memcpy(json_malloc<json_char>(result.length() + 1), result.c_str(), (result.length() + 1) * sizeof(json_char)));
|
||||
#else
|
||||
return (json_char*)std::memcpy(json_malloc<json_char>(result.length() + 1), result.c_str(), (result.length() + 1) * sizeof(json_char));
|
||||
#endif
|
||||
}
|
||||
|
||||
void * json_decode64(const json_char * text, unsigned long * size){
|
||||
return returnDecode64(JSONBase64::json_decode64(text), size);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef JSON_WRITE_PRIORITY
|
||||
json_char * json_write(json_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(json_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, json_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(TOCONST_CSTR(name));
|
||||
}
|
||||
|
||||
#ifdef JSON_COMMENTS
|
||||
void json_set_comment(JSONNODE * node, json_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(TOCONST_CSTR(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);
|
||||
}
|
||||
|
||||
#if !defined(JSON_PREPARSE) && defined(JSON_READ_PRIORITY)
|
||||
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, json_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, (size_t)length);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef JSON_CASTABLE
|
||||
void json_cast(JSONNODE * node, char type){
|
||||
JSON_ASSERT_SAFE(node, JSON_TEXT("null node to json_cast"), return;);
|
||||
((JSONNode*)node) -> cast(type);
|
||||
}
|
||||
#endif
|
||||
|
||||
//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;);
|
||||
json_try {
|
||||
return &((JSONNode*)node) -> at(pos);
|
||||
} json_catch (std::out_of_range, (void)0; )
|
||||
#ifndef JSON_NO_EXCEPTIONS
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
JSONNODE * json_get(JSONNODE * node, json_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;);
|
||||
json_try {
|
||||
return &((JSONNode*)node) -> at(TOCONST_CSTR(name));
|
||||
} json_catch (std::out_of_range, (void)0; )
|
||||
#ifndef JSON_NO_EXCEPTIONS
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifdef JSON_CASE_INSENSITIVE_FUNCTIONS
|
||||
JSONNODE * json_get_nocase(JSONNODE * node, json_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;);
|
||||
json_try {
|
||||
return &((JSONNode*)node) -> at_nocase(TOCONST_CSTR(name));
|
||||
} json_catch (std::out_of_range, (void)0; )
|
||||
#ifndef JSON_NO_EXCEPTIONS
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
JSONNODE * json_pop_back_nocase(JSONNODE * node, json_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(TOCONST_CSTR(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
|
||||
json_global(NODE_HANDLER).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, json_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(TOCONST_CSTR(name)));
|
||||
}
|
||||
|
||||
#ifdef JSON_ITERATORS
|
||||
JSONNODE_ITERATOR json_find(JSONNODE * node, json_const json_char * name){
|
||||
return (JSONNODE_ITERATOR)(((JSONNode*)node) -> find(TOCONST_CSTR(name)));
|
||||
}
|
||||
|
||||
#ifdef JSON_CASE_INSENSITIVE_FUNCTIONS
|
||||
JSONNODE_ITERATOR json_find_nocase(JSONNODE * node, json_const json_char * name){
|
||||
return (JSONNODE_ITERATOR)(((JSONNode*)node) -> find_nocase(TOCONST_CSTR(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
|
||||
json_global(NODE_HANDLER).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
|
||||
json_bool_t 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 (json_bool_t)(*((JSONNode*)node) == *((JSONNode*)node2));
|
||||
}
|
||||
|
||||
#endif //JSON_LIBRARY
|
371
src/libjson/_internal/TestSuite/All/Options.txt
Normal file
371
src/libjson/_internal/TestSuite/All/Options.txt
Normal file
|
@ -0,0 +1,371 @@
|
|||
#unittesting
|
||||
#library
|
||||
#unicode
|
||||
#standard set
|
||||
STREAM, UNICODE, LIBRARY, SAFE, REF_COUNT, BINARY, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
UNICODE, ESCAPE_WRITES, UNIT_TEST, LIBRARY, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
UNICODE, ESCAPE_WRITES, UNIT_TEST, LIBRARY, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, VALIDATE, CASE_INSENSITIVE_FUNCTIONS, STRICT
|
||||
STREAM, UNICODE, ESCAPE_WRITES, UNIT_TEST, LIBRARY, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
UNICODE, ESCAPE_WRITES, UNIT_TEST, LIBRARY, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, STREAM, UNICODE, ESCAPE_WRITES, UNIT_TEST, LIBRARY, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
CASTABLE, UNICODE, ESCAPE_WRITES, UNIT_TEST, LIBRARY, SAFE, PREPARSE, REF_COUNT, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
#no ref counting
|
||||
STREAM, UNICODE, LIBRARY, SAFE, BINARY, WRITER, COMMENTS, VALIDATE
|
||||
UNICODE, ESCAPE_WRITES, UNIT_TEST, LIBRARY, SAFE, PREPARSE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, UNICODE, ESCAPE_WRITES, UNIT_TEST, LIBRARY, SAFE, PREPARSE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
UNICODE, ESCAPE_WRITES, UNIT_TEST, LIBRARY, SAFE, PREPARSE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, STREAM, UNICODE, ESCAPE_WRITES, UNIT_TEST, LIBRARY, SAFE, PREPARSE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
CASTABLE, UNICODE, ESCAPE_WRITES, UNIT_TEST, LIBRARY, SAFE, PREPARSE, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
#no preparse
|
||||
UNICODE, ESCAPE_WRITES, UNIT_TEST, LIBRARY, SAFE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
UNICODE, ESCAPE_WRITES, UNIT_TEST, LIBRARY, SAFE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
UNICODE, ESCAPE_WRITES, UNIT_TEST, LIBRARY, SAFE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, UNICODE, ESCAPE_WRITES, UNIT_TEST, LIBRARY, SAFE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
CASTABLE, UNICODE, ESCAPE_WRITES, UNIT_TEST, LIBRARY, SAFE, REF_COUNT, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
#no safe
|
||||
VALIDATE, STREAM, UNICODE, LIBRARY, REF_COUNT, BINARY, WRITER, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
VALIDATE, UNICODE, ESCAPE_WRITES, UNIT_TEST, LIBRARY, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, CASE_INSENSITIVE_FUNCTIONS
|
||||
VALIDATE, STREAM, UNICODE, ESCAPE_WRITES, UNIT_TEST, LIBRARY, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
VALIDATE, UNICODE, ESCAPE_WRITES, UNIT_TEST, LIBRARY, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, VALIDATE, STREAM, UNICODE, ESCAPE_WRITES, UNIT_TEST, LIBRARY, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, WRITER, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
CASTABLE, VALIDATE, UNICODE, ESCAPE_WRITES, UNIT_TEST, LIBRARY, PREPARSE, REF_COUNT, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
#string header
|
||||
STREAM, UNICODE, STRINGU_HEADER, UNIT_TEST, LIBRARY, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
UNICODE, STRINGU_HEADER, UNIT_TEST, LIBRARY, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, UNICODE, STRINGU_HEADER, UNIT_TEST, LIBRARY, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, UNICODE, STRINGU_HEADER, UNIT_TEST, LIBRARY, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
CASTABLE, STREAM, UNICODE, STRINGU_HEADER, UNIT_TEST, LIBRARY, SAFE, PREPARSE, REF_COUNT, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
#no ref counting or preparsing
|
||||
STREAM, UNICODE, LIBRARY, SAFE, BINARY, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
UNICODE, ESCAPE_WRITES, UNIT_TEST, LIBRARY, SAFE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, UNICODE, ESCAPE_WRITES, UNIT_TEST, LIBRARY, SAFE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
UNICODE, ESCAPE_WRITES, UNIT_TEST, LIBRARY, SAFE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, STREAM, UNICODE, ESCAPE_WRITES, UNIT_TEST, LIBRARY, SAFE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
CASTABLE, UNICODE, ESCAPE_WRITES, UNIT_TEST, LIBRARY, SAFE, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
#no ref counting or preparsing or safety
|
||||
STREAM, UNICODE, LIBRARY, BINARY, WRITER, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
UNICODE, ESCAPE_WRITES, UNIT_TEST, LIBRARY, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, UNICODE, ESCAPE_WRITES, UNIT_TEST, LIBRARY, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
UNICODE, ESCAPE_WRITES, UNIT_TEST, LIBRARY, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, STREAM, UNICODE, ESCAPE_WRITES, UNIT_TEST, LIBRARY, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, WRITER, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, CASTABLE, UNICODE, ESCAPE_WRITES, UNIT_TEST, LIBRARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
#no unicode
|
||||
#standard set
|
||||
STREAM, LIBRARY, SAFE, REF_COUNT, BINARY, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
UNIT_TEST, LIBRARY, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, UNIT_TEST, LIBRARY, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
UNIT_TEST, LIBRARY, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, STREAM, UNIT_TEST, LIBRARY, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, CASTABLE, UNIT_TEST, LIBRARY, SAFE, PREPARSE, REF_COUNT, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
#no ref counting
|
||||
STREAM, LIBRARY, SAFE, BINARY, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
UNIT_TEST, LIBRARY, SAFE, PREPARSE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, UNIT_TEST, LIBRARY, SAFE, PREPARSE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
UNIT_TEST, LIBRARY, SAFE, PREPARSE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, STREAM, UNIT_TEST, LIBRARY, SAFE, PREPARSE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
CASTABLE, UNIT_TEST, LIBRARY, SAFE, PREPARSE, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
#no preparse
|
||||
STREAM, UNIT_TEST, LIBRARY, SAFE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
UNIT_TEST, LIBRARY, SAFE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, UNIT_TEST, LIBRARY, SAFE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, UNIT_TEST, LIBRARY, SAFE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
CASTABLE, STREAM, UNIT_TEST, LIBRARY, SAFE, REF_COUNT, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
#no safe
|
||||
VALIDATE, STREAM, LIBRARY, REF_COUNT, BINARY, WRITER, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
VALIDATE, UNIT_TEST, LIBRARY, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, CASE_INSENSITIVE_FUNCTIONS
|
||||
VALIDATE, STREAM, UNIT_TEST, LIBRARY, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
VALIDATE, UNIT_TEST, LIBRARY, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, VALIDATE, STREAM, UNIT_TEST, LIBRARY, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, WRITER, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
CASTABLE, VALIDATE, UNIT_TEST, LIBRARY, PREPARSE, REF_COUNT, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
#string header
|
||||
STREAM, STRING_HEADER, UNIT_TEST, LIBRARY, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
STRING_HEADER, UNIT_TEST, LIBRARY, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, STRING_HEADER, UNIT_TEST, LIBRARY, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, STREAM, STRING_HEADER, UNIT_TEST, LIBRARY, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
CASTABLE, STRING_HEADER, UNIT_TEST, LIBRARY, SAFE, PREPARSE, REF_COUNT, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
#no ref counting or preparsing
|
||||
STREAM, LIBRARY, SAFE, BINARY, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
UNIT_TEST, LIBRARY, SAFE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, UNIT_TEST, LIBRARY, SAFE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
UNIT_TEST, LIBRARY, SAFE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, STREAM, UNIT_TEST, LIBRARY, SAFE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
CASTABLE, UNIT_TEST, LIBRARY, SAFE, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
#no ref counting or preparsing or safety
|
||||
STREAM, LIBRARY, BINARY, WRITER, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
UNIT_TEST, LIBRARY, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, UNIT_TEST, LIBRARY, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
UNIT_TEST, LIBRARY, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, STREAM, UNIT_TEST, LIBRARY, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, WRITER, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
CASTABLE, UNIT_TEST, LIBRARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
#embedded
|
||||
#unicode
|
||||
#standard set
|
||||
STREAM, UNICODE, SAFE, REF_COUNT, BINARY, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
UNICODE, ESCAPE_WRITES, UNIT_TEST, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, UNICODE, ESCAPE_WRITES, UNIT_TEST, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
UNICODE, ESCAPE_WRITES, UNIT_TEST, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, STREAM, UNICODE, ESCAPE_WRITES, UNIT_TEST, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
CASTABLE, UNICODE, ESCAPE_WRITES, UNIT_TEST, SAFE, PREPARSE, REF_COUNT, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
#no ref counting
|
||||
STREAM, UNICODE, SAFE, BINARY, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
UNICODE, ESCAPE_WRITES, UNIT_TEST, SAFE, PREPARSE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, UNICODE, ESCAPE_WRITES, UNIT_TEST, SAFE, PREPARSE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
UNICODE, ESCAPE_WRITES, UNIT_TEST, SAFE, PREPARSE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, STREAM, UNICODE, ESCAPE_WRITES, UNIT_TEST, SAFE, PREPARSE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, CASTABLE, UNICODE, ESCAPE_WRITES, UNIT_TEST, SAFE, PREPARSE, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
#no preparse
|
||||
STREAM, UNICODE, ESCAPE_WRITES, UNIT_TEST, SAFE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
UNICODE, ESCAPE_WRITES, UNIT_TEST, SAFE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, UNICODE, ESCAPE_WRITES, UNIT_TEST, SAFE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, UNICODE, ESCAPE_WRITES, UNIT_TEST, SAFE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
CASTABLE, STREAM, UNICODE, ESCAPE_WRITES, UNIT_TEST, SAFE, REF_COUNT, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
#no safe
|
||||
VALIDATE, STREAM, UNICODE, REF_COUNT, BINARY, WRITER, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
VALIDATE, UNICODE, ESCAPE_WRITES, UNIT_TEST, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, CASE_INSENSITIVE_FUNCTIONS
|
||||
VALIDATE, STREAM, UNICODE, ESCAPE_WRITES, UNIT_TEST, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
VALIDATE, UNICODE, ESCAPE_WRITES, UNIT_TEST, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, VALIDATE, STREAM, UNICODE, ESCAPE_WRITES, UNIT_TEST, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, WRITER, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
CASTABLE, VALIDATE, UNICODE, ESCAPE_WRITES, UNIT_TEST, PREPARSE, REF_COUNT, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
#string header
|
||||
STREAM, UNICODE, STRINGU_HEADER, UNIT_TEST, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
UNICODE, STRINGU_HEADER, UNIT_TEST, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, UNICODE, STRINGU_HEADER, UNIT_TEST, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, UNICODE, STRINGU_HEADER, UNIT_TEST, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
CASTABLE, STREAM, UNICODE, STRINGU_HEADER, UNIT_TEST, SAFE, PREPARSE, REF_COUNT, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
#no ref counting or preparsing
|
||||
STREAM, UNICODE, SAFE, BINARY, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
UNICODE, ESCAPE_WRITES, UNIT_TEST, SAFE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, UNICODE, ESCAPE_WRITES, UNIT_TEST, SAFE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
UNICODE, ESCAPE_WRITES, UNIT_TEST, SAFE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, STREAM, UNICODE, ESCAPE_WRITES, UNIT_TEST, SAFE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
CASTABLE, UNICODE, ESCAPE_WRITES, UNIT_TEST, SAFE, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
#no ref counting or preparsing or safety
|
||||
STREAM, UNICODE, BINARY, WRITER, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
UNICODE, ESCAPE_WRITES, UNIT_TEST, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, UNICODE, ESCAPE_WRITES, UNIT_TEST, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
UNICODE, ESCAPE_WRITES, UNIT_TEST, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, STREAM, UNICODE, ESCAPE_WRITES, UNIT_TEST, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, WRITER, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
CASTABLE, UNICODE, ESCAPE_WRITES, UNIT_TEST, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
#no unicode
|
||||
#standard set
|
||||
STREAM, SAFE, REF_COUNT, BINARY, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
UNIT_TEST, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, UNIT_TEST, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
UNIT_TEST, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, STREAM, UNIT_TEST, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
CASTABLE, UNIT_TEST, SAFE, PREPARSE, REF_COUNT, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
#no ref counting
|
||||
STREAM, SAFE, BINARY, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
UNIT_TEST, SAFE, PREPARSE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, UNIT_TEST, SAFE, PREPARSE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
UNIT_TEST, SAFE, PREPARSE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, STREAM, UNIT_TEST, SAFE, PREPARSE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
CASTABLE, UNIT_TEST, SAFE, PREPARSE, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
#no preparse
|
||||
STREAM, UNIT_TEST, SAFE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
UNIT_TEST, SAFE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, UNIT_TEST, SAFE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, UNIT_TEST, SAFE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, CASTABLE, STREAM, UNIT_TEST, SAFE, REF_COUNT, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
#no safe
|
||||
VALIDATE, STREAM, REF_COUNT, BINARY, WRITER, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
VALIDATE, UNIT_TEST, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, CASE_INSENSITIVE_FUNCTIONS
|
||||
VALIDATE, STREAM, UNIT_TEST, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
VALIDATE, UNIT_TEST, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, VALIDATE, STREAM, UNIT_TEST, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, WRITER, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
CASTABLE, VALIDATE, UNIT_TEST, PREPARSE, REF_COUNT, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
#string header
|
||||
STREAM, STRING_HEADER, UNIT_TEST, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
STRING_HEADER, UNIT_TEST, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, STRING_HEADER, UNIT_TEST, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, STRING_HEADER, UNIT_TEST, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
CASTABLE, STREAM, STRING_HEADER, UNIT_TEST, SAFE, PREPARSE, REF_COUNT, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
#no ref counting or preparsing
|
||||
STREAM, SAFE, BINARY, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
UNIT_TEST, SAFE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, UNIT_TEST, SAFE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
UNIT_TEST, SAFE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, STREAM, UNIT_TEST, SAFE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
CASTABLE, UNIT_TEST, SAFE, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
#no ref counting or preparsing or safety
|
||||
STREAM, BINARY, WRITER, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
UNIT_TEST, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, UNIT_TEST, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
UNIT_TEST, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, STREAM, UNIT_TEST, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, WRITER, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
CASTABLE, UNIT_TEST, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
#no unittesting
|
||||
#library
|
||||
#unicode
|
||||
#standard set
|
||||
STREAM, UNICODE, LIBRARY, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
UNICODE, LIBRARY, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, UNICODE, LIBRARY, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, UNICODE, LIBRARY, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, UNICODE, LIBRARY, SAFE, PREPARSE, REF_COUNT, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
#no ref counting
|
||||
STREAM, UNICODE, LIBRARY, SAFE, PREPARSE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
UNICODE, LIBRARY, SAFE, PREPARSE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, UNICODE, LIBRARY, SAFE, PREPARSE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, UNICODE, LIBRARY, SAFE, PREPARSE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, UNICODE, LIBRARY, SAFE, PREPARSE, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
#no preparse
|
||||
STREAM, UNICODE, LIBRARY, SAFE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
UNICODE, LIBRARY, SAFE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, UNICODE, LIBRARY, SAFE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, UNICODE, LIBRARY, SAFE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, UNICODE, LIBRARY, SAFE, REF_COUNT, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
#no safe
|
||||
STREAM, UNICODE, LIBRARY, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, CASE_INSENSITIVE_FUNCTIONS
|
||||
UNICODE, LIBRARY, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, UNICODE, LIBRARY, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, UNICODE, LIBRARY, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, WRITER, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, STREAM, UNICODE, LIBRARY, PREPARSE, REF_COUNT, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
#string header
|
||||
STREAM, UNICODE, STRINGU_HEADER, LIBRARY, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
UNICODE, STRINGU_HEADER, LIBRARY, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, UNICODE, STRINGU_HEADER, LIBRARY, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, UNICODE, STRINGU_HEADER, LIBRARY, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, UNICODE, STRINGU_HEADER, LIBRARY, SAFE, PREPARSE, REF_COUNT, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
#no ref counting or preparsing
|
||||
STREAM, UNICODE, LIBRARY, SAFE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
UNICODE, LIBRARY, SAFE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, UNICODE, LIBRARY, SAFE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, UNICODE, LIBRARY, SAFE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, UNICODE, LIBRARY, SAFE, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
#no ref counting or preparsing or safety
|
||||
STREAM, UNICODE, LIBRARY, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, CASE_INSENSITIVE_FUNCTIONS
|
||||
UNICODE, LIBRARY, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, UNICODE, LIBRARY, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, UNICODE, LIBRARY, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, WRITER, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, UNICODE, LIBRARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
#no unicode
|
||||
#standard set
|
||||
STREAM, LIBRARY, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
LIBRARY, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, LIBRARY, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, LIBRARY, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, LIBRARY, SAFE, PREPARSE, REF_COUNT, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
#no ref counting
|
||||
STREAM, LIBRARY, SAFE, PREPARSE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
LIBRARY, SAFE, PREPARSE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, LIBRARY, SAFE, PREPARSE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, LIBRARY, SAFE, PREPARSE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, LIBRARY, SAFE, PREPARSE, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
#no preparse
|
||||
STREAM, LIBRARY, SAFE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
LIBRARY, SAFE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, LIBRARY, SAFE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, LIBRARY, SAFE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, LIBRARY, SAFE, REF_COUNT, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
#no safe
|
||||
STREAM, LIBRARY, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, CASE_INSENSITIVE_FUNCTIONS
|
||||
LIBRARY, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, LIBRARY, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, LIBRARY, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, WRITER, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, LIBRARY, PREPARSE, REF_COUNT, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
#string header
|
||||
STREAM, STRING_HEADER, LIBRARY, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
STRING_HEADER, LIBRARY, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, STRING_HEADER, LIBRARY, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, STRING_HEADER, LIBRARY, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, STREAM, STRING_HEADER, LIBRARY, SAFE, PREPARSE, REF_COUNT, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
#no ref counting or preparsing
|
||||
STREAM, LIBRARY, SAFE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
LIBRARY, SAFE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, LIBRARY, SAFE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, LIBRARY, SAFE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, LIBRARY, SAFE, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
#no ref counting or preparsing or safety
|
||||
STREAM, LIBRARY, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, CASE_INSENSITIVE_FUNCTIONS
|
||||
LIBRARY, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, LIBRARY, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, LIBRARY, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, WRITER, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, LIBRARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
#embedded
|
||||
#unicode
|
||||
#standard set
|
||||
STREAM, UNICODE, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
UNICODE, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, UNICODE, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, UNICODE, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, UNICODE, SAFE, PREPARSE, REF_COUNT, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
#no ref counting
|
||||
STREAM, UNICODE, SAFE, PREPARSE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
UNICODE, SAFE, PREPARSE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, UNICODE, SAFE, PREPARSE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, UNICODE, SAFE, PREPARSE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, UNICODE, SAFE, PREPARSE, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
#no preparse
|
||||
STREAM, UNICODE, SAFE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
UNICODE, SAFE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, UNICODE, SAFE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, UNICODE, SAFE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, UNICODE, SAFE, REF_COUNT, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
#no safe
|
||||
STREAM, UNICODE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, CASE_INSENSITIVE_FUNCTIONS
|
||||
UNICODE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, UNICODE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, UNICODE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, WRITER, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, UNICODE, PREPARSE, REF_COUNT, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
#string header
|
||||
STREAM, UNICODE, STRINGU_HEADER, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
UNICODE, STRINGU_HEADER, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, UNICODE, STRINGU_HEADER, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, UNICODE, STRINGU_HEADER, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, STREAM, UNICODE, STRINGU_HEADER, SAFE, PREPARSE, REF_COUNT, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
#no ref counting or preparsing
|
||||
STREAM, UNICODE, SAFE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
UNICODE, SAFE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, UNICODE, SAFE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, UNICODE, SAFE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, UNICODE, SAFE, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
#no ref counting or preparsing or safety
|
||||
STREAM, UNICODE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, CASE_INSENSITIVE_FUNCTIONS
|
||||
UNICODE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, UNICODE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, UNICODE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, WRITER, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, UNICODE, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
#no unicode
|
||||
#standard set
|
||||
STREAM, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, SAFE, PREPARSE, REF_COUNT, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
#no ref countingv
|
||||
STREAM, SAFE, PREPARSE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
SAFE, PREPARSE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, SAFE, PREPARSE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, SAFE, PREPARSE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, SAFE, PREPARSE, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
#no preparse
|
||||
STREAM, SAFE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
SAFE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, SAFE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, SAFE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, SAFE, REF_COUNT, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
#no safe
|
||||
STREAM, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, CASE_INSENSITIVE_FUNCTIONS
|
||||
PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, WRITER, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, PREPARSE, REF_COUNT, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
#string header
|
||||
STREAM, STRING_HEADER, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
STRING_HEADER, STRING_HEADER, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, STRING_HEADER, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, STRING_HEADER, SAFE, PREPARSE, REF_COUNT, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, STRING_HEADER, SAFE, PREPARSE, REF_COUNT, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
#no ref counting or preparsing
|
||||
STREAM, SAFE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
SAFE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, SAFE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, SAFE, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, STREAM, SAFE, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, VALIDATE, CASE_INSENSITIVE_FUNCTIONS
|
||||
#no ref counting or preparsing or safety
|
||||
STREAM, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, CASE_INSENSITIVE_FUNCTIONS
|
||||
BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
MEMORY_POOL, BINARY, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, WRITER, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
||||
STREAM, MEMORY_CALLBACKS, MEMORY_MANAGE, MUTEX_CALLBACKS, MUTEX_MANAGE, ITERATORS, WRITER, COMMENTS, CASE_INSENSITIVE_FUNCTIONS
|
246
src/libjson/_internal/TestSuite/All/main.cpp
Normal file
246
src/libjson/_internal/TestSuite/All/main.cpp
Normal file
|
@ -0,0 +1,246 @@
|
|||
#include <iostream>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <fstream>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <map>
|
||||
#include <sys/stat.h>
|
||||
#include "../UnitTest.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
map<string, string> options;
|
||||
vector<string> lines;
|
||||
vector<unsigned int> line_numbers;
|
||||
size_t counter = 0;
|
||||
string make;
|
||||
string ArchivedOptions;
|
||||
string makeStyle;
|
||||
|
||||
string makeOptions[] = {
|
||||
"single",
|
||||
"debug",
|
||||
"small"
|
||||
};
|
||||
|
||||
void makeMap(void){
|
||||
options["LIBRARY"] = "#define JSON_LIBRARY";
|
||||
options["DEBUG"] = "#define JSON_DEBUG";
|
||||
options["STREAM"] = "#define JSON_STREAM";
|
||||
options["SAFE"] = "#define JSON_SAFE";
|
||||
options["STDERROR"] = "#define JSON_STDERROR";
|
||||
options["PREPARSE"] = "#define JSON_PREPARSE";
|
||||
options["LESS_MEMORY"] = "#define JSON_LESS_MEMORY";
|
||||
options["UNICODE"] = "#define JSON_UNICODE";
|
||||
options["REF_COUNT"] = "#define JSON_REF_COUNT";
|
||||
options["BINARY"] = "#define JSON_BINARY";
|
||||
options["MEMORY_CALLBACKS"] = "#define JSON_MEMORY_CALLBACKS";
|
||||
options["MEMORY_MANAGE"] = "#define JSON_MEMORY_MANAGE";
|
||||
options["MUTEX_CALLBACKS"] = "#define JSON_MUTEX_CALLBACKS";
|
||||
options["MUTEX_MANAGE"] = "#define JSON_MUTEX_MANAGE";
|
||||
options["ITERATORS"] = "#define JSON_ITERATORS";
|
||||
options["WRITER"] = "#define JSON_WRITE_PRIORITY MID";
|
||||
options["READER"] = "#define JSON_READ_PRIORITY HIGH";
|
||||
options["NEWLINE"] = "#define JSON_NEWLINE \"\\r\\n\"";
|
||||
options["COMMENTS"] = "#define JSON_COMMENTS";
|
||||
options["INDENT"] = "#define JSON_INDENT \" \"";
|
||||
options["WRITE_BASH_COMMENTS"] = "#define JSON_WRITE_BASH_COMMENTS";
|
||||
options["WRITE_SINGLE_LINE_COMMENTS"] = "#define JSON_WRITE_SINGLE_LINE_COMMENTS";
|
||||
options["VALIDATE"] = "#define JSON_VALIDATE";
|
||||
options["UNIT_TEST"] = "#define JSON_UNIT_TEST";
|
||||
options["INDEX_TYPE"] = "#define JSON_INDEX_TYPE unsigned int";
|
||||
options["CASE_INSENSITIVE_FUNCTIONS"] = "#define JSON_CASE_INSENSITIVE_FUNCTIONS";
|
||||
options["ESCAPE_WRITES"] = "#define JSON_ESCAPE_WRITES";
|
||||
options["STRINGU_HEADER"] = "#define JSON_STRING_HEADER \"../TestSuite/UStringTest.h\"";
|
||||
options["STRING_HEADER"] = "#define JSON_STRING_HEADER \"../TestSuite/StringTest.h\"";
|
||||
options["CASTABLE"] = "#define JSON_CASTABLE";
|
||||
options["STRICT"] = "#define JSON_STRICT";
|
||||
options["MEMORY_POOL"] = "#define JSON_MEMORY_POOL 524288";
|
||||
}
|
||||
|
||||
void testRules(unsigned int i){
|
||||
remove("./testapp");
|
||||
int q = system(make.c_str());
|
||||
bool Archive = false;
|
||||
if (FILE * fp = fopen("./testapp", "r")){
|
||||
fclose(fp);
|
||||
|
||||
remove("./out.html");
|
||||
q = system("./testapp");
|
||||
if (FILE * fp = fopen("./out.html", "r")){
|
||||
char buffer[255];
|
||||
size_t qq = fread(&buffer[0], 255, 1, fp);
|
||||
buffer[254] = '\0';
|
||||
fclose(fp);
|
||||
string buf(&buffer[0]);
|
||||
size_t pos = buf.find("Failed Tests: <c style=\"color:#CC0000\">");
|
||||
if (pos == string::npos){
|
||||
FAIL("Something Wrong");
|
||||
} else {
|
||||
if(buf[pos + 39] == '0'){
|
||||
PASS("GOOD");
|
||||
} else {
|
||||
size_t pp = buf.find('<', pos + 39);
|
||||
FAIL(string("Didn't pass ") + buf.substr(pos + 39, pp - pos - 39) + " tests");
|
||||
ArchivedOptions = std::string("Fail_") + ArchivedOptions;
|
||||
Archive = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
FAIL("Running crashed");
|
||||
ArchivedOptions = std::string("Crashed_") + ArchivedOptions;
|
||||
Archive = true;
|
||||
}
|
||||
} else {
|
||||
FAIL(string("Compilation failed - ") + lines[i]);
|
||||
ArchivedOptions = std::string("Compile_") + ArchivedOptions;
|
||||
Archive = true;
|
||||
}
|
||||
|
||||
//If something broke, make a copy of the options used to make the failure, so it can be easily retested
|
||||
if (Archive){
|
||||
if (FILE * fp = fopen("../JSONOptions.h", "r")){
|
||||
ArchivedOptions = std::string("../") + ArchivedOptions;
|
||||
if (FILE * ofp = fopen(ArchivedOptions.c_str(), "w")){
|
||||
char buffer[2048] = {'\0'};
|
||||
size_t qq = fread(&buffer[0], 2048, 1, fp);
|
||||
fwrite(&buffer[0], strlen(&buffer[0]), 1, ofp);
|
||||
fclose(ofp);
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool makeTempOptions(unsigned int i){
|
||||
string & line = lines[i];
|
||||
|
||||
if (FILE * fp = fopen("../JSONOptions.h", "w")){
|
||||
string res("#ifndef JSON_OPTIONS_H\n#define JSON_OPTIONS_H\n");
|
||||
for (
|
||||
map<string, string>::iterator runner = options.begin(), end = options.end();
|
||||
runner != end;
|
||||
++runner){
|
||||
|
||||
if (line.find(runner -> first) != string::npos){
|
||||
res += runner -> second + "\n";
|
||||
}
|
||||
}
|
||||
res += "#endif\n";
|
||||
|
||||
fwrite(res.c_str(), res.length(), 1, fp);
|
||||
fclose(fp);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool hideGoodOptions(void){
|
||||
struct stat stFileInfo;
|
||||
if (stat("../__JSONOptions.h", &stFileInfo)){
|
||||
remove("../JSONOptions.h");
|
||||
return true;
|
||||
}
|
||||
return (rename("../JSONOptions.h", "../__JSONOptions.h") == 0);
|
||||
}
|
||||
|
||||
bool loadTests(){
|
||||
ifstream infile("All/Options.txt");
|
||||
|
||||
if (!infile){
|
||||
return false;
|
||||
}
|
||||
|
||||
string line;
|
||||
unsigned int iii = 0;
|
||||
while (getline(infile, line)){
|
||||
++iii;
|
||||
size_t pos = line.find_first_not_of(' ');
|
||||
if (pos != string::npos){
|
||||
line = line.substr(pos);
|
||||
pos = line.find_first_not_of("\r\n\t ");
|
||||
if ((line.length() > 5) && (line[0] != '#')){
|
||||
const string temp(line.substr(pos));
|
||||
lines.push_back(string("READER, ") + temp);
|
||||
line_numbers.push_back(iii);
|
||||
if ((temp.find("VALIDATE") == string::npos) && (temp.find("STREAM") == string::npos)){
|
||||
lines.push_back(temp);
|
||||
line_numbers.push_back(iii);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
infile.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
void RunTest(const std::string & version, unsigned int i){
|
||||
if(makeTempOptions(i)){
|
||||
stringstream mystream;
|
||||
mystream << version << " Line " << line_numbers[i];
|
||||
cout << "Compiling " << ++counter << " of " << line_numbers.size() * 3 << " - " << mystream.str() << endl;
|
||||
cout << " " << lines[i] << endl;
|
||||
UnitTest::SetPrefix(mystream.str());
|
||||
stringstream options_;
|
||||
options_ << version << "_Line_" << line_numbers[i] << "_JSONOptions.h";
|
||||
ArchivedOptions = options_.str();
|
||||
testRules(i);
|
||||
remove("../JSONOptions.h");
|
||||
UnitTest::SaveTo("progress.html");
|
||||
}
|
||||
}
|
||||
|
||||
void Go(const std::string & version, unsigned int test){
|
||||
echo(make);
|
||||
if (makeStyle.empty() || (makeStyle == version)){
|
||||
makeStyle.clear();
|
||||
for (unsigned int i = test; i < lines.size(); ++i){
|
||||
RunTest(version, i);
|
||||
}
|
||||
} else {
|
||||
echo("skipping");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void RunTests(unsigned int test){
|
||||
if (hideGoodOptions()){
|
||||
if(loadTests()){
|
||||
makeMap();
|
||||
for(unsigned int i = 0; i < sizeof(makeOptions); ++i){
|
||||
make = "make -j4 " + makeOptions[i];
|
||||
Go(makeOptions[i], test);
|
||||
}
|
||||
} else {
|
||||
FAIL("couldn't open options");
|
||||
}
|
||||
rename("../__JSONOptions.h", "../JSONOptions.h");
|
||||
} else {
|
||||
FAIL("Couldn't protect JSONOptions");
|
||||
}
|
||||
}
|
||||
|
||||
int main (int argc, char * const argv[]) {
|
||||
UnitTest::StartTime();
|
||||
unsigned int test = 0;
|
||||
if (argc == 3){
|
||||
test = atoi(argv[2]) - 1;
|
||||
counter = test;
|
||||
echo("starting on test " << test);
|
||||
makeStyle = argv[1];
|
||||
echo("starting with make " << makeStyle);
|
||||
} else if (argc == 2){
|
||||
test = 0;
|
||||
counter = test;
|
||||
echo("starting on test " << test);
|
||||
makeStyle = argv[1];
|
||||
echo("starting with make " << makeStyle);
|
||||
}
|
||||
|
||||
RunTests(test);
|
||||
|
||||
UnitTest::SaveTo("out.html");
|
||||
return 0;
|
||||
}
|
311
src/libjson/_internal/TestSuite/Benchmark/main.cpp
Normal file
311
src/libjson/_internal/TestSuite/Benchmark/main.cpp
Normal file
|
@ -0,0 +1,311 @@
|
|||
/**
|
||||
*
|
||||
* This test suite should get run before releasing a new version of libjson, once all
|
||||
* unit tests have passed. This asserts that the Options are in the default configuration,
|
||||
* this prevents me from accidentally releasing libjson using options that I had been testing
|
||||
* with. It also performs a speed benchmark, so I can keep track of how libjson is performing
|
||||
*
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <ctime>
|
||||
#include "../../libjson.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
#ifndef JSON_LIBRARY
|
||||
#error, JSON_LIBRARY not on
|
||||
#endif
|
||||
|
||||
#ifdef JSON_STRICT
|
||||
#error, JSON_STRICT on
|
||||
#endif
|
||||
|
||||
#ifdef JSON_DEBUG
|
||||
#error, JSON_DEBUG on
|
||||
#endif
|
||||
|
||||
#ifdef JSON_ISO_STRICT
|
||||
#error, JSON_ISO_STRICT on
|
||||
#endif
|
||||
|
||||
#ifndef JSON_SAFE
|
||||
#error, JSON_SAFE not on
|
||||
#endif
|
||||
|
||||
#ifndef JSON_CASTABLE
|
||||
#error, JSON_CASTABLE not on
|
||||
#endif
|
||||
|
||||
#ifdef JSON_STDERROR
|
||||
#error, JSON_STDERROR on
|
||||
#endif
|
||||
|
||||
#ifdef JSON_PREPARSE
|
||||
#error, JSON_PREPARSE on
|
||||
#endif
|
||||
|
||||
#ifdef JSON_LESS_MEMORY
|
||||
#error, JSON_LESS_MEMORY on
|
||||
#endif
|
||||
|
||||
#ifdef JSON_UNICODE
|
||||
#error, JSON_UNICODE on
|
||||
#endif
|
||||
|
||||
#ifndef JSON_REF_COUNT
|
||||
#error, JSON_REF_COUNT not on
|
||||
#endif
|
||||
|
||||
#ifndef JSON_BINARY
|
||||
#error, JSON_BINARY not on
|
||||
#endif
|
||||
|
||||
#ifndef JSON_EXPOSE_BASE64
|
||||
#error, JSON_EXPOSE_BASE64 not on
|
||||
#endif
|
||||
|
||||
#ifndef JSON_ITERATORS
|
||||
#error, JSON_ITERATORS not on
|
||||
#endif
|
||||
|
||||
#ifndef JSON_STREAM
|
||||
#error, JSON_STREAM not on
|
||||
#endif
|
||||
|
||||
#ifdef JSON_MEMORY_CALLBACKS
|
||||
#error, JSON_MEMORY_CALLBACKS on
|
||||
#endif
|
||||
|
||||
#ifdef JSON_MEMORY_MANAGE
|
||||
#error, JSON_MEMORY_MANAGE on
|
||||
#endif
|
||||
|
||||
#ifdef JSON_MUTEX_CALLBACKS
|
||||
#error, JSON_MUTEX_CALLBACKS on
|
||||
#endif
|
||||
|
||||
#ifdef JSON_MUTEX_MANAGE
|
||||
#error, JSON_MUTEX_MANAGE on
|
||||
#endif
|
||||
|
||||
#ifdef JSON_NO_C_CONSTS
|
||||
#error, JSON_NO_C_CONSTS on
|
||||
#endif
|
||||
|
||||
#ifdef JSON_OCTAL
|
||||
#error, JSON_OCTAL on
|
||||
#endif
|
||||
|
||||
#if (JSON_READ_PRIORITY != HIGH)
|
||||
#error JSON_READ_PRIORITY not high
|
||||
#endif
|
||||
|
||||
#if (JSON_WRITE_PRIORITY != MED)
|
||||
#error JSON_WRITE_PRIORITY not med
|
||||
#endif
|
||||
|
||||
#ifdef JSON_NEWLINE
|
||||
#error, JSON_NEWLINE on
|
||||
#endif
|
||||
|
||||
#ifdef JSON_INDENT
|
||||
#error, JSON_INDENT on
|
||||
#endif
|
||||
|
||||
#ifndef JSON_ESCAPE_WRITES
|
||||
#error, JSON_ESCAPE_WRITES not on
|
||||
#endif
|
||||
|
||||
#ifndef JSON_COMMENTS
|
||||
#error, JSON_COMMENTS not on
|
||||
#endif
|
||||
|
||||
#ifdef JSON_WRITE_BASH_COMMENTS
|
||||
#error, JSON_WRITE_BASH_COMMENTS on
|
||||
#endif
|
||||
|
||||
#ifdef JSON_WRITE_SINGLE_LINE_COMMENTS
|
||||
#error, JSON_WRITE_SINGLE_LINE_COMMENTS on
|
||||
#endif
|
||||
|
||||
#ifdef JSON_ARRAY_ON_ONE_LINE
|
||||
#error, JSON_ARRAY_ON_ONE_LINE on
|
||||
#endif
|
||||
|
||||
#ifndef JSON_VALIDATE
|
||||
#error, JSON_VALIDATE not on
|
||||
#endif
|
||||
|
||||
#ifndef JSON_CASE_INSENSITIVE_FUNCTIONS
|
||||
#error, JSON_CASE_INSENSITIVE_FUNCTIONS not on
|
||||
#endif
|
||||
|
||||
#ifdef JSON_INDEX_TYPE
|
||||
#error, JSON_INDEX_TYPE on
|
||||
#endif
|
||||
|
||||
#ifdef JSON_BOOL_TYPE
|
||||
#error, JSON_BOOL_TYPE on
|
||||
#endif
|
||||
|
||||
#ifdef JSON_INT_TYPE
|
||||
#error, JSON_INT_TYPE on
|
||||
#endif
|
||||
|
||||
#ifdef JSON_STRING_HEADER
|
||||
#error, JSON_STRING_HEADER on
|
||||
#endif
|
||||
|
||||
#ifdef JSON_NO_EXCEPTIONS
|
||||
#error, JSON_NO_EXCEPTIONS on
|
||||
#endif
|
||||
|
||||
#ifndef JSON_DEPRECATED_FUNCTIONS
|
||||
#error, JSON_DEPRECATED_FUNCTIONS not on
|
||||
#endif
|
||||
|
||||
#if (JSON_SECURITY_MAX_NEST_LEVEL != 128)
|
||||
#error JSON_SECURITY_MAX_NEST_LEVEL not 128
|
||||
#endif
|
||||
|
||||
#if (JSON_SECURITY_MAX_STRING_LENGTH != 33554432)
|
||||
#error JSON_SECURITY_MAX_STRING_LENGTH not 33554432
|
||||
#endif
|
||||
|
||||
#if (JSON_SECURITY_MAX_STREAM_OBJECTS != 128)
|
||||
#error JSON_SECURITY_MAX_STREAM_OBJECTS not 128
|
||||
#endif
|
||||
|
||||
#ifdef JSON_MEMORY_POOL
|
||||
#error JSON_MEMORY_POOL is on
|
||||
#endif
|
||||
|
||||
#ifdef JSON_UNIT_TEST
|
||||
#error, JSON_UNIT_TEST on
|
||||
#endif
|
||||
|
||||
#define IT_COUNT 50000
|
||||
static string makeBigFormatted(){
|
||||
string json = "{\n";
|
||||
for(unsigned int i = 0; i < IT_COUNT; ++i){
|
||||
json += "\t//This is an object\r\n\t{\n\t\t\"name\" : 14.783,\n\t\t/* This is a multilen commenet */\n\t\t\"another\" : \"I am a stirng\"\n\t},";
|
||||
json += "\n\n\t//This is an array\r\n\t[4, 16, true, false, 78.98],\n";
|
||||
}
|
||||
json += "\t\"number\" : null\n}";
|
||||
return json;
|
||||
}
|
||||
|
||||
static string makeBig(){
|
||||
string json = "{";
|
||||
for(unsigned int i = 0; i < IT_COUNT; ++i){
|
||||
json += "{\"name\":14.783,\"another\":\"I am a stirng\"},";
|
||||
json += "[4, 16, true, false, 78.98],";
|
||||
}
|
||||
json += "\"number\":null}";
|
||||
return json;
|
||||
}
|
||||
|
||||
int main (int argc, char * const argv[]) {
|
||||
JSONNODE * node;
|
||||
string mystr = makeBigFormatted();
|
||||
clock_t start = clock();
|
||||
for(unsigned int i = 0; i < 100; ++i){
|
||||
node = json_parse(mystr.c_str());
|
||||
for (unsigned int j = 0; j < IT_COUNT; ++j){
|
||||
JSONNODE * meh = json_at(node, j * 2);
|
||||
json_as_float(json_get(meh, "name"));
|
||||
char * str = json_as_string(json_get(meh, "another"));
|
||||
json_free(str);
|
||||
|
||||
meh = json_at(node, j * 2 + 1);
|
||||
json_as_int(json_at(meh, 0));
|
||||
json_as_int(json_at(meh, 1));
|
||||
json_as_bool(json_at(meh, 2));
|
||||
json_as_bool(json_at(meh, 3));
|
||||
json_as_int(json_at(meh, 4));
|
||||
}
|
||||
json_delete(node);
|
||||
}
|
||||
cout << "Reading: " << clock() - start << endl;
|
||||
|
||||
|
||||
|
||||
mystr = makeBig();
|
||||
start = clock();
|
||||
for(unsigned int i = 0; i < 100; ++i){
|
||||
node = json_parse(mystr.c_str());
|
||||
for (unsigned int j = 0; j < IT_COUNT; ++j){
|
||||
JSONNODE * meh = json_at(node, j * 2);
|
||||
json_as_float(json_get(meh, "name"));
|
||||
char * str = json_as_string(json_get(meh, "another"));
|
||||
json_free(str);
|
||||
|
||||
meh = json_at(node, j * 2 + 1);
|
||||
json_as_int(json_at(meh, 0));
|
||||
json_as_int(json_at(meh, 1));
|
||||
json_as_bool(json_at(meh, 2));
|
||||
json_as_bool(json_at(meh, 3));
|
||||
json_as_int(json_at(meh, 4));
|
||||
}
|
||||
json_delete(node);
|
||||
}
|
||||
cout << "Reading Unformatted: " << clock() - start << endl;
|
||||
|
||||
|
||||
start = clock();
|
||||
for(unsigned int i = 0; i < 100; ++i){
|
||||
node = json_new(JSON_NODE);
|
||||
for (unsigned int j = 0; j < IT_COUNT; ++j){
|
||||
JSONNODE * meh = json_new(JSON_NODE);
|
||||
json_push_back(meh, json_new_f("name", 14.783));
|
||||
json_push_back(meh, json_new_a("another", "I am a string"));
|
||||
json_push_back(node, meh);
|
||||
|
||||
meh = json_new(JSON_ARRAY);
|
||||
json_push_back(meh, json_new_i(NULL, 14));
|
||||
json_push_back(meh, json_new_i("", 1));
|
||||
json_push_back(meh, json_new_b(NULL, true));
|
||||
json_push_back(meh, json_new_b("", false));
|
||||
json_push_back(meh, json_new_f(NULL, 14.3243));
|
||||
json_push_back(node, meh);
|
||||
}
|
||||
json_delete(node);
|
||||
}
|
||||
cout << "Building: " << clock() - start << endl;
|
||||
|
||||
|
||||
|
||||
node = json_new(JSON_NODE);
|
||||
for (unsigned int j = 0; j < IT_COUNT; ++j){
|
||||
JSONNODE * meh = json_new(JSON_NODE);
|
||||
json_push_back(meh, json_new_f("name", 14.783));
|
||||
json_push_back(meh, json_new_a("another", "I am a string"));
|
||||
json_push_back(node, meh);
|
||||
|
||||
meh = json_new(JSON_ARRAY);
|
||||
json_push_back(meh, json_new_i(NULL, 14));
|
||||
json_push_back(meh, json_new_i("", 1));
|
||||
json_push_back(meh, json_new_b(NULL, true));
|
||||
json_push_back(meh, json_new_b("", false));
|
||||
json_push_back(meh, json_new_f(NULL, 14.3243));
|
||||
json_push_back(node, meh);
|
||||
}
|
||||
start = clock();
|
||||
for(unsigned int i = 0; i < 100; ++i){
|
||||
char * str = json_write_formatted(node);
|
||||
json_free(str);
|
||||
}
|
||||
cout << "Writing: " << clock() - start << endl;
|
||||
|
||||
start = clock();
|
||||
for(unsigned int i = 0; i < 100; ++i){
|
||||
char * str = json_write(node);
|
||||
json_free(str);
|
||||
}
|
||||
cout << "Writing Unformatted: " << clock() - start << endl;
|
||||
json_delete(node);
|
||||
|
||||
return 0;
|
||||
}
|
42
src/libjson/_internal/TestSuite/Benchmark/makefile
Normal file
42
src/libjson/_internal/TestSuite/Benchmark/makefile
Normal file
|
@ -0,0 +1,42 @@
|
|||
OS=$(shell uname)
|
||||
ifeq ($(OS), Darwin)
|
||||
fastflag = -fast
|
||||
else
|
||||
fastflag = -O3
|
||||
endif
|
||||
|
||||
single:
|
||||
g++ main.cpp \
|
||||
../../Source/internalJSONNode.cpp \
|
||||
../../Source/JSONChildren.cpp ../../Source/JSONDebug.cpp \
|
||||
../../Source/JSONIterators.cpp ../../Source/JSONMemory.cpp \
|
||||
../../Source/JSONNode_Mutex.cpp ../../Source/JSONNode.cpp \
|
||||
../../Source/JSONWorker.cpp ../../Source/JSONWriter.cpp \
|
||||
../../Source/libjson.cpp ../../Source/JSONValidator.cpp \
|
||||
../../Source/JSONStream.cpp ../../Source/JSONAllocator.cpp \
|
||||
../../Source/JSONPreparse.cpp \
|
||||
-Wfatal-errors -DNDEBUG $(fastflag) -ffast-math -fexpensive-optimizations -o testapp
|
||||
|
||||
debug:
|
||||
g++ main.cpp \
|
||||
../../Source/internalJSONNode.cpp \
|
||||
../../Source/JSONChildren.cpp ../../Source/JSONDebug.cpp \
|
||||
../../Source/JSONIterators.cpp ../../Source/JSONMemory.cpp \
|
||||
../../Source/JSONNode_Mutex.cpp ../../Source/JSONNode.cpp \
|
||||
../../Source/JSONWorker.cpp ../../Source/JSONWriter.cpp \
|
||||
../../Source/libjson.cpp ../../Source/JSONValidator.cpp \
|
||||
../../Source/JSONStream.cpp ../../Source/JSONAllocator.cpp \
|
||||
../../Source/JSONPreparse.cpp \
|
||||
-Wfatal-errors -DJSON_DEBUG -o testapp
|
||||
|
||||
small:
|
||||
g++ main.cpp \
|
||||
../../Source/internalJSONNode.cpp \
|
||||
../../Source/JSONChildren.cpp ../../Source/JSONDebug.cpp \
|
||||
../../Source/JSONIterators.cpp ../../Source/JSONMemory.cpp \
|
||||
../../Source/JSONNode_Mutex.cpp ../../Source/JSONNode.cpp \
|
||||
../../Source/JSONWorker.cpp ../../Source/JSONWriter.cpp \
|
||||
../../Source/libjson.cpp ../../Source/JSONValidator.cpp \
|
||||
../../Source/JSONStream.cpp ../../Source/JSONAllocator.cpp \
|
||||
../../Source/JSONPreparse.cpp \
|
||||
-Wfatal-errors -DNDEBUG -Os -ffast-math -DJSON_LESS_MEMORY -o testapp
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue