Compare commits

...

39 Commits

Author SHA1 Message Date
Christopher Dunn
d48bff5fcb gcc-4.6 in Travis
and clang-3.0, the default
2015-07-12 15:02:28 -05:00
Christopher Dunn
93d74678da Merge pull request #315 from cdunn2001/0.y.z
-Werror

and fixed a minor bug found by -Wshadow
2015-07-12 14:52:00 -05:00
Christopher Dunn
ed5d73fe1d 0.6.4 2015-07-12 14:47:59 -05:00
Christopher Dunn
b97e624ac1 -Werror 2015-07-12 14:47:58 -05:00
Christopher Dunn
542354902e fixed a bug found by -Wshadow 2015-07-12 14:47:37 -05:00
Christopher Dunn
17360f3d4b fix some warnings 2015-07-12 14:47:37 -05:00
Christopher Dunn
75747db30c -Wshadow
* https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
* http://programmers.stackexchange.com/questions/122608/clang-warning-flags-for-objective-c-development/124574#124574

In clang: `-Wconversion` implies `-Wshorten-64-to-32`, but we cannot use
`-Wconversion` yet.
2015-07-12 14:47:35 -05:00
Christopher Dunn
02839ef5b1 Merge pull request #310 from cdunn2001/0.y.z
gcc-4.6, clang-3.3
2015-07-12 09:55:20 -05:00
Christopher Dunn
138c48b7e8 gcc-4.6, clang-3.3 2015-07-12 09:50:14 -05:00
Christopher Dunn
72fb4a5b08 valgrind in Travis 2015-07-11 14:26:11 -05:00
Christopher Dunn
c6fa959318 dockerize the Travis build
Docker builds are *much* faster in Travis.

Also, we prepare to enable C++11.
2015-07-11 14:26:11 -05:00
Christopher Dunn
fb1301274f Merge pull request #308 from cdunn2001/0.y.z
0.10.3

No significant changes.
2015-07-11 14:07:55 -05:00
Christopher Dunn
7670e5151b 0.10.3 2015-07-11 13:53:05 -05:00
Mike Naberezny
2e185081b2 Fix undefined name "sys"
Same as #299 (bca0eff81a1c5ef160d9858b8e89b1c919b71c1f), but an earlier
commit needed to be rebased.
2015-07-11 13:52:27 -05:00
Stuart Eichert
cb8259f545 Fix #296: Explicitly cast size_t results to unsigned when needed
This is rebased from #297, where AppVeyor had been failing, and which
was not properly based on the master branch.
2015-07-11 13:52:27 -05:00
Stuart Eichert
bb5d0249ed Warn about implicit 64 to 32 bit conversions when using clang 2015-07-11 13:52:08 -05:00
Martyn Gigg
710260d070 Allow an optional suffix on the debug library name in CMake. 2015-07-11 13:51:40 -05:00
Christopher Dunn
dbda2aa36f Merge pull request #307 from cdunn2001/gaurav-fix-warnings
fix warnings (-Wno-long-long and unused tokenStart)

* closes #300
* closes #301
2015-07-11 12:02:22 -05:00
Gaurav
ef38374e99 Gcc warning unused "tokenStart"
(was #301)

In `0.y.z` branch, `tokenStart` is not used.
Comment it as done in other cases.
2015-07-11 11:57:21 -05:00
Gaurav
f1cafb6ded GCC warning removal for long long
(was #300)

I got below warning message on x86 linux machine :
```
"jsoncpp-0.10.2-p1/include/json/config.h💯 warning: ISO C++ 1998 does not support ‘long long’"
gcc version 4.4.7 20120313 (Red Hat 4.4.7-4) (GCC)
```
In reference to

* https://github.com/open-source-parsers/jsoncpp/pull/292

**long long** is supported in c++-11; for old compilers i.e `0.y.z` branch this patch should be merged.
2015-07-11 11:55:13 -05:00
Christopher Dunn
a13303e456 Merge pull request #306 from cdunn2001/0.y.z
fix appveyor 32-bit windows build
2015-07-11 11:52:16 -05:00
Christopher Dunn
7bc97db496 fix appveyor 32-bit windows build
* http://help.appveyor.com/discussions/problems/2229-v140-not-found-on-vs2105rc
```
Done Building Project "C:\projects\jsoncpp\jsoncpp.sln" (default targets) -- FAILED.

Build FAILED.

"C:\projects\jsoncpp\jsoncpp.sln" (default target) (1) ->
"C:\projects\jsoncpp\ALL_BUILD.vcxproj.metaproj" (default target) (2) ->
"C:\projects\jsoncpp\ZERO_CHECK.vcxproj" (default target) (3) ->
(PlatformPrepareForBuild target) ->
  C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V120\Microsoft.Cpp.Platform.targets(64,5): error MSB8020: The build tools for v140 (Platform Toolset = 'v140') cannot be found. To build using the v140 build tools, please install v140 build tools.  Alternatively, you may upgrade to the current Visual Studio tools by selecting the Project menu or right-click the solution, and then selecting "Upgrade Solution...". [C:\projects\jsoncpp\ZERO_CHECK.vcxproj]
```
2015-07-11 11:36:28 -05:00
Christopher Dunn
17181acf74 Merge remote-tracking branch 'up/master' into 0.y.z
fix ,/. problem in #294
2015-06-19 00:11:52 -05:00
Christopher Dunn
07623b71f2 Merge branch 'master' into 0.y.z 2015-06-18 22:34:40 -05:00
Christopher Dunn
f1ff13767c Merge pull request #291 from cdunn2001/0.y.z
fix #290
2015-06-10 22:05:45 -05:00
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: 28836b8acc2c002b0488c13dba28fd5be864970a

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 ae3c7a7aabfb345968a65001ea9bc25f1e2bb405
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 5bf16105b5a90f9fa7d5d4d43452feee46603a52.
2015-04-11 14:49:59 -05:00
Christopher Dunn
00d7bea0f6 revert 'Added structured error reporting to Reader.'
revert 68db6553471bb9cb050b1bb888b5933ee758b82d
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 45cd9490cd261da31cef84a44d2c587be7e26e99.

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
17 changed files with 114 additions and 422 deletions

View File

@ -2,13 +2,30 @@
# http://about.travis-ci.org/docs/user/build-configuration/ # http://about.travis-ci.org/docs/user/build-configuration/
# This file can be validated on: # This file can be validated on:
# http://lint.travis-ci.org/ # 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
#before_install: sudo apt-get install -y cmake install:
# cmake is pre-installed in Travis for both linux and osx # /usr/bin/gcc is 4.6 always, but gcc-X.Y is available.
#- if [ "$CXX" = "g++" ]; then export CXX="g++-4.8" CC="gcc-4.8"; fi
before_install: - if [ "$CXX" = "g++" ]; then export CXX="g++-4.6" CC="gcc-4.6"; fi
- sudo apt-get update -qq # /usr/bin/clang is our version already, and clang-X.Y does not exist.
- sudo apt-get install -qq valgrind #- if [ "$CXX" = "clang++" ]; then export CXX="clang++-3.0" CC="clang-3.0"; fi
- echo ${PATH}
- ls /usr/local
- export PATH=/usr/bin:${PATH}
- echo ${CXX}
- ${CXX} --version
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- gcc-4.6
- g++-4.6
- clang
- valgrind
os: os:
- linux - linux
language: cpp language: cpp
@ -23,3 +40,4 @@ env:
notifications: notifications:
email: email:
- aaronjjacobs@gmail.com - aaronjjacobs@gmail.com
sudo: false

View File

@ -21,6 +21,7 @@ IF(NOT WIN32)
ENDIF(NOT CMAKE_BUILD_TYPE) ENDIF(NOT CMAKE_BUILD_TYPE)
ENDIF(NOT WIN32) 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(LIB_SUFFIX "" CACHE STRING "Optional arch-dependent suffix for the library installation directory")
SET(RUNTIME_INSTALL_DIR bin SET(RUNTIME_INSTALL_DIR bin
@ -62,7 +63,7 @@ ENDMACRO(jsoncpp_parse_version)
#SET( JSONCPP_VERSION_MAJOR X ) #SET( JSONCPP_VERSION_MAJOR X )
#SET( JSONCPP_VERSION_MINOR Y ) #SET( JSONCPP_VERSION_MINOR Y )
#SET( JSONCPP_VERSION_PATCH Z ) #SET( JSONCPP_VERSION_PATCH Z )
SET( JSONCPP_VERSION 1.6.2 ) SET( JSONCPP_VERSION 0.10.4 )
jsoncpp_parse_version( ${JSONCPP_VERSION} JSONCPP_VERSION ) jsoncpp_parse_version( ${JSONCPP_VERSION} JSONCPP_VERSION )
#IF(NOT JSONCPP_VERSION_FOUND) #IF(NOT JSONCPP_VERSION_FOUND)
# MESSAGE(FATAL_ERROR "Failed to parse version string properly. Expect X.Y.Z") # MESSAGE(FATAL_ERROR "Failed to parse version string properly. Expect X.Y.Z")
@ -96,10 +97,11 @@ 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} -std=c++11 -Werror -Wall -Wshadow -Wshorten-64-to-32")
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} -Werror -Wall -Wshadow -Wextra -pedantic -Wno-long-long")
# not yet ready for -Wconversion
endif() endif()
IF(JSONCPP_WITH_WARNING_AS_ERROR) IF(JSONCPP_WITH_WARNING_AS_ERROR)

View File

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

View File

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

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,

View File

@ -160,8 +160,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.
@ -283,7 +286,7 @@ Json::Value obj_value(Json::objectValue); // {}
/// Deep copy, then swap(other). /// Deep copy, then swap(other).
/// \note Over-write existing comments. To preserve comments, use #swapPayload(). /// \note Over-write existing comments. To preserve comments, use #swapPayload().
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.
@ -530,13 +533,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);
@ -573,11 +569,6 @@ private:
unsigned int allocated_ : 1; // Notes: if declared as bool, bitfield is useless. unsigned int allocated_ : 1; // Notes: if declared as bool, bitfield is useless.
// If not allocated_, string_ must be null-terminated. // If not allocated_, string_ must be null-terminated.
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

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.6.2" # define JSONCPP_VERSION_STRING "0.10.4"
# define JSONCPP_VERSION_MAJOR 1 # define JSONCPP_VERSION_MAJOR 0
# define JSONCPP_VERSION_MINOR 6 # define JSONCPP_VERSION_MINOR 10
# define JSONCPP_VERSION_PATCH 2 # define JSONCPP_VERSION_PATCH 4
# 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

@ -158,15 +158,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);
@ -175,8 +166,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,7 +43,8 @@ IF(BUILD_SHARED_LIBS)
ADD_DEFINITIONS( -DJSON_DLL_BUILD ) ADD_DEFINITIONS( -DJSON_DLL_BUILD )
ADD_LIBRARY(jsoncpp_lib SHARED ${PUBLIC_HEADERS} ${jsoncpp_sources}) 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 VERSION ${JSONCPP_VERSION} SOVERSION ${JSONCPP_VERSION_MAJOR})
SET_TARGET_PROPERTIES( jsoncpp_lib PROPERTIES OUTPUT_NAME jsoncpp ) SET_TARGET_PROPERTIES( jsoncpp_lib PROPERTIES OUTPUT_NAME jsoncpp
DEBUG_OUTPUT_NAME jsoncpp${DEBUG_LIBNAME_SUFFIX} )
INSTALL( TARGETS jsoncpp_lib ${INSTALL_EXPORT} INSTALL( TARGETS jsoncpp_lib ${INSTALL_EXPORT}
RUNTIME DESTINATION ${RUNTIME_INSTALL_DIR} RUNTIME DESTINATION ${RUNTIME_INSTALL_DIR}
@ -61,7 +62,8 @@ ENDIF()
IF(BUILD_STATIC_LIBS) IF(BUILD_STATIC_LIBS)
ADD_LIBRARY(jsoncpp_lib_static STATIC ${PUBLIC_HEADERS} ${jsoncpp_sources}) 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 VERSION ${JSONCPP_VERSION} SOVERSION ${JSONCPP_VERSION_MAJOR})
SET_TARGET_PROPERTIES( jsoncpp_lib_static PROPERTIES OUTPUT_NAME jsoncpp ) SET_TARGET_PROPERTIES( jsoncpp_lib_static PROPERTIES OUTPUT_NAME jsoncpp
DEBUG_OUTPUT_NAME jsoncpp${DEBUG_LIBNAME_SUFFIX} )
INSTALL( TARGETS jsoncpp_lib_static ${INSTALL_EXPORT} INSTALL( TARGETS jsoncpp_lib_static ${INSTALL_EXPORT}
RUNTIME DESTINATION ${RUNTIME_INSTALL_DIR} RUNTIME DESTINATION ${RUNTIME_INSTALL_DIR}

View File

@ -32,27 +32,20 @@ static int stackDepth_g = 0; // see readValue()
namespace Json { namespace Json {
#if __cplusplus >= 201103L
typedef std::unique_ptr<CharReader> CharReaderPtr;
#else
typedef std::auto_ptr<CharReader> CharReaderPtr; typedef std::auto_ptr<CharReader> CharReaderPtr;
#endif
// Implementation of class Features // Implementation of class Features
// //////////////////////////////// // ////////////////////////////////
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;
} }
@ -162,11 +155,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);
@ -178,42 +169,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);
} }
@ -441,12 +412,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)
@ -459,11 +429,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;
} }
@ -497,10 +462,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
{ {
@ -540,8 +504,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;
} }
@ -590,8 +552,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;
} }
@ -613,8 +573,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;
} }
@ -826,59 +784,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 {
@ -928,10 +835,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
@ -1096,11 +999,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);
@ -1112,24 +1013,18 @@ 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:
@ -1141,13 +1036,9 @@ bool OurReader::readValue() {
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);
} }
@ -1374,12 +1265,11 @@ bool OurReader::readStringSingleQuote() {
return c == '\''; return c == '\'';
} }
bool OurReader::readObject(Token& tokenStart) { bool OurReader::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)
@ -1436,10 +1326,9 @@ bool OurReader::readObject(Token& tokenStart) {
"Missing '}' or object member name", tokenName, tokenObjectEnd); "Missing '}' or object member name", tokenName, tokenObjectEnd);
} }
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
{ {
@ -1479,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;
} }
@ -1529,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;
} }
@ -1576,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;
} }
@ -1784,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_;

View File

@ -30,8 +30,8 @@ static inline std::string codePointToUTF8(unsigned int cp) {
} else if (cp <= 0xFFFF) { } else if (cp <= 0xFFFF) {
result.resize(3); result.resize(3);
result[2] = static_cast<char>(0x80 | (0x3f & cp)); result[2] = static_cast<char>(0x80 | (0x3f & cp));
result[1] = 0x80 | static_cast<char>((0x3f & (cp >> 6))); result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 6)));
result[0] = 0xE0 | static_cast<char>((0xf & (cp >> 12))); result[0] = static_cast<char>(0xE0 | (0xf & (cp >> 12)));
} else if (cp <= 0x10FFFF) { } else if (cp <= 0x10FFFF) {
result.resize(4); result.resize(4);
result[3] = static_cast<char>(0x80 | (0x3f & cp)); result[3] = static_cast<char>(0x80 | (0x3f & cp));
@ -63,7 +63,7 @@ typedef char UIntToStringBuffer[uintToStringBufferSize];
static inline void uintToString(LargestUInt value, char*& current) { static inline void uintToString(LargestUInt value, char*& current) {
*--current = 0; *--current = 0;
do { do {
*--current = char(value % 10) + '0'; *--current = static_cast<signed char>(value % 10U + static_cast<unsigned>('0'));
value /= 10; value /= 10;
} while (value != 0); } while (value != 0);
} }

View File

@ -29,12 +29,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.
const Value 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);
@ -108,7 +109,7 @@ static inline char* duplicateAndPrefixStringValue(
JSON_ASSERT_MESSAGE(length <= (unsigned)Value::maxInt - sizeof(unsigned) - 1U, JSON_ASSERT_MESSAGE(length <= (unsigned)Value::maxInt - sizeof(unsigned) - 1U,
"in Json::Value::duplicateAndPrefixStringValue(): " "in Json::Value::duplicateAndPrefixStringValue(): "
"length too big for prefixing"); "length too big for prefixing");
unsigned actualLength = length + sizeof(unsigned) + 1U; unsigned actualLength = length + static_cast<unsigned>(sizeof(unsigned)) + 1U;
char* newString = static_cast<char*>(malloc(actualLength)); char* newString = static_cast<char*>(malloc(actualLength));
if (newString == 0) { if (newString == 0) {
throwRuntimeError( throwRuntimeError(
@ -125,7 +126,7 @@ inline static void decodePrefixedString(
unsigned* length, char const** value) unsigned* length, char const** value)
{ {
if (!isPrefixed) { if (!isPrefixed) {
*length = strlen(prefixed); *length = static_cast<unsigned>(strlen(prefixed));
*value = prefixed; *value = prefixed;
} else { } else {
*length = *reinterpret_cast<unsigned const*>(prefixed); *length = *reinterpret_cast<unsigned const*>(prefixed);
@ -232,14 +233,14 @@ void Value::CommentInfo::setComment(const char* text, size_t len) {
// Notes: policy_ indicates if the string was allocated when // Notes: policy_ indicates if the string was allocated when
// a string is stored. // a string is stored.
Value::CZString::CZString(ArrayIndex index) : cstr_(0), index_(index) {} Value::CZString::CZString(ArrayIndex aindex) : cstr_(0), index_(aindex) {}
Value::CZString::CZString(char const* str, unsigned length, DuplicationPolicy allocate) Value::CZString::CZString(char const* str, unsigned ulength, DuplicationPolicy allocate)
: cstr_(str) : cstr_(str)
{ {
// allocate != duplicate // allocate != duplicate
storage_.policy_ = allocate; storage_.policy_ = allocate & 0x3;
storage_.length_ = length; storage_.length_ = ulength & 0x3FFFFFFF;
} }
Value::CZString::CZString(const CZString& other) Value::CZString::CZString(const CZString& other)
@ -248,9 +249,9 @@ Value::CZString::CZString(const CZString& other)
: other.cstr_) : other.cstr_)
{ {
storage_.policy_ = (other.cstr_ storage_.policy_ = (other.cstr_
? (other.storage_.policy_ == noDuplication ? (static_cast<DuplicationPolicy>(other.storage_.policy_) == noDuplication
? noDuplication : duplicate) ? noDuplication : duplicate)
: other.storage_.policy_); : static_cast<DuplicationPolicy>(other.storage_.policy_));
storage_.length_ = other.storage_.length_; storage_.length_ = other.storage_.length_;
} }
@ -312,9 +313,9 @@ bool Value::CZString::isStaticString() const { return storage_.policy_ == noDupl
* memset( this, 0, sizeof(Value) ) * memset( this, 0, sizeof(Value) )
* This optimization is used in ValueInternalMap fast allocator. * This optimization is used in ValueInternalMap fast allocator.
*/ */
Value::Value(ValueType type) { Value::Value(ValueType vtype) {
initBasic(type); initBasic(vtype);
switch (type) { switch (vtype) {
case nullValue: case nullValue:
break; break;
case intValue: case intValue:
@ -401,7 +402,7 @@ Value::Value(bool value) {
Value::Value(Value const& other) Value::Value(Value const& other)
: type_(other.type_), allocated_(false) : type_(other.type_), allocated_(false)
, ,
comments_(0), start_(other.start_), limit_(other.limit_) comments_(0)
{ {
switch (type_) { switch (type_) {
case nullValue: case nullValue:
@ -466,8 +467,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;
} }
@ -478,14 +480,12 @@ void Value::swapPayload(Value& other) {
std::swap(value_, other.value_); std::swap(value_, other.value_);
int temp2 = allocated_; int temp2 = allocated_;
allocated_ = other.allocated_; allocated_ = other.allocated_;
other.allocated_ = temp2; other.allocated_ = temp2 & 0x1;
} }
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_; }
@ -606,12 +606,12 @@ const char* Value::asCString() const {
return this_str; return this_str;
} }
bool Value::getString(char const** str, char const** end) const { bool Value::getString(char const** str, char const** cend) const {
if (type_ != stringValue) return false; if (type_ != stringValue) return false;
if (value_.string_ == 0) return false; if (value_.string_ == 0) return false;
unsigned length; unsigned length;
decodePrefixedString(this->allocated_, this->value_.string_, &length, str); decodePrefixedString(this->allocated_, this->value_.string_, &length, str);
*end = *str + length; *cend = *str + length;
return true; return true;
} }
@ -810,7 +810,8 @@ bool Value::asBool() const {
case uintValue: case uintValue:
return value_.uint_ ? true : false; return value_.uint_ ? true : false;
case realValue: case realValue:
return value_.real_ ? true : false; // This is kind of strange. Not recommended.
return (value_.real_ != 0.0) ? true : false;
default: default:
break; break;
} }
@ -887,8 +888,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_) {
case arrayValue: case arrayValue:
case objectValue: case objectValue:
@ -960,12 +959,10 @@ const Value& Value::operator[](int index) const {
return (*this)[ArrayIndex(index)]; return (*this)[ArrayIndex(index)];
} }
void Value::initBasic(ValueType type, bool allocated) { void Value::initBasic(ValueType vtype, bool allocated) {
type_ = type; type_ = vtype;
allocated_ = allocated; allocated_ = allocated;
comments_ = 0; comments_ = 0;
start_ = 0;
limit_ = 0;
} }
// Access an object value by name, create a null member if it does not exist. // Access an object value by name, create a null member if it does not exist.
@ -990,7 +987,7 @@ Value& Value::resolveReference(const char* key) {
} }
// @param key is not null-terminated. // @param key is not null-terminated.
Value& Value::resolveReference(char const* key, char const* end) Value& Value::resolveReference(char const* key, char const* cend)
{ {
JSON_ASSERT_MESSAGE( JSON_ASSERT_MESSAGE(
type_ == nullValue || type_ == objectValue, type_ == nullValue || type_ == objectValue,
@ -998,7 +995,7 @@ Value& Value::resolveReference(char const* key, char const* end)
if (type_ == nullValue) if (type_ == nullValue)
*this = Value(objectValue); *this = Value(objectValue);
CZString actualKey( CZString actualKey(
key, static_cast<unsigned>(end-key), CZString::duplicateOnCopy); key, static_cast<unsigned>(cend-key), CZString::duplicateOnCopy);
ObjectValues::iterator it = value_.map_->lower_bound(actualKey); ObjectValues::iterator it = value_.map_->lower_bound(actualKey);
if (it != value_.map_->end() && (*it).first == actualKey) if (it != value_.map_->end() && (*it).first == actualKey)
return (*it).second; return (*it).second;
@ -1016,13 +1013,13 @@ Value Value::get(ArrayIndex index, const Value& defaultValue) const {
bool Value::isValidIndex(ArrayIndex index) const { return index < size(); } bool Value::isValidIndex(ArrayIndex index) const { return index < size(); }
Value const* Value::find(char const* key, char const* end) const Value const* Value::find(char const* key, char const* cend) const
{ {
JSON_ASSERT_MESSAGE( JSON_ASSERT_MESSAGE(
type_ == nullValue || type_ == objectValue, type_ == nullValue || type_ == objectValue,
"in Json::Value::find(key, end, found): requires objectValue or nullValue"); "in Json::Value::find(key, end, found): requires objectValue or nullValue");
if (type_ == nullValue) return NULL; if (type_ == nullValue) return NULL;
CZString actualKey(key, static_cast<unsigned>(end-key), CZString::noDuplication); CZString actualKey(key, static_cast<unsigned>(cend-key), CZString::noDuplication);
ObjectValues::const_iterator it = value_.map_->find(actualKey); ObjectValues::const_iterator it = value_.map_->find(actualKey);
if (it == value_.map_->end()) return NULL; if (it == value_.map_->end()) return NULL;
return &(*it).second; return &(*it).second;
@ -1066,9 +1063,9 @@ Value const& Value::operator[](CppTL::ConstString const& key) const
Value& Value::append(const Value& value) { return (*this)[size()] = value; } Value& Value::append(const Value& value) { return (*this)[size()] = value; }
Value Value::get(char const* key, char const* end, Value const& defaultValue) const Value Value::get(char const* key, char const* cend, Value const& defaultValue) const
{ {
Value const* found = find(key, end); Value const* found = find(key, cend);
return !found ? defaultValue : *found; return !found ? defaultValue : *found;
} }
Value Value::get(char const* key, Value const& defaultValue) const Value Value::get(char const* key, Value const& defaultValue) const
@ -1081,12 +1078,12 @@ Value Value::get(std::string const& key, Value const& defaultValue) const
} }
bool Value::removeMember(const char* key, const char* end, Value* removed) bool Value::removeMember(const char* key, const char* cend, Value* removed)
{ {
if (type_ != objectValue) { if (type_ != objectValue) {
return false; return false;
} }
CZString actualKey(key, static_cast<unsigned>(end-key), CZString::noDuplication); CZString actualKey(key, static_cast<unsigned>(cend-key), CZString::noDuplication);
ObjectValues::iterator it = value_.map_->find(actualKey); ObjectValues::iterator it = value_.map_->find(actualKey);
if (it == value_.map_->end()) if (it == value_.map_->end())
return false; return false;
@ -1131,8 +1128,8 @@ bool Value::removeIndex(ArrayIndex index, Value* removed) {
ArrayIndex oldSize = size(); ArrayIndex oldSize = size();
// shift left all items left, into the place of the "removed" // shift left all items left, into the place of the "removed"
for (ArrayIndex i = index; i < (oldSize - 1); ++i){ for (ArrayIndex i = index; i < (oldSize - 1); ++i){
CZString key(i); CZString keey(i);
(*value_.map_)[key] = (*this)[i + 1]; (*value_.map_)[keey] = (*this)[i + 1];
} }
// erase the last one ("leftover") // erase the last one ("leftover")
CZString keyLast(oldSize - 1); CZString keyLast(oldSize - 1);
@ -1148,9 +1145,9 @@ Value Value::get(const CppTL::ConstString& key,
} }
#endif #endif
bool Value::isMember(char const* key, char const* end) const bool Value::isMember(char const* key, char const* cend) const
{ {
Value const* value = find(key, end); Value const* value = find(key, cend);
return NULL != value; return NULL != value;
} }
bool Value::isMember(char const* key) const bool Value::isMember(char const* key) const
@ -1335,14 +1332,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);

View File

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

View File

@ -48,11 +48,7 @@
namespace Json { namespace Json {
#if __cplusplus >= 201103L
typedef std::unique_ptr<StreamWriter> StreamWriterPtr;
#else
typedef std::auto_ptr<StreamWriter> StreamWriterPtr; typedef std::auto_ptr<StreamWriter> StreamWriterPtr;
#endif
static bool containsControlCharacter(const char* str) { static bool containsControlCharacter(const char* str) {
while (*str) { while (*str) {
@ -292,28 +288,21 @@ 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_;
} }
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:
document_ += valueToString(value.asLargestInt()); document_ += valueToString(value.asLargestInt());
@ -354,7 +343,7 @@ void FastWriter::writeValue(const Value& value) {
const std::string& name = *it; const std::string& name = *it;
if (it != members.begin()) if (it != members.begin())
document_ += ','; document_ += ',';
document_ += valueToQuotedStringN(name.data(), name.length()); document_ += valueToQuotedStringN(name.data(), static_cast<unsigned>(name.length()));
document_ += yamlCompatiblityEnabled_ ? ": " : ":"; document_ += yamlCompatiblityEnabled_ ? ": " : ":";
writeValue(value[name]); writeValue(value[name]);
} }
@ -914,7 +903,7 @@ void BuiltStyledStreamWriter::writeValue(Value const& value) {
std::string const& name = *it; std::string const& name = *it;
Value const& childValue = value[name]; Value const& childValue = value[name];
writeCommentBeforeValue(childValue); writeCommentBeforeValue(childValue);
writeWithIndent(valueToQuotedStringN(name.data(), name.length())); writeWithIndent(valueToQuotedStringN(name.data(), static_cast<unsigned>(name.length())));
*sout_ << colonSymbol_; *sout_ << colonSymbol_;
writeValue(childValue); writeValue(childValue);
if (++it == members.end()) { if (++it == members.end()) {

View File

@ -296,7 +296,10 @@ JSONTEST_FIXTURE(ValueTest, null) {
JSONTEST_ASSERT_EQUAL(0.0, null_.asFloat()); JSONTEST_ASSERT_EQUAL(0.0, null_.asFloat());
JSONTEST_ASSERT_STRING_EQUAL("", null_.asString()); JSONTEST_ASSERT_STRING_EQUAL("", null_.asString());
#if !defined(__ARMEL__)
// See line #165 of include/json/value.h
JSONTEST_ASSERT_EQUAL(Json::Value::null, null_); JSONTEST_ASSERT_EQUAL(Json::Value::null, null_);
#endif
} }
JSONTEST_FIXTURE(ValueTest, strings) { JSONTEST_FIXTURE(ValueTest, strings) {
@ -1512,25 +1515,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);
}
JSONTEST_FIXTURE(ValueTest, StaticString) { JSONTEST_FIXTURE(ValueTest, StaticString) {
char mutant[] = "hello"; char mutant[] = "hello";
Json::StaticString ss(mutant); 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 {}; struct StreamWriterTest : JsonTest::TestCase {};
JSONTEST_FIXTURE(StreamWriterTest, dropNullPlaceholders) { JSONTEST_FIXTURE(StreamWriterTest, dropNullPlaceholders) {
@ -1703,7 +1676,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) {
@ -1715,25 +1687,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) {
@ -1744,13 +1697,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) {
@ -1761,13 +1707,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) {
@ -1778,12 +1717,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 {};
@ -2355,7 +2288,6 @@ 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, ValueTest, StaticString); JSONTEST_REGISTER_FIXTURE(runner, ValueTest, StaticString);
JSONTEST_REGISTER_FIXTURE(runner, ValueTest, CommentBefore); 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, zeroes);
JSONTEST_REGISTER_FIXTURE(runner, ValueTest, zeroesInKeys); JSONTEST_REGISTER_FIXTURE(runner, ValueTest, zeroesInKeys);
JSONTEST_REGISTER_FIXTURE(runner, WriterTest, dropNullPlaceholders);
JSONTEST_REGISTER_FIXTURE(runner, StreamWriterTest, dropNullPlaceholders); JSONTEST_REGISTER_FIXTURE(runner, StreamWriterTest, dropNullPlaceholders);
JSONTEST_REGISTER_FIXTURE(runner, StreamWriterTest, writeZeroes); JSONTEST_REGISTER_FIXTURE(runner, StreamWriterTest, writeZeroes);

View File

@ -1 +1 @@
1.6.2 0.10.4