Compare commits

..

9 Commits
1.4.4 ... 0.8.0

Author SHA1 Message Date
Christopher Dunn
b31d224fd6 partially revert 'Added features that allow the reader to accept common non-standard JSON.'
revert '642befc836ac5093b528e7d8b4fd66b66735a98c',
but keep the *added* methods for `decodedNumber()` and `decodedDouble()`.
2015-02-11 11:22:07 -06:00
Christopher Dunn
a901a04c28 partially revert 'fix bug for static init'
re: 28836b8acc

A global instance of a Value (viz. 'null') was a mistake,
but dropping it breaks binary-compatibility. So we will keep it
everywhere except the one platform where it was crashing, ARM.
2015-02-11 11:22:07 -06:00
Christopher Dunn
c9afea87e3 revert 'Made it possible to drop null placeholders from array output.'
revert ae3c7a7aab
2015-02-11 11:22:07 -06:00
Christopher Dunn
edf9369493 Revert "added option to FastWriter which omits the trailing new line character"
This reverts commit 5bf16105b5.
2015-02-11 11:22:06 -06:00
Christopher Dunn
18ae85b44c revert 'Added structured error reporting to Reader.'
revert 68db655347
issue #147
2015-02-11 11:22:06 -06:00
Christopher Dunn
bd2aa77b94 revert 'Add public semantic error reporting'
for binary-compatibility with 0.6.0
issue #147
was #57
2015-02-11 11:22:06 -06:00
Christopher Dunn
6a12fb8999 Revert "Switch to copy-and-swap idiom for operator=."
This reverts commit 45cd9490cd.

Ignored ValueInternal* changes, since those did not produce symbols for
Debian build. (They must not have used the INTERNAL stuff.)

  https://github.com/open-source-parsers/jsoncpp/issues/78

Conflicts:
	include/json/value.h
	src/lib_json/json_internalarray.inl
	src/lib_json/json_internalmap.inl
	src/lib_json/json_value.cpp
2015-02-11 11:22:06 -06:00
Christopher Dunn
a1ca466e04 NOT C++11 2015-02-11 11:22:06 -06:00
Christopher Dunn
5a14ab5ea3 0.8.0 2015-02-11 11:22:06 -06:00
17 changed files with 100 additions and 756 deletions

View File

@@ -85,10 +85,10 @@ endif( MSVC )
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
# using regular Clang or AppleClang # using regular Clang or AppleClang
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
# using GCC # using GCC
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x -Wall -Wextra -pedantic") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic")
endif() endif()
IF(JSONCPP_WITH_WARNING_AS_ERROR) IF(JSONCPP_WITH_WARNING_AS_ERROR)

View File

@@ -7,20 +7,17 @@ pairs.
[json-org]: http://json.org/ [json-org]: http://json.org/
[JsonCpp][] is a C++ library that allows manipulating JSON values, including JsonCpp is a C++ library that allows manipulating JSON values, including
serialization and deserialization to and from strings. It can also preserve serialization and deserialization to and from strings. It can also preserve
existing comment in unserialization/serialization steps, making it a convenient existing comment in unserialization/serialization steps, making it a convenient
format to store user input files. format to store user input files.
[JsonCpp]: http://open-source-parsers.github.io/jsoncpp-docs/doxygen/index.html
## A note on backward-compatibility ## A note on backward-compatibility
* `1.y.z` is built with C++11. Very soon, we are switching to C++11 only. For older compilers, try the `pre-C++11` branch.
* `0.8.z` can be used with older compilers.
* Major versions maintain binary-compatibility.
Using JsonCpp in your project Using JsonCpp in your project
----------------------------- -----------------------------
The recommended approach to integrating JsonCpp in your project is to build The recommended approach to integrating JsonCpp in your project is to build
the amalgamated source (a single `.cpp` file) with your own build system. This the amalgamated source (a single `.cpp` file) with your own build system. This
ensures consistency of compilation flags and ABI compatibility. See the section ensures consistency of compilation flags and ABI compatibility. See the section
@@ -31,11 +28,13 @@ should be included as follow:
#include <json/json.h> #include <json/json.h>
If JsonCpp was built as a dynamic library on Windows, then your project needs to If JsonCpp was build as a dynamic library on Windows, then your project needs to
define the macro `JSON_DLL`. define the macro `JSON_DLL`.
Building and testing with CMake
------------------------------- Building and testing with new CMake
-----------------------------------
[CMake][] is a C++ Makefiles/Solution generator. It is usually available on most [CMake][] is a C++ Makefiles/Solution generator. It is usually available on most
Linux system as package. On Ubuntu: Linux system as package. On Ubuntu:
@@ -76,8 +75,10 @@ the `-G` option).
By default CMake hides compilation commands. This can be modified by specifying By default CMake hides compilation commands. This can be modified by specifying
`-DCMAKE_VERBOSE_MAKEFILE=true` when generating makefiles. `-DCMAKE_VERBOSE_MAKEFILE=true` when generating makefiles.
Building and testing with SCons Building and testing with SCons
------------------------------- -------------------------------
**Note:** The SCons-based build system is deprecated. Please use CMake; see the **Note:** The SCons-based build system is deprecated. Please use CMake; see the
section above. section above.
@@ -106,7 +107,14 @@ If you are building with Microsoft Visual Studio 2008, you need to set up the
environment by running `vcvars32.bat` (e.g. MSVC 2008 command prompt) before environment by running `vcvars32.bat` (e.g. MSVC 2008 command prompt) before
running SCons. running SCons.
# Running the tests manually
Running the tests manually
--------------------------
Note that test can be run using SCons using the `check` target:
scons platform=$PLATFORM check
You need to run tests manually only if you are troubleshooting an issue. You need to run tests manually only if you are troubleshooting an issue.
In the instructions below, replace `path/to/jsontest` with the path of the In the instructions below, replace `path/to/jsontest` with the path of the
@@ -129,21 +137,20 @@ In the instructions below, replace `path/to/jsontest` with the path of the
# You can run the tests using valgrind: # You can run the tests using valgrind:
python rununittests.py --valgrind path/to/test_lib_json python rununittests.py --valgrind path/to/test_lib_json
## Running the tests using scons
Note that tests can be run using SCons using the `check` target:
scons platform=$PLATFORM check
Building the documentation Building the documentation
-------------------------- --------------------------
Run the Python script `doxybuild.py` from the top directory: Run the Python script `doxybuild.py` from the top directory:
python doxybuild.py --doxygen=$(which doxygen) --open --with-dot python doxybuild.py --doxygen=$(which doxygen) --open --with-dot
See `doxybuild.py --help` for options. See `doxybuild.py --help` for options.
Generating amalgamated source and header Generating amalgamated source and header
---------------------------------------- ----------------------------------------
JsonCpp is provided with a script to generate a single header and a single JsonCpp is provided with a script to generate a single header and a single
source file to ease inclusion into an existing project. The amalgamated source source file to ease inclusion into an existing project. The amalgamated source
can be generated at any time by running the following command from the can be generated at any time by running the following command from the
@@ -165,8 +172,10 @@ The amalgamated sources are generated by concatenating JsonCpp source in the
correct order and defining the macro `JSON_IS_AMALGAMATION` to prevent inclusion correct order and defining the macro `JSON_IS_AMALGAMATION` to prevent inclusion
of other headers. of other headers.
Adding a reader/writer test Adding a reader/writer test
--------------------------- ---------------------------
To add a test, you need to create two files in test/data: To add a test, you need to create two files in test/data:
* a `TESTNAME.json` file, that contains the input document in JSON format. * a `TESTNAME.json` file, that contains the input document in JSON format.
@@ -186,8 +195,10 @@ The `TESTNAME.expected` file format is as follows:
See the examples `test_complex_01.json` and `test_complex_01.expected` to better See the examples `test_complex_01.json` and `test_complex_01.expected` to better
understand element paths. understand element paths.
Understanding reader/writer test output Understanding reader/writer test output
--------------------------------------- ---------------------------------------
When a test is run, output files are generated beside the input test files. When a test is run, output files are generated beside the input test files.
Below is a short description of the content of each file: Below is a short description of the content of each file:
@@ -204,7 +215,10 @@ Below is a short description of the content of each file:
* `test_complex_01.process-output`: `jsontest` output, typically useful for * `test_complex_01.process-output`: `jsontest` output, typically useful for
understanding parsing errors. understanding parsing errors.
License License
------- -------
See the `LICENSE` file for details. In summary, JsonCpp is licensed under the See the `LICENSE` file for details. In summary, JsonCpp is licensed under the
MIT license, or public domain if desired and recognized in your jurisdiction. MIT license, or public domain if desired and recognized in your jurisdiction.

View File

@@ -59,7 +59,7 @@ def amalgamate_source(source_top_dir=None,
print("Amalgating header...") print("Amalgating header...")
header = AmalgamationFile(source_top_dir) header = AmalgamationFile(source_top_dir)
header.add_text("/// Json-cpp amalgated header (http://jsoncpp.sourceforge.net/).") header.add_text("/// Json-cpp amalgated header (http://jsoncpp.sourceforge.net/).")
header.add_text('/// It is intended to be used with #include "%s"' % header_include_path) header.add_text("/// It is intented to be used with #include <%s>" % header_include_path)
header.add_file("LICENSE", wrap_in_comment=True) header.add_file("LICENSE", wrap_in_comment=True)
header.add_text("#ifndef JSON_AMALGATED_H_INCLUDED") header.add_text("#ifndef JSON_AMALGATED_H_INCLUDED")
header.add_text("# define JSON_AMALGATED_H_INCLUDED") header.add_text("# define JSON_AMALGATED_H_INCLUDED")
@@ -85,7 +85,7 @@ def amalgamate_source(source_top_dir=None,
print("Amalgating forward header...") print("Amalgating forward header...")
header = AmalgamationFile(source_top_dir) header = AmalgamationFile(source_top_dir)
header.add_text("/// Json-cpp amalgated forward header (http://jsoncpp.sourceforge.net/).") header.add_text("/// Json-cpp amalgated forward header (http://jsoncpp.sourceforge.net/).")
header.add_text('/// It is intended to be used with #include "%s"' % forward_header_include_path) header.add_text("/// It is intented to be used with #include <%s>" % forward_header_include_path)
header.add_text("/// This header provides forward declaration for all JsonCpp types.") header.add_text("/// This header provides forward declaration for all JsonCpp types.")
header.add_file("LICENSE", wrap_in_comment=True) header.add_file("LICENSE", wrap_in_comment=True)
header.add_text("#ifndef JSON_FORWARD_AMALGATED_H_INCLUDED") header.add_text("#ifndef JSON_FORWARD_AMALGATED_H_INCLUDED")
@@ -105,15 +105,10 @@ def amalgamate_source(source_top_dir=None,
print("Amalgating source...") print("Amalgating source...")
source = AmalgamationFile(source_top_dir) source = AmalgamationFile(source_top_dir)
source.add_text("/// Json-cpp amalgated source (http://jsoncpp.sourceforge.net/).") source.add_text("/// Json-cpp amalgated source (http://jsoncpp.sourceforge.net/).")
source.add_text('/// It is intended to be used with #include "%s"' % header_include_path) source.add_text("/// It is intented to be used with #include <%s>" % header_include_path)
source.add_file("LICENSE", wrap_in_comment=True) source.add_file("LICENSE", wrap_in_comment=True)
source.add_text("") source.add_text("")
source.add_text('#include "%s"' % header_include_path) source.add_text("#include <%s>" % header_include_path)
source.add_text("""
#ifndef JSON_IS_AMALGAMATION
#error "Compile with -I PATH_TO_JSON_DIRECTORY"
#endif
""")
source.add_text("") source.add_text("")
lib_json = "src/lib_json" lib_json = "src/lib_json"
source.add_file(os.path.join(lib_json, "json_tool.h")) source.add_file(os.path.join(lib_json, "json_tool.h"))

View File

@@ -1,19 +1,5 @@
# This is only for jsoncpp developers/contributors. all: build test-amalgamate
# We use this to sign releases, generate documentation, etc.
VER?=$(shell cat version)
default:
@echo "VER=${VER}"
sign: jsoncpp-${VER}.tar.gz
gpg --armor --detach-sign $<
gpg --verify $<.asc
# Then upload .asc to the release.
jsoncpp-%.tar.gz:
curl https://github.com/open-source-parsers/jsoncpp/archive/$*.tar.gz -o $@
dox:
python doxybuild.py --doxygen=$$(which doxygen) --in doc/web_doxyfile.in
rsync -va --delete dist/doxygen/jsoncpp-api-html-${VER}/ ../jsoncpp-docs/doxygen/
# Then 'git add -A' and 'git push' in jsoncpp-docs.
build: build:
mkdir -p build/debug mkdir -p build/debug
cd build/debug; cmake -DCMAKE_BUILD_TYPE=debug -DJSONCPP_LIB_BUILD_SHARED=ON -G "Unix Makefiles" ../.. cd build/debug; cmake -DCMAKE_BUILD_TYPE=debug -DJSONCPP_LIB_BUILD_SHARED=ON -G "Unix Makefiles" ../..
@@ -21,11 +7,8 @@ build:
# Currently, this depends on include/json/version.h generated # Currently, this depends on include/json/version.h generated
# by cmake. # by cmake.
test-amalgamate: test-amalgamate: build
python2.7 amalgamate.py python2.7 amalgamate.py
python3.4 amalgamate.py python3.4 amalgamate.py
clean:
\rm -rf *.gz *.asc dist/
.PHONY: build .PHONY: build

View File

@@ -56,24 +56,20 @@ std::cin >> root;
// You can also read into a particular sub-value. // You can also read into a particular sub-value.
std::cin >> root["subtree"]; std::cin >> root["subtree"];
// Get the value of the member of root named 'encoding', // Get the value of the member of root named 'encoding', return 'UTF-8' if there is no
// and return 'UTF-8' if there is no such member. // such member.
std::string encoding = root.get("encoding", "UTF-8" ).asString(); std::string encoding = root.get("encoding", "UTF-8" ).asString();
// Get the value of the member of root named 'encoding'; return a 'null' value if
// Get the value of the member of root named 'plug-ins'; return a 'null' value if
// there is no such member. // there is no such member.
const Json::Value plugins = root["plug-ins"]; const Json::Value plugins = root["plug-ins"];
for ( int index = 0; index < plugins.size(); ++index ) // Iterates over the sequence elements.
// Iterate over the sequence elements.
for ( int index = 0; index < plugins.size(); ++index )
loadPlugIn( plugins[index].asString() ); loadPlugIn( plugins[index].asString() );
// Try other datatypes. Some are auto-convertible to others.
foo::setIndentLength( root["indent"].get("length", 3).asInt() ); foo::setIndentLength( root["indent"].get("length", 3).asInt() );
foo::setIndentUseSpace( root["indent"].get("use_space", true).asBool() ); foo::setIndentUseSpace( root["indent"].get("use_space", true).asBool() );
// Since Json::Value has an implicit constructor for all value types, it is not // Since Json::Value has implicit constructor for all value types, it is not
// necessary to explicitly construct the Json::Value object. // necessary to explicitly construct the Json::Value object:
root["encoding"] = foo::getCurrentEncoding(); root["encoding"] = foo::getCurrentEncoding();
root["indent"]["length"] = foo::getCurrentIndentLength(); root["indent"]["length"] = foo::getCurrentIndentLength();
root["indent"]["use_space"] = foo::getCurrentIndentUseSpace(); root["indent"]["use_space"] = foo::getCurrentIndentUseSpace();
@@ -156,7 +152,6 @@ Basically JsonCpp is licensed under MIT license, or public domain if desired
and recognized in your jurisdiction. and recognized in your jurisdiction.
\author Baptiste Lepilleur <blep@users.sourceforge.net> (originator) \author Baptiste Lepilleur <blep@users.sourceforge.net> (originator)
\author Christopher Dunn <cdunn2001@gmail.com> (primary maintainer)
\version \include version \version \include version
We make strong guarantees about binary-compatibility, consistent with We make strong guarantees about binary-compatibility, consistent with
<a href="http://apr.apache.org/versioning.html">the Apache versioning scheme</a>. <a href="http://apr.apache.org/versioning.html">the Apache versioning scheme</a>.

View File

@@ -16,7 +16,7 @@
#if JSON_USE_EXCEPTION #if JSON_USE_EXCEPTION
#include <stdexcept> #include <stdexcept>
#define JSON_ASSERT(condition) \ #define JSON_ASSERT(condition) \
if (!(condition)) {throw std::runtime_error( "assert json failed" );} // @todo <= add detail about condition in exception assert(condition); // @todo <= change this into an exception throw
#define JSON_FAIL_MESSAGE(message) do{std::ostringstream oss; oss << message; throw std::runtime_error(oss.str());}while(0) #define JSON_FAIL_MESSAGE(message) do{std::ostringstream oss; oss << message; throw std::runtime_error(oss.str());}while(0)
//#define JSON_FAIL_MESSAGE(message) throw std::runtime_error(message) //#define JSON_FAIL_MESSAGE(message) throw std::runtime_error(message)
#else // JSON_USE_EXCEPTION #else // JSON_USE_EXCEPTION

View File

@@ -44,12 +44,6 @@ public:
/// \c true if root must be either an array or an object value. Default: \c /// \c true if root must be either an array or an object value. Default: \c
/// false. /// false.
bool strictRoot_; bool strictRoot_;
/// \c true if dropped null placeholders are allowed. Default: \c false.
bool allowDroppedNullPlaceholders_;
/// \c true if numeric object key are allowed. Default: \c false.
bool allowNumericKeys_;
}; };
} // namespace Json } // namespace Json

View File

@@ -35,18 +35,6 @@ public:
typedef char Char; typedef char Char;
typedef const Char* Location; typedef const Char* Location;
/** \brief An error tagged with where in the JSON text it was encountered.
*
* The offsets give the [start, limit) range of bytes within the text. Note
* that this is bytes, not codepoints.
*
*/
struct StructuredError {
size_t offset_start;
size_t offset_limit;
std::string message;
};
/** \brief Constructs a Reader allowing all features /** \brief Constructs a Reader allowing all features
* for parsing. * for parsing.
*/ */
@@ -123,38 +111,6 @@ public:
*/ */
std::string getFormattedErrorMessages() const; std::string getFormattedErrorMessages() const;
/** \brief Returns a vector of structured erros encounted while parsing.
* \return A (possibly empty) vector of StructuredError objects. Currently
* only one error can be returned, but the caller should tolerate
* multiple
* errors. This can occur if the parser recovers from a non-fatal
* parse error and then encounters additional errors.
*/
std::vector<StructuredError> getStructuredErrors() const;
/** \brief Add a semantic error message.
* \param value JSON Value location associated with the error
* \param message The error message.
* \return \c true if the error was successfully added, \c false if the
* Value offset exceeds the document size.
*/
bool pushError(const Value& value, const std::string& message);
/** \brief Add a semantic error message with extra context.
* \param value JSON Value location associated with the error
* \param message The error message.
* \param extra Additional JSON Value location to contextualize the error
* \return \c true if the error was successfully added, \c false if either
* Value offset exceeds the document size.
*/
bool pushError(const Value& value, const std::string& message, const Value& extra);
/** \brief Return whether there are any errors.
* \return \c true if there are no errors to report \c false if
* errors have occurred.
*/
bool good() const;
private: private:
enum TokenType { enum TokenType {
tokenEndOfStream = 0, tokenEndOfStream = 0,
@@ -298,26 +254,21 @@ public:
/** Configuration of this builder. /** Configuration of this builder.
These are case-sensitive. These are case-sensitive.
Available settings (case-sensitive): Available settings (case-sensitive):
- `"collectComments": false or true` - "collectComments": false or true
- true to collect comment and allow writing them - true to collect comment and allow writing them
back during serialization, false to discard comments. back during serialization, false to discard comments.
This parameter is ignored if allowComments is false. This parameter is ignored if allowComments is false.
- `"allowComments": false or true` - "allowComments": false or true
- true if comments are allowed. - true if comments are allowed.
- `"strictRoot": false or true` - "strictRoot": false or true
- true if root must be either an array or an object value - true if root must be either an array or an object value
- `"allowDroppedNullPlaceholders": false or true` - "allowDroppedNullPlaceholders": false or true
- true if dropped null placeholders are allowed. (See StreamWriterBuilder.) - true if dropped null placeholders are allowed. (See StreamWriterBuilder.)
- `"allowNumericKeys": false or true` - "allowNumericKeys": false or true
- true if numeric object keys are allowed. - true if numeric object keys are allowed.
- `"stackLimit": integer` - "stackLimit": integer
- Exceeding stackLimit (recursive depth of `readValue()`) will
cause an exception.
- This is a security issue (seg-faults caused by deeply nested JSON), - This is a security issue (seg-faults caused by deeply nested JSON),
so the default is low. so the default is low.
- `"failIfExtra": false or true`
- If true, `parse()` returns false when extra non-whitespace trails
the JSON value in the input string.
You can examine 'settings_` yourself You can examine 'settings_` yourself
to see the defaults. You can also write and read them just like any to see the defaults. You can also write and read them just like any

View File

@@ -133,8 +133,11 @@ public:
typedef Json::LargestUInt LargestUInt; typedef Json::LargestUInt LargestUInt;
typedef Json::ArrayIndex ArrayIndex; typedef Json::ArrayIndex ArrayIndex;
static const Value& null; ///! We regret this reference to a global instance; prefer the simpler Value(). static const Value& nullRef;
static const Value& nullRef; ///! just a kludge for binary-compatibility; same as null #if !defined(__ARMEL__)
/// \deprecated This exists for binary compatibility only. Use nullRef.
static const Value null;
#endif
/// Minimum signed integer value that can be stored in a Json::Value. /// Minimum signed integer value that can be stored in a Json::Value.
static const LargestInt minLargestInt; static const LargestInt minLargestInt;
/// Maximum signed integer value that can be stored in a Json::Value. /// Maximum signed integer value that can be stored in a Json::Value.
@@ -172,7 +175,7 @@ private:
CZString(const char* cstr, DuplicationPolicy allocate); CZString(const char* cstr, DuplicationPolicy allocate);
CZString(const CZString& other); CZString(const CZString& other);
~CZString(); ~CZString();
CZString& operator=(CZString other); CZString &operator=(const CZString &other);
bool operator<(const CZString& other) const; bool operator<(const CZString& other) const;
bool operator==(const CZString& other) const; bool operator==(const CZString& other) const;
ArrayIndex index() const; ArrayIndex index() const;
@@ -241,7 +244,7 @@ Json::Value obj_value(Json::objectValue); // {}
~Value(); ~Value();
// Deep copy, then swap(other). // Deep copy, then swap(other).
Value& operator=(Value other); Value &operator=(const Value &other);
/// Swap everything. /// Swap everything.
void swap(Value& other); void swap(Value& other);
/// Swap values but leave comments and source offsets in place. /// Swap values but leave comments and source offsets in place.
@@ -451,13 +454,6 @@ Json::Value obj_value(Json::objectValue); // {}
iterator begin(); iterator begin();
iterator end(); iterator end();
// Accessors for the [start, limit) range of bytes within the JSON text from
// which this value was parsed, if any.
void setOffsetStart(size_t start);
void setOffsetLimit(size_t limit);
size_t getOffsetStart() const;
size_t getOffsetLimit() const;
private: private:
void initBasic(ValueType type, bool allocated = false); void initBasic(ValueType type, bool allocated = false);
@@ -514,11 +510,6 @@ private:
unsigned int memberNameIsStatic_ : 1; // used by the ValueInternalMap container. unsigned int memberNameIsStatic_ : 1; // used by the ValueInternalMap container.
#endif #endif
CommentInfo* comments_; CommentInfo* comments_;
// [start, limit) byte offsets in the source JSON text from which this Value
// was extracted.
size_t start_;
size_t limit_;
}; };
/** \brief Experimental and untested: represents an element of the "path" to /** \brief Experimental and untested: represents an element of the "path" to
@@ -946,7 +937,7 @@ public:
bool operator!=(const SelfType& other) const { return !isEqual(other); } bool operator!=(const SelfType& other) const { return !isEqual(other); }
difference_type operator-(const SelfType& other) const { difference_type operator-(const SelfType& other) const {
return other.computeDistance(*this); return computeDistance(other);
} }
/// Return either the index or the member name of the referenced value as a /// Return either the index or the member name of the referenced value as a

View File

@@ -4,10 +4,10 @@
#ifndef JSON_VERSION_H_INCLUDED #ifndef JSON_VERSION_H_INCLUDED
# define JSON_VERSION_H_INCLUDED # define JSON_VERSION_H_INCLUDED
# define JSONCPP_VERSION_STRING "1.4.4" # define JSONCPP_VERSION_STRING "0.8.0"
# define JSONCPP_VERSION_MAJOR 1 # define JSONCPP_VERSION_MAJOR 0
# define JSONCPP_VERSION_MINOR 4 # define JSONCPP_VERSION_MINOR 8
# define JSONCPP_VERSION_PATCH 4 # define JSONCPP_VERSION_PATCH 0
# define JSONCPP_VERSION_QUALIFIER # define JSONCPP_VERSION_QUALIFIER
# define JSONCPP_VERSION_HEXA ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | (JSONCPP_VERSION_PATCH << 8)) # define JSONCPP_VERSION_HEXA ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | (JSONCPP_VERSION_PATCH << 8))

View File

@@ -153,15 +153,6 @@ public:
void enableYAMLCompatibility(); void enableYAMLCompatibility();
/** \brief Drop the "null" string from the writer's output for nullValues.
* Strictly speaking, this is not valid JSON. But when the output is being
* fed to a browser's Javascript, it makes for smaller output and the
* browser can handle the output just fine.
*/
void dropNullPlaceholders();
void omitEndingLineFeed();
public: // overridden from Writer public: // overridden from Writer
virtual std::string write(const Value& root); virtual std::string write(const Value& root);
@@ -170,8 +161,6 @@ private:
std::string document_; std::string document_;
bool yamlCompatiblityEnabled_; bool yamlCompatiblityEnabled_;
bool dropNullPlaceholders_;
bool omitEndingLineFeed_;
}; };
/** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a /** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a

View File

@@ -43,17 +43,14 @@ typedef std::auto_ptr<CharReader> CharReaderPtr;
// //////////////////////////////// // ////////////////////////////////
Features::Features() Features::Features()
: allowComments_(true), strictRoot_(false), : allowComments_(true), strictRoot_(false)
allowDroppedNullPlaceholders_(false), allowNumericKeys_(false) {} {}
Features Features::all() { return Features(); } Features Features::all() { return Features(); }
Features Features::strictMode() { Features Features::strictMode() {
Features features; Features features;
features.allowComments_ = false; features.allowComments_ = false;
features.strictRoot_ = true; features.strictRoot_ = true;
features.allowDroppedNullPlaceholders_ = false;
features.allowNumericKeys_ = false;
return features; return features;
} }
@@ -163,11 +160,9 @@ bool Reader::readValue() {
switch (token.type_) { switch (token.type_) {
case tokenObjectBegin: case tokenObjectBegin:
successful = readObject(token); successful = readObject(token);
currentValue().setOffsetLimit(current_ - begin_);
break; break;
case tokenArrayBegin: case tokenArrayBegin:
successful = readArray(token); successful = readArray(token);
currentValue().setOffsetLimit(current_ - begin_);
break; break;
case tokenNumber: case tokenNumber:
successful = decodeNumber(token); successful = decodeNumber(token);
@@ -179,42 +174,22 @@ bool Reader::readValue() {
{ {
Value v(true); Value v(true);
currentValue().swapPayload(v); currentValue().swapPayload(v);
currentValue().setOffsetStart(token.start_ - begin_);
currentValue().setOffsetLimit(token.end_ - begin_);
} }
break; break;
case tokenFalse: case tokenFalse:
{ {
Value v(false); Value v(false);
currentValue().swapPayload(v); currentValue().swapPayload(v);
currentValue().setOffsetStart(token.start_ - begin_);
currentValue().setOffsetLimit(token.end_ - begin_);
} }
break; break;
case tokenNull: case tokenNull:
{ {
Value v; Value v;
currentValue().swapPayload(v); currentValue().swapPayload(v);
currentValue().setOffsetStart(token.start_ - begin_);
currentValue().setOffsetLimit(token.end_ - begin_);
} }
break; break;
case tokenArraySeparator: // Else, fall through...
case tokenObjectEnd:
case tokenArrayEnd:
if (features_.allowDroppedNullPlaceholders_) {
// "Un-read" the current token and mark the current value as a null
// token.
current_--;
Value v;
currentValue().swapPayload(v);
currentValue().setOffsetStart(current_ - begin_ - 1);
currentValue().setOffsetLimit(current_ - begin_);
break;
} // Else, fall through...
default: default:
currentValue().setOffsetStart(token.start_ - begin_);
currentValue().setOffsetLimit(token.end_ - begin_);
return addError("Syntax error: value, object or array expected.", token); return addError("Syntax error: value, object or array expected.", token);
} }
@@ -442,12 +417,11 @@ bool Reader::readString() {
return c == '"'; return c == '"';
} }
bool Reader::readObject(Token& tokenStart) { bool Reader::readObject(Token& /*tokenStart*/) {
Token tokenName; Token tokenName;
std::string name; std::string name;
Value init(objectValue); Value init(objectValue);
currentValue().swapPayload(init); currentValue().swapPayload(init);
currentValue().setOffsetStart(tokenStart.start_ - begin_);
while (readToken(tokenName)) { while (readToken(tokenName)) {
bool initialTokenOk = true; bool initialTokenOk = true;
while (tokenName.type_ == tokenComment && initialTokenOk) while (tokenName.type_ == tokenComment && initialTokenOk)
@@ -460,11 +434,6 @@ bool Reader::readObject(Token& tokenStart) {
if (tokenName.type_ == tokenString) { if (tokenName.type_ == tokenString) {
if (!decodeString(tokenName, name)) if (!decodeString(tokenName, name))
return recoverFromError(tokenObjectEnd); return recoverFromError(tokenObjectEnd);
} else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) {
Value numberName;
if (!decodeNumber(tokenName, numberName))
return recoverFromError(tokenObjectEnd);
name = numberName.asString();
} else { } else {
break; break;
} }
@@ -498,10 +467,9 @@ bool Reader::readObject(Token& tokenStart) {
"Missing '}' or object member name", tokenName, tokenObjectEnd); "Missing '}' or object member name", tokenName, tokenObjectEnd);
} }
bool Reader::readArray(Token& tokenStart) { bool Reader::readArray(Token& /*tokenStart*/) {
Value init(arrayValue); Value init(arrayValue);
currentValue().swapPayload(init); currentValue().swapPayload(init);
currentValue().setOffsetStart(tokenStart.start_ - begin_);
skipSpaces(); skipSpaces();
if (*current_ == ']') // empty array if (*current_ == ']') // empty array
{ {
@@ -541,8 +509,6 @@ bool Reader::decodeNumber(Token& token) {
if (!decodeNumber(token, decoded)) if (!decodeNumber(token, decoded))
return false; return false;
currentValue().swapPayload(decoded); currentValue().swapPayload(decoded);
currentValue().setOffsetStart(token.start_ - begin_);
currentValue().setOffsetLimit(token.end_ - begin_);
return true; return true;
} }
@@ -591,8 +557,6 @@ bool Reader::decodeDouble(Token& token) {
if (!decodeDouble(token, decoded)) if (!decodeDouble(token, decoded))
return false; return false;
currentValue().swapPayload(decoded); currentValue().swapPayload(decoded);
currentValue().setOffsetStart(token.start_ - begin_);
currentValue().setOffsetLimit(token.end_ - begin_);
return true; return true;
} }
@@ -638,8 +602,6 @@ bool Reader::decodeString(Token& token) {
return false; return false;
Value decoded(decoded_string); Value decoded(decoded_string);
currentValue().swapPayload(decoded); currentValue().swapPayload(decoded);
currentValue().setOffsetStart(token.start_ - begin_);
currentValue().setOffsetLimit(token.end_ - begin_);
return true; return true;
} }
@@ -851,59 +813,8 @@ std::string Reader::getFormattedErrorMessages() const {
return formattedMessage; return formattedMessage;
} }
std::vector<Reader::StructuredError> Reader::getStructuredErrors() const { // Reader
std::vector<Reader::StructuredError> allErrors; /////////////////////////
for (Errors::const_iterator itError = errors_.begin();
itError != errors_.end();
++itError) {
const ErrorInfo& error = *itError;
Reader::StructuredError structured;
structured.offset_start = error.token_.start_ - begin_;
structured.offset_limit = error.token_.end_ - begin_;
structured.message = error.message_;
allErrors.push_back(structured);
}
return allErrors;
}
bool Reader::pushError(const Value& value, const std::string& message) {
size_t length = end_ - begin_;
if(value.getOffsetStart() > length
|| value.getOffsetLimit() > length)
return false;
Token token;
token.type_ = tokenError;
token.start_ = begin_ + value.getOffsetStart();
token.end_ = end_ + value.getOffsetLimit();
ErrorInfo info;
info.token_ = token;
info.message_ = message;
info.extra_ = 0;
errors_.push_back(info);
return true;
}
bool Reader::pushError(const Value& value, const std::string& message, const Value& extra) {
size_t length = end_ - begin_;
if(value.getOffsetStart() > length
|| value.getOffsetLimit() > length
|| extra.getOffsetLimit() > length)
return false;
Token token;
token.type_ = tokenError;
token.start_ = begin_ + value.getOffsetStart();
token.end_ = begin_ + value.getOffsetLimit();
ErrorInfo info;
info.token_ = token;
info.message_ = message;
info.extra_ = begin_ + extra.getOffsetStart();
errors_.push_back(info);
return true;
}
bool Reader::good() const {
return !errors_.size();
}
// exact copy of Features // exact copy of Features
class OurFeatures { class OurFeatures {
@@ -915,7 +826,6 @@ public:
bool strictRoot_; bool strictRoot_;
bool allowDroppedNullPlaceholders_; bool allowDroppedNullPlaceholders_;
bool allowNumericKeys_; bool allowNumericKeys_;
bool failIfExtra_;
int stackLimit_; int stackLimit_;
}; // OurFeatures }; // OurFeatures
@@ -957,10 +867,6 @@ public:
Value& root, Value& root,
bool collectComments = true); bool collectComments = true);
std::string getFormattedErrorMessages() const; std::string getFormattedErrorMessages() const;
std::vector<StructuredError> getStructuredErrors() const;
bool pushError(const Value& value, const std::string& message);
bool pushError(const Value& value, const std::string& message, const Value& extra);
bool good() const;
private: private:
OurReader(OurReader const&); // no impl OurReader(OurReader const&); // no impl
@@ -1085,12 +991,6 @@ bool OurReader::parse(const char* beginDoc,
bool successful = readValue(); bool successful = readValue();
Token token; Token token;
skipCommentTokens(token); skipCommentTokens(token);
if (features_.failIfExtra_) {
if (token.type_ != tokenError && token.type_ != tokenEndOfStream) {
addError("Extra non-whitespace after JSON value.", token);
return false;
}
}
if (collectComments_ && !commentsBefore_.empty()) if (collectComments_ && !commentsBefore_.empty())
root.setComment(commentsBefore_, commentAfter); root.setComment(commentsBefore_, commentAfter);
if (features_.strictRoot_) { if (features_.strictRoot_) {
@@ -1124,11 +1024,9 @@ bool OurReader::readValue() {
switch (token.type_) { switch (token.type_) {
case tokenObjectBegin: case tokenObjectBegin:
successful = readObject(token); successful = readObject(token);
currentValue().setOffsetLimit(current_ - begin_);
break; break;
case tokenArrayBegin: case tokenArrayBegin:
successful = readArray(token); successful = readArray(token);
currentValue().setOffsetLimit(current_ - begin_);
break; break;
case tokenNumber: case tokenNumber:
successful = decodeNumber(token); successful = decodeNumber(token);
@@ -1140,42 +1038,31 @@ bool OurReader::readValue() {
{ {
Value v(true); Value v(true);
currentValue().swapPayload(v); currentValue().swapPayload(v);
currentValue().setOffsetStart(token.start_ - begin_);
currentValue().setOffsetLimit(token.end_ - begin_);
} }
break; break;
case tokenFalse: case tokenFalse:
{ {
Value v(false); Value v(false);
currentValue().swapPayload(v); currentValue().swapPayload(v);
currentValue().setOffsetStart(token.start_ - begin_);
currentValue().setOffsetLimit(token.end_ - begin_);
} }
break; break;
case tokenNull: case tokenNull:
{ {
Value v; Value v;
currentValue().swapPayload(v); currentValue().swapPayload(v);
currentValue().setOffsetStart(token.start_ - begin_);
currentValue().setOffsetLimit(token.end_ - begin_);
} }
break; break;
case tokenArraySeparator: case tokenArraySeparator:
case tokenObjectEnd:
case tokenArrayEnd:
if (features_.allowDroppedNullPlaceholders_) { if (features_.allowDroppedNullPlaceholders_) {
// "Un-read" the current token and mark the current value as a null // "Un-read" the current token and mark the current value as a null
// token. // token.
current_--; current_--;
Value v; Value v;
currentValue().swapPayload(v); currentValue().swapPayload(v);
currentValue().setOffsetStart(current_ - begin_ - 1);
currentValue().setOffsetLimit(current_ - begin_);
break; break;
} // else, fall through ... }
// Else, fall through...
default: default:
currentValue().setOffsetStart(token.start_ - begin_);
currentValue().setOffsetLimit(token.end_ - begin_);
return addError("Syntax error: value, object or array expected.", token); return addError("Syntax error: value, object or array expected.", token);
} }
@@ -1389,7 +1276,6 @@ bool OurReader::readObject(Token& tokenStart) {
std::string name; std::string name;
Value init(objectValue); Value init(objectValue);
currentValue().swapPayload(init); currentValue().swapPayload(init);
currentValue().setOffsetStart(tokenStart.start_ - begin_);
while (readToken(tokenName)) { while (readToken(tokenName)) {
bool initialTokenOk = true; bool initialTokenOk = true;
while (tokenName.type_ == tokenComment && initialTokenOk) while (tokenName.type_ == tokenComment && initialTokenOk)
@@ -1443,7 +1329,6 @@ bool OurReader::readObject(Token& tokenStart) {
bool OurReader::readArray(Token& tokenStart) { bool OurReader::readArray(Token& tokenStart) {
Value init(arrayValue); Value init(arrayValue);
currentValue().swapPayload(init); currentValue().swapPayload(init);
currentValue().setOffsetStart(tokenStart.start_ - begin_);
skipSpaces(); skipSpaces();
if (*current_ == ']') // empty array if (*current_ == ']') // empty array
{ {
@@ -1483,8 +1368,6 @@ bool OurReader::decodeNumber(Token& token) {
if (!decodeNumber(token, decoded)) if (!decodeNumber(token, decoded))
return false; return false;
currentValue().swapPayload(decoded); currentValue().swapPayload(decoded);
currentValue().setOffsetStart(token.start_ - begin_);
currentValue().setOffsetLimit(token.end_ - begin_);
return true; return true;
} }
@@ -1533,8 +1416,6 @@ bool OurReader::decodeDouble(Token& token) {
if (!decodeDouble(token, decoded)) if (!decodeDouble(token, decoded))
return false; return false;
currentValue().swapPayload(decoded); currentValue().swapPayload(decoded);
currentValue().setOffsetStart(token.start_ - begin_);
currentValue().setOffsetLimit(token.end_ - begin_);
return true; return true;
} }
@@ -1580,8 +1461,6 @@ bool OurReader::decodeString(Token& token) {
return false; return false;
Value decoded(decoded_string); Value decoded(decoded_string);
currentValue().swapPayload(decoded); currentValue().swapPayload(decoded);
currentValue().setOffsetStart(token.start_ - begin_);
currentValue().setOffsetLimit(token.end_ - begin_);
return true; return true;
} }
@@ -1788,60 +1667,6 @@ std::string OurReader::getFormattedErrorMessages() const {
return formattedMessage; return formattedMessage;
} }
std::vector<OurReader::StructuredError> OurReader::getStructuredErrors() const {
std::vector<OurReader::StructuredError> allErrors;
for (Errors::const_iterator itError = errors_.begin();
itError != errors_.end();
++itError) {
const ErrorInfo& error = *itError;
OurReader::StructuredError structured;
structured.offset_start = error.token_.start_ - begin_;
structured.offset_limit = error.token_.end_ - begin_;
structured.message = error.message_;
allErrors.push_back(structured);
}
return allErrors;
}
bool OurReader::pushError(const Value& value, const std::string& message) {
size_t length = end_ - begin_;
if(value.getOffsetStart() > length
|| value.getOffsetLimit() > length)
return false;
Token token;
token.type_ = tokenError;
token.start_ = begin_ + value.getOffsetStart();
token.end_ = end_ + value.getOffsetLimit();
ErrorInfo info;
info.token_ = token;
info.message_ = message;
info.extra_ = 0;
errors_.push_back(info);
return true;
}
bool OurReader::pushError(const Value& value, const std::string& message, const Value& extra) {
size_t length = end_ - begin_;
if(value.getOffsetStart() > length
|| value.getOffsetLimit() > length
|| extra.getOffsetLimit() > length)
return false;
Token token;
token.type_ = tokenError;
token.start_ = begin_ + value.getOffsetStart();
token.end_ = begin_ + value.getOffsetLimit();
ErrorInfo info;
info.token_ = token;
info.message_ = message;
info.extra_ = begin_ + extra.getOffsetStart();
errors_.push_back(info);
return true;
}
bool OurReader::good() const {
return !errors_.size();
}
class OurCharReader : public CharReader { class OurCharReader : public CharReader {
bool const collectComments_; bool const collectComments_;
@@ -1879,7 +1704,6 @@ CharReader* CharReaderBuilder::newCharReader() const
features.allowDroppedNullPlaceholders_ = settings_["allowDroppedNullPlaceholders"].asBool(); features.allowDroppedNullPlaceholders_ = settings_["allowDroppedNullPlaceholders"].asBool();
features.allowNumericKeys_ = settings_["allowNumericKeys"].asBool(); features.allowNumericKeys_ = settings_["allowNumericKeys"].asBool();
features.stackLimit_ = settings_["stackLimit"].asInt(); features.stackLimit_ = settings_["stackLimit"].asInt();
features.failIfExtra_ = settings_["failIfExtra"].asBool();
return new OurCharReader(collectComments, features); return new OurCharReader(collectComments, features);
} }
static void getValidReaderKeys(std::set<std::string>* valid_keys) static void getValidReaderKeys(std::set<std::string>* valid_keys)
@@ -1891,7 +1715,6 @@ static void getValidReaderKeys(std::set<std::string>* valid_keys)
valid_keys->insert("allowDroppedNullPlaceholders"); valid_keys->insert("allowDroppedNullPlaceholders");
valid_keys->insert("allowNumericKeys"); valid_keys->insert("allowNumericKeys");
valid_keys->insert("stackLimit"); valid_keys->insert("stackLimit");
valid_keys->insert("failIfExtra");
} }
bool CharReaderBuilder::validate(Json::Value* invalid) const bool CharReaderBuilder::validate(Json::Value* invalid) const
{ {
@@ -1919,7 +1742,6 @@ void CharReaderBuilder::strictMode(Json::Value* settings)
(*settings)["strictRoot"] = true; (*settings)["strictRoot"] = true;
(*settings)["allowDroppedNullPlaceholders"] = false; (*settings)["allowDroppedNullPlaceholders"] = false;
(*settings)["allowNumericKeys"] = false; (*settings)["allowNumericKeys"] = false;
(*settings)["failIfExtra"] = true;
//! [CharReaderBuilderStrictMode] //! [CharReaderBuilderStrictMode]
} }
// static // static
@@ -1932,7 +1754,6 @@ void CharReaderBuilder::setDefaults(Json::Value* settings)
(*settings)["allowDroppedNullPlaceholders"] = false; (*settings)["allowDroppedNullPlaceholders"] = false;
(*settings)["allowNumericKeys"] = false; (*settings)["allowNumericKeys"] = false;
(*settings)["stackLimit"] = 1000; (*settings)["stackLimit"] = 1000;
(*settings)["failIfExtra"] = false;
//! [CharReaderBuilderDefaults] //! [CharReaderBuilderDefaults]
} }

View File

@@ -31,12 +31,13 @@ namespace Json {
#if defined(__ARMEL__) #if defined(__ARMEL__)
#define ALIGNAS(byte_alignment) __attribute__((aligned(byte_alignment))) #define ALIGNAS(byte_alignment) __attribute__((aligned(byte_alignment)))
#else #else
// This exists for binary compatibility only. Use nullRef.
static const Value null;
#define ALIGNAS(byte_alignment) #define ALIGNAS(byte_alignment)
#endif #endif
static const unsigned char ALIGNAS(8) kNull[sizeof(Value)] = { 0 }; static const unsigned char ALIGNAS(8) kNull[sizeof(Value)] = { 0 };
const unsigned char& kNullRef = kNull[0]; const unsigned char& kNullRef = kNull[0];
const Value& Value::null = reinterpret_cast<const Value&>(kNullRef); const Value& Value::nullRef = reinterpret_cast<const Value&>(kNullRef);
const Value& Value::nullRef = null;
const Int Value::minInt = Int(~(UInt(-1) / 2)); const Int Value::minInt = Int(~(UInt(-1) / 2));
const Int Value::maxInt = Int(UInt(-1) / 2); const Int Value::maxInt = Int(UInt(-1) / 2);
@@ -192,8 +193,9 @@ void Value::CZString::swap(CZString& other) {
std::swap(index_, other.index_); std::swap(index_, other.index_);
} }
Value::CZString& Value::CZString::operator=(CZString other) { Value::CZString &Value::CZString::operator=(const CZString &other) {
swap(other); CZString temp(other);
swap(temp);
return *this; return *this;
} }
@@ -331,7 +333,7 @@ Value::Value(const Value& other)
itemIsUsed_(0) itemIsUsed_(0)
#endif #endif
, ,
comments_(0), start_(other.start_), limit_(other.limit_) { comments_(0) {
switch (type_) { switch (type_) {
case nullValue: case nullValue:
case intValue: case intValue:
@@ -409,8 +411,9 @@ Value::~Value() {
delete[] comments_; delete[] comments_;
} }
Value& Value::operator=(Value other) { Value &Value::operator=(const Value &other) {
swap(other); Value temp(other);
swap(temp);
return *this; return *this;
} }
@@ -427,8 +430,6 @@ void Value::swapPayload(Value& other) {
void Value::swap(Value& other) { void Value::swap(Value& other) {
swapPayload(other); swapPayload(other);
std::swap(comments_, other.comments_); std::swap(comments_, other.comments_);
std::swap(start_, other.start_);
std::swap(limit_, other.limit_);
} }
ValueType Value::type() const { return type_; } ValueType Value::type() const { return type_; }
@@ -803,8 +804,6 @@ void Value::clear() {
JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue || JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue ||
type_ == objectValue, type_ == objectValue,
"in Json::Value::clear(): requires complex value"); "in Json::Value::clear(): requires complex value");
start_ = 0;
limit_ = 0;
switch (type_) { switch (type_) {
#ifndef JSON_VALUE_USE_INTERNAL_MAP #ifndef JSON_VALUE_USE_INTERNAL_MAP
case arrayValue: case arrayValue:
@@ -858,7 +857,7 @@ Value& Value::operator[](ArrayIndex index) {
if (it != value_.map_->end() && (*it).first == key) if (it != value_.map_->end() && (*it).first == key)
return (*it).second; return (*it).second;
ObjectValues::value_type defaultValue(key, null); ObjectValues::value_type defaultValue(key, nullRef);
it = value_.map_->insert(it, defaultValue); it = value_.map_->insert(it, defaultValue);
return (*it).second; return (*it).second;
#else #else
@@ -878,16 +877,16 @@ const Value& Value::operator[](ArrayIndex index) const {
type_ == nullValue || type_ == arrayValue, type_ == nullValue || type_ == arrayValue,
"in Json::Value::operator[](ArrayIndex)const: requires arrayValue"); "in Json::Value::operator[](ArrayIndex)const: requires arrayValue");
if (type_ == nullValue) if (type_ == nullValue)
return null; return nullRef;
#ifndef JSON_VALUE_USE_INTERNAL_MAP #ifndef JSON_VALUE_USE_INTERNAL_MAP
CZString key(index); CZString key(index);
ObjectValues::const_iterator it = value_.map_->find(key); ObjectValues::const_iterator it = value_.map_->find(key);
if (it == value_.map_->end()) if (it == value_.map_->end())
return null; return nullRef;
return (*it).second; return (*it).second;
#else #else
Value* value = value_.array_->find(index); Value* value = value_.array_->find(index);
return value ? *value : null; return value ? *value : nullRef;
#endif #endif
} }
@@ -909,8 +908,6 @@ void Value::initBasic(ValueType type, bool allocated) {
itemIsUsed_ = 0; itemIsUsed_ = 0;
#endif #endif
comments_ = 0; comments_ = 0;
start_ = 0;
limit_ = 0;
} }
Value& Value::resolveReference(const char* key, bool isStatic) { Value& Value::resolveReference(const char* key, bool isStatic) {
@@ -926,7 +923,7 @@ Value& Value::resolveReference(const char* key, bool isStatic) {
if (it != value_.map_->end() && (*it).first == actualKey) if (it != value_.map_->end() && (*it).first == actualKey)
return (*it).second; return (*it).second;
ObjectValues::value_type defaultValue(actualKey, null); ObjectValues::value_type defaultValue(actualKey, nullRef);
it = value_.map_->insert(it, defaultValue); it = value_.map_->insert(it, defaultValue);
Value& value = (*it).second; Value& value = (*it).second;
return value; return value;
@@ -937,7 +934,7 @@ Value& Value::resolveReference(const char* key, bool isStatic) {
Value Value::get(ArrayIndex index, const Value& defaultValue) const { Value Value::get(ArrayIndex index, const Value& defaultValue) const {
const Value* value = &((*this)[index]); const Value* value = &((*this)[index]);
return value == &null ? defaultValue : *value; return value == &nullRef ? defaultValue : *value;
} }
bool Value::isValidIndex(ArrayIndex index) const { return index < size(); } bool Value::isValidIndex(ArrayIndex index) const { return index < size(); }
@@ -947,16 +944,16 @@ const Value& Value::operator[](const char* key) const {
type_ == nullValue || type_ == objectValue, type_ == nullValue || type_ == objectValue,
"in Json::Value::operator[](char const*)const: requires objectValue"); "in Json::Value::operator[](char const*)const: requires objectValue");
if (type_ == nullValue) if (type_ == nullValue)
return null; return nullRef;
#ifndef JSON_VALUE_USE_INTERNAL_MAP #ifndef JSON_VALUE_USE_INTERNAL_MAP
CZString actualKey(key, CZString::noDuplication); CZString actualKey(key, CZString::noDuplication);
ObjectValues::const_iterator it = value_.map_->find(actualKey); ObjectValues::const_iterator it = value_.map_->find(actualKey);
if (it == value_.map_->end()) if (it == value_.map_->end())
return null; return nullRef;
return (*it).second; return (*it).second;
#else #else
const Value* value = value_.map_->find(key); const Value* value = value_.map_->find(key);
return value ? *value : null; return value ? *value : nullRef;
#endif #endif
} }
@@ -986,7 +983,7 @@ Value& Value::append(const Value& value) { return (*this)[size()] = value; }
Value Value::get(const char* key, const Value& defaultValue) const { Value Value::get(const char* key, const Value& defaultValue) const {
const Value* value = &((*this)[key]); const Value* value = &((*this)[key]);
return value == &null ? defaultValue : *value; return value == &nullRef ? defaultValue : *value;
} }
Value Value::get(const std::string& key, const Value& defaultValue) const { Value Value::get(const std::string& key, const Value& defaultValue) const {
@@ -1022,7 +1019,7 @@ Value Value::removeMember(const char* key) {
JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == objectValue, JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == objectValue,
"in Json::Value::removeMember(): requires objectValue"); "in Json::Value::removeMember(): requires objectValue");
if (type_ == nullValue) if (type_ == nullValue)
return null; return nullRef;
Value removed; // null Value removed; // null
removeMember(key, &removed); removeMember(key, &removed);
@@ -1070,7 +1067,7 @@ Value Value::get(const CppTL::ConstString& key,
bool Value::isMember(const char* key) const { bool Value::isMember(const char* key) const {
const Value* value = &((*this)[key]); const Value* value = &((*this)[key]);
return value != &null; return value != &nullRef;
} }
bool Value::isMember(const std::string& key) const { bool Value::isMember(const std::string& key) const {
@@ -1257,14 +1254,6 @@ std::string Value::getComment(CommentPlacement placement) const {
return ""; return "";
} }
void Value::setOffsetStart(size_t start) { start_ = start; }
void Value::setOffsetLimit(size_t limit) { limit_ = limit; }
size_t Value::getOffsetStart() const { return start_; }
size_t Value::getOffsetLimit() const { return limit_; }
std::string Value::toStyledString() const { std::string Value::toStyledString() const {
StyledWriter writer; StyledWriter writer;
return writer.write(*this); return writer.write(*this);
@@ -1484,7 +1473,7 @@ const Value& Path::resolve(const Value& root) const {
// Error: unable to resolve path (object value expected at position...) // Error: unable to resolve path (object value expected at position...)
} }
node = &((*node)[arg.key_]); node = &((*node)[arg.key_]);
if (node == &Value::null) { if (node == &Value::nullRef) {
// Error: unable to resolve path (object has no member named '' at // Error: unable to resolve path (object has no member named '' at
// position...) // position...)
} }
@@ -1505,7 +1494,7 @@ Value Path::resolve(const Value& root, const Value& defaultValue) const {
if (!node->isObject()) if (!node->isObject())
return defaultValue; return defaultValue;
node = &((*node)[arg.key_]); node = &((*node)[arg.key_]);
if (node == &Value::null) if (node == &Value::nullRef)
return defaultValue; return defaultValue;
} }
} }

View File

@@ -77,7 +77,7 @@ ValueIteratorBase::difference_type
ValueIteratorBase::computeDistance(const SelfType& other) const { ValueIteratorBase::computeDistance(const SelfType& other) const {
#ifndef JSON_VALUE_USE_INTERNAL_MAP #ifndef JSON_VALUE_USE_INTERNAL_MAP
#ifdef JSON_USE_CPPTL_SMALLMAP #ifdef JSON_USE_CPPTL_SMALLMAP
return other.current_ - current_; return current_ - other.current_;
#else #else
// Iterator for null value are initialized using the default // Iterator for null value are initialized using the default
// constructor, which initialize current_ to the default // constructor, which initialize current_ to the default

View File

@@ -192,19 +192,13 @@ Writer::~Writer() {}
// ////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////
FastWriter::FastWriter() FastWriter::FastWriter()
: yamlCompatiblityEnabled_(false), dropNullPlaceholders_(false), : yamlCompatiblityEnabled_(false) {}
omitEndingLineFeed_(false) {}
void FastWriter::enableYAMLCompatibility() { yamlCompatiblityEnabled_ = true; } void FastWriter::enableYAMLCompatibility() { yamlCompatiblityEnabled_ = true; }
void FastWriter::dropNullPlaceholders() { dropNullPlaceholders_ = true; }
void FastWriter::omitEndingLineFeed() { omitEndingLineFeed_ = true; }
std::string FastWriter::write(const Value& root) { std::string FastWriter::write(const Value& root) {
document_ = ""; document_ = "";
writeValue(root); writeValue(root);
if (!omitEndingLineFeed_)
document_ += "\n"; document_ += "\n";
return document_; return document_;
} }
@@ -212,7 +206,6 @@ std::string FastWriter::write(const Value& root) {
void FastWriter::writeValue(const Value& value) { void FastWriter::writeValue(const Value& value) {
switch (value.type()) { switch (value.type()) {
case nullValue: case nullValue:
if (!dropNullPlaceholders_)
document_ += "null"; document_ += "null";
break; break;
case intValue: case intValue:

View File

@@ -1497,36 +1497,6 @@ JSONTEST_FIXTURE(ValueTest, typeChecksThrowExceptions) {
#endif #endif
} }
JSONTEST_FIXTURE(ValueTest, offsetAccessors) {
Json::Value x;
JSONTEST_ASSERT(x.getOffsetStart() == 0);
JSONTEST_ASSERT(x.getOffsetLimit() == 0);
x.setOffsetStart(10);
x.setOffsetLimit(20);
JSONTEST_ASSERT(x.getOffsetStart() == 10);
JSONTEST_ASSERT(x.getOffsetLimit() == 20);
Json::Value y(x);
JSONTEST_ASSERT(y.getOffsetStart() == 10);
JSONTEST_ASSERT(y.getOffsetLimit() == 20);
Json::Value z;
z.swap(y);
JSONTEST_ASSERT(z.getOffsetStart() == 10);
JSONTEST_ASSERT(z.getOffsetLimit() == 20);
JSONTEST_ASSERT(y.getOffsetStart() == 0);
JSONTEST_ASSERT(y.getOffsetLimit() == 0);
}
struct WriterTest : JsonTest::TestCase {};
JSONTEST_FIXTURE(WriterTest, dropNullPlaceholders) {
Json::FastWriter writer;
Json::Value nullValue;
JSONTEST_ASSERT(writer.write(nullValue) == "null\n");
writer.dropNullPlaceholders();
JSONTEST_ASSERT(writer.write(nullValue) == "\n");
}
struct StreamWriterTest : JsonTest::TestCase {}; struct StreamWriterTest : JsonTest::TestCase {};
JSONTEST_FIXTURE(StreamWriterTest, dropNullPlaceholders) { JSONTEST_FIXTURE(StreamWriterTest, dropNullPlaceholders) {
@@ -1546,7 +1516,6 @@ JSONTEST_FIXTURE(ReaderTest, parseWithNoErrors) {
bool ok = reader.parse("{ \"property\" : \"value\" }", root); bool ok = reader.parse("{ \"property\" : \"value\" }", root);
JSONTEST_ASSERT(ok); JSONTEST_ASSERT(ok);
JSONTEST_ASSERT(reader.getFormattedErrorMessages().size() == 0); JSONTEST_ASSERT(reader.getFormattedErrorMessages().size() == 0);
JSONTEST_ASSERT(reader.getStructuredErrors().size() == 0);
} }
JSONTEST_FIXTURE(ReaderTest, parseWithNoErrorsTestingOffsets) { JSONTEST_FIXTURE(ReaderTest, parseWithNoErrorsTestingOffsets) {
@@ -1558,25 +1527,6 @@ JSONTEST_FIXTURE(ReaderTest, parseWithNoErrorsTestingOffsets) {
root); root);
JSONTEST_ASSERT(ok); JSONTEST_ASSERT(ok);
JSONTEST_ASSERT(reader.getFormattedErrorMessages().size() == 0); JSONTEST_ASSERT(reader.getFormattedErrorMessages().size() == 0);
JSONTEST_ASSERT(reader.getStructuredErrors().size() == 0);
JSONTEST_ASSERT(root["property"].getOffsetStart() == 15);
JSONTEST_ASSERT(root["property"].getOffsetLimit() == 34);
JSONTEST_ASSERT(root["property"][0].getOffsetStart() == 16);
JSONTEST_ASSERT(root["property"][0].getOffsetLimit() == 23);
JSONTEST_ASSERT(root["property"][1].getOffsetStart() == 25);
JSONTEST_ASSERT(root["property"][1].getOffsetLimit() == 33);
JSONTEST_ASSERT(root["obj"].getOffsetStart() == 44);
JSONTEST_ASSERT(root["obj"].getOffsetLimit() == 76);
JSONTEST_ASSERT(root["obj"]["nested"].getOffsetStart() == 57);
JSONTEST_ASSERT(root["obj"]["nested"].getOffsetLimit() == 60);
JSONTEST_ASSERT(root["obj"]["bool"].getOffsetStart() == 71);
JSONTEST_ASSERT(root["obj"]["bool"].getOffsetLimit() == 75);
JSONTEST_ASSERT(root["null"].getOffsetStart() == 87);
JSONTEST_ASSERT(root["null"].getOffsetLimit() == 91);
JSONTEST_ASSERT(root["false"].getOffsetStart() == 103);
JSONTEST_ASSERT(root["false"].getOffsetLimit() == 108);
JSONTEST_ASSERT(root.getOffsetStart() == 0);
JSONTEST_ASSERT(root.getOffsetLimit() == 110);
} }
JSONTEST_FIXTURE(ReaderTest, parseWithOneError) { JSONTEST_FIXTURE(ReaderTest, parseWithOneError) {
@@ -1587,13 +1537,6 @@ JSONTEST_FIXTURE(ReaderTest, parseWithOneError) {
JSONTEST_ASSERT(reader.getFormattedErrorMessages() == JSONTEST_ASSERT(reader.getFormattedErrorMessages() ==
"* Line 1, Column 15\n Syntax error: value, object or array " "* Line 1, Column 15\n Syntax error: value, object or array "
"expected.\n"); "expected.\n");
std::vector<Json::Reader::StructuredError> errors =
reader.getStructuredErrors();
JSONTEST_ASSERT(errors.size() == 1);
JSONTEST_ASSERT(errors.at(0).offset_start == 14);
JSONTEST_ASSERT(errors.at(0).offset_limit == 15);
JSONTEST_ASSERT(errors.at(0).message ==
"Syntax error: value, object or array expected.");
} }
JSONTEST_FIXTURE(ReaderTest, parseChineseWithOneError) { JSONTEST_FIXTURE(ReaderTest, parseChineseWithOneError) {
@@ -1604,13 +1547,6 @@ JSONTEST_FIXTURE(ReaderTest, parseChineseWithOneError) {
JSONTEST_ASSERT(reader.getFormattedErrorMessages() == JSONTEST_ASSERT(reader.getFormattedErrorMessages() ==
"* Line 1, Column 19\n Syntax error: value, object or array " "* Line 1, Column 19\n Syntax error: value, object or array "
"expected.\n"); "expected.\n");
std::vector<Json::Reader::StructuredError> errors =
reader.getStructuredErrors();
JSONTEST_ASSERT(errors.size() == 1);
JSONTEST_ASSERT(errors.at(0).offset_start == 18);
JSONTEST_ASSERT(errors.at(0).offset_limit == 19);
JSONTEST_ASSERT(errors.at(0).message ==
"Syntax error: value, object or array expected.");
} }
JSONTEST_FIXTURE(ReaderTest, parseWithDetailError) { JSONTEST_FIXTURE(ReaderTest, parseWithDetailError) {
@@ -1621,12 +1557,6 @@ JSONTEST_FIXTURE(ReaderTest, parseWithDetailError) {
JSONTEST_ASSERT(reader.getFormattedErrorMessages() == JSONTEST_ASSERT(reader.getFormattedErrorMessages() ==
"* Line 1, Column 16\n Bad escape sequence in string\nSee " "* Line 1, Column 16\n Bad escape sequence in string\nSee "
"Line 1, Column 20 for detail.\n"); "Line 1, Column 20 for detail.\n");
std::vector<Json::Reader::StructuredError> errors =
reader.getStructuredErrors();
JSONTEST_ASSERT(errors.size() == 1);
JSONTEST_ASSERT(errors.at(0).offset_start == 15);
JSONTEST_ASSERT(errors.at(0).offset_limit == 23);
JSONTEST_ASSERT(errors.at(0).message == "Bad escape sequence in string");
} }
struct CharReaderTest : JsonTest::TestCase {}; struct CharReaderTest : JsonTest::TestCase {};
@@ -1741,295 +1671,6 @@ JSONTEST_FIXTURE(CharReaderTest, parseWithStackLimit) {
} }
} }
struct CharReaderFailIfExtraTest : JsonTest::TestCase {};
JSONTEST_FIXTURE(CharReaderFailIfExtraTest, issue164) {
// This is interpretted as a string value followed by a colon.
Json::CharReaderBuilder b;
Json::Value root;
char const doc[] =
" \"property\" : \"value\" }";
{
b.settings_["failIfExtra"] = false;
Json::CharReader* reader(b.newCharReader());
std::string errs;
bool ok = reader->parse(
doc, doc + std::strlen(doc),
&root, &errs);
JSONTEST_ASSERT(ok);
JSONTEST_ASSERT(errs == "");
JSONTEST_ASSERT_EQUAL("property", root);
delete reader;
}
{
b.settings_["failIfExtra"] = true;
Json::CharReader* reader(b.newCharReader());
std::string errs;
bool ok = reader->parse(
doc, doc + std::strlen(doc),
&root, &errs);
JSONTEST_ASSERT(!ok);
JSONTEST_ASSERT_STRING_EQUAL(errs,
"* Line 1, Column 13\n"
" Extra non-whitespace after JSON value.\n");
JSONTEST_ASSERT_EQUAL("property", root);
delete reader;
}
{
b.settings_["failIfExtra"] = false;
b.strictMode(&b.settings_);
Json::CharReader* reader(b.newCharReader());
std::string errs;
bool ok = reader->parse(
doc, doc + std::strlen(doc),
&root, &errs);
JSONTEST_ASSERT(!ok);
JSONTEST_ASSERT_STRING_EQUAL(errs,
"* Line 1, Column 13\n"
" Extra non-whitespace after JSON value.\n");
JSONTEST_ASSERT_EQUAL("property", root);
delete reader;
}
}
JSONTEST_FIXTURE(CharReaderFailIfExtraTest, issue107) {
// This is interpretted as an int value followed by a colon.
Json::CharReaderBuilder b;
Json::Value root;
char const doc[] =
"1:2:3";
b.settings_["failIfExtra"] = true;
Json::CharReader* reader(b.newCharReader());
std::string errs;
bool ok = reader->parse(
doc, doc + std::strlen(doc),
&root, &errs);
JSONTEST_ASSERT(!ok);
JSONTEST_ASSERT_STRING_EQUAL(
"* Line 1, Column 2\n"
" Extra non-whitespace after JSON value.\n",
errs);
JSONTEST_ASSERT_EQUAL(1, root.asInt());
delete reader;
}
JSONTEST_FIXTURE(CharReaderFailIfExtraTest, commentAfterObject) {
Json::CharReaderBuilder b;
Json::Value root;
{
char const doc[] =
"{ \"property\" : \"value\" } //trailing\n//comment\n";
b.settings_["failIfExtra"] = true;
Json::CharReader* reader(b.newCharReader());
std::string errs;
bool ok = reader->parse(
doc, doc + std::strlen(doc),
&root, &errs);
JSONTEST_ASSERT(ok);
JSONTEST_ASSERT_STRING_EQUAL("", errs);
JSONTEST_ASSERT_EQUAL("value", root["property"]);
delete reader;
}
}
JSONTEST_FIXTURE(CharReaderFailIfExtraTest, commentAfterArray) {
Json::CharReaderBuilder b;
Json::Value root;
char const doc[] =
"[ \"property\" , \"value\" ] //trailing\n//comment\n";
b.settings_["failIfExtra"] = true;
Json::CharReader* reader(b.newCharReader());
std::string errs;
bool ok = reader->parse(
doc, doc + std::strlen(doc),
&root, &errs);
JSONTEST_ASSERT(ok);
JSONTEST_ASSERT_STRING_EQUAL("", errs);
JSONTEST_ASSERT_EQUAL("value", root[1u]);
delete reader;
}
JSONTEST_FIXTURE(CharReaderFailIfExtraTest, commentAfterBool) {
Json::CharReaderBuilder b;
Json::Value root;
char const doc[] =
" true /*trailing\ncomment*/";
b.settings_["failIfExtra"] = true;
Json::CharReader* reader(b.newCharReader());
std::string errs;
bool ok = reader->parse(
doc, doc + std::strlen(doc),
&root, &errs);
JSONTEST_ASSERT(ok);
JSONTEST_ASSERT_STRING_EQUAL("", errs);
JSONTEST_ASSERT_EQUAL(true, root.asBool());
delete reader;
}
struct CharReaderAllowDropNullTest : JsonTest::TestCase {};
JSONTEST_FIXTURE(CharReaderAllowDropNullTest, issue178) {
Json::CharReaderBuilder b;
b.settings_["allowDroppedNullPlaceholders"] = true;
Json::Value root;
std::string errs;
Json::CharReader* reader(b.newCharReader());
{
char const doc[] = "{\"a\":,\"b\":true}";
bool ok = reader->parse(
doc, doc + std::strlen(doc),
&root, &errs);
JSONTEST_ASSERT(ok);
JSONTEST_ASSERT_STRING_EQUAL("", errs);
JSONTEST_ASSERT_EQUAL(2u, root.size());
JSONTEST_ASSERT_EQUAL(Json::nullValue, root.get("a", true));
}
{
char const doc[] = "{\"a\":}";
bool ok = reader->parse(
doc, doc + std::strlen(doc),
&root, &errs);
JSONTEST_ASSERT(ok);
JSONTEST_ASSERT_STRING_EQUAL("", errs);
JSONTEST_ASSERT_EQUAL(1u, root.size());
JSONTEST_ASSERT_EQUAL(Json::nullValue, root.get("a", true));
}
{
char const doc[] = "[]";
bool ok = reader->parse(
doc, doc + std::strlen(doc),
&root, &errs);
JSONTEST_ASSERT(ok);
JSONTEST_ASSERT(errs == "");
JSONTEST_ASSERT_EQUAL(0u, root.size());
JSONTEST_ASSERT_EQUAL(Json::arrayValue, root);
}
{
char const doc[] = "[null]";
bool ok = reader->parse(
doc, doc + std::strlen(doc),
&root, &errs);
JSONTEST_ASSERT(ok);
JSONTEST_ASSERT(errs == "");
JSONTEST_ASSERT_EQUAL(1u, root.size());
}
{
char const doc[] = "[,]";
bool ok = reader->parse(
doc, doc + std::strlen(doc),
&root, &errs);
JSONTEST_ASSERT(ok);
JSONTEST_ASSERT_STRING_EQUAL("", errs);
JSONTEST_ASSERT_EQUAL(2u, root.size());
}
{
char const doc[] = "[,,,]";
bool ok = reader->parse(
doc, doc + std::strlen(doc),
&root, &errs);
JSONTEST_ASSERT(ok);
JSONTEST_ASSERT_STRING_EQUAL("", errs);
JSONTEST_ASSERT_EQUAL(4u, root.size());
}
{
char const doc[] = "[null,]";
bool ok = reader->parse(
doc, doc + std::strlen(doc),
&root, &errs);
JSONTEST_ASSERT(ok);
JSONTEST_ASSERT_STRING_EQUAL("", errs);
JSONTEST_ASSERT_EQUAL(2u, root.size());
}
{
char const doc[] = "[,null]";
bool ok = reader->parse(
doc, doc + std::strlen(doc),
&root, &errs);
JSONTEST_ASSERT(ok);
JSONTEST_ASSERT(errs == "");
JSONTEST_ASSERT_EQUAL(2u, root.size());
}
{
char const doc[] = "[,,]";
bool ok = reader->parse(
doc, doc + std::strlen(doc),
&root, &errs);
JSONTEST_ASSERT(ok);
JSONTEST_ASSERT_STRING_EQUAL("", errs);
JSONTEST_ASSERT_EQUAL(3u, root.size());
}
{
char const doc[] = "[null,,]";
bool ok = reader->parse(
doc, doc + std::strlen(doc),
&root, &errs);
JSONTEST_ASSERT(ok);
JSONTEST_ASSERT_STRING_EQUAL("", errs);
JSONTEST_ASSERT_EQUAL(3u, root.size());
}
{
char const doc[] = "[,null,]";
bool ok = reader->parse(
doc, doc + std::strlen(doc),
&root, &errs);
JSONTEST_ASSERT(ok);
JSONTEST_ASSERT_STRING_EQUAL("", errs);
JSONTEST_ASSERT_EQUAL(3u, root.size());
}
{
char const doc[] = "[,,null]";
bool ok = reader->parse(
doc, doc + std::strlen(doc),
&root, &errs);
JSONTEST_ASSERT(ok);
JSONTEST_ASSERT(errs == "");
JSONTEST_ASSERT_EQUAL(3u, root.size());
}
{
char const doc[] = "[[],,,]";
bool ok = reader->parse(
doc, doc + std::strlen(doc),
&root, &errs);
JSONTEST_ASSERT(ok);
JSONTEST_ASSERT_STRING_EQUAL("", errs);
JSONTEST_ASSERT_EQUAL(4u, root.size());
JSONTEST_ASSERT_EQUAL(Json::arrayValue, root[0u]);
}
{
char const doc[] = "[,[],,]";
bool ok = reader->parse(
doc, doc + std::strlen(doc),
&root, &errs);
JSONTEST_ASSERT(ok);
JSONTEST_ASSERT_STRING_EQUAL("", errs);
JSONTEST_ASSERT_EQUAL(4u, root.size());
JSONTEST_ASSERT_EQUAL(Json::arrayValue, root[1u]);
}
{
char const doc[] = "[,,,[]]";
bool ok = reader->parse(
doc, doc + std::strlen(doc),
&root, &errs);
JSONTEST_ASSERT(ok);
JSONTEST_ASSERT(errs == "");
JSONTEST_ASSERT_EQUAL(4u, root.size());
JSONTEST_ASSERT_EQUAL(Json::arrayValue, root[3u]);
}
delete reader;
}
struct IteratorTest : JsonTest::TestCase {};
JSONTEST_FIXTURE(IteratorTest, distance) {
Json::Value json;
json["k1"] = "a";
json["k2"] = "b";
int dist;
std::string str;
for (Json::ValueIterator it = json.begin(); it != json.end(); ++it) {
dist = it - json.begin();
str = it->asString().c_str();
}
JSONTEST_ASSERT_EQUAL(1, dist);
JSONTEST_ASSERT_STRING_EQUAL("b", str);
}
int main(int argc, const char* argv[]) { int main(int argc, const char* argv[]) {
JsonTest::Runner runner; JsonTest::Runner runner;
JSONTEST_REGISTER_FIXTURE(runner, ValueTest, checkNormalizeFloatingPointStr); JSONTEST_REGISTER_FIXTURE(runner, ValueTest, checkNormalizeFloatingPointStr);
@@ -2050,12 +1691,8 @@ int main(int argc, const char* argv[]) {
JSONTEST_REGISTER_FIXTURE(runner, ValueTest, compareArray); JSONTEST_REGISTER_FIXTURE(runner, ValueTest, compareArray);
JSONTEST_REGISTER_FIXTURE(runner, ValueTest, compareObject); JSONTEST_REGISTER_FIXTURE(runner, ValueTest, compareObject);
JSONTEST_REGISTER_FIXTURE(runner, ValueTest, compareType); JSONTEST_REGISTER_FIXTURE(runner, ValueTest, compareType);
JSONTEST_REGISTER_FIXTURE(runner, ValueTest, offsetAccessors);
JSONTEST_REGISTER_FIXTURE(runner, ValueTest, typeChecksThrowExceptions); JSONTEST_REGISTER_FIXTURE(runner, ValueTest, typeChecksThrowExceptions);
JSONTEST_REGISTER_FIXTURE(runner, WriterTest, dropNullPlaceholders);
JSONTEST_REGISTER_FIXTURE(runner, StreamWriterTest, dropNullPlaceholders);
JSONTEST_REGISTER_FIXTURE(runner, ReaderTest, parseWithNoErrors); JSONTEST_REGISTER_FIXTURE(runner, ReaderTest, parseWithNoErrors);
JSONTEST_REGISTER_FIXTURE( JSONTEST_REGISTER_FIXTURE(
runner, ReaderTest, parseWithNoErrorsTestingOffsets); runner, ReaderTest, parseWithNoErrorsTestingOffsets);
@@ -2071,15 +1708,7 @@ int main(int argc, const char* argv[]) {
JSONTEST_REGISTER_FIXTURE(runner, CharReaderTest, parseWithDetailError); JSONTEST_REGISTER_FIXTURE(runner, CharReaderTest, parseWithDetailError);
JSONTEST_REGISTER_FIXTURE(runner, CharReaderTest, parseWithStackLimit); JSONTEST_REGISTER_FIXTURE(runner, CharReaderTest, parseWithStackLimit);
JSONTEST_REGISTER_FIXTURE(runner, CharReaderFailIfExtraTest, issue164); JSONTEST_REGISTER_FIXTURE(runner, StreamWriterTest, dropNullPlaceholders);
JSONTEST_REGISTER_FIXTURE(runner, CharReaderFailIfExtraTest, issue107);
JSONTEST_REGISTER_FIXTURE(runner, CharReaderFailIfExtraTest, commentAfterObject);
JSONTEST_REGISTER_FIXTURE(runner, CharReaderFailIfExtraTest, commentAfterArray);
JSONTEST_REGISTER_FIXTURE(runner, CharReaderFailIfExtraTest, commentAfterBool);
JSONTEST_REGISTER_FIXTURE(runner, CharReaderAllowDropNullTest, issue178);
JSONTEST_REGISTER_FIXTURE(runner, IteratorTest, distance);
return runner.runCommandLine(argc, argv); return runner.runCommandLine(argc, argv);
} }

View File

@@ -1 +1 @@
1.4.4 0.8.0