mirror of
https://github.com/open-source-parsers/jsoncpp.git
synced 2025-08-04 10:36:23 -04:00
Compare commits
14 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
ca98c98457 | ||
![]() |
037752d9a1 | ||
![]() |
ba004477a6 | ||
![]() |
60ccc1f5de | ||
![]() |
07a8fe6a23 | ||
![]() |
dca8a24cf8 | ||
![]() |
3f86349128 | ||
![]() |
2b3815c90d | ||
![]() |
bd25fc5ea0 | ||
![]() |
8214f717e7 | ||
![]() |
07e3d1b076 | ||
![]() |
871f0cc43b | ||
![]() |
54fc4e28ed | ||
![]() |
76ff1db84d |
4
.gitignore
vendored
4
.gitignore
vendored
@ -55,3 +55,7 @@ compile_commands.json
|
|||||||
|
|
||||||
# temps
|
# temps
|
||||||
/version
|
/version
|
||||||
|
|
||||||
|
# Bazel output paths
|
||||||
|
/bazel-*
|
||||||
|
/MODULE.bazel.lock
|
||||||
|
2
AUTHORS
2
AUTHORS
@ -16,7 +16,7 @@ Baruch Siach <baruch@tkos.co.il>
|
|||||||
Ben Boeckel <mathstuf@gmail.com>
|
Ben Boeckel <mathstuf@gmail.com>
|
||||||
Benjamin Knecht <bknecht@logitech.com>
|
Benjamin Knecht <bknecht@logitech.com>
|
||||||
Bernd Kuhls <bernd.kuhls@t-online.de>
|
Bernd Kuhls <bernd.kuhls@t-online.de>
|
||||||
Billy Donahue <billydonahue@google.com>
|
Billy Donahue <billy.donahue@gmail.com>
|
||||||
Braden McDorman <bmcdorman@gmail.com>
|
Braden McDorman <bmcdorman@gmail.com>
|
||||||
Brandon Myers <bmyers1788@gmail.com>
|
Brandon Myers <bmyers1788@gmail.com>
|
||||||
Brendan Drew <brendan.drew@daqri.com>
|
Brendan Drew <brendan.drew@daqri.com>
|
||||||
|
@ -55,18 +55,19 @@ endif()
|
|||||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||||
|
|
||||||
project(jsoncpp
|
project(jsoncpp
|
||||||
# Note: version must be updated in three places when doing a release. This
|
# Note: version must be updated in four places when doing a release. This
|
||||||
# annoying process ensures that amalgamate, CMake, and meson all report the
|
# annoying process ensures that amalgamate, CMake, and meson all report the
|
||||||
# correct version.
|
# correct version.
|
||||||
# 1. ./meson.build
|
# 1. ./meson.build
|
||||||
# 2. ./include/json/version.h
|
# 2. ./include/json/version.h
|
||||||
# 3. ./CMakeLists.txt
|
# 3. ./CMakeLists.txt
|
||||||
|
# 4. ./MODULE.bazel
|
||||||
# IMPORTANT: also update the PROJECT_SOVERSION!!
|
# IMPORTANT: also update the PROJECT_SOVERSION!!
|
||||||
VERSION 1.9.6 # <major>[.<minor>[.<patch>[.<tweak>]]]
|
VERSION 1.9.7 # <major>[.<minor>[.<patch>[.<tweak>]]]
|
||||||
LANGUAGES CXX)
|
LANGUAGES CXX)
|
||||||
|
|
||||||
message(STATUS "JsonCpp Version: ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
|
message(STATUS "JsonCpp Version: ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
|
||||||
set(PROJECT_SOVERSION 26)
|
set(PROJECT_SOVERSION 27)
|
||||||
|
|
||||||
include(${CMAKE_CURRENT_SOURCE_DIR}/include/PreventInSourceBuilds.cmake)
|
include(${CMAKE_CURRENT_SOURCE_DIR}/include/PreventInSourceBuilds.cmake)
|
||||||
include(${CMAKE_CURRENT_SOURCE_DIR}/include/PreventInBuildInstalls.cmake)
|
include(${CMAKE_CURRENT_SOURCE_DIR}/include/PreventInBuildInstalls.cmake)
|
||||||
@ -93,6 +94,12 @@ if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
|
|||||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" CACHE PATH "Executable/dll output dir.")
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" CACHE PATH "Executable/dll output dir.")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
include(CheckFunctionExists)
|
||||||
|
check_function_exists(memset_s HAVE_MEMSET_S)
|
||||||
|
if(HAVE_MEMSET_S)
|
||||||
|
add_definitions("-DHAVE_MEMSET_S=1")
|
||||||
|
endif()
|
||||||
|
|
||||||
if(JSONCPP_USE_SECURE_MEMORY)
|
if(JSONCPP_USE_SECURE_MEMORY)
|
||||||
add_definitions("-DJSONCPP_USE_SECURE_MEMORY=1")
|
add_definitions("-DJSONCPP_USE_SECURE_MEMORY=1")
|
||||||
endif()
|
endif()
|
||||||
|
14
MODULE.bazel
Normal file
14
MODULE.bazel
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
module(
|
||||||
|
name = "jsoncpp",
|
||||||
|
|
||||||
|
# Note: version must be updated in four places when doing a release. This
|
||||||
|
# annoying process ensures that amalgamate, CMake, and meson all report the
|
||||||
|
# correct version.
|
||||||
|
# 1. /meson.build
|
||||||
|
# 2. /include/json/version.h
|
||||||
|
# 3. /CMakeLists.txt
|
||||||
|
# 4. /MODULE.bazel
|
||||||
|
# IMPORTANT: also update the SOVERSION!!
|
||||||
|
version = "1.9.7",
|
||||||
|
compatibility_level = 1,
|
||||||
|
)
|
@ -9,7 +9,7 @@ import shutil
|
|||||||
import string
|
import string
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import cgi
|
import html
|
||||||
|
|
||||||
class BuildDesc:
|
class BuildDesc:
|
||||||
def __init__(self, prepend_envs=None, variables=None, build_type=None, generator=None):
|
def __init__(self, prepend_envs=None, variables=None, build_type=None, generator=None):
|
||||||
@ -195,12 +195,12 @@ def generate_html_report(html_report_path, builds):
|
|||||||
for variable in variables:
|
for variable in variables:
|
||||||
build_types = sorted(build_types_by_variable[variable])
|
build_types = sorted(build_types_by_variable[variable])
|
||||||
nb_build_type = len(build_types_by_variable[variable])
|
nb_build_type = len(build_types_by_variable[variable])
|
||||||
th_vars.append('<th colspan="%d">%s</th>' % (nb_build_type, cgi.escape(' '.join(variable))))
|
th_vars.append('<th colspan="%d">%s</th>' % (nb_build_type, html.escape(' '.join(variable))))
|
||||||
for build_type in build_types:
|
for build_type in build_types:
|
||||||
th_build_types.append('<th>%s</th>' % cgi.escape(build_type))
|
th_build_types.append('<th>%s</th>' % html.escape(build_type))
|
||||||
tr_builds = []
|
tr_builds = []
|
||||||
for generator in sorted(builds_by_generator):
|
for generator in sorted(builds_by_generator):
|
||||||
tds = [ '<td>%s</td>\n' % cgi.escape(generator) ]
|
tds = [ '<td>%s</td>\n' % html.escape(generator) ]
|
||||||
for variable in variables:
|
for variable in variables:
|
||||||
build_types = sorted(build_types_by_variable[variable])
|
build_types = sorted(build_types_by_variable[variable])
|
||||||
for build_type in build_types:
|
for build_type in build_types:
|
||||||
|
33
example/BUILD.bazel
Normal file
33
example/BUILD.bazel
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
cc_binary(
|
||||||
|
name = "readFromStream_ok",
|
||||||
|
srcs = ["readFromStream/readFromStream.cpp"],
|
||||||
|
deps = ["//:jsoncpp"],
|
||||||
|
args = ["$(location :readFromStream/withComment.json)"],
|
||||||
|
data = ["readFromStream/withComment.json"],
|
||||||
|
)
|
||||||
|
|
||||||
|
cc_binary(
|
||||||
|
name = "readFromStream_err",
|
||||||
|
srcs = ["readFromStream/readFromStream.cpp"],
|
||||||
|
deps = ["//:jsoncpp"],
|
||||||
|
args = ["$(location :readFromStream/errorFormat.json)"],
|
||||||
|
data = ["readFromStream/errorFormat.json"],
|
||||||
|
)
|
||||||
|
|
||||||
|
cc_binary(
|
||||||
|
name = "readFromString",
|
||||||
|
srcs = ["readFromString/readFromString.cpp"],
|
||||||
|
deps = ["//:jsoncpp"],
|
||||||
|
)
|
||||||
|
|
||||||
|
cc_binary(
|
||||||
|
name = "streamWrite",
|
||||||
|
srcs = ["streamWrite/streamWrite.cpp"],
|
||||||
|
deps = ["//:jsoncpp"],
|
||||||
|
)
|
||||||
|
|
||||||
|
cc_binary(
|
||||||
|
name = "stringWrite",
|
||||||
|
srcs = ["stringWrite/stringWrite.cpp"],
|
||||||
|
deps = ["//:jsoncpp"],
|
||||||
|
)
|
@ -6,6 +6,7 @@
|
|||||||
#ifndef JSON_ALLOCATOR_H_INCLUDED
|
#ifndef JSON_ALLOCATOR_H_INCLUDED
|
||||||
#define JSON_ALLOCATOR_H_INCLUDED
|
#define JSON_ALLOCATOR_H_INCLUDED
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
@ -38,8 +39,16 @@ public:
|
|||||||
* The memory block is filled with zeroes before being released.
|
* The memory block is filled with zeroes before being released.
|
||||||
*/
|
*/
|
||||||
void deallocate(pointer p, size_type n) {
|
void deallocate(pointer p, size_type n) {
|
||||||
// memset_s is used because memset may be optimized away by the compiler
|
// These constructs will not be removed by the compiler during optimization,
|
||||||
|
// unlike memset.
|
||||||
|
#if defined(HAVE_MEMSET_S)
|
||||||
memset_s(p, n * sizeof(T), 0, n * sizeof(T));
|
memset_s(p, n * sizeof(T), 0, n * sizeof(T));
|
||||||
|
#elif defined(_WIN32)
|
||||||
|
RtlSecureZeroMemory(p, n * sizeof(T));
|
||||||
|
#else
|
||||||
|
std::fill_n(reinterpret_cast<volatile unsigned char*>(p), n, 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
// free using "global operator delete"
|
// free using "global operator delete"
|
||||||
::operator delete(p);
|
::operator delete(p);
|
||||||
}
|
}
|
||||||
|
@ -127,7 +127,7 @@ using LargestUInt = UInt64;
|
|||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using Allocator =
|
using Allocator =
|
||||||
typename std::conditional<JSONCPP_USING_SECURE_MEMORY, SecureAllocator<T>,
|
typename std::conditional<JSONCPP_USE_SECURE_MEMORY, SecureAllocator<T>,
|
||||||
std::allocator<T>>::type;
|
std::allocator<T>>::type;
|
||||||
using String = std::basic_string<char, std::char_traits<char>, Allocator<char>>;
|
using String = std::basic_string<char, std::char_traits<char>, Allocator<char>>;
|
||||||
using IStringStream =
|
using IStringStream =
|
||||||
|
@ -39,6 +39,10 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if __cplusplus >= 201703L
|
||||||
|
#define JSONCPP_HAS_STRING_VIEW 1
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <map>
|
#include <map>
|
||||||
@ -46,6 +50,10 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#ifdef JSONCPP_HAS_STRING_VIEW
|
||||||
|
#include <string_view>
|
||||||
|
#endif
|
||||||
|
|
||||||
// Disable warning C4251: <data member>: <type> needs to have dll-interface to
|
// Disable warning C4251: <data member>: <type> needs to have dll-interface to
|
||||||
// be used by...
|
// be used by...
|
||||||
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
||||||
@ -342,6 +350,9 @@ public:
|
|||||||
*/
|
*/
|
||||||
Value(const StaticString& value);
|
Value(const StaticString& value);
|
||||||
Value(const String& value);
|
Value(const String& value);
|
||||||
|
#ifdef JSONCPP_HAS_STRING_VIEW
|
||||||
|
Value(std::string_view value);
|
||||||
|
#endif
|
||||||
Value(bool value);
|
Value(bool value);
|
||||||
Value(std::nullptr_t ptr) = delete;
|
Value(std::nullptr_t ptr) = delete;
|
||||||
Value(const Value& other);
|
Value(const Value& other);
|
||||||
@ -375,7 +386,7 @@ public:
|
|||||||
int compare(const Value& other) const;
|
int compare(const Value& other) const;
|
||||||
|
|
||||||
const char* asCString() const; ///< Embedded zeroes could cause you trouble!
|
const char* asCString() const; ///< Embedded zeroes could cause you trouble!
|
||||||
#if JSONCPP_USING_SECURE_MEMORY
|
#if JSONCPP_USE_SECURE_MEMORY
|
||||||
unsigned getCStringLength() const; // Allows you to understand the length of
|
unsigned getCStringLength() const; // Allows you to understand the length of
|
||||||
// the CString
|
// the CString
|
||||||
#endif
|
#endif
|
||||||
@ -384,6 +395,12 @@ public:
|
|||||||
* \return false if !string. (Seg-fault if str or end are NULL.)
|
* \return false if !string. (Seg-fault if str or end are NULL.)
|
||||||
*/
|
*/
|
||||||
bool getString(char const** begin, char const** end) const;
|
bool getString(char const** begin, char const** end) const;
|
||||||
|
#ifdef JSONCPP_HAS_STRING_VIEW
|
||||||
|
/** Get string_view of string-value.
|
||||||
|
* \return false if !string. (Seg-fault if str is NULL.)
|
||||||
|
*/
|
||||||
|
bool getString(std::string_view* str) const;
|
||||||
|
#endif
|
||||||
Int asInt() const;
|
Int asInt() const;
|
||||||
UInt asUInt() const;
|
UInt asUInt() const;
|
||||||
#if defined(JSON_HAS_INT64)
|
#if defined(JSON_HAS_INT64)
|
||||||
@ -470,6 +487,15 @@ public:
|
|||||||
bool insert(ArrayIndex index, const Value& newValue);
|
bool insert(ArrayIndex index, const Value& newValue);
|
||||||
bool insert(ArrayIndex index, Value&& newValue);
|
bool insert(ArrayIndex index, Value&& newValue);
|
||||||
|
|
||||||
|
#ifdef JSONCPP_HAS_STRING_VIEW
|
||||||
|
/// Access an object value by name, create a null member if it does not exist.
|
||||||
|
/// \param key may contain embedded nulls.
|
||||||
|
Value& operator[](std::string_view key);
|
||||||
|
/// Access an object value by name, returns null if there is no member with
|
||||||
|
/// that name.
|
||||||
|
/// \param key may contain embedded nulls.
|
||||||
|
const Value& operator[](std::string_view key) const;
|
||||||
|
#else
|
||||||
/// 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.
|
||||||
/// \note Because of our implementation, keys are limited to 2^30 -1 chars.
|
/// \note Because of our implementation, keys are limited to 2^30 -1 chars.
|
||||||
/// Exceeding that will cause an exception.
|
/// Exceeding that will cause an exception.
|
||||||
@ -484,6 +510,7 @@ public:
|
|||||||
/// that name.
|
/// that name.
|
||||||
/// \param key may contain embedded nulls.
|
/// \param key may contain embedded nulls.
|
||||||
const Value& operator[](const String& key) const;
|
const Value& operator[](const String& key) const;
|
||||||
|
#endif
|
||||||
/** \brief Access an object value by name, create a null member if it does not
|
/** \brief Access an object value by name, create a null member if it does not
|
||||||
* exist.
|
* exist.
|
||||||
*
|
*
|
||||||
@ -497,18 +524,24 @@ public:
|
|||||||
* \endcode
|
* \endcode
|
||||||
*/
|
*/
|
||||||
Value& operator[](const StaticString& key);
|
Value& operator[](const StaticString& key);
|
||||||
|
#ifdef JSONCPP_HAS_STRING_VIEW
|
||||||
|
/// Return the member named key if it exist, defaultValue otherwise.
|
||||||
|
/// \note deep copy
|
||||||
|
Value get(std::string_view key, const Value& defaultValue) const;
|
||||||
|
#else
|
||||||
/// Return the member named key if it exist, defaultValue otherwise.
|
/// Return the member named key if it exist, defaultValue otherwise.
|
||||||
/// \note deep copy
|
/// \note deep copy
|
||||||
Value get(const char* key, const Value& defaultValue) const;
|
Value get(const char* key, const Value& defaultValue) const;
|
||||||
|
/// Return the member named key if it exist, defaultValue otherwise.
|
||||||
|
/// \note deep copy
|
||||||
|
/// \param key may contain embedded nulls.
|
||||||
|
Value get(const String& key, const Value& defaultValue) const;
|
||||||
|
#endif
|
||||||
/// Return the member named key if it exist, defaultValue otherwise.
|
/// Return the member named key if it exist, defaultValue otherwise.
|
||||||
/// \note deep copy
|
/// \note deep copy
|
||||||
/// \note key may contain embedded nulls.
|
/// \note key may contain embedded nulls.
|
||||||
Value get(const char* begin, const char* end,
|
Value get(const char* begin, const char* end,
|
||||||
const Value& defaultValue) const;
|
const Value& defaultValue) const;
|
||||||
/// Return the member named key if it exist, defaultValue otherwise.
|
|
||||||
/// \note deep copy
|
|
||||||
/// \param key may contain embedded nulls.
|
|
||||||
Value get(const String& key, const Value& defaultValue) const;
|
|
||||||
/// Most general and efficient version of isMember()const, get()const,
|
/// Most general and efficient version of isMember()const, get()const,
|
||||||
/// and operator[]const
|
/// and operator[]const
|
||||||
/// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30
|
/// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30
|
||||||
@ -516,6 +549,29 @@ public:
|
|||||||
/// Most general and efficient version of isMember()const, get()const,
|
/// Most general and efficient version of isMember()const, get()const,
|
||||||
/// and operator[]const
|
/// and operator[]const
|
||||||
Value const* find(const String& key) const;
|
Value const* find(const String& key) const;
|
||||||
|
|
||||||
|
/// Calls find and only returns a valid pointer if the type is found
|
||||||
|
template <typename T, bool (T::*TMemFn)() const>
|
||||||
|
Value const* findValue(const String& key) const {
|
||||||
|
Value const* found = find(key);
|
||||||
|
if (!found || !(found->*TMemFn)())
|
||||||
|
return nullptr;
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
Value const* findNull(const String& key) const;
|
||||||
|
Value const* findBool(const String& key) const;
|
||||||
|
Value const* findInt(const String& key) const;
|
||||||
|
Value const* findInt64(const String& key) const;
|
||||||
|
Value const* findUInt(const String& key) const;
|
||||||
|
Value const* findUInt64(const String& key) const;
|
||||||
|
Value const* findIntegral(const String& key) const;
|
||||||
|
Value const* findDouble(const String& key) const;
|
||||||
|
Value const* findNumeric(const String& key) const;
|
||||||
|
Value const* findString(const String& key) const;
|
||||||
|
Value const* findArray(const String& key) const;
|
||||||
|
Value const* findObject(const String& key) const;
|
||||||
|
|
||||||
/// Most general and efficient version of object-mutators.
|
/// Most general and efficient version of object-mutators.
|
||||||
/// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30
|
/// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30
|
||||||
/// \return non-zero, but JSON_ASSERT if this is neither object nor nullValue.
|
/// \return non-zero, but JSON_ASSERT if this is neither object nor nullValue.
|
||||||
@ -525,20 +581,28 @@ public:
|
|||||||
/// Do nothing if it did not exist.
|
/// Do nothing if it did not exist.
|
||||||
/// \pre type() is objectValue or nullValue
|
/// \pre type() is objectValue or nullValue
|
||||||
/// \post type() is unchanged
|
/// \post type() is unchanged
|
||||||
|
#if JSONCPP_HAS_STRING_VIEW
|
||||||
|
void removeMember(std::string_view key);
|
||||||
|
#else
|
||||||
void removeMember(const char* key);
|
void removeMember(const char* key);
|
||||||
/// Same as removeMember(const char*)
|
/// Same as removeMember(const char*)
|
||||||
/// \param key may contain embedded nulls.
|
/// \param key may contain embedded nulls.
|
||||||
void removeMember(const String& key);
|
void removeMember(const String& key);
|
||||||
/// Same as removeMember(const char* begin, const char* end, Value* removed),
|
#endif
|
||||||
/// but 'key' is null-terminated.
|
|
||||||
bool removeMember(const char* key, Value* removed);
|
|
||||||
/** \brief Remove the named map member.
|
/** \brief Remove the named map member.
|
||||||
*
|
*
|
||||||
* Update 'removed' iff removed.
|
* Update 'removed' iff removed.
|
||||||
* \param key may contain embedded nulls.
|
* \param key may contain embedded nulls.
|
||||||
* \return true iff removed (no exceptions)
|
* \return true iff removed (no exceptions)
|
||||||
*/
|
*/
|
||||||
|
#if JSONCPP_HAS_STRING_VIEW
|
||||||
|
bool removeMember(std::string_view key, Value* removed);
|
||||||
|
#else
|
||||||
bool removeMember(String const& key, Value* removed);
|
bool removeMember(String const& key, Value* removed);
|
||||||
|
/// Same as removeMember(const char* begin, const char* end, Value* removed),
|
||||||
|
/// but 'key' is null-terminated.
|
||||||
|
bool removeMember(const char* key, Value* removed);
|
||||||
|
#endif
|
||||||
/// Same as removeMember(String const& key, Value* removed)
|
/// Same as removeMember(String const& key, Value* removed)
|
||||||
bool removeMember(const char* begin, const char* end, Value* removed);
|
bool removeMember(const char* begin, const char* end, Value* removed);
|
||||||
/** \brief Remove the indexed array element.
|
/** \brief Remove the indexed array element.
|
||||||
@ -549,12 +613,18 @@ public:
|
|||||||
*/
|
*/
|
||||||
bool removeIndex(ArrayIndex index, Value* removed);
|
bool removeIndex(ArrayIndex index, Value* removed);
|
||||||
|
|
||||||
|
#ifdef JSONCPP_HAS_STRING_VIEW
|
||||||
|
/// Return true if the object has a member named key.
|
||||||
|
/// \param key may contain embedded nulls.
|
||||||
|
bool isMember(std::string_view key) const;
|
||||||
|
#else
|
||||||
/// Return true if the object has a member named key.
|
/// Return true if the object has a member named key.
|
||||||
/// \note 'key' must be null-terminated.
|
/// \note 'key' must be null-terminated.
|
||||||
bool isMember(const char* key) const;
|
bool isMember(const char* key) const;
|
||||||
/// Return true if the object has a member named key.
|
/// Return true if the object has a member named key.
|
||||||
/// \param key may contain embedded nulls.
|
/// \param key may contain embedded nulls.
|
||||||
bool isMember(const String& key) const;
|
bool isMember(const String& key) const;
|
||||||
|
#endif
|
||||||
/// Same as isMember(String const& key)const
|
/// Same as isMember(String const& key)const
|
||||||
bool isMember(const char* begin, const char* end) const;
|
bool isMember(const char* begin, const char* end) const;
|
||||||
|
|
||||||
|
@ -1,25 +1,26 @@
|
|||||||
#ifndef JSON_VERSION_H_INCLUDED
|
#ifndef JSON_VERSION_H_INCLUDED
|
||||||
#define JSON_VERSION_H_INCLUDED
|
#define JSON_VERSION_H_INCLUDED
|
||||||
|
|
||||||
// Note: version must be updated in three places when doing a release. This
|
// Note: version must be updated in four places when doing a release. This
|
||||||
// annoying process ensures that amalgamate, CMake, and meson all report the
|
// annoying process ensures that amalgamate, CMake, and meson all report the
|
||||||
// correct version.
|
// correct version.
|
||||||
// 1. /meson.build
|
// 1. /meson.build
|
||||||
// 2. /include/json/version.h
|
// 2. /include/json/version.h
|
||||||
// 3. /CMakeLists.txt
|
// 3. /CMakeLists.txt
|
||||||
|
// 4. /MODULE.bazel
|
||||||
// IMPORTANT: also update the SOVERSION!!
|
// IMPORTANT: also update the SOVERSION!!
|
||||||
|
|
||||||
#define JSONCPP_VERSION_STRING "1.9.6"
|
#define JSONCPP_VERSION_STRING "1.9.7"
|
||||||
#define JSONCPP_VERSION_MAJOR 1
|
#define JSONCPP_VERSION_MAJOR 1
|
||||||
#define JSONCPP_VERSION_MINOR 9
|
#define JSONCPP_VERSION_MINOR 9
|
||||||
#define JSONCPP_VERSION_PATCH 6
|
#define JSONCPP_VERSION_PATCH 7
|
||||||
#define JSONCPP_VERSION_QUALIFIER
|
#define JSONCPP_VERSION_QUALIFIER
|
||||||
#define JSONCPP_VERSION_HEXA \
|
#define JSONCPP_VERSION_HEXA \
|
||||||
((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | \
|
((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | \
|
||||||
(JSONCPP_VERSION_PATCH << 8))
|
(JSONCPP_VERSION_PATCH << 8))
|
||||||
|
|
||||||
#if !defined(JSONCPP_USE_SECURE_MEMORY)
|
#if !defined(JSONCPP_USE_SECURE_MEMORY)
|
||||||
#define JSONCPP_USING_SECURE_MEMORY 0
|
#define JSONCPP_USE_SECURE_MEMORY 0
|
||||||
#endif
|
#endif
|
||||||
// If non-zero, the library zeroes any memory that it has allocated before
|
// If non-zero, the library zeroes any memory that it has allocated before
|
||||||
// it frees its memory.
|
// it frees its memory.
|
||||||
|
@ -4,5 +4,3 @@
|
|||||||
@MESON_STATIC_TARGET@
|
@MESON_STATIC_TARGET@
|
||||||
|
|
||||||
include ( "${CMAKE_CURRENT_LIST_DIR}/jsoncpp-namespaced-targets.cmake" )
|
include ( "${CMAKE_CURRENT_LIST_DIR}/jsoncpp-namespaced-targets.cmake" )
|
||||||
|
|
||||||
check_required_components(JsonCpp)
|
|
||||||
|
@ -2,14 +2,15 @@ project(
|
|||||||
'jsoncpp',
|
'jsoncpp',
|
||||||
'cpp',
|
'cpp',
|
||||||
|
|
||||||
# Note: version must be updated in three places when doing a release. This
|
# Note: version must be updated in four places when doing a release. This
|
||||||
# annoying process ensures that amalgamate, CMake, and meson all report the
|
# annoying process ensures that amalgamate, CMake, and meson all report the
|
||||||
# correct version.
|
# correct version.
|
||||||
# 1. /meson.build
|
# 1. /meson.build
|
||||||
# 2. /include/json/version.h
|
# 2. /include/json/version.h
|
||||||
# 3. /CMakeLists.txt
|
# 3. /CMakeLists.txt
|
||||||
|
# 4. /MODULE.bazel
|
||||||
# IMPORTANT: also update the SOVERSION!!
|
# IMPORTANT: also update the SOVERSION!!
|
||||||
version : '1.9.6',
|
version : '1.9.7',
|
||||||
default_options : [
|
default_options : [
|
||||||
'buildtype=release',
|
'buildtype=release',
|
||||||
'cpp_std=c++11',
|
'cpp_std=c++11',
|
||||||
@ -50,7 +51,7 @@ jsoncpp_lib = library(
|
|||||||
'src/lib_json/json_value.cpp',
|
'src/lib_json/json_value.cpp',
|
||||||
'src/lib_json/json_writer.cpp',
|
'src/lib_json/json_writer.cpp',
|
||||||
]),
|
]),
|
||||||
soversion : 26,
|
soversion : 27,
|
||||||
install : true,
|
install : true,
|
||||||
include_directories : jsoncpp_include_directories,
|
include_directories : jsoncpp_include_directories,
|
||||||
cpp_args: dll_export_flag)
|
cpp_args: dll_export_flag)
|
||||||
|
@ -143,7 +143,7 @@ if(BUILD_STATIC_LIBS)
|
|||||||
|
|
||||||
# avoid name clashes on windows as the shared import lib is also named jsoncpp.lib
|
# avoid name clashes on windows as the shared import lib is also named jsoncpp.lib
|
||||||
if(NOT DEFINED STATIC_SUFFIX AND BUILD_SHARED_LIBS)
|
if(NOT DEFINED STATIC_SUFFIX AND BUILD_SHARED_LIBS)
|
||||||
if (WIN32)
|
if (MSVC OR ("${CMAKE_C_SIMULATE_ID}" STREQUAL "MSVC"))
|
||||||
set(STATIC_SUFFIX "_static")
|
set(STATIC_SUFFIX "_static")
|
||||||
else()
|
else()
|
||||||
set(STATIC_SUFFIX "")
|
set(STATIC_SUFFIX "")
|
||||||
|
@ -23,13 +23,6 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#if __cplusplus >= 201103L
|
|
||||||
|
|
||||||
#if !defined(sscanf)
|
|
||||||
#define sscanf std::sscanf
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif //__cplusplus
|
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
#if !defined(_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES)
|
#if !defined(_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES)
|
||||||
@ -53,11 +46,7 @@ static size_t const stackLimit_g =
|
|||||||
|
|
||||||
namespace Json {
|
namespace Json {
|
||||||
|
|
||||||
#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
|
|
||||||
using CharReaderPtr = std::unique_ptr<CharReader>;
|
using CharReaderPtr = std::unique_ptr<CharReader>;
|
||||||
#else
|
|
||||||
using CharReaderPtr = std::auto_ptr<CharReader>;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Implementation of class Features
|
// Implementation of class Features
|
||||||
// ////////////////////////////////
|
// ////////////////////////////////
|
||||||
|
@ -17,6 +17,10 @@
|
|||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
#ifdef JSONCPP_HAS_STRING_VIEW
|
||||||
|
#include <string_view>
|
||||||
|
#endif
|
||||||
|
|
||||||
// Provide implementation equivalent of std::snprintf for older _MSC compilers
|
// Provide implementation equivalent of std::snprintf for older _MSC compilers
|
||||||
#if defined(_MSC_VER) && _MSC_VER < 1900
|
#if defined(_MSC_VER) && _MSC_VER < 1900
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
@ -87,7 +91,8 @@ template <typename T, typename U>
|
|||||||
static inline bool InRange(double d, T min, U max) {
|
static inline bool InRange(double d, T min, U max) {
|
||||||
// The casts can lose precision, but we are looking only for
|
// The casts can lose precision, but we are looking only for
|
||||||
// an approximate range. Might fail on edge cases though. ~cdunn
|
// an approximate range. Might fail on edge cases though. ~cdunn
|
||||||
return d >= static_cast<double>(min) && d <= static_cast<double>(max);
|
return d >= static_cast<double>(min) && d <= static_cast<double>(max) &&
|
||||||
|
!(static_cast<U>(d) == min && d != static_cast<double>(min));
|
||||||
}
|
}
|
||||||
#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
|
#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
|
||||||
static inline double integerToDouble(Json::UInt64 value) {
|
static inline double integerToDouble(Json::UInt64 value) {
|
||||||
@ -101,7 +106,8 @@ template <typename T> static inline double integerToDouble(T value) {
|
|||||||
|
|
||||||
template <typename T, typename U>
|
template <typename T, typename U>
|
||||||
static inline bool InRange(double d, T min, U max) {
|
static inline bool InRange(double d, T min, U max) {
|
||||||
return d >= integerToDouble(min) && d <= integerToDouble(max);
|
return d >= integerToDouble(min) && d <= integerToDouble(max) &&
|
||||||
|
!(static_cast<U>(d) == min && d != integerToDouble(min));
|
||||||
}
|
}
|
||||||
#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
|
#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
|
||||||
|
|
||||||
@ -163,7 +169,7 @@ inline static void decodePrefixedString(bool isPrefixed, char const* prefixed,
|
|||||||
/** Free the string duplicated by
|
/** Free the string duplicated by
|
||||||
* duplicateStringValue()/duplicateAndPrefixStringValue().
|
* duplicateStringValue()/duplicateAndPrefixStringValue().
|
||||||
*/
|
*/
|
||||||
#if JSONCPP_USING_SECURE_MEMORY
|
#if JSONCPP_USE_SECURE_MEMORY
|
||||||
static inline void releasePrefixedStringValue(char* value) {
|
static inline void releasePrefixedStringValue(char* value) {
|
||||||
unsigned length = 0;
|
unsigned length = 0;
|
||||||
char const* valueDecoded;
|
char const* valueDecoded;
|
||||||
@ -178,10 +184,10 @@ static inline void releaseStringValue(char* value, unsigned length) {
|
|||||||
memset(value, 0, size);
|
memset(value, 0, size);
|
||||||
free(value);
|
free(value);
|
||||||
}
|
}
|
||||||
#else // !JSONCPP_USING_SECURE_MEMORY
|
#else // !JSONCPP_USE_SECURE_MEMORY
|
||||||
static inline void releasePrefixedStringValue(char* value) { free(value); }
|
static inline void releasePrefixedStringValue(char* value) { free(value); }
|
||||||
static inline void releaseStringValue(char* value, unsigned) { free(value); }
|
static inline void releaseStringValue(char* value, unsigned) { free(value); }
|
||||||
#endif // JSONCPP_USING_SECURE_MEMORY
|
#endif // JSONCPP_USE_SECURE_MEMORY
|
||||||
|
|
||||||
} // namespace Json
|
} // namespace Json
|
||||||
|
|
||||||
@ -418,6 +424,14 @@ Value::Value(const String& value) {
|
|||||||
value.data(), static_cast<unsigned>(value.length()));
|
value.data(), static_cast<unsigned>(value.length()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef JSONCPP_HAS_STRING_VIEW
|
||||||
|
Value::Value(std::string_view value) {
|
||||||
|
initBasic(stringValue, true);
|
||||||
|
value_.string_ = duplicateAndPrefixStringValue(
|
||||||
|
value.data(), static_cast<unsigned>(value.length()));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
Value::Value(const StaticString& value) {
|
Value::Value(const StaticString& value) {
|
||||||
initBasic(stringValue);
|
initBasic(stringValue);
|
||||||
value_.string_ = const_cast<char*>(value.c_str());
|
value_.string_ = const_cast<char*>(value.c_str());
|
||||||
@ -599,7 +613,7 @@ const char* Value::asCString() const {
|
|||||||
return this_str;
|
return this_str;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if JSONCPP_USING_SECURE_MEMORY
|
#if JSONCPP_USE_SECURE_MEMORY
|
||||||
unsigned Value::getCStringLength() const {
|
unsigned Value::getCStringLength() const {
|
||||||
JSON_ASSERT_MESSAGE(type() == stringValue,
|
JSON_ASSERT_MESSAGE(type() == stringValue,
|
||||||
"in Json::Value::asCString(): requires stringValue");
|
"in Json::Value::asCString(): requires stringValue");
|
||||||
@ -625,6 +639,21 @@ bool Value::getString(char const** begin, char const** end) const {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef JSONCPP_HAS_STRING_VIEW
|
||||||
|
bool Value::getString(std::string_view* str) const {
|
||||||
|
if (type() != stringValue)
|
||||||
|
return false;
|
||||||
|
if (value_.string_ == nullptr)
|
||||||
|
return false;
|
||||||
|
const char* begin;
|
||||||
|
unsigned length;
|
||||||
|
decodePrefixedString(this->isAllocated(), this->value_.string_, &length,
|
||||||
|
&begin);
|
||||||
|
*str = std::string_view(begin, length);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
String Value::asString() const {
|
String Value::asString() const {
|
||||||
switch (type()) {
|
switch (type()) {
|
||||||
case nullValue:
|
case nullValue:
|
||||||
@ -682,7 +711,7 @@ Value::UInt Value::asUInt() const {
|
|||||||
JSON_ASSERT_MESSAGE(isUInt(), "LargestUInt out of UInt range");
|
JSON_ASSERT_MESSAGE(isUInt(), "LargestUInt out of UInt range");
|
||||||
return UInt(value_.uint_);
|
return UInt(value_.uint_);
|
||||||
case realValue:
|
case realValue:
|
||||||
JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt),
|
JSON_ASSERT_MESSAGE(InRange(value_.real_, 0u, maxUInt),
|
||||||
"double out of UInt range");
|
"double out of UInt range");
|
||||||
return UInt(value_.real_);
|
return UInt(value_.real_);
|
||||||
case nullValue:
|
case nullValue:
|
||||||
@ -705,6 +734,11 @@ Value::Int64 Value::asInt64() const {
|
|||||||
JSON_ASSERT_MESSAGE(isInt64(), "LargestUInt out of Int64 range");
|
JSON_ASSERT_MESSAGE(isInt64(), "LargestUInt out of Int64 range");
|
||||||
return Int64(value_.uint_);
|
return Int64(value_.uint_);
|
||||||
case realValue:
|
case realValue:
|
||||||
|
// If the double value is in proximity to minInt64, it will be rounded to
|
||||||
|
// minInt64. The correct value in this scenario is indeterminable
|
||||||
|
JSON_ASSERT_MESSAGE(
|
||||||
|
value_.real_ != minInt64,
|
||||||
|
"Double value is minInt64, precise value cannot be determined");
|
||||||
JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt64, maxInt64),
|
JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt64, maxInt64),
|
||||||
"double out of Int64 range");
|
"double out of Int64 range");
|
||||||
return Int64(value_.real_);
|
return Int64(value_.real_);
|
||||||
@ -726,7 +760,7 @@ Value::UInt64 Value::asUInt64() const {
|
|||||||
case uintValue:
|
case uintValue:
|
||||||
return UInt64(value_.uint_);
|
return UInt64(value_.uint_);
|
||||||
case realValue:
|
case realValue:
|
||||||
JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt64),
|
JSON_ASSERT_MESSAGE(InRange(value_.real_, 0u, maxUInt64),
|
||||||
"double out of UInt64 range");
|
"double out of UInt64 range");
|
||||||
return UInt64(value_.real_);
|
return UInt64(value_.real_);
|
||||||
case nullValue:
|
case nullValue:
|
||||||
@ -837,7 +871,7 @@ bool Value::isConvertibleTo(ValueType other) const {
|
|||||||
type() == booleanValue || type() == nullValue;
|
type() == booleanValue || type() == nullValue;
|
||||||
case uintValue:
|
case uintValue:
|
||||||
return isUInt() ||
|
return isUInt() ||
|
||||||
(type() == realValue && InRange(value_.real_, 0, maxUInt)) ||
|
(type() == realValue && InRange(value_.real_, 0u, maxUInt)) ||
|
||||||
type() == booleanValue || type() == nullValue;
|
type() == booleanValue || type() == nullValue;
|
||||||
case realValue:
|
case realValue:
|
||||||
return isNumeric() || type() == booleanValue || type() == nullValue;
|
return isNumeric() || type() == booleanValue || type() == nullValue;
|
||||||
@ -1095,12 +1129,61 @@ Value const* Value::find(char const* begin, char const* end) const {
|
|||||||
Value const* Value::find(const String& key) const {
|
Value const* Value::find(const String& key) const {
|
||||||
return find(key.data(), key.data() + key.length());
|
return find(key.data(), key.data() + key.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Value const* Value::findNull(const String& key) const {
|
||||||
|
return findValue<Value, &Value::isNull>(key);
|
||||||
|
}
|
||||||
|
Value const* Value::findBool(const String& key) const {
|
||||||
|
return findValue<Value, &Value::isBool>(key);
|
||||||
|
}
|
||||||
|
Value const* Value::findInt(const String& key) const {
|
||||||
|
return findValue<Value, &Value::isInt>(key);
|
||||||
|
}
|
||||||
|
Value const* Value::findInt64(const String& key) const {
|
||||||
|
return findValue<Value, &Value::isInt64>(key);
|
||||||
|
}
|
||||||
|
Value const* Value::findUInt(const String& key) const {
|
||||||
|
return findValue<Value, &Value::isUInt>(key);
|
||||||
|
}
|
||||||
|
Value const* Value::findUInt64(const String& key) const {
|
||||||
|
return findValue<Value, &Value::isUInt64>(key);
|
||||||
|
}
|
||||||
|
Value const* Value::findIntegral(const String& key) const {
|
||||||
|
return findValue<Value, &Value::isIntegral>(key);
|
||||||
|
}
|
||||||
|
Value const* Value::findDouble(const String& key) const {
|
||||||
|
return findValue<Value, &Value::isDouble>(key);
|
||||||
|
}
|
||||||
|
Value const* Value::findNumeric(const String& key) const {
|
||||||
|
return findValue<Value, &Value::isNumeric>(key);
|
||||||
|
}
|
||||||
|
Value const* Value::findString(const String& key) const {
|
||||||
|
return findValue<Value, &Value::isString>(key);
|
||||||
|
}
|
||||||
|
Value const* Value::findArray(const String& key) const {
|
||||||
|
return findValue<Value, &Value::isArray>(key);
|
||||||
|
}
|
||||||
|
Value const* Value::findObject(const String& key) const {
|
||||||
|
return findValue<Value, &Value::isObject>(key);
|
||||||
|
}
|
||||||
|
|
||||||
Value* Value::demand(char const* begin, char const* end) {
|
Value* Value::demand(char const* begin, char const* end) {
|
||||||
JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue,
|
JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue,
|
||||||
"in Json::Value::demand(begin, end): requires "
|
"in Json::Value::demand(begin, end): requires "
|
||||||
"objectValue or nullValue");
|
"objectValue or nullValue");
|
||||||
return &resolveReference(begin, end);
|
return &resolveReference(begin, end);
|
||||||
}
|
}
|
||||||
|
#ifdef JSONCPP_HAS_STRING_VIEW
|
||||||
|
const Value& Value::operator[](std::string_view key) const {
|
||||||
|
Value const* found = find(key.data(), key.data() + key.length());
|
||||||
|
if (!found)
|
||||||
|
return nullSingleton();
|
||||||
|
return *found;
|
||||||
|
}
|
||||||
|
Value& Value::operator[](std::string_view key) {
|
||||||
|
return resolveReference(key.data(), key.data() + key.length());
|
||||||
|
}
|
||||||
|
#else
|
||||||
const Value& Value::operator[](const char* key) const {
|
const Value& Value::operator[](const char* key) const {
|
||||||
Value const* found = find(key, key + strlen(key));
|
Value const* found = find(key, key + strlen(key));
|
||||||
if (!found)
|
if (!found)
|
||||||
@ -1121,6 +1204,7 @@ Value& Value::operator[](const char* key) {
|
|||||||
Value& Value::operator[](const String& key) {
|
Value& Value::operator[](const String& key) {
|
||||||
return resolveReference(key.data(), key.data() + key.length());
|
return resolveReference(key.data(), key.data() + key.length());
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
Value& Value::operator[](const StaticString& key) {
|
Value& Value::operator[](const StaticString& key) {
|
||||||
return resolveReference(key.c_str());
|
return resolveReference(key.c_str());
|
||||||
@ -1160,12 +1244,18 @@ Value Value::get(char const* begin, char const* end,
|
|||||||
Value const* found = find(begin, end);
|
Value const* found = find(begin, end);
|
||||||
return !found ? defaultValue : *found;
|
return !found ? defaultValue : *found;
|
||||||
}
|
}
|
||||||
|
#ifdef JSONCPP_HAS_STRING_VIEW
|
||||||
|
Value Value::get(std::string_view key, const Value& defaultValue) const {
|
||||||
|
return get(key.data(), key.data() + key.length(), defaultValue);
|
||||||
|
}
|
||||||
|
#else
|
||||||
Value Value::get(char const* key, Value const& defaultValue) const {
|
Value Value::get(char const* key, Value const& defaultValue) const {
|
||||||
return get(key, key + strlen(key), defaultValue);
|
return get(key, key + strlen(key), defaultValue);
|
||||||
}
|
}
|
||||||
Value Value::get(String const& key, Value const& defaultValue) const {
|
Value Value::get(String const& key, Value const& defaultValue) const {
|
||||||
return get(key.data(), key.data() + key.length(), defaultValue);
|
return get(key.data(), key.data() + key.length(), defaultValue);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
bool Value::removeMember(const char* begin, const char* end, Value* removed) {
|
bool Value::removeMember(const char* begin, const char* end, Value* removed) {
|
||||||
if (type() != objectValue) {
|
if (type() != objectValue) {
|
||||||
@ -1181,12 +1271,31 @@ bool Value::removeMember(const char* begin, const char* end, Value* removed) {
|
|||||||
value_.map_->erase(it);
|
value_.map_->erase(it);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
#ifdef JSONCPP_HAS_STRING_VIEW
|
||||||
|
bool Value::removeMember(std::string_view key, Value* removed) {
|
||||||
|
return removeMember(key.data(), key.data() + key.length(), removed);
|
||||||
|
}
|
||||||
|
#else
|
||||||
bool Value::removeMember(const char* key, Value* removed) {
|
bool Value::removeMember(const char* key, Value* removed) {
|
||||||
return removeMember(key, key + strlen(key), removed);
|
return removeMember(key, key + strlen(key), removed);
|
||||||
}
|
}
|
||||||
bool Value::removeMember(String const& key, Value* removed) {
|
bool Value::removeMember(String const& key, Value* removed) {
|
||||||
return removeMember(key.data(), key.data() + key.length(), removed);
|
return removeMember(key.data(), key.data() + key.length(), removed);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef JSONCPP_HAS_STRING_VIEW
|
||||||
|
void Value::removeMember(std::string_view key) {
|
||||||
|
JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue,
|
||||||
|
"in Json::Value::removeMember(): requires objectValue");
|
||||||
|
if (type() == nullValue)
|
||||||
|
return;
|
||||||
|
|
||||||
|
CZString actualKey(key.data(), unsigned(key.length()),
|
||||||
|
CZString::noDuplication);
|
||||||
|
value_.map_->erase(actualKey);
|
||||||
|
}
|
||||||
|
#else
|
||||||
void Value::removeMember(const char* key) {
|
void Value::removeMember(const char* key) {
|
||||||
JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue,
|
JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue,
|
||||||
"in Json::Value::removeMember(): requires objectValue");
|
"in Json::Value::removeMember(): requires objectValue");
|
||||||
@ -1197,6 +1306,7 @@ void Value::removeMember(const char* key) {
|
|||||||
value_.map_->erase(actualKey);
|
value_.map_->erase(actualKey);
|
||||||
}
|
}
|
||||||
void Value::removeMember(const String& key) { removeMember(key.c_str()); }
|
void Value::removeMember(const String& key) { removeMember(key.c_str()); }
|
||||||
|
#endif
|
||||||
|
|
||||||
bool Value::removeIndex(ArrayIndex index, Value* removed) {
|
bool Value::removeIndex(ArrayIndex index, Value* removed) {
|
||||||
if (type() != arrayValue) {
|
if (type() != arrayValue) {
|
||||||
@ -1226,12 +1336,18 @@ bool Value::isMember(char const* begin, char const* end) const {
|
|||||||
Value const* value = find(begin, end);
|
Value const* value = find(begin, end);
|
||||||
return nullptr != value;
|
return nullptr != value;
|
||||||
}
|
}
|
||||||
|
#ifdef JSONCPP_HAS_STRING_VIEW
|
||||||
|
bool Value::isMember(std::string_view key) const {
|
||||||
|
return isMember(key.data(), key.data() + key.length());
|
||||||
|
}
|
||||||
|
#else
|
||||||
bool Value::isMember(char const* key) const {
|
bool Value::isMember(char const* key) const {
|
||||||
return isMember(key, key + strlen(key));
|
return isMember(key, key + strlen(key));
|
||||||
}
|
}
|
||||||
bool Value::isMember(String const& key) const {
|
bool Value::isMember(String const& key) const {
|
||||||
return isMember(key.data(), key.data() + key.length());
|
return isMember(key.data(), key.data() + key.length());
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
Value::Members Value::getMemberNames() const {
|
Value::Members Value::getMemberNames() const {
|
||||||
JSON_ASSERT_MESSAGE(
|
JSON_ASSERT_MESSAGE(
|
||||||
@ -1311,8 +1427,12 @@ bool Value::isInt64() const {
|
|||||||
// Note that maxInt64 (= 2^63 - 1) is not exactly representable as a
|
// Note that maxInt64 (= 2^63 - 1) is not exactly representable as a
|
||||||
// double, so double(maxInt64) will be rounded up to 2^63. Therefore we
|
// double, so double(maxInt64) will be rounded up to 2^63. Therefore we
|
||||||
// require the value to be strictly less than the limit.
|
// require the value to be strictly less than the limit.
|
||||||
return value_.real_ >= double(minInt64) &&
|
// minInt64 is -2^63 which can be represented as a double, but since double
|
||||||
value_.real_ < double(maxInt64) && IsIntegral(value_.real_);
|
// values in its proximity are also rounded to -2^63, we require the value
|
||||||
|
// to be strictly greater than the limit to avoid returning 'true' for
|
||||||
|
// values that are not in the range
|
||||||
|
return value_.real_ > double(minInt64) && value_.real_ < double(maxInt64) &&
|
||||||
|
IsIntegral(value_.real_);
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1350,7 +1470,11 @@ bool Value::isIntegral() const {
|
|||||||
// Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a
|
// Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a
|
||||||
// double, so double(maxUInt64) will be rounded up to 2^64. Therefore we
|
// double, so double(maxUInt64) will be rounded up to 2^64. Therefore we
|
||||||
// require the value to be strictly less than the limit.
|
// require the value to be strictly less than the limit.
|
||||||
return value_.real_ >= double(minInt64) &&
|
// minInt64 is -2^63 which can be represented as a double, but since double
|
||||||
|
// values in its proximity are also rounded to -2^63, we require the value
|
||||||
|
// to be strictly greater than the limit to avoid returning 'true' for
|
||||||
|
// values that are not in the range
|
||||||
|
return value_.real_ > double(minInt64) &&
|
||||||
value_.real_ < maxUInt64AsDouble && IsIntegral(value_.real_);
|
value_.real_ < maxUInt64AsDouble && IsIntegral(value_.real_);
|
||||||
#else
|
#else
|
||||||
return value_.real_ >= minInt && value_.real_ <= maxUInt &&
|
return value_.real_ >= minInt && value_.real_ <= maxUInt &&
|
||||||
|
@ -10,6 +10,8 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
|
#include <cmath>
|
||||||
|
#include <cstdio>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@ -17,67 +19,6 @@
|
|||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#if __cplusplus >= 201103L
|
|
||||||
#include <cmath>
|
|
||||||
#include <cstdio>
|
|
||||||
|
|
||||||
#if !defined(isnan)
|
|
||||||
#define isnan std::isnan
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(isfinite)
|
|
||||||
#define isfinite std::isfinite
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#else
|
|
||||||
#include <cmath>
|
|
||||||
#include <cstdio>
|
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
|
||||||
#if !defined(isnan)
|
|
||||||
#include <float.h>
|
|
||||||
#define isnan _isnan
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(isfinite)
|
|
||||||
#include <float.h>
|
|
||||||
#define isfinite _finite
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES)
|
|
||||||
#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1
|
|
||||||
#endif //_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES
|
|
||||||
|
|
||||||
#endif //_MSC_VER
|
|
||||||
|
|
||||||
#if defined(__sun) && defined(__SVR4) // Solaris
|
|
||||||
#if !defined(isfinite)
|
|
||||||
#include <ieeefp.h>
|
|
||||||
#define isfinite finite
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__hpux)
|
|
||||||
#if !defined(isfinite)
|
|
||||||
#if defined(__ia64) && !defined(finite)
|
|
||||||
#define isfinite(x) \
|
|
||||||
((sizeof(x) == sizeof(float) ? _Isfinitef(x) : _IsFinite(x)))
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(isnan)
|
|
||||||
// IEEE standard states that NaN values will not compare to themselves
|
|
||||||
#define isnan(x) ((x) != (x))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(__APPLE__)
|
|
||||||
#if !defined(isfinite)
|
|
||||||
#define isfinite finite
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
// Disable warning about strdup being deprecated.
|
// Disable warning about strdup being deprecated.
|
||||||
#pragma warning(disable : 4996)
|
#pragma warning(disable : 4996)
|
||||||
@ -85,11 +26,7 @@
|
|||||||
|
|
||||||
namespace Json {
|
namespace Json {
|
||||||
|
|
||||||
#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
|
|
||||||
using StreamWriterPtr = std::unique_ptr<StreamWriter>;
|
using StreamWriterPtr = std::unique_ptr<StreamWriter>;
|
||||||
#else
|
|
||||||
using StreamWriterPtr = std::auto_ptr<StreamWriter>;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
String valueToString(LargestInt value) {
|
String valueToString(LargestInt value) {
|
||||||
UIntToStringBuffer buffer;
|
UIntToStringBuffer buffer;
|
||||||
@ -129,12 +66,12 @@ String valueToString(double value, bool useSpecialFloats,
|
|||||||
// Print into the buffer. We need not request the alternative representation
|
// Print into the buffer. We need not request the alternative representation
|
||||||
// that always has a decimal point because JSON doesn't distinguish the
|
// that always has a decimal point because JSON doesn't distinguish the
|
||||||
// concepts of reals and integers.
|
// concepts of reals and integers.
|
||||||
if (!isfinite(value)) {
|
if (!std::isfinite(value)) {
|
||||||
static const char* const reps[2][3] = {{"NaN", "-Infinity", "Infinity"},
|
if (std::isnan(value))
|
||||||
{"null", "-1e+9999", "1e+9999"}};
|
return useSpecialFloats ? "NaN" : "null";
|
||||||
return reps[useSpecialFloats ? 0 : 1][isnan(value) ? 0
|
if (value < 0)
|
||||||
: (value < 0) ? 1
|
return useSpecialFloats ? "-Infinity" : "-1e+9999";
|
||||||
: 2];
|
return useSpecialFloats ? "Infinity" : "1e+9999";
|
||||||
}
|
}
|
||||||
|
|
||||||
String buffer(size_t(36), '\0');
|
String buffer(size_t(36), '\0');
|
||||||
|
@ -410,7 +410,7 @@ Json::String ToJsonString(const char* toConvert) {
|
|||||||
|
|
||||||
Json::String ToJsonString(Json::String in) { return in; }
|
Json::String ToJsonString(Json::String in) { return in; }
|
||||||
|
|
||||||
#if JSONCPP_USING_SECURE_MEMORY
|
#if JSONCPP_USE_SECURE_MEMORY
|
||||||
Json::String ToJsonString(std::string in) {
|
Json::String ToJsonString(std::string in) {
|
||||||
return Json::String(in.data(), in.data() + in.length());
|
return Json::String(in.data(), in.data() + in.length());
|
||||||
}
|
}
|
||||||
|
@ -185,7 +185,7 @@ TestResult& checkEqual(TestResult& result, T expected, U actual,
|
|||||||
|
|
||||||
Json::String ToJsonString(const char* toConvert);
|
Json::String ToJsonString(const char* toConvert);
|
||||||
Json::String ToJsonString(Json::String in);
|
Json::String ToJsonString(Json::String in);
|
||||||
#if JSONCPP_USING_SECURE_MEMORY
|
#if JSONCPP_USE_SECURE_MEMORY
|
||||||
Json::String ToJsonString(std::string in);
|
Json::String ToJsonString(std::string in);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -76,6 +76,8 @@ struct ValueTest : JsonTest::TestCase {
|
|||||||
Json::Value float_{0.00390625f};
|
Json::Value float_{0.00390625f};
|
||||||
Json::Value array1_;
|
Json::Value array1_;
|
||||||
Json::Value object1_;
|
Json::Value object1_;
|
||||||
|
Json::Value object2_;
|
||||||
|
Json::Value object3_;
|
||||||
Json::Value emptyString_{""};
|
Json::Value emptyString_{""};
|
||||||
Json::Value string1_{"a"};
|
Json::Value string1_{"a"};
|
||||||
Json::Value string_{"sometext with space"};
|
Json::Value string_{"sometext with space"};
|
||||||
@ -85,6 +87,34 @@ struct ValueTest : JsonTest::TestCase {
|
|||||||
ValueTest() {
|
ValueTest() {
|
||||||
array1_.append(1234);
|
array1_.append(1234);
|
||||||
object1_["id"] = 1234;
|
object1_["id"] = 1234;
|
||||||
|
|
||||||
|
// object2 with matching values
|
||||||
|
object2_["null"] = Json::nullValue;
|
||||||
|
object2_["bool"] = true;
|
||||||
|
object2_["int"] = Json::Int{Json::Value::maxInt};
|
||||||
|
object2_["int64"] = Json::Int64{Json::Value::maxInt64};
|
||||||
|
object2_["uint"] = Json::UInt{Json::Value::maxUInt};
|
||||||
|
object2_["uint64"] = Json::UInt64{Json::Value::maxUInt64};
|
||||||
|
object2_["integral"] = 1234;
|
||||||
|
object2_["double"] = 1234.56789;
|
||||||
|
object2_["numeric"] = 0.12345f;
|
||||||
|
object2_["string"] = "string";
|
||||||
|
object2_["array"] = Json::arrayValue;
|
||||||
|
object2_["object"] = Json::objectValue;
|
||||||
|
|
||||||
|
// object3 with not matching values
|
||||||
|
object3_["object"] = Json::nullValue;
|
||||||
|
object3_["null"] = true;
|
||||||
|
object3_["bool"] = Json::Int{Json::Value::maxInt};
|
||||||
|
object3_["int"] = "not_an_int";
|
||||||
|
object3_["int64"] = "not_an_int64";
|
||||||
|
object3_["uint"] = "not_an_uint";
|
||||||
|
object3_["uin64"] = "not_an_uint64";
|
||||||
|
object3_["integral"] = 1234.56789;
|
||||||
|
object3_["double"] = false;
|
||||||
|
object3_["numeric"] = "string";
|
||||||
|
object3_["string"] = Json::arrayValue;
|
||||||
|
object3_["array"] = Json::objectValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct IsCheck {
|
struct IsCheck {
|
||||||
@ -234,6 +264,62 @@ JSONTEST_FIXTURE_LOCAL(ValueTest, objects) {
|
|||||||
const Json::Value* stringFoundUnknownId = object1_.find(stringUnknownIdKey);
|
const Json::Value* stringFoundUnknownId = object1_.find(stringUnknownIdKey);
|
||||||
JSONTEST_ASSERT_EQUAL(nullptr, stringFoundUnknownId);
|
JSONTEST_ASSERT_EQUAL(nullptr, stringFoundUnknownId);
|
||||||
|
|
||||||
|
// Access through find<Type>()
|
||||||
|
const Json::Value* nullFound = object2_.findNull("null");
|
||||||
|
JSONTEST_ASSERT(nullFound != nullptr);
|
||||||
|
JSONTEST_ASSERT_EQUAL(Json::nullValue, *nullFound);
|
||||||
|
JSONTEST_ASSERT(object3_.findNull("null") == nullptr);
|
||||||
|
|
||||||
|
const Json::Value* boolFound = object2_.findBool("bool");
|
||||||
|
JSONTEST_ASSERT(boolFound != nullptr);
|
||||||
|
JSONTEST_ASSERT_EQUAL(true, *boolFound);
|
||||||
|
JSONTEST_ASSERT(object3_.findBool("bool") == nullptr);
|
||||||
|
|
||||||
|
const Json::Value* intFound = object2_.findInt("int");
|
||||||
|
JSONTEST_ASSERT(intFound != nullptr);
|
||||||
|
JSONTEST_ASSERT_EQUAL(Json::Int{Json::Value::maxInt}, *intFound);
|
||||||
|
JSONTEST_ASSERT(object3_.findInt("int") == nullptr);
|
||||||
|
|
||||||
|
const Json::Value* int64Found = object2_.findInt64("int64");
|
||||||
|
JSONTEST_ASSERT(int64Found != nullptr);
|
||||||
|
JSONTEST_ASSERT_EQUAL(Json::Int64{Json::Value::maxInt64}, *int64Found);
|
||||||
|
JSONTEST_ASSERT(object3_.findInt64("int64") == nullptr);
|
||||||
|
|
||||||
|
const Json::Value* uintFound = object2_.findUInt("uint");
|
||||||
|
JSONTEST_ASSERT(uintFound != nullptr);
|
||||||
|
JSONTEST_ASSERT_EQUAL(Json::UInt{Json::Value::maxUInt}, *uintFound);
|
||||||
|
JSONTEST_ASSERT(object3_.findUInt("uint") == nullptr);
|
||||||
|
|
||||||
|
const Json::Value* uint64Found = object2_.findUInt64("uint64");
|
||||||
|
JSONTEST_ASSERT(uint64Found != nullptr);
|
||||||
|
JSONTEST_ASSERT_EQUAL(Json::UInt64{Json::Value::maxUInt64}, *uint64Found);
|
||||||
|
JSONTEST_ASSERT(object3_.findUInt64("uint64") == nullptr);
|
||||||
|
|
||||||
|
const Json::Value* integralFound = object2_.findIntegral("integral");
|
||||||
|
JSONTEST_ASSERT(integralFound != nullptr);
|
||||||
|
JSONTEST_ASSERT_EQUAL(1234, *integralFound);
|
||||||
|
JSONTEST_ASSERT(object3_.findIntegral("integral") == nullptr);
|
||||||
|
|
||||||
|
const Json::Value* doubleFound = object2_.findDouble("double");
|
||||||
|
JSONTEST_ASSERT(doubleFound != nullptr);
|
||||||
|
JSONTEST_ASSERT_EQUAL(1234.56789, *doubleFound);
|
||||||
|
JSONTEST_ASSERT(object3_.findDouble("double") == nullptr);
|
||||||
|
|
||||||
|
const Json::Value* numericFound = object2_.findNumeric("numeric");
|
||||||
|
JSONTEST_ASSERT(numericFound != nullptr);
|
||||||
|
JSONTEST_ASSERT_EQUAL(0.12345f, *numericFound);
|
||||||
|
JSONTEST_ASSERT(object3_.findNumeric("numeric") == nullptr);
|
||||||
|
|
||||||
|
const Json::Value* stringFound = object2_.findString("string");
|
||||||
|
JSONTEST_ASSERT(stringFound != nullptr);
|
||||||
|
JSONTEST_ASSERT_EQUAL(std::string{"string"}, *stringFound);
|
||||||
|
JSONTEST_ASSERT(object3_.findString("string") == nullptr);
|
||||||
|
|
||||||
|
const Json::Value* arrayFound = object2_.findArray("array");
|
||||||
|
JSONTEST_ASSERT(arrayFound != nullptr);
|
||||||
|
JSONTEST_ASSERT_EQUAL(Json::arrayValue, *arrayFound);
|
||||||
|
JSONTEST_ASSERT(object3_.findArray("array") == nullptr);
|
||||||
|
|
||||||
// Access through demand()
|
// Access through demand()
|
||||||
const char yetAnotherIdKey[] = "yet another id";
|
const char yetAnotherIdKey[] = "yet another id";
|
||||||
const Json::Value* foundYetAnotherId =
|
const Json::Value* foundYetAnotherId =
|
||||||
@ -1191,15 +1277,13 @@ JSONTEST_FIXTURE_LOCAL(ValueTest, integers) {
|
|||||||
JSONTEST_ASSERT_EQUAL(true, val.asBool());
|
JSONTEST_ASSERT_EQUAL(true, val.asBool());
|
||||||
JSONTEST_ASSERT_STRING_EQUAL("-9223372036854775808", val.asString());
|
JSONTEST_ASSERT_STRING_EQUAL("-9223372036854775808", val.asString());
|
||||||
|
|
||||||
// int64 min (floating point constructor). Note that kint64min *is* exactly
|
// int64 min (floating point constructor). Since double values in proximity of
|
||||||
// representable as a double.
|
// kint64min are rounded to kint64min, we don't check for conversion to int64.
|
||||||
val = Json::Value(double(kint64min));
|
val = Json::Value(double(kint64min));
|
||||||
|
|
||||||
JSONTEST_ASSERT_EQUAL(Json::realValue, val.type());
|
JSONTEST_ASSERT_EQUAL(Json::realValue, val.type());
|
||||||
|
|
||||||
checks = IsCheck();
|
checks = IsCheck();
|
||||||
checks.isInt64_ = true;
|
|
||||||
checks.isIntegral_ = true;
|
|
||||||
checks.isDouble_ = true;
|
checks.isDouble_ = true;
|
||||||
checks.isNumeric_ = true;
|
checks.isNumeric_ = true;
|
||||||
JSONTEST_ASSERT_PRED(checkIs(val, checks));
|
JSONTEST_ASSERT_PRED(checkIs(val, checks));
|
||||||
@ -1208,8 +1292,6 @@ JSONTEST_FIXTURE_LOCAL(ValueTest, integers) {
|
|||||||
JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue));
|
JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue));
|
||||||
JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue));
|
JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue));
|
||||||
|
|
||||||
JSONTEST_ASSERT_EQUAL(kint64min, val.asInt64());
|
|
||||||
JSONTEST_ASSERT_EQUAL(kint64min, val.asLargestInt());
|
|
||||||
JSONTEST_ASSERT_EQUAL(-9223372036854775808.0, val.asDouble());
|
JSONTEST_ASSERT_EQUAL(-9223372036854775808.0, val.asDouble());
|
||||||
JSONTEST_ASSERT_EQUAL(-9223372036854775808.0, val.asFloat());
|
JSONTEST_ASSERT_EQUAL(-9223372036854775808.0, val.asFloat());
|
||||||
JSONTEST_ASSERT_EQUAL(true, val.asBool());
|
JSONTEST_ASSERT_EQUAL(true, val.asBool());
|
||||||
|
Loading…
x
Reference in New Issue
Block a user