mirror of
https://github.com/open-source-parsers/jsoncpp.git
synced 2025-10-15 07:14:45 +02:00
Compare commits
11 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
24682e37bf | ||
![]() |
c2b988ee74 | ||
![]() |
e255ce31a4 | ||
![]() |
779b5bc5ba | ||
![]() |
63860617b3 | ||
![]() |
9cb88d2ca6 | ||
![]() |
363e51c0a9 | ||
![]() |
240ddb6a1b | ||
![]() |
9dd77dc0ef | ||
![]() |
244b1496e1 | ||
![]() |
c083835261 |
@@ -60,7 +60,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.10.0 )
|
SET( JSONCPP_VERSION 1.6.2 )
|
||||||
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")
|
||||||
@@ -94,10 +94,10 @@ endif( MSVC )
|
|||||||
|
|
||||||
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||||
# using regular Clang or AppleClang
|
# using regular Clang or AppleClang
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall")
|
||||||
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
||||||
# using GCC
|
# using GCC
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x -Wall -Wextra -pedantic")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
IF(JSONCPP_WITH_WARNING_AS_ERROR)
|
IF(JSONCPP_WITH_WARNING_AS_ERROR)
|
||||||
|
@@ -1 +1,6 @@
|
|||||||
# module
|
# Copyright 2010 Baptiste Lepilleur
|
||||||
|
# Distributed under MIT license, or public domain if desired and
|
||||||
|
# recognized in your jurisdiction.
|
||||||
|
# See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
|
|
||||||
|
# module
|
||||||
|
@@ -1,6 +1,9 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# encoding: utf-8
|
# encoding: utf-8
|
||||||
# Baptiste Lepilleur, 2009
|
# Copyright 2009 Baptiste Lepilleur
|
||||||
|
# Distributed under MIT license, or public domain if desired and
|
||||||
|
# recognized in your jurisdiction.
|
||||||
|
# See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
|
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
from dircache import listdir
|
from dircache import listdir
|
||||||
|
@@ -1,3 +1,8 @@
|
|||||||
|
# Copyright 2010 Baptiste Lepilleur
|
||||||
|
# Distributed under MIT license, or public domain if desired and
|
||||||
|
# recognized in your jurisdiction.
|
||||||
|
# See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
|
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
import os.path
|
import os.path
|
||||||
|
|
||||||
|
@@ -1,3 +1,8 @@
|
|||||||
|
# Copyright 2010 Baptiste Lepilleur
|
||||||
|
# Distributed under MIT license, or public domain if desired and
|
||||||
|
# recognized in your jurisdiction.
|
||||||
|
# See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
|
|
||||||
from contextlib import closing
|
from contextlib import closing
|
||||||
import os
|
import os
|
||||||
import tarfile
|
import tarfile
|
||||||
|
@@ -31,7 +31,7 @@ def find_program(*filenames):
|
|||||||
paths = os.environ.get('PATH', '').split(os.pathsep)
|
paths = os.environ.get('PATH', '').split(os.pathsep)
|
||||||
suffixes = ('win32' in sys.platform) and '.exe .com .bat .cmd' or ''
|
suffixes = ('win32' in sys.platform) and '.exe .com .bat .cmd' or ''
|
||||||
for filename in filenames:
|
for filename in filenames:
|
||||||
for name in [filename+ext for ext in suffixes.split()]:
|
for name in [filename+ext for ext in suffixes.split(' ')]:
|
||||||
for directory in paths:
|
for directory in paths:
|
||||||
full_path = os.path.join(directory, name)
|
full_path = os.path.join(directory, name)
|
||||||
if os.path.isfile(full_path):
|
if os.path.isfile(full_path):
|
||||||
|
@@ -44,6 +44,12 @@ 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
|
||||||
|
@@ -35,6 +35,18 @@ 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.
|
||||||
*/
|
*/
|
||||||
@@ -111,6 +123,38 @@ 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,
|
||||||
|
@@ -160,11 +160,8 @@ public:
|
|||||||
typedef Json::LargestUInt LargestUInt;
|
typedef Json::LargestUInt LargestUInt;
|
||||||
typedef Json::ArrayIndex ArrayIndex;
|
typedef Json::ArrayIndex ArrayIndex;
|
||||||
|
|
||||||
static const Value& nullRef;
|
static const Value& null; ///< We regret this reference to a global instance; prefer the simpler Value().
|
||||||
#if !defined(__ARMEL__)
|
static const Value& nullRef; ///< just a kludge for binary-compatibility; same as null
|
||||||
/// \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.
|
||||||
@@ -286,7 +283,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=(const Value &other);
|
Value& operator=(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.
|
||||||
@@ -515,7 +512,6 @@ Json::Value obj_value(Json::objectValue); // {}
|
|||||||
//# endif
|
//# endif
|
||||||
|
|
||||||
/// \deprecated Always pass len.
|
/// \deprecated Always pass len.
|
||||||
JSONCPP_DEPRECATED("Use setComment(std::string const&) instead.")
|
|
||||||
void setComment(const char* comment, CommentPlacement placement);
|
void setComment(const char* comment, CommentPlacement placement);
|
||||||
/// Comments must be //... or /* ... */
|
/// Comments must be //... or /* ... */
|
||||||
void setComment(const char* comment, size_t len, CommentPlacement placement);
|
void setComment(const char* comment, size_t len, CommentPlacement placement);
|
||||||
@@ -533,6 +529,13 @@ 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);
|
||||||
|
|
||||||
@@ -569,6 +572,11 @@ 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
|
||||||
|
@@ -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.10.0"
|
# define JSONCPP_VERSION_STRING "1.6.2"
|
||||||
# define JSONCPP_VERSION_MAJOR 1
|
# define JSONCPP_VERSION_MAJOR 1
|
||||||
# define JSONCPP_VERSION_MINOR 10
|
# define JSONCPP_VERSION_MINOR 6
|
||||||
# define JSONCPP_VERSION_PATCH 0
|
# define JSONCPP_VERSION_PATCH 2
|
||||||
# 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))
|
||||||
|
|
||||||
|
@@ -158,6 +158,15 @@ 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);
|
||||||
|
|
||||||
@@ -166,6 +175,8 @@ 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
|
||||||
|
@@ -1,3 +1,8 @@
|
|||||||
|
# Copyright 2010 Baptiste Lepilleur
|
||||||
|
# Distributed under MIT license, or public domain if desired and
|
||||||
|
# recognized in your jurisdiction.
|
||||||
|
# See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
|
|
||||||
"""Tag the sandbox for release, make source and doc tarballs.
|
"""Tag the sandbox for release, make source and doc tarballs.
|
||||||
|
|
||||||
Requires Python 2.6
|
Requires Python 2.6
|
||||||
@@ -14,6 +19,7 @@ python makerelease.py 0.5.0 0.6.0-dev
|
|||||||
Note: This was for Subversion. Now that we are in GitHub, we do not
|
Note: This was for Subversion. Now that we are in GitHub, we do not
|
||||||
need to build versioned tarballs anymore, so makerelease.py is defunct.
|
need to build versioned tarballs anymore, so makerelease.py is defunct.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
import os.path
|
import os.path
|
||||||
import subprocess
|
import subprocess
|
||||||
|
@@ -1,3 +1,8 @@
|
|||||||
|
# Copyright 2009 Baptiste Lepilleur
|
||||||
|
# Distributed under MIT license, or public domain if desired and
|
||||||
|
# recognized in your jurisdiction.
|
||||||
|
# See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
|
|
||||||
import fnmatch
|
import fnmatch
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
@@ -1,3 +1,8 @@
|
|||||||
|
# Copyright 2007 Baptiste Lepilleur
|
||||||
|
# Distributed under MIT license, or public domain if desired and
|
||||||
|
# recognized in your jurisdiction.
|
||||||
|
# See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import os.path
|
import os.path
|
||||||
from fnmatch import fnmatch
|
from fnmatch import fnmatch
|
||||||
|
@@ -1,3 +1,8 @@
|
|||||||
|
# Copyright 2010 Baptiste Lepilleur
|
||||||
|
# Distributed under MIT license, or public domain if desired and
|
||||||
|
# recognized in your jurisdiction.
|
||||||
|
# See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
|
|
||||||
import re
|
import re
|
||||||
from SCons.Script import * # the usual scons stuff you get in a SConscript
|
from SCons.Script import * # the usual scons stuff you get in a SConscript
|
||||||
import collections
|
import collections
|
||||||
|
@@ -1,3 +1,8 @@
|
|||||||
|
# Copyright 2007 Baptiste Lepilleur
|
||||||
|
# Distributed under MIT license, or public domain if desired and
|
||||||
|
# recognized in your jurisdiction.
|
||||||
|
# See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
|
|
||||||
"""tarball
|
"""tarball
|
||||||
|
|
||||||
Tool-specific initialization for tarball.
|
Tool-specific initialization for tarball.
|
||||||
|
@@ -42,14 +42,17 @@ typedef std::auto_ptr<CharReader> CharReaderPtr;
|
|||||||
// ////////////////////////////////
|
// ////////////////////////////////
|
||||||
|
|
||||||
Features::Features()
|
Features::Features()
|
||||||
: allowComments_(true), strictRoot_(false)
|
: allowComments_(true), strictRoot_(false),
|
||||||
{}
|
allowDroppedNullPlaceholders_(false), allowNumericKeys_(false) {}
|
||||||
|
|
||||||
Features Features::all() { return Features(); }
|
Features Features::all() { return Features(); }
|
||||||
|
|
||||||
Features Features::strictMode() {
|
Features Features::strictMode() {
|
||||||
Features features;
|
Features features;
|
||||||
features.allowComments_ = false;
|
features.allowComments_ = false;
|
||||||
features.strictRoot_ = true;
|
features.strictRoot_ = true;
|
||||||
|
features.allowDroppedNullPlaceholders_ = false;
|
||||||
|
features.allowNumericKeys_ = false;
|
||||||
return features;
|
return features;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,9 +162,11 @@ 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);
|
||||||
@@ -173,22 +178,42 @@ 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;
|
||||||
// Else, fall through...
|
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...
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -416,11 +441,12 @@ 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)
|
||||||
@@ -433,6 +459,11 @@ 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;
|
||||||
}
|
}
|
||||||
@@ -466,9 +497,10 @@ 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
|
||||||
{
|
{
|
||||||
@@ -508,6 +540,8 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -556,6 +590,8 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -601,6 +637,8 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -812,8 +850,59 @@ std::string Reader::getFormattedErrorMessages() const {
|
|||||||
return formattedMessage;
|
return formattedMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reader
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
// exact copy of Features
|
// exact copy of Features
|
||||||
class OurFeatures {
|
class OurFeatures {
|
||||||
@@ -863,6 +952,10 @@ 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
|
||||||
@@ -1027,9 +1120,11 @@ 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);
|
||||||
@@ -1041,18 +1136,24 @@ 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:
|
||||||
@@ -1064,9 +1165,13 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1298,6 +1403,7 @@ bool OurReader::readObject(Token& tokenStart) {
|
|||||||
std::string name;
|
std::string name;
|
||||||
Value init(objectValue);
|
Value init(objectValue);
|
||||||
currentValue().swapPayload(init);
|
currentValue().swapPayload(init);
|
||||||
|
currentValue().setOffsetStart(tokenStart.start_ - begin_);
|
||||||
while (readToken(tokenName)) {
|
while (readToken(tokenName)) {
|
||||||
bool initialTokenOk = true;
|
bool initialTokenOk = true;
|
||||||
while (tokenName.type_ == tokenComment && initialTokenOk)
|
while (tokenName.type_ == tokenComment && initialTokenOk)
|
||||||
@@ -1357,6 +1463,7 @@ bool OurReader::readObject(Token& tokenStart) {
|
|||||||
bool OurReader::readArray(Token& tokenStart) {
|
bool OurReader::readArray(Token& tokenStart) {
|
||||||
Value init(arrayValue);
|
Value init(arrayValue);
|
||||||
currentValue().swapPayload(init);
|
currentValue().swapPayload(init);
|
||||||
|
currentValue().setOffsetStart(tokenStart.start_ - begin_);
|
||||||
skipSpaces();
|
skipSpaces();
|
||||||
if (*current_ == ']') // empty array
|
if (*current_ == ']') // empty array
|
||||||
{
|
{
|
||||||
@@ -1396,6 +1503,8 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1444,6 +1553,8 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1489,6 +1600,8 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1695,6 +1808,60 @@ 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_;
|
||||||
|
@@ -29,13 +29,12 @@ 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::nullRef = reinterpret_cast<const Value&>(kNullRef);
|
const Value& Value::null = 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);
|
||||||
@@ -402,7 +401,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)
|
comments_(0), start_(other.start_), limit_(other.limit_)
|
||||||
{
|
{
|
||||||
switch (type_) {
|
switch (type_) {
|
||||||
case nullValue:
|
case nullValue:
|
||||||
@@ -467,9 +466,8 @@ Value::~Value() {
|
|||||||
delete[] comments_;
|
delete[] comments_;
|
||||||
}
|
}
|
||||||
|
|
||||||
Value &Value::operator=(const Value &other) {
|
Value& Value::operator=(Value other) {
|
||||||
Value temp(other);
|
swap(other);
|
||||||
swap(temp);
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -486,6 +484,8 @@ void Value::swapPayload(Value& other) {
|
|||||||
void Value::swap(Value& other) {
|
void Value::swap(Value& other) {
|
||||||
swapPayload(other);
|
swapPayload(other);
|
||||||
std::swap(comments_, other.comments_);
|
std::swap(comments_, other.comments_);
|
||||||
|
std::swap(start_, other.start_);
|
||||||
|
std::swap(limit_, other.limit_);
|
||||||
}
|
}
|
||||||
|
|
||||||
ValueType Value::type() const { return type_; }
|
ValueType Value::type() const { return type_; }
|
||||||
@@ -887,6 +887,8 @@ 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:
|
||||||
@@ -962,6 +964,8 @@ void Value::initBasic(ValueType type, bool allocated) {
|
|||||||
type_ = type;
|
type_ = type;
|
||||||
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.
|
||||||
@@ -1331,6 +1335,14 @@ 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);
|
||||||
|
@@ -29,7 +29,7 @@
|
|||||||
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER < 1500 // VC++ 8.0 and below
|
#if defined(_MSC_VER) && _MSC_VER < 1500 // VC++ 8.0 and below
|
||||||
#define snprintf _snprintf
|
#define snprintf _snprintf
|
||||||
#else
|
#elif __cplusplus >= 201103L
|
||||||
#define snprintf std::snprintf
|
#define snprintf std::snprintf
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -284,21 +284,28 @@ Writer::~Writer() {}
|
|||||||
// //////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
FastWriter::FastWriter()
|
FastWriter::FastWriter()
|
||||||
: yamlCompatiblityEnabled_(false) {}
|
: yamlCompatiblityEnabled_(false), dropNullPlaceholders_(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);
|
||||||
document_ += "\n";
|
if (!omitEndingLineFeed_)
|
||||||
|
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:
|
||||||
document_ += "null";
|
if (!dropNullPlaceholders_)
|
||||||
|
document_ += "null";
|
||||||
break;
|
break;
|
||||||
case intValue:
|
case intValue:
|
||||||
document_ += valueToString(value.asLargestInt());
|
document_ += valueToString(value.asLargestInt());
|
||||||
@@ -310,8 +317,14 @@ void FastWriter::writeValue(const Value& value) {
|
|||||||
document_ += valueToString(value.asDouble());
|
document_ += valueToString(value.asDouble());
|
||||||
break;
|
break;
|
||||||
case stringValue:
|
case stringValue:
|
||||||
document_ += valueToQuotedString(value.asCString());
|
{
|
||||||
|
// Is NULL possible for value.string_?
|
||||||
|
char const* str;
|
||||||
|
char const* end;
|
||||||
|
bool ok = value.getString(&str, &end);
|
||||||
|
if (ok) document_ += valueToQuotedStringN(str, static_cast<unsigned>(end-str));
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case booleanValue:
|
case booleanValue:
|
||||||
document_ += valueToString(value.asBool());
|
document_ += valueToString(value.asBool());
|
||||||
break;
|
break;
|
||||||
@@ -375,7 +388,7 @@ void StyledWriter::writeValue(const Value& value) {
|
|||||||
break;
|
break;
|
||||||
case stringValue:
|
case stringValue:
|
||||||
{
|
{
|
||||||
// Is NULL is possible for value.string_?
|
// Is NULL possible for value.string_?
|
||||||
char const* str;
|
char const* str;
|
||||||
char const* end;
|
char const* end;
|
||||||
bool ok = value.getString(&str, &end);
|
bool ok = value.getString(&str, &end);
|
||||||
@@ -592,8 +605,15 @@ void StyledStreamWriter::writeValue(const Value& value) {
|
|||||||
pushValue(valueToString(value.asDouble()));
|
pushValue(valueToString(value.asDouble()));
|
||||||
break;
|
break;
|
||||||
case stringValue:
|
case stringValue:
|
||||||
pushValue(valueToQuotedString(value.asCString()));
|
{
|
||||||
|
// Is NULL possible for value.string_?
|
||||||
|
char const* str;
|
||||||
|
char const* end;
|
||||||
|
bool ok = value.getString(&str, &end);
|
||||||
|
if (ok) pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end-str)));
|
||||||
|
else pushValue("");
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case booleanValue:
|
case booleanValue:
|
||||||
pushValue(valueToString(value.asBool()));
|
pushValue(valueToString(value.asBool()));
|
||||||
break;
|
break;
|
||||||
|
@@ -1498,6 +1498,25 @@ 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);
|
||||||
@@ -1523,7 +1542,7 @@ JSONTEST_FIXTURE(ValueTest, StaticString) {
|
|||||||
|
|
||||||
JSONTEST_FIXTURE(ValueTest, CommentBefore) {
|
JSONTEST_FIXTURE(ValueTest, CommentBefore) {
|
||||||
Json::Value val; // fill val
|
Json::Value val; // fill val
|
||||||
val.setComment(std::string("// this comment should appear before"), Json::commentBefore);
|
val.setComment("// this comment should appear before", Json::commentBefore);
|
||||||
Json::StreamWriterBuilder wbuilder;
|
Json::StreamWriterBuilder wbuilder;
|
||||||
wbuilder.settings_["commentStyle"] = "All";
|
wbuilder.settings_["commentStyle"] = "All";
|
||||||
{
|
{
|
||||||
@@ -1618,6 +1637,17 @@ 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) {
|
||||||
@@ -1659,6 +1689,7 @@ 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) {
|
||||||
@@ -1670,6 +1701,25 @@ 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) {
|
||||||
@@ -1680,6 +1730,13 @@ 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) {
|
||||||
@@ -1690,6 +1747,13 @@ 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) {
|
||||||
@@ -1700,6 +1764,12 @@ 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 {};
|
||||||
@@ -2268,6 +2338,7 @@ 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);
|
||||||
@@ -2275,6 +2346,7 @@ 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);
|
||||||
|
|
||||||
|
@@ -1,4 +1,10 @@
|
|||||||
# removes all files created during testing
|
# Copyright 2007 Baptiste Lepilleur
|
||||||
|
# Distributed under MIT license, or public domain if desired and
|
||||||
|
# recognized in your jurisdiction.
|
||||||
|
# See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
|
|
||||||
|
"""Removes all files created during testing."""
|
||||||
|
|
||||||
import glob
|
import glob
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
@@ -1,3 +1,8 @@
|
|||||||
|
# Copyright 2007 Baptiste Lepilleur
|
||||||
|
# Distributed under MIT license, or public domain if desired and
|
||||||
|
# recognized in your jurisdiction.
|
||||||
|
# See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
|
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
import glob
|
import glob
|
||||||
import os.path
|
import os.path
|
||||||
|
@@ -1,4 +1,11 @@
|
|||||||
# Simple implementation of a json test runner to run the test against json-py.
|
# Copyright 2007 Baptiste Lepilleur
|
||||||
|
# Distributed under MIT license, or public domain if desired and
|
||||||
|
# recognized in your jurisdiction.
|
||||||
|
# See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
|
|
||||||
|
"""Simple implementation of a json test runner to run the test against
|
||||||
|
json-py."""
|
||||||
|
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
import sys
|
import sys
|
||||||
import os.path
|
import os.path
|
||||||
|
@@ -1,3 +1,8 @@
|
|||||||
|
# Copyright 2007 Baptiste Lepilleur
|
||||||
|
# Distributed under MIT license, or public domain if desired and
|
||||||
|
# recognized in your jurisdiction.
|
||||||
|
# See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
|
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
from io import open
|
from io import open
|
||||||
|
@@ -1,3 +1,8 @@
|
|||||||
|
# Copyright 2009 Baptiste Lepilleur
|
||||||
|
# Distributed under MIT license, or public domain if desired and
|
||||||
|
# recognized in your jurisdiction.
|
||||||
|
# See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
|
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
from io import open
|
from io import open
|
||||||
|
Reference in New Issue
Block a user