# 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: pyenv install 3.5.4 && pyenv global 3.5.4
install:
- if [[ $TRAVIS_OS_NAME == osx ]]; then
brew update;
#SET( JSONCPP_VERSION_MAJOR X )
#SET( JSONCPP_VERSION_MINOR Y )
#SET( JSONCPP_VERSION_PATCH Z )
-SET( JSONCPP_VERSION 1.8.3 )
+SET( JSONCPP_VERSION 1.8.4 )
jsoncpp_parse_version( ${JSONCPP_VERSION} JSONCPP_VERSION )
#IF(NOT JSONCPP_VERSION_FOUND)
# MESSAGE(FATAL_ERROR "Failed to parse version string properly. Expect X.Y.Z")
Thanks to David Seifert (@SoapGentoo), we (the maintainers) now use [meson](http://mesonbuild.com/) and [ninja](https://ninja-build.org/) to build for debugging, as well as for continuous integration (see [`travis.sh`](travis.sh) ). Other systems may work, but minor things like version strings might break.
First, install both meson (which requires Python3) and ninja.
+If you wish to install to a directory other than /usr/local, set an environment variable called DESTDIR with the desired path:
+ DESTDIR=/path/to/install/dir
Then,
cd jsoncpp/
- BUILD_TYPE=shared
- #BUILD_TYPE=static
- LIB_TYPE=debug
- #LIB_TYPE=release
+ BUILD_TYPE=debug
+ #BUILD_TYPE=release
+ LIB_TYPE=shared
+ #LIB_TYPE=static
meson --buildtype ${BUILD_TYPE} --default-library ${LIB_TYPE} . build-${LIB_TYPE}
ninja -v -C build-${LIB_TYPE} test
+ cd build-${LIB_TYPE}
+ sudo ninja install
### Building and testing with other build systems
See https://github.com/open-source-parsers/jsoncpp/wiki/Building
-"""Amalgate json-cpp library sources into a single source and header file.
+"""Amalgamate json-cpp library sources into a single source and header file.
Works with python2.6+ and python3.4+.
Example of invocation (must be invoked from json-cpp top directory):
-python amalgate.py
+python amalgamate.py
"""
import os
import os.path
def amalgamate_source(source_top_dir=None,
target_source_path=None,
header_include_path=None):
- """Produces amalgated source.
+ """Produces amalgamated source.
Parameters:
source_top_dir: top-directory
target_source_path: output .cpp path
header_include_path: generated header path relative to target_source_path.
"""
- print("Amalgating header...")
+ print("Amalgamating header...")
header = AmalgamationFile(source_top_dir)
- header.add_text("/// Json-cpp amalgated header (http://jsoncpp.sourceforge.net/).")
+ header.add_text("/// Json-cpp amalgamated header (http://jsoncpp.sourceforge.net/).")
header.add_text('/// It is intended to be used with #include "%s"' % header_include_path)
header.add_file("LICENSE", wrap_in_comment=True)
- header.add_text("#ifndef JSON_AMALGATED_H_INCLUDED")
- header.add_text("# define JSON_AMALGATED_H_INCLUDED")
- header.add_text("/// If defined, indicates that the source file is amalgated")
+ header.add_text("#ifndef JSON_AMALGAMATED_H_INCLUDED")
+ header.add_text("# define JSON_AMALGAMATED_H_INCLUDED")
+ header.add_text("/// If defined, indicates that the source file is amalgamated")
header.add_text("/// to prevent private header inclusion.")
header.add_text("#define JSON_IS_AMALGAMATION")
header.add_file("include/json/version.h")
header.add_file("include/json/reader.h")
header.add_file("include/json/writer.h")
header.add_file("include/json/assertions.h")
- header.add_text("#endif //ifndef JSON_AMALGATED_H_INCLUDED")
+ header.add_text("#endif //ifndef JSON_AMALGAMATED_H_INCLUDED")
target_header_path = os.path.join(os.path.dirname(target_source_path), header_include_path)
- print("Writing amalgated header to %r" % target_header_path)
+ print("Writing amalgamated header to %r" % target_header_path)
header.write_to(target_header_path)
base, ext = os.path.splitext(header_include_path)
forward_header_include_path = base + "-forwards" + ext
- print("Amalgating forward header...")
+ print("Amalgamating forward header...")
header = AmalgamationFile(source_top_dir)
- header.add_text("/// Json-cpp amalgated forward header (http://jsoncpp.sourceforge.net/).")
+ header.add_text("/// Json-cpp amalgamated forward header (http://jsoncpp.sourceforge.net/).")
header.add_text('/// It is intended to be used with #include "%s"' % forward_header_include_path)
header.add_text("/// This header provides forward declaration for all JsonCpp types.")
header.add_file("LICENSE", wrap_in_comment=True)
- header.add_text("#ifndef JSON_FORWARD_AMALGATED_H_INCLUDED")
- header.add_text("# define JSON_FORWARD_AMALGATED_H_INCLUDED")
- header.add_text("/// If defined, indicates that the source file is amalgated")
+ header.add_text("#ifndef JSON_FORWARD_AMALGAMATED_H_INCLUDED")
+ header.add_text("# define JSON_FORWARD_AMALGAMATED_H_INCLUDED")
+ header.add_text("/// If defined, indicates that the source file is amalgamated")
header.add_text("/// to prevent private header inclusion.")
header.add_text("#define JSON_IS_AMALGAMATION")
header.add_file("include/json/config.h")
header.add_file("include/json/forwards.h")
- header.add_text("#endif //ifndef JSON_FORWARD_AMALGATED_H_INCLUDED")
+ header.add_text("#endif //ifndef JSON_FORWARD_AMALGAMATED_H_INCLUDED")
target_forward_header_path = os.path.join(os.path.dirname(target_source_path),
forward_header_include_path)
- print("Writing amalgated forward header to %r" % target_forward_header_path)
+ print("Writing amalgamated forward header to %r" % target_forward_header_path)
header.write_to(target_forward_header_path)
- print("Amalgating source...")
+ print("Amalgamating source...")
source = AmalgamationFile(source_top_dir)
- source.add_text("/// Json-cpp amalgated source (http://jsoncpp.sourceforge.net/).")
+ source.add_text("/// Json-cpp amalgamated source (http://jsoncpp.sourceforge.net/).")
source.add_text('/// It is intended to be used with #include "%s"' % header_include_path)
source.add_file("LICENSE", wrap_in_comment=True)
source.add_text("")
source.add_file(os.path.join(lib_json, "json_value.cpp"))
source.add_file(os.path.join(lib_json, "json_writer.cpp"))
- print("Writing amalgated source to %r" % target_source_path)
+ print("Writing amalgamated source to %r" % target_source_path)
source.write_to(target_source_path)
def main():
usage = """%prog [options]
-Generate a single amalgated source and header file from the sources.
+Generate a single amalgamated source and header file from the sources.
"""
from optparse import OptionParser
parser = OptionParser(usage=usage)
parser.add_option("-s", "--source", dest="target_source_path", action="store", default="dist/jsoncpp.cpp",
help="""Output .cpp source path. [Default: %default]""")
parser.add_option("-i", "--include", dest="header_include_path", action="store", default="json/json.h",
- help="""Header include path. Used to include the header from the amalgated source file. [Default: %default]""")
+ help="""Header include path. Used to include the header from the amalgamated source file. [Default: %default]""")
parser.add_option("-t", "--top-dir", dest="top_dir", action="store", default=os.getcwd(),
help="""Source top-directory. [Default: %default]""")
parser.enable_interspersed_args()
sys.stderr.write(msg + "\n")
sys.exit(1)
else:
- print("Source succesfully amalagated")
+ print("Source successfully amalgamated")
if __name__ == "__main__":
main()
curl https://github.com/open-source-parsers/jsoncpp/archive/$*.tar.gz -o $@
dox:
python doxybuild.py --doxygen=$$(which doxygen) --in doc/web_doxyfile.in
- rsync -va --delete dist/doxygen/jsoncpp-api-html-${VER}/ ../jsoncpp-docs/doxygen/
+ rsync -va -c --delete dist/doxygen/jsoncpp-api-html-${VER}/ ../jsoncpp-docs/doxygen/
# Then 'git add -A' and 'git push' in jsoncpp-docs.
build:
mkdir -p build/debug
# parses. With this tag you can assign which parser to use for a given
# extension. Doxygen has a built-in mapping, but you can override or extend it
# using this tag. The format is ext=language, where ext is a file extension, and
-# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
+# language is one of the parsers supported by doxygen: IDL, Java, JavaScript,
# C#, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL. For instance to make
# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C
# (default is Fortran), use: inc=Fortran f=C.
# classes, structs, unions or interfaces.
# The default value is: YES.
-ALPHABETICAL_INDEX = NO
+ALPHABETICAL_INDEX = YES
+TOC_INCLUDE_HEADINGS = 2
# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
# which the alphabetical index list will be split.
FORMULA_TRANSPARENT = YES
# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
-# http://www.mathjax.org) which uses client side Javascript for the rendering
+# http://www.mathjax.org) which uses client side JavaScript for the rendering
# instead of using prerendered bitmaps. Use this if you do not have LaTeX
# installed or if you want to formulas look prettier in the HTML output. When
# enabled you may also need to install MathJax separately and configure the path
SEARCHENGINE = NO
# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
-# implemented using a web server instead of a web client using Javascript. There
+# implemented using a web server instead of a web client using JavaScript. There
# are two flavours of web server based searching depending on the
# EXTERNAL_SEARCH setting. When disabled, doxygen will generate a PHP script for
# searching and an index file used by the script. When EXTERNAL_SEARCH is
EXPAND_AS_DEFINED =
# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
-# remove all refrences to function-like macros that are alone on a line, have an
+# remove all references to function-like macros that are alone on a line, have an
# all uppercase name, and do not end with a semicolon. Such function macros are
# typically used for boiler-plate code, and will confuse the parser if not
# removed.
-<hr>
-</body>
+<!-- HTML footer for doxygen 1.8.13-->
+<!-- start footer part -->
+<!--BEGIN GENERATE_TREEVIEW-->
+<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
+ <ul>
+ $navpath
+ <li class="footer">$generatedby
+ <a href="http://www.doxygen.org/index.html">
+ <img class="footer" src="$relpath^doxygen.png" alt="doxygen"/></a> $doxygenversion </li>
+ </ul>
+</div>
+<!--END GENERATE_TREEVIEW-->
+<!--BEGIN !GENERATE_TREEVIEW-->
+<hr class="footer"/><address class="footer"><small>
+$generatedby  <a href="http://www.doxygen.org/index.html">
+<img class="footer" src="$relpath^doxygen.png" alt="doxygen"/>
+</a> $doxygenversion
+</small></address>
+<!--END !GENERATE_TREEVIEW-->
+</body>
</html>
-<html>
+<!-- HTML header for doxygen 1.8.13-->
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
<head>
-<title>
-JsonCpp - JSON data format manipulation library
-</title>
-<link href="doxygen.css" rel="stylesheet" type="text/css">
-<link href="tabs.css" rel="stylesheet" type="text/css">
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen $doxygenversion"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<link href="$relpath^tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="$relpath^jquery.js"></script>
+<script type="text/javascript" src="$relpath^dynsections.js"></script>
+$treeview
+$search
+$mathjax
+<link href="$relpath^$stylesheet" rel="stylesheet" type="text/css" />
+$extrastylesheet
</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
-<body bgcolor="#ffffff">
+<!--BEGIN TITLEAREA-->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <!--BEGIN PROJECT_LOGO-->
+ <td id="projectlogo"><img alt="Logo" src="$relpath^$projectlogo"/></td>
+ <!--END PROJECT_LOGO-->
+ <!--BEGIN DISABLE_INDEX-->
+ <!--BEGIN SEARCHENGINE-->
+ <td>$searchbox</td>
+ <!--END SEARCHENGINE-->
+ <!--END DISABLE_INDEX-->
+ </tr>
+ </tbody>
+</table>
+</div>
+<!--END TITLEAREA-->
+<body bgcolor="#ffffff">
<table width="100%">
<tr>
- <td width="40%" align="left" valign="center">
+ <td width="30%" align="left" valign="center">
<a href="https://github.com/open-source-parsers/jsoncpp">
JsonCpp project page
</a>
</td>
- <td width="40%" align="right" valign="center">
+ <td width="20%" align="center" valign="center">
+ <a href="hierarchy.html">
+ Classes
+ </a>
+ </td>
+ <td width="20%" align="center" valign="center">
+ <a href="namespace_json.html">
+ Namespace
+ </a>
+ </td>
+ <td width="30%" align="right" valign="center">
<a href="http://open-source-parsers.github.io/jsoncpp-docs/doxygen/">JsonCpp home page</a>
</td>
</tr>
</table>
<hr>
+<!-- end header part -->
# for a project that appears at the top of each page and should give viewer a
# quick idea about the purpose of the project. Keep the description short.
-PROJECT_BRIEF =
+PROJECT_BRIEF = "JSON data format manipulation library"
# With the PROJECT_LOGO tag one can specify an logo or icon that is included in
# the documentation. The maximum height of the logo should not exceed 55 pixels
# parses. With this tag you can assign which parser to use for a given
# extension. Doxygen has a built-in mapping, but you can override or extend it
# using this tag. The format is ext=language, where ext is a file extension, and
-# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
+# language is one of the parsers supported by doxygen: IDL, Java, JavaScript,
# C#, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL. For instance to make
# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C
# (default is Fortran), use: inc=Fortran f=C.
# classes, structs, unions or interfaces.
# The default value is: YES.
-ALPHABETICAL_INDEX = NO
+ALPHABETICAL_INDEX = YES
+TOC_INCLUDE_HEADINGS = 2
# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
# which the alphabetical index list will be split.
# The default value is: YES.
# This tag requires that the tag GENERATE_HTML is set to YES.
-HTML_TIMESTAMP = YES
+HTML_TIMESTAMP = NO
# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
# documentation will contain sections that can be hidden and shown after the
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
-GENERATE_TREEVIEW = NO
+GENERATE_TREEVIEW = YES
# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
# doxygen will group on one line in the generated HTML documentation.
FORMULA_TRANSPARENT = YES
# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
-# http://www.mathjax.org) which uses client side Javascript for the rendering
+# http://www.mathjax.org) which uses client side JavaScript for the rendering
# instead of using prerendered bitmaps. Use this if you do not have LaTeX
# installed or if you want to formulas look prettier in the HTML output. When
# enabled you may also need to install MathJax separately and configure the path
SEARCHENGINE = NO
# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
-# implemented using a web server instead of a web client using Javascript. There
+# implemented using a web server instead of a web client using JavaScript. There
# are two flavours of web server based searching depending on the
# EXTERNAL_SEARCH setting. When disabled, doxygen will generate a PHP script for
# searching and an index file used by the script. When EXTERNAL_SEARCH is
XML_OUTPUT = xml
-# The XML_SCHEMA tag can be used to specify a XML schema, which can be used by a
-# validating XML parser to check the syntax of the XML files.
-# This tag requires that the tag GENERATE_XML is set to YES.
-
-XML_SCHEMA =
-
-# The XML_DTD tag can be used to specify a XML DTD, which can be used by a
-# validating XML parser to check the syntax of the XML files.
-# This tag requires that the tag GENERATE_XML is set to YES.
-
-XML_DTD =
-
# If the XML_PROGRAMLISTING tag is set to YES doxygen will dump the program
# listings (including syntax highlighting and cross-referencing information) to
# the XML output. Note that enabling this will significantly increase the size
EXPAND_AS_DEFINED =
# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
-# remove all refrences to function-like macros that are alone on a line, have an
+# remove all references to function-like macros that are alone on a line, have an
# all uppercase name, and do not end with a semicolon. Such function macros are
# typically used for boiler-plate code, and will confuse the parser if not
# removed.
def main():
usage = """%prog
Generates doxygen documentation in build/doxygen.
- Optionaly makes a tarball of the documentation to dist/.
+ Optionally makes a tarball of the documentation to dist/.
Must be started in the project top directory.
"""
#define JSON_USE_EXCEPTION 1
#endif
-/// If defined, indicates that the source file is amalgated
+/// If defined, indicates that the source file is amalgamated
/// to prevent private header inclusion.
-/// Remarks: it is automatically defined in the generated amalgated header.
+/// Remarks: it is automatically defined in the generated amalgamated header.
// #define JSON_IS_AMALGAMATION
#ifdef JSON_IN_CPPTL
#endif // defined(_MSC_VER)
-// In c++11 the override keyword allows you to explicity define that a function
+// In c++11 the override keyword allows you to explicitly define that a function
// is intended to override the base-class version. This makes the code more
// managable and fixes a set of common hard-to-find bugs.
#if __cplusplus >= 201103L
/** \brief Lightweight wrapper to tag static string.
*
- * Value constructor and objectValue member assignement takes advantage of the
+ * Value constructor and objectValue member assignment takes advantage of the
* StaticString and avoid the cost of string duplication when storing the
* string or the member name.
*
typedef Json::LargestUInt LargestUInt;
typedef Json::ArrayIndex ArrayIndex;
+ // Required for boost integration, e. g. BOOST_TEST
+ typedef std::string value_type;
+
static const Value& null; ///< We regret this reference to a global instance; prefer the simpler Value().
static const Value& nullRef; ///< just a kludge for binary-compatibility; same as null
static Value const& nullSingleton(); ///< Prefer this to null or nullRef.
/// otherwise, false.
bool empty() const;
- /// Return isNull()
- bool operator!() const;
+ /// Return !isNull()
+ explicit operator bool() const;
/// Remove all object members and array elements.
/// \pre type() is arrayValue, objectValue, or nullValue
/// \pre type() is objectValue or nullValue
/// \post type() is unchanged
/// \deprecated
- JSONCPP_DEPRECATED("")
- Value removeMember(const char* key);
+ void removeMember(const char* key);
/// Same as removeMember(const char*)
/// \param key may contain embedded nulls.
/// \deprecated
- JSONCPP_DEPRECATED("")
- Value removeMember(const JSONCPP_STRING& key);
+ void removeMember(const JSONCPP_STRING& key);
/// Same as removeMember(const char* begin, const char* end, Value* removed),
/// but 'key' is null-terminated.
bool removeMember(const char* key, Value* removed);
#ifndef JSON_VERSION_H_INCLUDED
# define JSON_VERSION_H_INCLUDED
-# define JSONCPP_VERSION_STRING "1.8.3"
+# define JSONCPP_VERSION_STRING "1.8.4"
# define JSONCPP_VERSION_MAJOR 1
# define JSONCPP_VERSION_MINOR 8
-# define JSONCPP_VERSION_PATCH 3
+# define JSONCPP_VERSION_PATCH 4
# define JSONCPP_VERSION_QUALIFIER
# define JSONCPP_VERSION_HEXA ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | (JSONCPP_VERSION_PATCH << 8))
// Disable warning C4251: <data member>: <type> needs to have dll-interface to
// be used by...
-#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) && defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable : 4251)
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
- "dropNullPlaceholders": false or true
- 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
+ fed to a browser's JavaScript, it makes for smaller output and the
browser can handle the output just fine.
- "useSpecialFloats": false or true
- If true, outputs non-finite floating point values in the following way:
* \sa Reader, Value
* \deprecated Use StreamWriterBuilder.
*/
+#if defined(_MSC_VER)
+#pragma warning(push)
+#pragma warning(disable:4996) // Deriving from deprecated class
+#endif
class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API FastWriter : public Writer {
-
public:
FastWriter();
~FastWriter() JSONCPP_OVERRIDE {}
/** \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
+ * fed to a browser's JavaScript, it makes for smaller output and the
* browser can handle the output just fine.
*/
void dropNullPlaceholders();
void writeValue(const Value& value);
JSONCPP_STRING document_;
- bool yamlCompatiblityEnabled_;
+ bool yamlCompatibilityEnabled_;
bool dropNullPlaceholders_;
bool omitEndingLineFeed_;
};
+#if defined(_MSC_VER)
+#pragma warning(pop)
+#endif
/** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a
*human friendly way.
* \sa Reader, Value, Value::setComment()
* \deprecated Use StreamWriterBuilder.
*/
+#if defined(_MSC_VER)
+#pragma warning(push)
+#pragma warning(disable:4996) // Deriving from deprecated class
+#endif
class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API StyledWriter : public Writer {
public:
StyledWriter();
private:
void writeValue(const Value& value);
void writeArrayValue(const Value& value);
- bool isMultineArray(const Value& value);
+ bool isMultilineArray(const Value& value);
void pushValue(const JSONCPP_STRING& value);
void writeIndent();
void writeWithIndent(const JSONCPP_STRING& value);
unsigned int indentSize_;
bool addChildValues_;
};
+#if defined(_MSC_VER)
+#pragma warning(pop)
+#endif
/** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a
human friendly way,
* \sa Reader, Value, Value::setComment()
* \deprecated Use StreamWriterBuilder.
*/
+#if defined(_MSC_VER)
+#pragma warning(push)
+#pragma warning(disable:4996) // Deriving from deprecated class
+#endif
class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API StyledStreamWriter {
public:
/**
private:
void writeValue(const Value& value);
void writeArrayValue(const Value& value);
- bool isMultineArray(const Value& value);
+ bool isMultilineArray(const Value& value);
void pushValue(const JSONCPP_STRING& value);
void writeIndent();
void writeWithIndent(const JSONCPP_STRING& value);
bool addChildValues_ : 1;
bool indented_ : 1;
};
+#if defined(_MSC_VER)
+#pragma warning(pop)
+#endif
#if defined(JSON_HAS_INT64)
JSONCPP_STRING JSON_API valueToString(Int value);
Must be started in the project top directory.
-Warning: --force should only be used when developping/testing the release script.
+Warning: --force should only be used when developing/testing the release script.
"""
from optparse import OptionParser
parser = OptionParser(usage=usage)
user=options.user, sftp=options.sftp)
print('Source and doc release tarballs uploaded')
else:
- print('No upload user specified. Web site and download tarbal were not uploaded.')
+ print('No upload user specified. Web site and download tarball were not uploaded.')
print('Tarball can be found at:', doc_tarball_path)
# Set next version number and commit
project(
'jsoncpp',
'cpp',
- version : '1.8.3',
+ version : '1.8.4',
default_options : [
'buildtype=release',
'warning_level=1'],
jsoncpp_cdata.set('JSONCPP_VERSION_MAJOR', jsoncpp_major_version)
jsoncpp_cdata.set('JSONCPP_VERSION_MINOR', jsoncpp_minor_version)
jsoncpp_cdata.set('JSONCPP_VERSION_PATCH', jsoncpp_patch_version)
+jsoncpp_cdata.set('JSONCPP_USE_SECURE_MEMORY',0)
jsoncpp_gen_sources = configure_file(
input : 'src/lib_json/version.h.in',
'src/lib_json/json_reader.cpp',
'src/lib_json/json_value.cpp',
'src/lib_json/json_writer.cpp'],
- soversion : 19,
+ soversion : 20,
install : true,
include_directories : jsoncpp_include_directories)
description : 'A C++ library for interacting with JSON')
# for libraries bundling jsoncpp
-declare_dependency(
+jsoncpp_dep = declare_dependency(
include_directories : jsoncpp_include_directories,
link_with : jsoncpp_lib,
version : meson.project_version(),
// recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+#if defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#elif defined(_MSC_VER)
+#pragma warning(disable : 4996)
+#endif
/* This executable is used for testing parser/writer using real JSON files.
*/
#include <sstream>
#include <stdio.h>
-#if defined(_MSC_VER) && _MSC_VER >= 1310
-#pragma warning(disable : 4996) // disable fopen deprecation warning
-#endif
-
struct Options
{
JSONCPP_STRING path;
}
}
+#if defined(__GNUC__)
#pragma GCC diagnostic pop
+#endif
token.type_ = tokenString;
ok = readStringSingleQuote();
break;
- } // else continue
+ } // else fall through
case '/':
token.type_ = tokenComment;
ok = readComment();
JSONCPP_STRING errs;
bool ok = parseFromStream(b, sin, &root, &errs);
if (!ok) {
- fprintf(stderr,
- "Error from reader: %s",
- errs.c_str());
-
throwRuntimeError(errs);
}
return sin;
return result;
}
-/// Returns true if ch is a control character (in range [1,31]).
-static inline bool isControlCharacter(char ch) { return ch > 0 && ch <= 0x1F; }
-
enum {
/// Constant that specify the size of the buffer that must be passed to
/// uintToString.
typedef char UIntToStringBuffer[uintToStringBufferSize];
/** Converts an unsigned integer to string.
- * @param value Unsigned interger to convert to string
+ * @param value Unsigned integer to convert to string
* @param current Input/Output string buffer.
* Must have at least uintToStringBufferSize chars free.
*/
return false;
}
-bool Value::operator!() const { return isNull(); }
+Value::operator bool() const { return ! isNull(); }
void Value::clear() {
JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue ||
Value& Value::append(const Value& value) { return (*this)[size()] = value; }
#if JSON_HAS_RVALUE_REFERENCES
- Value& Value::append(Value&& value) { return (*this)[size()] = value; }
+ Value& Value::append(Value&& value) { return (*this)[size()] = std::move(value); }
#endif
Value Value::get(char const* key, char const* cend, Value const& defaultValue) const
{
return removeMember(key.data(), key.data() + key.length(), removed);
}
-Value Value::removeMember(const char* key)
+void Value::removeMember(const char* key)
{
JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == objectValue,
"in Json::Value::removeMember(): requires objectValue");
if (type_ == nullValue)
- return nullSingleton();
+ return;
- Value removed; // null
- removeMember(key, key + strlen(key), &removed);
- return removed; // still null if removeMember() did nothing
+ CZString actualKey(key, unsigned(strlen(key)), CZString::noDuplication);
+ value_.map_->erase(actualKey);
}
-Value Value::removeMember(const JSONCPP_STRING& key)
+void Value::removeMember(const JSONCPP_STRING& key)
{
- return removeMember(key.c_str());
+ removeMember(key.c_str());
}
bool Value::removeIndex(ArrayIndex index, Value* removed) {
typedef std::auto_ptr<StreamWriter> StreamWriterPtr;
#endif
-static bool containsControlCharacter(const char* str) {
- while (*str) {
- if (isControlCharacter(*(str++)))
- return true;
- }
- return false;
-}
-
-static bool containsControlCharacter0(const char* str, unsigned len) {
- char const* end = str + len;
- while (end != str) {
- if (isControlCharacter(*str) || 0==*str)
- return true;
- ++str;
- }
- return false;
-}
-
JSONCPP_STRING valueToString(LargestInt value) {
UIntToStringBuffer buffer;
char* current = buffer + sizeof(buffer);
int len = -1;
char formatString[15];
- snprintf(formatString, sizeof(formatString), "%%.%dg", precision);
+ snprintf(formatString, sizeof(formatString), "%%.%ug", precision);
// Print into the buffer. We need not request the alternative representation
- // that always has a decimal point because JSON doesn't distingish the
+ // that always has a decimal point because JSON doesn't distinguish the
// concepts of reals and integers.
if (isfinite(value)) {
len = snprintf(buffer, sizeof(buffer), formatString, value);
JSONCPP_STRING valueToString(bool value) { return value ? "true" : "false"; }
-JSONCPP_STRING valueToQuotedString(const char* value) {
- if (value == NULL)
- return "";
- // Not sure how to handle unicode...
- if (strpbrk(value, "\"\\\b\f\n\r\t") == NULL &&
- !containsControlCharacter(value))
- return JSONCPP_STRING("\"") + value + "\"";
- // We have to walk value and escape any special characters.
- // Appending to JSONCPP_STRING is not efficient, but this should be rare.
- // (Note: forward slashes are *not* rare, but I am not escaping them.)
- JSONCPP_STRING::size_type maxsize =
- strlen(value) * 2 + 3; // allescaped+quotes+NULL
- JSONCPP_STRING result;
- result.reserve(maxsize); // to avoid lots of mallocs
- result += "\"";
- for (const char* c = value; *c != 0; ++c) {
- switch (*c) {
- case '\"':
- result += "\\\"";
- break;
- case '\\':
- result += "\\\\";
- break;
- case '\b':
- result += "\\b";
- break;
- case '\f':
- result += "\\f";
- break;
- case '\n':
- result += "\\n";
- break;
- case '\r':
- result += "\\r";
- break;
- case '\t':
- result += "\\t";
- break;
- // case '/':
- // Even though \/ is considered a legal escape in JSON, a bare
- // slash is also legal, so I see no reason to escape it.
- // (I hope I am not misunderstanding something.
- // blep notes: actually escaping \/ may be useful in javascript to avoid </
- // sequence.
- // Should add a flag to allow this compatibility mode and prevent this
- // sequence from occurring.
- default:
- if (isControlCharacter(*c)) {
- JSONCPP_OSTRINGSTREAM oss;
- oss << "\\u" << std::hex << std::uppercase << std::setfill('0')
- << std::setw(4) << static_cast<int>(*c);
- result += oss.str();
- } else {
- result += *c;
- }
- break;
- }
+static bool isAnyCharRequiredQuoting(char const* s, size_t n) {
+ assert(s || !n);
+
+ char const* const end = s + n;
+ for (char const* cur = s; cur < end; ++cur) {
+ if (*cur == '\\' || *cur == '\"' || *cur < ' '
+ || static_cast<unsigned char>(*cur) < 0x80)
+ return true;
}
- result += "\"";
- return result;
+ return false;
}
-// https://github.com/upcaste/upcaste/blob/master/src/upcore/src/cstring/strnpbrk.cpp
-static char const* strnpbrk(char const* s, char const* accept, size_t n) {
- assert((s || !n) && accept);
+static unsigned int utf8ToCodepoint(const char*& s, const char* e) {
+ const unsigned int REPLACEMENT_CHARACTER = 0xFFFD;
- char const* const end = s + n;
- for (char const* cur = s; cur < end; ++cur) {
- int const c = *cur;
- for (char const* a = accept; *a; ++a) {
- if (*a == c) {
- return cur;
- }
- }
+ unsigned int firstByte = static_cast<unsigned char>(*s);
+
+ if (firstByte < 0x80)
+ return firstByte;
+
+ if (firstByte < 0xE0) {
+ if (e - s < 2)
+ return REPLACEMENT_CHARACTER;
+
+ unsigned int calculated = ((firstByte & 0x1F) << 6)
+ | (static_cast<unsigned int>(s[1]) & 0x3F);
+ s += 1;
+ // oversized encoded characters are invalid
+ return calculated < 0x80 ? REPLACEMENT_CHARACTER : calculated;
}
- return NULL;
+
+ if (firstByte < 0xF0) {
+ if (e - s < 3)
+ return REPLACEMENT_CHARACTER;
+
+ unsigned int calculated = ((firstByte & 0x0F) << 12)
+ | ((static_cast<unsigned int>(s[1]) & 0x3F) << 6)
+ | (static_cast<unsigned int>(s[2]) & 0x3F);
+ s += 2;
+ // surrogates aren't valid codepoints itself
+ // shouldn't be UTF-8 encoded
+ if (calculated >= 0xD800 && calculated <= 0xDFFF)
+ return REPLACEMENT_CHARACTER;
+ // oversized encoded characters are invalid
+ return calculated < 0x800 ? REPLACEMENT_CHARACTER : calculated;
+ }
+
+ if (firstByte < 0xF8) {
+ if (e - s < 4)
+ return REPLACEMENT_CHARACTER;
+
+ unsigned int calculated = ((firstByte & 0x07) << 24)
+ | ((static_cast<unsigned int>(s[1]) & 0x3F) << 12)
+ | ((static_cast<unsigned int>(s[2]) & 0x3F) << 6)
+ | (static_cast<unsigned int>(s[3]) & 0x3F);
+ s += 3;
+ // oversized encoded characters are invalid
+ return calculated < 0x10000 ? REPLACEMENT_CHARACTER : calculated;
+ }
+
+ return REPLACEMENT_CHARACTER;
}
+
+static const char hex2[] =
+ "000102030405060708090a0b0c0d0e0f"
+ "101112131415161718191a1b1c1d1e1f"
+ "202122232425262728292a2b2c2d2e2f"
+ "303132333435363738393a3b3c3d3e3f"
+ "404142434445464748494a4b4c4d4e4f"
+ "505152535455565758595a5b5c5d5e5f"
+ "606162636465666768696a6b6c6d6e6f"
+ "707172737475767778797a7b7c7d7e7f"
+ "808182838485868788898a8b8c8d8e8f"
+ "909192939495969798999a9b9c9d9e9f"
+ "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf"
+ "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
+ "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf"
+ "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf"
+ "e0e1e2e3e4e5e6e7e8e9eaebecedeeef"
+ "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff";
+
+static JSONCPP_STRING toHex16Bit(unsigned int x) {
+ const unsigned int hi = (x >> 8) & 0xff;
+ const unsigned int lo = x & 0xff;
+ JSONCPP_STRING result(4, ' ');
+ result[0] = hex2[2 * hi];
+ result[1] = hex2[2 * hi + 1];
+ result[2] = hex2[2 * lo];
+ result[3] = hex2[2 * lo + 1];
+ return result;
+}
+
static JSONCPP_STRING valueToQuotedStringN(const char* value, unsigned length) {
if (value == NULL)
return "";
- // Not sure how to handle unicode...
- if (strnpbrk(value, "\"\\\b\f\n\r\t", length) == NULL &&
- !containsControlCharacter0(value, length))
+
+ if (!isAnyCharRequiredQuoting(value, length))
return JSONCPP_STRING("\"") + value + "\"";
// We have to walk value and escape any special characters.
// Appending to JSONCPP_STRING is not efficient, but this should be rare.
// sequence.
// Should add a flag to allow this compatibility mode and prevent this
// sequence from occurring.
- default:
- if ((isControlCharacter(*c)) || (*c == 0)) {
- JSONCPP_OSTRINGSTREAM oss;
- oss << "\\u" << std::hex << std::uppercase << std::setfill('0')
- << std::setw(4) << static_cast<int>(*c);
- result += oss.str();
- } else {
- result += *c;
+ default: {
+ unsigned int cp = utf8ToCodepoint(c, end);
+ // don't escape non-control characters
+ // (short escape sequence are applied above)
+ if (cp < 0x80 && cp >= 0x20)
+ result += static_cast<char>(cp);
+ else if (cp < 0x10000) { // codepoint is in Basic Multilingual Plane
+ result += "\\u";
+ result += toHex16Bit(cp);
+ }
+ else { // codepoint is not in Basic Multilingual Plane
+ // convert to surrogate pair first
+ cp -= 0x10000;
+ result += "\\u";
+ result += toHex16Bit((cp >> 10) + 0xD800);
+ result += "\\u";
+ result += toHex16Bit((cp & 0x3FF) + 0xDC00);
+ }
}
break;
}
return result;
}
+JSONCPP_STRING valueToQuotedString(const char* value) {
+ return valueToQuotedStringN(value, static_cast<unsigned int>(strlen(value)));
+}
+
// Class Writer
// //////////////////////////////////////////////////////////////////
Writer::~Writer() {}
// //////////////////////////////////////////////////////////////////
FastWriter::FastWriter()
- : yamlCompatiblityEnabled_(false), dropNullPlaceholders_(false),
+ : yamlCompatibilityEnabled_(false), dropNullPlaceholders_(false),
omitEndingLineFeed_(false) {}
-void FastWriter::enableYAMLCompatibility() { yamlCompatiblityEnabled_ = true; }
+void FastWriter::enableYAMLCompatibility() { yamlCompatibilityEnabled_ = true; }
void FastWriter::dropNullPlaceholders() { dropNullPlaceholders_ = true; }
if (it != members.begin())
document_ += ',';
document_ += valueToQuotedStringN(name.data(), static_cast<unsigned>(name.length()));
- document_ += yamlCompatiblityEnabled_ ? ": " : ":";
+ document_ += yamlCompatibilityEnabled_ ? ": " : ":";
writeValue(value[name]);
}
document_ += '}';
if (size == 0)
pushValue("[]");
else {
- bool isArrayMultiLine = isMultineArray(value);
+ bool isArrayMultiLine = isMultilineArray(value);
if (isArrayMultiLine) {
writeWithIndent("[");
indent();
}
}
-bool StyledWriter::isMultineArray(const Value& value) {
+bool StyledWriter::isMultilineArray(const Value& value) {
ArrayIndex const size = value.size();
bool isMultiLine = size * 3 >= rightMargin_;
childValues_.clear();
if (size == 0)
pushValue("[]");
else {
- bool isArrayMultiLine = isMultineArray(value);
+ bool isArrayMultiLine = isMultilineArray(value);
if (isArrayMultiLine) {
writeWithIndent("[");
indent();
}
}
-bool StyledStreamWriter::isMultineArray(const Value& value) {
+bool StyledStreamWriter::isMultilineArray(const Value& value) {
ArrayIndex const size = value.size();
bool isMultiLine = size * 3 >= rightMargin_;
childValues_.clear();
private:
void writeValue(Value const& value);
void writeArrayValue(Value const& value);
- bool isMultineArray(Value const& value);
+ bool isMultilineArray(Value const& value);
void pushValue(JSONCPP_STRING const& value);
void writeIndent();
void writeWithIndent(JSONCPP_STRING const& value);
if (size == 0)
pushValue("[]");
else {
- bool isMultiLine = (cs_ == CommentStyle::All) || isMultineArray(value);
+ bool isMultiLine = (cs_ == CommentStyle::All) || isMultilineArray(value);
if (isMultiLine) {
writeWithIndent("[");
indent();
}
}
-bool BuiltStyledStreamWriter::isMultineArray(Value const& value) {
+bool BuiltStyledStreamWriter::isMultilineArray(Value const& value) {
ArrayIndex const size = value.size();
bool isMultiLine = size * 3 >= rightMargin_;
childValues_.clear();
_CrtSetReportHook(&msvcrtSilentReportHook);
#endif // if defined(_MSC_VER)
-// @todo investiguate this handler (for buffer overflow)
+// @todo investigate this handler (for buffer overflow)
// _set_security_error_handler
#if defined(_WIN32)
// recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+#if defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#elif defined(_MSC_VER)
+#pragma warning(disable : 4996)
+#endif
#include "jsontest.h"
#include <json/config.h>
JSONTEST_ASSERT_STRING_EQUAL("", null_.asString());
JSONTEST_ASSERT_EQUAL(Json::Value::null, null_);
+
+ // Test using a Value in a boolean context (false iff null)
+ JSONTEST_ASSERT_EQUAL(null_,false);
+ JSONTEST_ASSERT_EQUAL(object1_,true);
+ JSONTEST_ASSERT_EQUAL(!null_,true);
+ JSONTEST_ASSERT_EQUAL(!object1_,false);
}
JSONTEST_FIXTURE(ValueTest, strings) {
}
}
JSONTEST_FIXTURE(CharReaderFailIfExtraTest, issue107) {
- // This is interpretted as an int value followed by a colon.
+ // This is interpreted as an int value followed by a colon.
Json::CharReaderBuilder b;
Json::Value root;
char const doc[] =
return runner.runCommandLine(argc, argv);
}
+#if defined(__GNUC__)
#pragma GCC diagnostic pop
+#endif