Compare commits

..

14 Commits

Author SHA1 Message Date
Christopher Dunn
2760c7902a fix #290 2015-06-10 21:22:24 -05:00
Christopher Dunn
f40dd0f3ed Merge branch 'master' into 0.y.z
BORLANDC compilation issues
2015-04-28 05:09:58 +01:00
Christopher Dunn
c334ac0376 Merge branch 'master' into 0.y.z
- fix for "C++ Builder" IDE
- Travis CI/AppVeyor
- **cmake** tweak
- fix memory leak in unit-test

See #268 and #252.
2015-04-27 18:33:07 -07:00
Christopher Dunn
c66cc277f5 Merge pull request #249 from cdunn2001/master
Merge appveyor changes into 0.y.z
2015-04-18 18:27:32 -07:00
Sam Clegg
db7ad75794 Don't use unique_ptr on pre-c++11 branch
Don't use C++11 unique_ptr in the 0.y.z branch.
Although this usage is guarded with __cplusplus >= 201103
some build configurations (notably chromium) use a
C++11-compliant compiler but a pre-11 library.

pull #238
2015-04-12 00:39:25 -05:00
Christopher Dunn
f4bdc1b602 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-04-11 14:49:59 -05:00
Christopher Dunn
93f45d065c 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-04-11 14:49:59 -05:00
Christopher Dunn
6f6ddaa91c revert 'Made it possible to drop null placeholders from array output.'
revert ae3c7a7aab
2015-04-11 14:49:59 -05:00
Christopher Dunn
254fe6a07a Revert "added option to FastWriter which omits the trailing new line character"
This reverts commit 5bf16105b5.
2015-04-11 14:49:59 -05:00
Christopher Dunn
00d7bea0f6 revert 'Added structured error reporting to Reader.'
revert 68db655347
issue #147
2015-04-11 14:49:59 -05:00
Christopher Dunn
a9d06d2650 revert 'Add public semantic error reporting'
for binary-compatibility with 0.6.0
issue #147
was #57
2015-04-11 14:49:59 -05:00
Christopher Dunn
1c4f6a2d79 partially revert "Switch to copy-and-swap idiom for operator=."
This partially reverts commit 45cd9490cd.

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

Ignored CZString changes since those are private (and sizeof struct did
not change).

  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-04-11 14:49:59 -05:00
Christopher Dunn
e49bd30950 NOT C++11 2015-04-11 14:49:59 -05:00
Christopher Dunn
13d78e3da3 0.10.z (based on 1.6.z, but binary-compat w/ 0.6.0-rc2) 2015-04-11 14:49:59 -05:00
21 changed files with 189 additions and 525 deletions

View File

@@ -2,31 +2,13 @@
# http://about.travis-ci.org/docs/user/build-configuration/
# This file can be validated on:
# http://lint.travis-ci.org/
# See also
# http://stackoverflow.com/questions/22111549/travis-ci-with-clang-3-4-and-c11/30925448#30925448
# to allow C++11, though we are not yet building with -std=c++11
install:
# /usr/bin/gcc is 4.6 always, but gcc-X.Y is available.
- if [ "$CXX" = "g++" ]; then export CXX="g++-4.9" CC="gcc-4.9"; fi
# /usr/bin/clang is our version already, and clang-X.Y does not exist.
#- if [ "$CXX" = "clang++" ]; then export CXX="clang++-3.7" CC="clang-3.7"; fi
- echo ${PATH}
- ls /usr/local
- ls /usr/local/bin
- export PATH=/usr/local/bin:/usr/bin:${PATH}
- echo ${CXX}
- ${CXX} --version
- which valgrind
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- gcc-4.9
- g++-4.9
- clang
- valgrind
#before_install: sudo apt-get install -y cmake
# cmake is pre-installed in Travis for both linux and osx
before_install:
- sudo apt-get update -qq
- sudo apt-get install -qq valgrind
os:
- linux
language: cpp
@@ -39,5 +21,5 @@ env:
- SHARED_LIB=ON STATIC_LIB=ON CMAKE_PKG=ON BUILD_TYPE=release VERBOSE_MAKE=false
- SHARED_LIB=OFF STATIC_LIB=ON CMAKE_PKG=OFF BUILD_TYPE=debug VERBOSE_MAKE=true VERBOSE
notifications:
email: false
sudo: false
email:
- aaronjjacobs@gmail.com

View File

@@ -21,16 +21,15 @@ IF(NOT WIN32)
ENDIF(NOT CMAKE_BUILD_TYPE)
ENDIF(NOT WIN32)
SET(DEBUG_LIBNAME_SUFFIX "" CACHE STRING "Optional suffix to append to the library name for a debug build")
SET(LIB_SUFFIX "" CACHE STRING "Optional arch-dependent suffix for the library installation directory")
SET(RUNTIME_INSTALL_DIR bin
CACHE PATH "Install dir for executables and dlls")
SET(ARCHIVE_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}
SET(ARCHIVE_INSTALL_DIR lib${LIB_SUFFIX}
CACHE PATH "Install dir for static libraries")
SET(LIBRARY_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}
SET(LIBRARY_INSTALL_DIR lib${LIB_SUFFIX}
CACHE PATH "Install dir for shared libraries")
SET(INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/include
SET(INCLUDE_INSTALL_DIR include
CACHE PATH "Install dir for headers")
SET(PACKAGE_INSTALL_DIR lib${LIB_SUFFIX}/cmake
CACHE PATH "Install dir for cmake package config files")
@@ -63,7 +62,7 @@ ENDMACRO(jsoncpp_parse_version)
#SET( JSONCPP_VERSION_MAJOR X )
#SET( JSONCPP_VERSION_MINOR Y )
#SET( JSONCPP_VERSION_PATCH Z )
SET( JSONCPP_VERSION 1.6.5 )
SET( JSONCPP_VERSION 0.10.2 )
jsoncpp_parse_version( ${JSONCPP_VERSION} JSONCPP_VERSION )
#IF(NOT JSONCPP_VERSION_FOUND)
# MESSAGE(FATAL_ERROR "Failed to parse version string properly. Expect X.Y.Z")
@@ -97,11 +96,10 @@ endif( MSVC )
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
# using regular Clang or AppleClang
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Werror -Wall -Wconversion -Wshadow -Wno-sign-conversion")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
# using GCC
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Werror -Wall -Wconversion -Wshadow -Wextra -pedantic")
# not yet ready for -Wsign-conversion
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic")
endif()
IF(JSONCPP_WITH_WARNING_AS_ERROR)

View File

@@ -19,14 +19,12 @@ format to store user input files.
* `0.y.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 include
the [amalgamated source](#generating-amalgamated-source-and-header) (a single
`.cpp` file and two `.h` files) in your project, and compile and build as you
would any other source file. This ensures consistency of compilation flags and
ABI compatibility, issues which arise when building shared or static
libraries. See the next section for instructions.
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
ensures consistency of compilation flags and ABI compatibility. See the section
"Generating amalgamated source and header" for instructions.
The `include/` should be added to your compiler include path. Jsoncpp headers
should be included as follow:
@@ -36,31 +34,6 @@ should be included as follow:
If JsonCpp was built as a dynamic library on Windows, then your project needs to
define the macro `JSON_DLL`.
Generating amalgamated source and header
----------------------------------------
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
can be generated at any time by running the following command from the
top-directory (this requires Python 2.6):
python amalgamate.py
It is possible to specify header name. See the `-h` option for detail.
By default, the following files are generated:
* `dist/jsoncpp.cpp`: source file that needs to be added to your project.
* `dist/json/json.h`: corresponding header file for use in your project. It is
equivalent to including `json/json.h` in non-amalgamated source. This header
only depends on standard headers.
* `dist/json/json-forwards.h`: header that provides forward declaration of all
JsonCpp types.
The amalgamated sources are generated by concatenating JsonCpp source in the
correct order and defining the macro `JSON_IS_AMALGAMATION` to prevent inclusion
of other headers.
# Contributing to JsonCpp
Building and testing with CMake
-------------------------------
[CMake][] is a C++ Makefiles/Solution generator. It is usually available on most
@@ -94,10 +67,10 @@ Alternatively, from the command-line on Unix in the source directory:
mkdir -p build/debug
cd build/debug
cmake -DCMAKE_BUILD_TYPE=debug -DBUILD_STATIC_LIBS=ON -DBUILD_SHARED_LIBS=OFF -DARCHIVE_INSTALL_DIR=. -G "Unix Makefiles" ../..
cmake -DCMAKE_BUILD_TYPE=debug -DBUILD_STATIC_LIBS=ON -DBUILD_SHARED_LIBS=OFF -G "Unix Makefiles" ../..
make
Running `cmake -h` will display the list of available generators (passed using
Running `cmake -`" will display the list of available generators (passed using
the `-G` option).
By default CMake hides compilation commands. This can be modified by specifying
@@ -133,7 +106,7 @@ 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
running SCons.
## Running the tests manually
# Running the tests manually
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
@@ -169,6 +142,29 @@ Run the Python script `doxybuild.py` from the top directory:
See `doxybuild.py --help` for options.
Generating amalgamated source and header
----------------------------------------
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
can be generated at any time by running the following command from the
top-directory (this requires Python 2.6):
python amalgamate.py
It is possible to specify header name. See the `-h` option for detail.
By default, the following files are generated:
* `dist/jsoncpp.cpp`: source file that needs to be added to your project.
* `dist/json/json.h`: corresponding header file for use in your project. It is
equivalent to including `json/json.h` in non-amalgamated source. This header
only depends on standard headers.
* `dist/json/json-forwards.h`: header that provides forward declaration of all
JsonCpp types.
The amalgamated sources are generated by concatenating JsonCpp source in the
correct order and defining the macro `JSON_IS_AMALGAMATION` to prevent inclusion
of other headers.
Adding a reader/writer test
---------------------------
To add a test, you need to create two files in test/data:

View File

@@ -19,7 +19,6 @@ before_build:
- echo "Running cmake..."
- cd c:\projects\jsoncpp
- cmake --version
- set PATH=C:\Program Files (x86)\MSBuild\14.0\Bin;%PATH%
- if %PLATFORM% == Win32 cmake .
- if %PLATFORM% == x64 cmake -G "Visual Studio 12 2013 Win64" .

View File

@@ -5,7 +5,6 @@
from __future__ import print_function
import os.path
import sys
def fix_source_eol(path, is_dry_run = True, verbose = True, eol = '\n'):
"""Makes sure that all sources have the specified eol sequence (default: unix)."""

View File

@@ -72,7 +72,7 @@ def run_cmd(cmd, silent=False):
if silent:
status, output = getstatusoutput(cmd)
else:
status, output = subprocess.call(cmd), ''
status, output = os.system(' '.join(cmd)), ''
if status:
msg = 'Error while %s ...\n\terror=%d, output="""%s"""' %(info, status, output)
raise Exception(msg)

View File

@@ -44,12 +44,6 @@ public:
/// \c true if root must be either an array or an object value. Default: \c
/// false.
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

View File

@@ -35,18 +35,6 @@ public:
typedef char Char;
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
* for parsing.
*/
@@ -123,38 +111,6 @@ public:
*/
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:
enum TokenType {
tokenEndOfStream = 0,

View File

@@ -37,36 +37,21 @@ namespace Json {
*
* We use nothing but these internally. Of course, STL can throw others.
*/
class JSON_API Exception : public std::exception {
public:
Exception(std::string const& msg);
virtual ~Exception() throw();
virtual char const* what() const throw();
protected:
std::string const msg_;
};
class JSON_API Exception;
/** Exceptions which the user cannot easily avoid.
*
* E.g. out-of-memory (when we use malloc), stack-overflow, malicious input
*
* \remark derived from Json::Exception
*/
class JSON_API RuntimeError : public Exception {
public:
RuntimeError(std::string const& msg);
};
class JSON_API RuntimeError;
/** Exceptions thrown by JSON_ASSERT/JSON_FAIL macros.
*
* These are precondition-violations (user bugs) and internal errors (our bugs).
*
* \remark derived from Json::Exception
*/
class JSON_API LogicError : public Exception {
public:
LogicError(std::string const& msg);
};
class JSON_API LogicError;
/// used internally
void throwRuntimeError(std::string const& msg);
@@ -175,8 +160,11 @@ public:
typedef Json::LargestUInt LargestUInt;
typedef Json::ArrayIndex ArrayIndex;
static const Value& null; ///< We regret this reference to a global instance; prefer the simpler Value().
static const Value& nullRef; ///< just a kludge for binary-compatibility; same as null
static const Value& nullRef;
#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.
static const LargestInt minLargestInt;
/// Maximum signed integer value that can be stored in a Json::Value.
@@ -270,7 +258,7 @@ Json::Value obj_value(Json::objectValue); // {}
#endif // if defined(JSON_HAS_INT64)
Value(double value);
Value(const char* value); ///< Copy til first 0. (NULL causes to seg-fault.)
Value(const char* begin, const char* end); ///< Copy all, incl zeroes.
Value(const char* beginValue, const char* endValue); ///< Copy all, incl zeroes.
/** \brief Constructs a value from a static string.
* Like other value string constructor but do not duplicate the string for
@@ -298,7 +286,7 @@ Json::Value obj_value(Json::objectValue); // {}
/// Deep copy, then swap(other).
/// \note Over-write existing comments. To preserve comments, use #swapPayload().
Value& operator=(Value other);
Value &operator=(const Value &other);
/// Swap everything.
void swap(Value& other);
/// Swap values but leave comments and source offsets in place.
@@ -321,7 +309,7 @@ Json::Value obj_value(Json::objectValue); // {}
* \return false if !string. (Seg-fault if str or end are NULL.)
*/
bool getString(
char const** begin, char const** end) const;
char const** str, char const** end) const;
#ifdef JSON_USE_CPPTL
CppTL::ConstString asConstString() const;
#endif
@@ -450,8 +438,8 @@ Json::Value obj_value(Json::objectValue); // {}
Value get(const char* key, const Value& defaultValue) const;
/// Return the member named key if it exist, defaultValue otherwise.
/// \note deep copy
/// \note key may contain embedded nulls.
Value get(const char* begin, const char* end, const Value& defaultValue) const;
/// \param key may contain embedded nulls.
Value get(const char* key, const char* end, const Value& defaultValue) const;
/// Return the member named key if it exist, defaultValue otherwise.
/// \note deep copy
/// \param key may contain embedded nulls.
@@ -463,12 +451,12 @@ Json::Value obj_value(Json::objectValue); // {}
#endif
/// Most general and efficient version of isMember()const, get()const,
/// and operator[]const
/// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30
Value const* find(char const* begin, char const* end) const;
/// \note As stated elsewhere, behavior is undefined if (end-key) >= 2^30
Value const* find(char const* key, char const* end) const;
/// Most general and efficient version of object-mutators.
/// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30
/// \note As stated elsewhere, behavior is undefined if (end-key) >= 2^30
/// \return non-zero, but JSON_ASSERT if this is neither object nor nullValue.
Value const* demand(char const* begin, char const* end);
Value const* demand(char const* key, char const* end);
/// \brief Remove and return the named member.
///
/// Do nothing if it did not exist.
@@ -481,7 +469,7 @@ Json::Value obj_value(Json::objectValue); // {}
/// \param key may contain embedded nulls.
/// \deprecated
Value removeMember(const std::string& key);
/// Same as removeMember(const char* begin, const char* end, Value* removed),
/// Same as removeMember(const char* key, const char* end, Value* removed),
/// but 'key' is null-terminated.
bool removeMember(const char* key, Value* removed);
/** \brief Remove the named map member.
@@ -492,7 +480,7 @@ Json::Value obj_value(Json::objectValue); // {}
*/
bool removeMember(std::string const& key, Value* removed);
/// Same as removeMember(std::string const& key, Value* removed)
bool removeMember(const char* begin, const char* end, Value* removed);
bool removeMember(const char* key, const char* end, Value* removed);
/** \brief Remove the indexed array element.
O(n) expensive operations.
@@ -508,7 +496,7 @@ Json::Value obj_value(Json::objectValue); // {}
/// \param key may contain embedded nulls.
bool isMember(const std::string& key) const;
/// Same as isMember(std::string const& key)const
bool isMember(const char* begin, const char* end) const;
bool isMember(const char* key, const char* end) const;
#ifdef JSON_USE_CPPTL
/// Return true if the object has a member named key.
bool isMember(const CppTL::ConstString& key) const;
@@ -545,13 +533,6 @@ Json::Value obj_value(Json::objectValue); // {}
iterator begin();
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:
void initBasic(ValueType type, bool allocated = false);
@@ -588,11 +569,6 @@ private:
unsigned int allocated_ : 1; // Notes: if declared as bool, bitfield is useless.
// If not allocated_, string_ must be null-terminated.
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

View File

@@ -1,12 +1,13 @@
// DO NOT EDIT. This file (and "version") is generated by CMake.
// DO NOT EDIT. This file is generated by CMake from "version"
// and "version.h.in" files.
// Run CMake configure step to update it.
#ifndef JSON_VERSION_H_INCLUDED
# define JSON_VERSION_H_INCLUDED
# define JSONCPP_VERSION_STRING "1.6.5"
# define JSONCPP_VERSION_MAJOR 1
# define JSONCPP_VERSION_MINOR 6
# define JSONCPP_VERSION_PATCH 5
# define JSONCPP_VERSION_STRING "0.10.2"
# define JSONCPP_VERSION_MAJOR 0
# define JSONCPP_VERSION_MINOR 10
# define JSONCPP_VERSION_PATCH 2
# define JSONCPP_VERSION_QUALIFIER
# define JSONCPP_VERSION_HEXA ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | (JSONCPP_VERSION_PATCH << 8))

View File

@@ -158,15 +158,6 @@ public:
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
virtual std::string write(const Value& root);
@@ -175,8 +166,6 @@ private:
std::string document_;
bool yamlCompatiblityEnabled_;
bool dropNullPlaceholders_;
bool omitEndingLineFeed_;
};
/** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a

View File

@@ -1,7 +1,7 @@
prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=${prefix}
libdir=@LIBRARY_INSTALL_DIR@
includedir=@INCLUDE_INSTALL_DIR@
libdir=${exec_prefix}/@LIBRARY_INSTALL_DIR@
includedir=${prefix}/@INCLUDE_INSTALL_DIR@
Name: jsoncpp
Description: A C++ library for interacting with JSON

View File

@@ -2,7 +2,7 @@ if( CMAKE_COMPILER_IS_GNUCXX )
#Get compiler version.
execute_process( COMMAND ${CMAKE_CXX_COMPILER} -dumpversion
OUTPUT_VARIABLE GNUCXX_VERSION )
#-Werror=* was introduced -after- GCC 4.1.2
if( GNUCXX_VERSION VERSION_GREATER 4.1.2 )
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror=strict-aliasing")
@@ -43,8 +43,7 @@ IF(BUILD_SHARED_LIBS)
ADD_DEFINITIONS( -DJSON_DLL_BUILD )
ADD_LIBRARY(jsoncpp_lib SHARED ${PUBLIC_HEADERS} ${jsoncpp_sources})
SET_TARGET_PROPERTIES( jsoncpp_lib PROPERTIES VERSION ${JSONCPP_VERSION} SOVERSION ${JSONCPP_VERSION_MAJOR})
SET_TARGET_PROPERTIES( jsoncpp_lib PROPERTIES OUTPUT_NAME jsoncpp
DEBUG_OUTPUT_NAME jsoncpp${DEBUG_LIBNAME_SUFFIX} )
SET_TARGET_PROPERTIES( jsoncpp_lib PROPERTIES OUTPUT_NAME jsoncpp )
INSTALL( TARGETS jsoncpp_lib ${INSTALL_EXPORT}
RUNTIME DESTINATION ${RUNTIME_INSTALL_DIR}
@@ -62,8 +61,7 @@ ENDIF()
IF(BUILD_STATIC_LIBS)
ADD_LIBRARY(jsoncpp_lib_static STATIC ${PUBLIC_HEADERS} ${jsoncpp_sources})
SET_TARGET_PROPERTIES( jsoncpp_lib_static PROPERTIES VERSION ${JSONCPP_VERSION} SOVERSION ${JSONCPP_VERSION_MAJOR})
SET_TARGET_PROPERTIES( jsoncpp_lib_static PROPERTIES OUTPUT_NAME jsoncpp
DEBUG_OUTPUT_NAME jsoncpp${DEBUG_LIBNAME_SUFFIX} )
SET_TARGET_PROPERTIES( jsoncpp_lib_static PROPERTIES OUTPUT_NAME jsoncpp )
INSTALL( TARGETS jsoncpp_lib_static ${INSTALL_EXPORT}
RUNTIME DESTINATION ${RUNTIME_INSTALL_DIR}

View File

@@ -32,27 +32,20 @@ static int stackDepth_g = 0; // see readValue()
namespace Json {
#if __cplusplus >= 201103L
typedef std::unique_ptr<CharReader> CharReaderPtr;
#else
typedef std::auto_ptr<CharReader> CharReaderPtr;
#endif
// Implementation of class Features
// ////////////////////////////////
Features::Features()
: allowComments_(true), strictRoot_(false),
allowDroppedNullPlaceholders_(false), allowNumericKeys_(false) {}
: allowComments_(true), strictRoot_(false)
{}
Features Features::all() { return Features(); }
Features Features::strictMode() {
Features features;
features.allowComments_ = false;
features.strictRoot_ = true;
features.allowDroppedNullPlaceholders_ = false;
features.allowNumericKeys_ = false;
return features;
}
@@ -162,11 +155,9 @@ bool Reader::readValue() {
switch (token.type_) {
case tokenObjectBegin:
successful = readObject(token);
currentValue().setOffsetLimit(current_ - begin_);
break;
case tokenArrayBegin:
successful = readArray(token);
currentValue().setOffsetLimit(current_ - begin_);
break;
case tokenNumber:
successful = decodeNumber(token);
@@ -178,42 +169,22 @@ bool Reader::readValue() {
{
Value v(true);
currentValue().swapPayload(v);
currentValue().setOffsetStart(token.start_ - begin_);
currentValue().setOffsetLimit(token.end_ - begin_);
}
break;
case tokenFalse:
{
Value v(false);
currentValue().swapPayload(v);
currentValue().setOffsetStart(token.start_ - begin_);
currentValue().setOffsetLimit(token.end_ - begin_);
}
break;
case tokenNull:
{
Value v;
currentValue().swapPayload(v);
currentValue().setOffsetStart(token.start_ - begin_);
currentValue().setOffsetLimit(token.end_ - begin_);
}
break;
case tokenArraySeparator:
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...
// Else, fall through...
default:
currentValue().setOffsetStart(token.start_ - begin_);
currentValue().setOffsetLimit(token.end_ - begin_);
return addError("Syntax error: value, object or array expected.", token);
}
@@ -441,12 +412,11 @@ bool Reader::readString() {
return c == '"';
}
bool Reader::readObject(Token& tokenStart) {
bool Reader::readObject(Token& /*tokenStart*/) {
Token tokenName;
std::string name;
Value init(objectValue);
currentValue().swapPayload(init);
currentValue().setOffsetStart(tokenStart.start_ - begin_);
while (readToken(tokenName)) {
bool initialTokenOk = true;
while (tokenName.type_ == tokenComment && initialTokenOk)
@@ -459,11 +429,6 @@ bool Reader::readObject(Token& tokenStart) {
if (tokenName.type_ == tokenString) {
if (!decodeString(tokenName, name))
return recoverFromError(tokenObjectEnd);
} else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) {
Value numberName;
if (!decodeNumber(tokenName, numberName))
return recoverFromError(tokenObjectEnd);
name = numberName.asString();
} else {
break;
}
@@ -497,10 +462,9 @@ bool Reader::readObject(Token& tokenStart) {
"Missing '}' or object member name", tokenName, tokenObjectEnd);
}
bool Reader::readArray(Token& tokenStart) {
bool Reader::readArray(Token& /*tokenStart*/) {
Value init(arrayValue);
currentValue().swapPayload(init);
currentValue().setOffsetStart(tokenStart.start_ - begin_);
skipSpaces();
if (*current_ == ']') // empty array
{
@@ -540,8 +504,6 @@ bool Reader::decodeNumber(Token& token) {
if (!decodeNumber(token, decoded))
return false;
currentValue().swapPayload(decoded);
currentValue().setOffsetStart(token.start_ - begin_);
currentValue().setOffsetLimit(token.end_ - begin_);
return true;
}
@@ -590,16 +552,38 @@ bool Reader::decodeDouble(Token& token) {
if (!decodeDouble(token, decoded))
return false;
currentValue().swapPayload(decoded);
currentValue().setOffsetStart(token.start_ - begin_);
currentValue().setOffsetLimit(token.end_ - begin_);
return true;
}
bool Reader::decodeDouble(Token& token, Value& decoded) {
double value = 0;
std::string buffer(token.start_, token.end_);
std::istringstream is(buffer);
if (!(is >> value))
const int bufferSize = 32;
int count;
int length = int(token.end_ - token.start_);
// Sanity check to avoid buffer overflow exploits.
if (length < 0) {
return addError("Unable to parse token length", token);
}
// Avoid using a string constant for the format control string given to
// sscanf, as this can cause hard to debug crashes on OS X. See here for more
// info:
//
// http://developer.apple.com/library/mac/#DOCUMENTATION/DeveloperTools/gcc-4.0.1/gcc/Incompatibilities.html
char format[] = "%lf";
if (length <= bufferSize) {
Char buffer[bufferSize + 1];
memcpy(buffer, token.start_, length);
buffer[length] = 0;
count = sscanf(buffer, format, &value);
} else {
std::string buffer(token.start_, token.end_);
count = sscanf(buffer.c_str(), format, &value);
}
if (count != 1)
return addError("'" + std::string(token.start_, token.end_) +
"' is not a number.",
token);
@@ -613,8 +597,6 @@ bool Reader::decodeString(Token& token) {
return false;
Value decoded(decoded_string);
currentValue().swapPayload(decoded);
currentValue().setOffsetStart(token.start_ - begin_);
currentValue().setOffsetLimit(token.end_ - begin_);
return true;
}
@@ -826,59 +808,8 @@ std::string Reader::getFormattedErrorMessages() const {
return formattedMessage;
}
std::vector<Reader::StructuredError> Reader::getStructuredErrors() const {
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();
}
// Reader
/////////////////////////
// exact copy of Features
class OurFeatures {
@@ -928,10 +859,6 @@ public:
Value& root,
bool collectComments = true);
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:
OurReader(OurReader const&); // no impl
@@ -1096,11 +1023,9 @@ bool OurReader::readValue() {
switch (token.type_) {
case tokenObjectBegin:
successful = readObject(token);
currentValue().setOffsetLimit(current_ - begin_);
break;
case tokenArrayBegin:
successful = readArray(token);
currentValue().setOffsetLimit(current_ - begin_);
break;
case tokenNumber:
successful = decodeNumber(token);
@@ -1112,24 +1037,18 @@ bool OurReader::readValue() {
{
Value v(true);
currentValue().swapPayload(v);
currentValue().setOffsetStart(token.start_ - begin_);
currentValue().setOffsetLimit(token.end_ - begin_);
}
break;
case tokenFalse:
{
Value v(false);
currentValue().swapPayload(v);
currentValue().setOffsetStart(token.start_ - begin_);
currentValue().setOffsetLimit(token.end_ - begin_);
}
break;
case tokenNull:
{
Value v;
currentValue().swapPayload(v);
currentValue().setOffsetStart(token.start_ - begin_);
currentValue().setOffsetLimit(token.end_ - begin_);
}
break;
case tokenArraySeparator:
@@ -1141,13 +1060,9 @@ bool OurReader::readValue() {
current_--;
Value v;
currentValue().swapPayload(v);
currentValue().setOffsetStart(current_ - begin_ - 1);
currentValue().setOffsetLimit(current_ - begin_);
break;
} // else, fall through ...
default:
currentValue().setOffsetStart(token.start_ - begin_);
currentValue().setOffsetLimit(token.end_ - begin_);
return addError("Syntax error: value, object or array expected.", token);
}
@@ -1379,7 +1294,6 @@ bool OurReader::readObject(Token& tokenStart) {
std::string name;
Value init(objectValue);
currentValue().swapPayload(init);
currentValue().setOffsetStart(tokenStart.start_ - begin_);
while (readToken(tokenName)) {
bool initialTokenOk = true;
while (tokenName.type_ == tokenComment && initialTokenOk)
@@ -1439,7 +1353,6 @@ bool OurReader::readObject(Token& tokenStart) {
bool OurReader::readArray(Token& tokenStart) {
Value init(arrayValue);
currentValue().swapPayload(init);
currentValue().setOffsetStart(tokenStart.start_ - begin_);
skipSpaces();
if (*current_ == ']') // empty array
{
@@ -1479,8 +1392,6 @@ bool OurReader::decodeNumber(Token& token) {
if (!decodeNumber(token, decoded))
return false;
currentValue().swapPayload(decoded);
currentValue().setOffsetStart(token.start_ - begin_);
currentValue().setOffsetLimit(token.end_ - begin_);
return true;
}
@@ -1529,8 +1440,6 @@ bool OurReader::decodeDouble(Token& token) {
if (!decodeDouble(token, decoded))
return false;
currentValue().swapPayload(decoded);
currentValue().setOffsetStart(token.start_ - begin_);
currentValue().setOffsetLimit(token.end_ - begin_);
return true;
}
@@ -1576,8 +1485,6 @@ bool OurReader::decodeString(Token& token) {
return false;
Value decoded(decoded_string);
currentValue().swapPayload(decoded);
currentValue().setOffsetStart(token.start_ - begin_);
currentValue().setOffsetLimit(token.end_ - begin_);
return true;
}
@@ -1784,60 +1691,6 @@ std::string OurReader::getFormattedErrorMessages() const {
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 {
bool const collectComments_;

View File

@@ -30,8 +30,8 @@ static inline std::string codePointToUTF8(unsigned int cp) {
} else if (cp <= 0xFFFF) {
result.resize(3);
result[2] = static_cast<char>(0x80 | (0x3f & cp));
result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 6)));
result[0] = static_cast<char>(0xE0 | (0xf & (cp >> 12)));
result[1] = 0x80 | static_cast<char>((0x3f & (cp >> 6)));
result[0] = 0xE0 | static_cast<char>((0xf & (cp >> 12)));
} else if (cp <= 0x10FFFF) {
result.resize(4);
result[3] = static_cast<char>(0x80 | (0x3f & cp));
@@ -43,7 +43,7 @@ static inline std::string codePointToUTF8(unsigned int cp) {
return result;
}
/// Returns true if ch is a control character (in range [1,31]).
/// Returns true if ch is a control character (in range [0,32[).
static inline bool isControlCharacter(char ch) { return ch > 0 && ch <= 0x1F; }
enum {
@@ -63,7 +63,7 @@ typedef char UIntToStringBuffer[uintToStringBufferSize];
static inline void uintToString(LargestUInt value, char*& current) {
*--current = 0;
do {
*--current = static_cast<signed char>(value % 10U + static_cast<unsigned>('0'));
*--current = char(value % 10) + '0';
value /= 10;
} while (value != 0);
}

View File

@@ -29,12 +29,13 @@ namespace Json {
#if defined(__ARMEL__)
#define ALIGNAS(byte_alignment) __attribute__((aligned(byte_alignment)))
#else
// This exists for binary compatibility only. Use nullRef.
const Value Value::null;
#define ALIGNAS(byte_alignment)
#endif
static const unsigned char ALIGNAS(8) kNull[sizeof(Value)] = { 0 };
const unsigned char& kNullRef = kNull[0];
const Value& Value::null = reinterpret_cast<const Value&>(kNullRef);
const Value& Value::nullRef = null;
const Value& Value::nullRef = reinterpret_cast<const Value&>(kNullRef);
const Int Value::minInt = Int(~(UInt(-1) / 2));
const Int Value::maxInt = Int(UInt(-1) / 2);
@@ -108,7 +109,7 @@ static inline char* duplicateAndPrefixStringValue(
JSON_ASSERT_MESSAGE(length <= (unsigned)Value::maxInt - sizeof(unsigned) - 1U,
"in Json::Value::duplicateAndPrefixStringValue(): "
"length too big for prefixing");
unsigned actualLength = length + static_cast<unsigned>(sizeof(unsigned)) + 1U;
unsigned actualLength = length + sizeof(unsigned) + 1U;
char* newString = static_cast<char*>(malloc(actualLength));
if (newString == 0) {
throwRuntimeError(
@@ -125,7 +126,7 @@ inline static void decodePrefixedString(
unsigned* length, char const** value)
{
if (!isPrefixed) {
*length = static_cast<unsigned>(strlen(prefixed));
*length = strlen(prefixed);
*value = prefixed;
} else {
*length = *reinterpret_cast<unsigned const*>(prefixed);
@@ -152,6 +153,23 @@ static inline void releaseStringValue(char* value) { free(value); }
namespace Json {
class JSON_API Exception : public std::exception {
public:
Exception(std::string const& msg);
virtual ~Exception() throw();
virtual char const* what() const throw();
protected:
std::string const msg_;
};
class JSON_API RuntimeError : public Exception {
public:
RuntimeError(std::string const& msg);
};
class JSON_API LogicError : public Exception {
public:
LogicError(std::string const& msg);
};
Exception::Exception(std::string const& msg)
: msg_(msg)
{}
@@ -215,14 +233,14 @@ void Value::CommentInfo::setComment(const char* text, size_t len) {
// Notes: policy_ indicates if the string was allocated when
// a string is stored.
Value::CZString::CZString(ArrayIndex aindex) : cstr_(0), index_(aindex) {}
Value::CZString::CZString(ArrayIndex index) : cstr_(0), index_(index) {}
Value::CZString::CZString(char const* str, unsigned ulength, DuplicationPolicy allocate)
Value::CZString::CZString(char const* str, unsigned length, DuplicationPolicy allocate)
: cstr_(str)
{
// allocate != duplicate
storage_.policy_ = allocate & 0x3;
storage_.length_ = ulength & 0x3FFFFFFF;
storage_.policy_ = allocate;
storage_.length_ = length;
}
Value::CZString::CZString(const CZString& other)
@@ -231,9 +249,9 @@ Value::CZString::CZString(const CZString& other)
: other.cstr_)
{
storage_.policy_ = (other.cstr_
? (static_cast<DuplicationPolicy>(other.storage_.policy_) == noDuplication
? (other.storage_.policy_ == noDuplication
? noDuplication : duplicate)
: static_cast<DuplicationPolicy>(other.storage_.policy_));
: other.storage_.policy_);
storage_.length_ = other.storage_.length_;
}
@@ -295,9 +313,9 @@ bool Value::CZString::isStaticString() const { return storage_.policy_ == noDupl
* memset( this, 0, sizeof(Value) )
* This optimization is used in ValueInternalMap fast allocator.
*/
Value::Value(ValueType vtype) {
initBasic(vtype);
switch (vtype) {
Value::Value(ValueType type) {
initBasic(type);
switch (type) {
case nullValue:
break;
case intValue:
@@ -384,7 +402,7 @@ Value::Value(bool value) {
Value::Value(Value const& other)
: type_(other.type_), allocated_(false)
,
comments_(0), start_(other.start_), limit_(other.limit_)
comments_(0)
{
switch (type_) {
case nullValue:
@@ -449,8 +467,9 @@ Value::~Value() {
delete[] comments_;
}
Value& Value::operator=(Value other) {
swap(other);
Value &Value::operator=(const Value &other) {
Value temp(other);
swap(temp);
return *this;
}
@@ -461,14 +480,12 @@ void Value::swapPayload(Value& other) {
std::swap(value_, other.value_);
int temp2 = allocated_;
allocated_ = other.allocated_;
other.allocated_ = temp2 & 0x1;
other.allocated_ = temp2;
}
void Value::swap(Value& other) {
swapPayload(other);
std::swap(comments_, other.comments_);
std::swap(start_, other.start_);
std::swap(limit_, other.limit_);
}
ValueType Value::type() const { return type_; }
@@ -589,12 +606,12 @@ const char* Value::asCString() const {
return this_str;
}
bool Value::getString(char const** str, char const** cend) const {
bool Value::getString(char const** str, char const** end) const {
if (type_ != stringValue) return false;
if (value_.string_ == 0) return false;
unsigned length;
decodePrefixedString(this->allocated_, this->value_.string_, &length, str);
*cend = *str + length;
*end = *str + length;
return true;
}
@@ -793,8 +810,7 @@ bool Value::asBool() const {
case uintValue:
return value_.uint_ ? true : false;
case realValue:
// This is kind of strange. Not recommended.
return (value_.real_ != 0.0) ? true : false;
return value_.real_ ? true : false;
default:
break;
}
@@ -871,8 +887,6 @@ void Value::clear() {
JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue ||
type_ == objectValue,
"in Json::Value::clear(): requires complex value");
start_ = 0;
limit_ = 0;
switch (type_) {
case arrayValue:
case objectValue:
@@ -944,12 +958,10 @@ const Value& Value::operator[](int index) const {
return (*this)[ArrayIndex(index)];
}
void Value::initBasic(ValueType vtype, bool allocated) {
type_ = vtype;
void Value::initBasic(ValueType type, bool allocated) {
type_ = type;
allocated_ = allocated;
comments_ = 0;
start_ = 0;
limit_ = 0;
}
// Access an object value by name, create a null member if it does not exist.
@@ -974,7 +986,7 @@ Value& Value::resolveReference(const char* key) {
}
// @param key is not null-terminated.
Value& Value::resolveReference(char const* key, char const* cend)
Value& Value::resolveReference(char const* key, char const* end)
{
JSON_ASSERT_MESSAGE(
type_ == nullValue || type_ == objectValue,
@@ -982,7 +994,7 @@ Value& Value::resolveReference(char const* key, char const* cend)
if (type_ == nullValue)
*this = Value(objectValue);
CZString actualKey(
key, static_cast<unsigned>(cend-key), CZString::duplicateOnCopy);
key, static_cast<unsigned>(end-key), CZString::duplicateOnCopy);
ObjectValues::iterator it = value_.map_->lower_bound(actualKey);
if (it != value_.map_->end() && (*it).first == actualKey)
return (*it).second;
@@ -1000,13 +1012,13 @@ Value Value::get(ArrayIndex index, const Value& defaultValue) const {
bool Value::isValidIndex(ArrayIndex index) const { return index < size(); }
Value const* Value::find(char const* key, char const* cend) const
Value const* Value::find(char const* key, char const* end) const
{
JSON_ASSERT_MESSAGE(
type_ == nullValue || type_ == objectValue,
"in Json::Value::find(key, end, found): requires objectValue or nullValue");
if (type_ == nullValue) return NULL;
CZString actualKey(key, static_cast<unsigned>(cend-key), CZString::noDuplication);
CZString actualKey(key, static_cast<unsigned>(end-key), CZString::noDuplication);
ObjectValues::const_iterator it = value_.map_->find(actualKey);
if (it == value_.map_->end()) return NULL;
return &(*it).second;
@@ -1050,9 +1062,9 @@ Value const& Value::operator[](CppTL::ConstString const& key) const
Value& Value::append(const Value& value) { return (*this)[size()] = value; }
Value Value::get(char const* key, char const* cend, Value const& defaultValue) const
Value Value::get(char const* key, char const* end, Value const& defaultValue) const
{
Value const* found = find(key, cend);
Value const* found = find(key, end);
return !found ? defaultValue : *found;
}
Value Value::get(char const* key, Value const& defaultValue) const
@@ -1065,12 +1077,12 @@ Value Value::get(std::string const& key, Value const& defaultValue) const
}
bool Value::removeMember(const char* key, const char* cend, Value* removed)
bool Value::removeMember(const char* key, const char* end, Value* removed)
{
if (type_ != objectValue) {
return false;
}
CZString actualKey(key, static_cast<unsigned>(cend-key), CZString::noDuplication);
CZString actualKey(key, static_cast<unsigned>(end-key), CZString::noDuplication);
ObjectValues::iterator it = value_.map_->find(actualKey);
if (it == value_.map_->end())
return false;
@@ -1115,8 +1127,8 @@ bool Value::removeIndex(ArrayIndex index, Value* removed) {
ArrayIndex oldSize = size();
// shift left all items left, into the place of the "removed"
for (ArrayIndex i = index; i < (oldSize - 1); ++i){
CZString keey(i);
(*value_.map_)[keey] = (*this)[i + 1];
CZString key(i);
(*value_.map_)[key] = (*this)[i + 1];
}
// erase the last one ("leftover")
CZString keyLast(oldSize - 1);
@@ -1132,9 +1144,9 @@ Value Value::get(const CppTL::ConstString& key,
}
#endif
bool Value::isMember(char const* key, char const* cend) const
bool Value::isMember(char const* key, char const* end) const
{
Value const* value = find(key, cend);
Value const* value = find(key, end);
return NULL != value;
}
bool Value::isMember(char const* key) const
@@ -1319,14 +1331,6 @@ std::string Value::getComment(CommentPlacement placement) const {
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 {
StyledWriter writer;
return writer.write(*this);

View File

@@ -93,26 +93,26 @@ UInt ValueIteratorBase::index() const {
}
std::string ValueIteratorBase::name() const {
char const* keey;
char const* key;
char const* end;
keey = memberName(&end);
if (!keey) return std::string();
return std::string(keey, end);
key = memberName(&end);
if (!key) return std::string();
return std::string(key, end);
}
char const* ValueIteratorBase::memberName() const {
const char* cname = (*current_).first.data();
return cname ? cname : "";
const char* name = (*current_).first.data();
return name ? name : "";
}
char const* ValueIteratorBase::memberName(char const** end) const {
const char* cname = (*current_).first.data();
if (!cname) {
const char* name = (*current_).first.data();
if (!name) {
*end = NULL;
return NULL;
}
*end = cname + (*current_).first.length();
return cname;
*end = name + (*current_).first.length();
return name;
}
// //////////////////////////////////////////////////////////////////

View File

@@ -29,8 +29,6 @@
#if defined(_MSC_VER) && _MSC_VER < 1500 // VC++ 8.0 and below
#define snprintf _snprintf
#elif defined(__ANDROID__)
#define snprintf snprintf
#elif __cplusplus >= 201103L
#define snprintf std::snprintf
#endif
@@ -48,11 +46,7 @@
namespace Json {
#if __cplusplus >= 201103L
typedef std::unique_ptr<StreamWriter> StreamWriterPtr;
#else
typedef std::auto_ptr<StreamWriter> StreamWriterPtr;
#endif
static bool containsControlCharacter(const char* str) {
while (*str) {
@@ -292,28 +286,21 @@ Writer::~Writer() {}
// //////////////////////////////////////////////////////////////////
FastWriter::FastWriter()
: yamlCompatiblityEnabled_(false), dropNullPlaceholders_(false),
omitEndingLineFeed_(false) {}
: yamlCompatiblityEnabled_(false) {}
void FastWriter::enableYAMLCompatibility() { yamlCompatiblityEnabled_ = true; }
void FastWriter::dropNullPlaceholders() { dropNullPlaceholders_ = true; }
void FastWriter::omitEndingLineFeed() { omitEndingLineFeed_ = true; }
std::string FastWriter::write(const Value& root) {
document_ = "";
writeValue(root);
if (!omitEndingLineFeed_)
document_ += "\n";
document_ += "\n";
return document_;
}
void FastWriter::writeValue(const Value& value) {
switch (value.type()) {
case nullValue:
if (!dropNullPlaceholders_)
document_ += "null";
document_ += "null";
break;
case intValue:
document_ += valueToString(value.asLargestInt());
@@ -354,7 +341,7 @@ void FastWriter::writeValue(const Value& value) {
const std::string& name = *it;
if (it != members.begin())
document_ += ',';
document_ += valueToQuotedStringN(name.data(), static_cast<unsigned>(name.length()));
document_ += valueToQuotedStringN(name.data(), name.length());
document_ += yamlCompatiblityEnabled_ ? ": " : ":";
writeValue(value[name]);
}
@@ -914,7 +901,7 @@ void BuiltStyledStreamWriter::writeValue(Value const& value) {
std::string const& name = *it;
Value const& childValue = value[name];
writeCommentBeforeValue(childValue);
writeWithIndent(valueToQuotedStringN(name.data(), static_cast<unsigned>(name.length())));
writeWithIndent(valueToQuotedStringN(name.data(), name.length()));
*sout_ << colonSymbol_;
writeValue(childValue);
if (++it == members.end()) {

View File

@@ -1,4 +1,5 @@
// DO NOT EDIT. This file (and "version") is generated by CMake.
// DO NOT EDIT. This file is generated by CMake from "version"
// and "version.h.in" files.
// Run CMake configure step to update it.
#ifndef JSON_VERSION_H_INCLUDED
# define JSON_VERSION_H_INCLUDED

View File

@@ -296,7 +296,10 @@ JSONTEST_FIXTURE(ValueTest, null) {
JSONTEST_ASSERT_EQUAL(0.0, null_.asFloat());
JSONTEST_ASSERT_STRING_EQUAL("", null_.asString());
#if !defined(__ARMEL__)
// See line #165 of include/json/value.h
JSONTEST_ASSERT_EQUAL(Json::Value::null, null_);
#endif
}
JSONTEST_FIXTURE(ValueTest, strings) {
@@ -1512,25 +1515,6 @@ JSONTEST_FIXTURE(ValueTest, typeChecksThrowExceptions) {
#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);
}
JSONTEST_FIXTURE(ValueTest, StaticString) {
char mutant[] = "hello";
Json::StaticString ss(mutant);
@@ -1651,17 +1635,6 @@ JSONTEST_FIXTURE(ValueTest, zeroesInKeys) {
}
}
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 {};
JSONTEST_FIXTURE(StreamWriterTest, dropNullPlaceholders) {
@@ -1703,7 +1676,6 @@ JSONTEST_FIXTURE(ReaderTest, parseWithNoErrors) {
bool ok = reader.parse("{ \"property\" : \"value\" }", root);
JSONTEST_ASSERT(ok);
JSONTEST_ASSERT(reader.getFormattedErrorMessages().size() == 0);
JSONTEST_ASSERT(reader.getStructuredErrors().size() == 0);
}
JSONTEST_FIXTURE(ReaderTest, parseWithNoErrorsTestingOffsets) {
@@ -1715,25 +1687,6 @@ JSONTEST_FIXTURE(ReaderTest, parseWithNoErrorsTestingOffsets) {
root);
JSONTEST_ASSERT(ok);
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) {
@@ -1744,13 +1697,6 @@ JSONTEST_FIXTURE(ReaderTest, parseWithOneError) {
JSONTEST_ASSERT(reader.getFormattedErrorMessages() ==
"* Line 1, Column 15\n Syntax error: value, object or array "
"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) {
@@ -1761,13 +1707,6 @@ JSONTEST_FIXTURE(ReaderTest, parseChineseWithOneError) {
JSONTEST_ASSERT(reader.getFormattedErrorMessages() ==
"* Line 1, Column 19\n Syntax error: value, object or array "
"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) {
@@ -1778,12 +1717,6 @@ JSONTEST_FIXTURE(ReaderTest, parseWithDetailError) {
JSONTEST_ASSERT(reader.getFormattedErrorMessages() ==
"* Line 1, Column 16\n Bad escape sequence in string\nSee "
"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 {};
@@ -2355,7 +2288,6 @@ int main(int argc, const char* argv[]) {
JSONTEST_REGISTER_FIXTURE(runner, ValueTest, compareArray);
JSONTEST_REGISTER_FIXTURE(runner, ValueTest, compareObject);
JSONTEST_REGISTER_FIXTURE(runner, ValueTest, compareType);
JSONTEST_REGISTER_FIXTURE(runner, ValueTest, offsetAccessors);
JSONTEST_REGISTER_FIXTURE(runner, ValueTest, typeChecksThrowExceptions);
JSONTEST_REGISTER_FIXTURE(runner, ValueTest, StaticString);
JSONTEST_REGISTER_FIXTURE(runner, ValueTest, CommentBefore);
@@ -2363,7 +2295,6 @@ int main(int argc, const char* argv[]) {
JSONTEST_REGISTER_FIXTURE(runner, ValueTest, zeroes);
JSONTEST_REGISTER_FIXTURE(runner, ValueTest, zeroesInKeys);
JSONTEST_REGISTER_FIXTURE(runner, WriterTest, dropNullPlaceholders);
JSONTEST_REGISTER_FIXTURE(runner, StreamWriterTest, dropNullPlaceholders);
JSONTEST_REGISTER_FIXTURE(runner, StreamWriterTest, writeZeroes);

View File

@@ -1 +1 @@
1.6.5
0.10.2