mirror of
https://github.com/Kitware/CMake.git
synced 2026-04-24 23:28:32 -05:00
Merge branch 'upstream-jsoncpp' into update-jsoncpp
* upstream-jsoncpp: jsoncpp 2017-08-27 (4cfae897)
This commit is contained in:
@@ -2,13 +2,13 @@ The JsonCpp library's source code, including accompanying documentation,
|
|||||||
tests and demonstration applications, are licensed under the following
|
tests and demonstration applications, are licensed under the following
|
||||||
conditions...
|
conditions...
|
||||||
|
|
||||||
The author (Baptiste Lepilleur) explicitly disclaims copyright in all
|
Baptiste Lepilleur and The JsonCpp Authors explicitly disclaim copyright in all
|
||||||
jurisdictions which recognize such a disclaimer. In such jurisdictions,
|
jurisdictions which recognize such a disclaimer. In such jurisdictions,
|
||||||
this software is released into the Public Domain.
|
this software is released into the Public Domain.
|
||||||
|
|
||||||
In jurisdictions which do not recognize Public Domain property (e.g. Germany as of
|
In jurisdictions which do not recognize Public Domain property (e.g. Germany as of
|
||||||
2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur, and is
|
2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur and
|
||||||
released under the terms of the MIT License (see below).
|
The JsonCpp Authors, and is released under the terms of the MIT License (see below).
|
||||||
|
|
||||||
In jurisdictions which recognize Public Domain property, the user of this
|
In jurisdictions which recognize Public Domain property, the user of this
|
||||||
software may choose to accept it either as 1) Public Domain, 2) under the
|
software may choose to accept it either as 1) Public Domain, 2) under the
|
||||||
@@ -23,7 +23,7 @@ described in clear, concise terms at:
|
|||||||
The full text of the MIT License follows:
|
The full text of the MIT License follows:
|
||||||
|
|
||||||
========================================================================
|
========================================================================
|
||||||
Copyright (c) 2007-2010 Baptiste Lepilleur
|
Copyright (c) 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person
|
Permission is hereby granted, free of charge, to any person
|
||||||
obtaining a copy of this software and associated documentation
|
obtaining a copy of this software and associated documentation
|
||||||
|
|||||||
@@ -0,0 +1,98 @@
|
|||||||
|
// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
|
||||||
|
// Distributed under MIT license, or public domain if desired and
|
||||||
|
// recognized in your jurisdiction.
|
||||||
|
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
|
|
||||||
|
#ifndef CPPTL_JSON_ALLOCATOR_H_INCLUDED
|
||||||
|
#define CPPTL_JSON_ALLOCATOR_H_INCLUDED
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#pragma pack(push, 8)
|
||||||
|
|
||||||
|
namespace Json {
|
||||||
|
template<typename T>
|
||||||
|
class SecureAllocator {
|
||||||
|
public:
|
||||||
|
// Type definitions
|
||||||
|
using value_type = T;
|
||||||
|
using pointer = T*;
|
||||||
|
using const_pointer = const T*;
|
||||||
|
using reference = T&;
|
||||||
|
using const_reference = const T&;
|
||||||
|
using size_type = std::size_t;
|
||||||
|
using difference_type = std::ptrdiff_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate memory for N items using the standard allocator.
|
||||||
|
*/
|
||||||
|
pointer allocate(size_type n) {
|
||||||
|
// allocate using "global operator new"
|
||||||
|
return static_cast<pointer>(::operator new(n * sizeof(T)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Release memory which was allocated for N items at pointer P.
|
||||||
|
*
|
||||||
|
* The memory block is filled with zeroes before being released.
|
||||||
|
* The pointer argument is tagged as "volatile" to prevent the
|
||||||
|
* compiler optimizing out this critical step.
|
||||||
|
*/
|
||||||
|
void deallocate(volatile pointer p, size_type n) {
|
||||||
|
std::memset(p, 0, n * sizeof(T));
|
||||||
|
// free using "global operator delete"
|
||||||
|
::operator delete(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct an item in-place at pointer P.
|
||||||
|
*/
|
||||||
|
template<typename... Args>
|
||||||
|
void construct(pointer p, Args&&... args) {
|
||||||
|
// construct using "placement new" and "perfect forwarding"
|
||||||
|
::new (static_cast<void*>(p)) T(std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_type max_size() const {
|
||||||
|
return size_t(-1) / sizeof(T);
|
||||||
|
}
|
||||||
|
|
||||||
|
pointer address( reference x ) const {
|
||||||
|
return std::addressof(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
const_pointer address( const_reference x ) const {
|
||||||
|
return std::addressof(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroy an item in-place at pointer P.
|
||||||
|
*/
|
||||||
|
void destroy(pointer p) {
|
||||||
|
// destroy using "explicit destructor"
|
||||||
|
p->~T();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Boilerplate
|
||||||
|
SecureAllocator() {}
|
||||||
|
template<typename U> SecureAllocator(const SecureAllocator<U>&) {}
|
||||||
|
template<typename U> struct rebind { using other = SecureAllocator<U>; };
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template<typename T, typename U>
|
||||||
|
bool operator==(const SecureAllocator<T>&, const SecureAllocator<U>&) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, typename U>
|
||||||
|
bool operator!=(const SecureAllocator<T>&, const SecureAllocator<U>&) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} //namespace Json
|
||||||
|
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
#endif // CPPTL_JSON_ALLOCATOR_H_INCLUDED
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2007-2010 Baptiste Lepilleur
|
// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
|
||||||
// Distributed under MIT license, or public domain if desired and
|
// Distributed under MIT license, or public domain if desired and
|
||||||
// recognized in your jurisdiction.
|
// recognized in your jurisdiction.
|
||||||
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
@@ -11,31 +11,44 @@
|
|||||||
#endif // if !defined(JSON_IS_AMALGAMATION)
|
#endif // if !defined(JSON_IS_AMALGAMATION)
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
/** It should not be possible for a maliciously designed file to
|
||||||
|
* cause an abort() or seg-fault, so these macros are used only
|
||||||
|
* for pre-condition violations and internal logic errors.
|
||||||
|
*/
|
||||||
#if JSON_USE_EXCEPTION
|
#if JSON_USE_EXCEPTION
|
||||||
#include <stdexcept>
|
|
||||||
#define JSON_ASSERT(condition) \
|
// @todo <= add detail about condition in exception
|
||||||
assert(condition); // @todo <= change this into an exception throw
|
# define JSON_ASSERT(condition) \
|
||||||
#define JSON_FAIL_MESSAGE(message) throw std::runtime_error(message);
|
{if (!(condition)) {Json::throwLogicError( "assert json failed" );}}
|
||||||
|
|
||||||
|
# define JSON_FAIL_MESSAGE(message) \
|
||||||
|
{ \
|
||||||
|
JSONCPP_OSTRINGSTREAM oss; oss << message; \
|
||||||
|
Json::throwLogicError(oss.str()); \
|
||||||
|
abort(); \
|
||||||
|
}
|
||||||
|
|
||||||
#else // JSON_USE_EXCEPTION
|
#else // JSON_USE_EXCEPTION
|
||||||
#define JSON_ASSERT(condition) assert(condition);
|
|
||||||
|
# define JSON_ASSERT(condition) assert(condition)
|
||||||
|
|
||||||
// The call to assert() will show the failure message in debug builds. In
|
// The call to assert() will show the failure message in debug builds. In
|
||||||
// release bugs we write to invalid memory in order to crash hard, so that a
|
// release builds we abort, for a core-dump or debugger.
|
||||||
// debugger or crash reporter gets the chance to take over. We still call exit()
|
# define JSON_FAIL_MESSAGE(message) \
|
||||||
// afterward in order to tell the compiler that this macro doesn't return.
|
|
||||||
#define JSON_FAIL_MESSAGE(message) \
|
|
||||||
{ \
|
{ \
|
||||||
assert(false&& message); \
|
JSONCPP_OSTRINGSTREAM oss; oss << message; \
|
||||||
strcpy(reinterpret_cast<char*>(666), message); \
|
assert(false && oss.str().c_str()); \
|
||||||
exit(123); \
|
abort(); \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define JSON_ASSERT_MESSAGE(condition, message) \
|
#define JSON_ASSERT_MESSAGE(condition, message) \
|
||||||
if (!(condition)) { \
|
if (!(condition)) { \
|
||||||
JSON_FAIL_MESSAGE(message) \
|
JSON_FAIL_MESSAGE(message); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // CPPTL_JSON_ASSERTIONS_H_INCLUDED
|
#endif // CPPTL_JSON_ASSERTIONS_H_INCLUDED
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
// Copyright 2007-2010 Baptiste Lepilleur
|
// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
|
||||||
// Distributed under MIT license, or public domain if desired and
|
// Distributed under MIT license, or public domain if desired and
|
||||||
// recognized in your jurisdiction.
|
// recognized in your jurisdiction.
|
||||||
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
|
|
||||||
#ifndef JSON_CONFIG_H_INCLUDED
|
#ifndef JSON_CONFIG_H_INCLUDED
|
||||||
#define JSON_CONFIG_H_INCLUDED
|
#define JSON_CONFIG_H_INCLUDED
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <string> //typedef String
|
||||||
|
#include <stdint.h> //typedef int64_t, uint64_t
|
||||||
|
|
||||||
// Include KWSys Large File Support configuration.
|
// Include KWSys Large File Support configuration.
|
||||||
#include <cmsys/Configure.h>
|
#include <cmsys/Configure.h>
|
||||||
@@ -22,17 +25,6 @@
|
|||||||
/// std::map
|
/// std::map
|
||||||
/// as Value container.
|
/// as Value container.
|
||||||
//# define JSON_USE_CPPTL_SMALLMAP 1
|
//# define JSON_USE_CPPTL_SMALLMAP 1
|
||||||
/// If defined, indicates that Json specific container should be used
|
|
||||||
/// (hash table & simple deque container with customizable allocator).
|
|
||||||
/// THIS FEATURE IS STILL EXPERIMENTAL! There is know bugs: See #3177332
|
|
||||||
//# define JSON_VALUE_USE_INTERNAL_MAP 1
|
|
||||||
/// Force usage of standard new/malloc based allocator instead of memory pool
|
|
||||||
/// based allocator.
|
|
||||||
/// The memory pools allocator used optimization (initializing Value and
|
|
||||||
/// ValueInternalLink
|
|
||||||
/// as if it was a POD) that may cause some validation tool to report errors.
|
|
||||||
/// Only has effects if JSON_VALUE_USE_INTERNAL_MAP is defined.
|
|
||||||
//# define JSON_USE_SIMPLE_INTERNAL_ALLOCATOR 1
|
|
||||||
|
|
||||||
// If non-zero, the library uses exceptions to report bad input instead of C
|
// If non-zero, the library uses exceptions to report bad input instead of C
|
||||||
// assertion macros. The default is to use exceptions.
|
// assertion macros. The default is to use exceptions.
|
||||||
@@ -55,12 +47,12 @@
|
|||||||
#ifdef JSON_IN_CPPTL
|
#ifdef JSON_IN_CPPTL
|
||||||
#define JSON_API CPPTL_API
|
#define JSON_API CPPTL_API
|
||||||
#elif defined(JSON_DLL_BUILD)
|
#elif defined(JSON_DLL_BUILD)
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||||
#define JSON_API __declspec(dllexport)
|
#define JSON_API __declspec(dllexport)
|
||||||
#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
|
#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
|
||||||
#endif // if defined(_MSC_VER)
|
#endif // if defined(_MSC_VER)
|
||||||
#elif defined(JSON_DLL)
|
#elif defined(JSON_DLL)
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||||
#define JSON_API __declspec(dllimport)
|
#define JSON_API __declspec(dllimport)
|
||||||
#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
|
#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
|
||||||
#endif // if defined(_MSC_VER)
|
#endif // if defined(_MSC_VER)
|
||||||
@@ -74,26 +66,96 @@
|
|||||||
// Storages, and 64 bits integer support is disabled.
|
// Storages, and 64 bits integer support is disabled.
|
||||||
// #define JSON_NO_INT64 1
|
// #define JSON_NO_INT64 1
|
||||||
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER <= 1200 // MSVC 6
|
#if defined(_MSC_VER) // MSVC
|
||||||
// Microsoft Visual Studio 6 only support conversion from __int64 to double
|
# if _MSC_VER <= 1200 // MSVC 6
|
||||||
// (no conversion from unsigned __int64).
|
// Microsoft Visual Studio 6 only support conversion from __int64 to double
|
||||||
#define JSON_USE_INT64_DOUBLE_CONVERSION 1
|
// (no conversion from unsigned __int64).
|
||||||
// Disable warning 4786 for VS6 caused by STL (identifier was truncated to '255'
|
# define JSON_USE_INT64_DOUBLE_CONVERSION 1
|
||||||
// characters in the debug information)
|
// Disable warning 4786 for VS6 caused by STL (identifier was truncated to '255'
|
||||||
// All projects I've ever seen with VS6 were using this globally (not bothering
|
// characters in the debug information)
|
||||||
// with pragma push/pop).
|
// All projects I've ever seen with VS6 were using this globally (not bothering
|
||||||
#pragma warning(disable : 4786)
|
// with pragma push/pop).
|
||||||
#endif // if defined(_MSC_VER) && _MSC_VER < 1200 // MSVC 6
|
# pragma warning(disable : 4786)
|
||||||
|
# endif // MSVC 6
|
||||||
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER >= 1500 // MSVC 2008
|
# if _MSC_VER >= 1500 // MSVC 2008
|
||||||
/// Indicates that the following function is deprecated.
|
/// Indicates that the following function is deprecated.
|
||||||
#define JSONCPP_DEPRECATED(message) __declspec(deprecated(message))
|
# define JSONCPP_DEPRECATED(message) __declspec(deprecated(message))
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#endif // defined(_MSC_VER)
|
||||||
|
|
||||||
|
// In c++11 the override keyword allows you to explicity 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
|
||||||
|
# define JSONCPP_OVERRIDE override
|
||||||
|
# define JSONCPP_NOEXCEPT noexcept
|
||||||
|
#elif defined(_MSC_VER) && _MSC_VER > 1600 && _MSC_VER < 1900
|
||||||
|
# define JSONCPP_OVERRIDE override
|
||||||
|
# define JSONCPP_NOEXCEPT throw()
|
||||||
|
#elif defined(_MSC_VER) && _MSC_VER >= 1900
|
||||||
|
# define JSONCPP_OVERRIDE override
|
||||||
|
# define JSONCPP_NOEXCEPT noexcept
|
||||||
|
#else
|
||||||
|
# define JSONCPP_OVERRIDE
|
||||||
|
# define JSONCPP_NOEXCEPT throw()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef JSON_HAS_RVALUE_REFERENCES
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && _MSC_VER >= 1600 // MSVC >= 2010
|
||||||
|
#define JSON_HAS_RVALUE_REFERENCES 1
|
||||||
|
#endif // MSVC >= 2010
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
#if __has_feature(cxx_rvalue_references)
|
||||||
|
#define JSON_HAS_RVALUE_REFERENCES 1
|
||||||
|
#endif // has_feature
|
||||||
|
|
||||||
|
#elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc)
|
||||||
|
#if defined(__GXX_EXPERIMENTAL_CXX0X__) || (__cplusplus >= 201103L)
|
||||||
|
#define JSON_HAS_RVALUE_REFERENCES 1
|
||||||
|
#endif // GXX_EXPERIMENTAL
|
||||||
|
|
||||||
|
#endif // __clang__ || __GNUC__
|
||||||
|
|
||||||
|
#endif // not defined JSON_HAS_RVALUE_REFERENCES
|
||||||
|
|
||||||
|
#ifndef JSON_HAS_RVALUE_REFERENCES
|
||||||
|
#define JSON_HAS_RVALUE_REFERENCES 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
# if __has_extension(attribute_deprecated_with_message)
|
||||||
|
# define JSONCPP_DEPRECATED(message) __attribute__ ((deprecated(message)))
|
||||||
|
# endif
|
||||||
|
#elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc)
|
||||||
|
# if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5))
|
||||||
|
# define JSONCPP_DEPRECATED(message) __attribute__ ((deprecated(message)))
|
||||||
|
# elif (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
|
||||||
|
# define JSONCPP_DEPRECATED(message) __attribute__((__deprecated__))
|
||||||
|
# endif // GNUC version
|
||||||
|
#endif // __clang__ || __GNUC__
|
||||||
|
|
||||||
#if !defined(JSONCPP_DEPRECATED)
|
#if !defined(JSONCPP_DEPRECATED)
|
||||||
#define JSONCPP_DEPRECATED(message)
|
#define JSONCPP_DEPRECATED(message)
|
||||||
#endif // if !defined(JSONCPP_DEPRECATED)
|
#endif // if !defined(JSONCPP_DEPRECATED)
|
||||||
|
|
||||||
|
#if __GNUC__ >= 6
|
||||||
|
# define JSON_USE_INT64_DOUBLE_CONVERSION 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(JSON_IS_AMALGAMATION)
|
||||||
|
|
||||||
|
# include "version.h"
|
||||||
|
|
||||||
|
# if JSONCPP_USING_SECURE_MEMORY
|
||||||
|
# include "allocator.h" //typedef Allocator
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#endif // if !defined(JSON_IS_AMALGAMATION)
|
||||||
|
|
||||||
namespace Json {
|
namespace Json {
|
||||||
typedef int Int;
|
typedef int Int;
|
||||||
typedef unsigned int UInt;
|
typedef unsigned int UInt;
|
||||||
@@ -107,13 +169,26 @@ typedef unsigned int LargestUInt;
|
|||||||
typedef __int64 Int64;
|
typedef __int64 Int64;
|
||||||
typedef unsigned __int64 UInt64;
|
typedef unsigned __int64 UInt64;
|
||||||
#else // if defined(_MSC_VER) // Other platforms, use long long
|
#else // if defined(_MSC_VER) // Other platforms, use long long
|
||||||
typedef long long int Int64;
|
typedef int64_t Int64;
|
||||||
typedef unsigned long long int UInt64;
|
typedef uint64_t UInt64;
|
||||||
#endif // if defined(_MSC_VER)
|
#endif // if defined(_MSC_VER)
|
||||||
typedef Int64 LargestInt;
|
typedef Int64 LargestInt;
|
||||||
typedef UInt64 LargestUInt;
|
typedef UInt64 LargestUInt;
|
||||||
#define JSON_HAS_INT64
|
#define JSON_HAS_INT64
|
||||||
#endif // if defined(JSON_NO_INT64)
|
#endif // if defined(JSON_NO_INT64)
|
||||||
|
#if JSONCPP_USING_SECURE_MEMORY
|
||||||
|
#define JSONCPP_STRING std::basic_string<char, std::char_traits<char>, Json::SecureAllocator<char> >
|
||||||
|
#define JSONCPP_OSTRINGSTREAM std::basic_ostringstream<char, std::char_traits<char>, Json::SecureAllocator<char> >
|
||||||
|
#define JSONCPP_OSTREAM std::basic_ostream<char, std::char_traits<char>>
|
||||||
|
#define JSONCPP_ISTRINGSTREAM std::basic_istringstream<char, std::char_traits<char>, Json::SecureAllocator<char> >
|
||||||
|
#define JSONCPP_ISTREAM std::istream
|
||||||
|
#else
|
||||||
|
#define JSONCPP_STRING std::string
|
||||||
|
#define JSONCPP_OSTRINGSTREAM std::ostringstream
|
||||||
|
#define JSONCPP_OSTREAM std::ostream
|
||||||
|
#define JSONCPP_ISTRINGSTREAM std::istringstream
|
||||||
|
#define JSONCPP_ISTREAM std::istream
|
||||||
|
#endif // if JSONCPP_USING_SECURE_MEMORY
|
||||||
} // end namespace Json
|
} // end namespace Json
|
||||||
|
|
||||||
#endif // JSON_CONFIG_H_INCLUDED
|
#endif // JSON_CONFIG_H_INCLUDED
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2007-2010 Baptiste Lepilleur
|
// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
|
||||||
// Distributed under MIT license, or public domain if desired and
|
// Distributed under MIT license, or public domain if desired and
|
||||||
// recognized in your jurisdiction.
|
// recognized in your jurisdiction.
|
||||||
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
@@ -10,6 +10,8 @@
|
|||||||
#include "forwards.h"
|
#include "forwards.h"
|
||||||
#endif // if !defined(JSON_IS_AMALGAMATION)
|
#endif // if !defined(JSON_IS_AMALGAMATION)
|
||||||
|
|
||||||
|
#pragma pack(push, 8)
|
||||||
|
|
||||||
namespace Json {
|
namespace Json {
|
||||||
|
|
||||||
/** \brief Configuration passed to reader and writer.
|
/** \brief Configuration passed to reader and writer.
|
||||||
@@ -54,4 +56,6 @@ public:
|
|||||||
|
|
||||||
} // namespace Json
|
} // namespace Json
|
||||||
|
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
#endif // CPPTL_JSON_FEATURES_H_INCLUDED
|
#endif // CPPTL_JSON_FEATURES_H_INCLUDED
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2007-2010 Baptiste Lepilleur
|
// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
|
||||||
// Distributed under MIT license, or public domain if desired and
|
// Distributed under MIT license, or public domain if desired and
|
||||||
// recognized in your jurisdiction.
|
// recognized in your jurisdiction.
|
||||||
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
@@ -31,12 +31,6 @@ class Value;
|
|||||||
class ValueIteratorBase;
|
class ValueIteratorBase;
|
||||||
class ValueIterator;
|
class ValueIterator;
|
||||||
class ValueConstIterator;
|
class ValueConstIterator;
|
||||||
#ifdef JSON_VALUE_USE_INTERNAL_MAP
|
|
||||||
class ValueMapAllocator;
|
|
||||||
class ValueInternalLink;
|
|
||||||
class ValueInternalArray;
|
|
||||||
class ValueInternalMap;
|
|
||||||
#endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP
|
|
||||||
|
|
||||||
} // namespace Json
|
} // namespace Json
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2007-2010 Baptiste Lepilleur
|
// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
|
||||||
// Distributed under MIT license, or public domain if desired and
|
// Distributed under MIT license, or public domain if desired and
|
||||||
// recognized in your jurisdiction.
|
// recognized in your jurisdiction.
|
||||||
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2007-2010 Baptiste Lepilleur
|
// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
|
||||||
// Distributed under MIT license, or public domain if desired and
|
// Distributed under MIT license, or public domain if desired and
|
||||||
// recognized in your jurisdiction.
|
// recognized in your jurisdiction.
|
||||||
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
@@ -14,6 +14,7 @@
|
|||||||
#include <iosfwd>
|
#include <iosfwd>
|
||||||
#include <stack>
|
#include <stack>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <istream>
|
||||||
|
|
||||||
// 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...
|
||||||
@@ -22,13 +23,16 @@
|
|||||||
#pragma warning(disable : 4251)
|
#pragma warning(disable : 4251)
|
||||||
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
||||||
|
|
||||||
|
#pragma pack(push, 8)
|
||||||
|
|
||||||
namespace Json {
|
namespace Json {
|
||||||
|
|
||||||
/** \brief Unserialize a <a HREF="http://www.json.org">JSON</a> document into a
|
/** \brief Unserialize a <a HREF="http://www.json.org">JSON</a> document into a
|
||||||
*Value.
|
*Value.
|
||||||
*
|
*
|
||||||
|
* \deprecated Use CharReader and CharReaderBuilder.
|
||||||
*/
|
*/
|
||||||
class JSON_API Reader {
|
class JSONCPP_DEPRECATED("Use CharReader and CharReaderBuilder instead") JSON_API Reader {
|
||||||
public:
|
public:
|
||||||
typedef char Char;
|
typedef char Char;
|
||||||
typedef const Char* Location;
|
typedef const Char* Location;
|
||||||
@@ -40,9 +44,9 @@ public:
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
struct StructuredError {
|
struct StructuredError {
|
||||||
size_t offset_start;
|
ptrdiff_t offset_start;
|
||||||
size_t offset_limit;
|
ptrdiff_t offset_limit;
|
||||||
std::string message;
|
JSONCPP_STRING message;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** \brief Constructs a Reader allowing all features
|
/** \brief Constructs a Reader allowing all features
|
||||||
@@ -78,7 +82,7 @@ public:
|
|||||||
document to read.
|
document to read.
|
||||||
* \param endDoc Pointer on the end of the UTF-8 encoded string of the
|
* \param endDoc Pointer on the end of the UTF-8 encoded string of the
|
||||||
document to read.
|
document to read.
|
||||||
\ Must be >= beginDoc.
|
* Must be >= beginDoc.
|
||||||
* \param root [out] Contains the root value of the document if it was
|
* \param root [out] Contains the root value of the document if it was
|
||||||
* successfully parsed.
|
* successfully parsed.
|
||||||
* \param collectComments \c true to collect comment and allow writing them
|
* \param collectComments \c true to collect comment and allow writing them
|
||||||
@@ -97,7 +101,19 @@ public:
|
|||||||
|
|
||||||
/// \brief Parse from input stream.
|
/// \brief Parse from input stream.
|
||||||
/// \see Json::operator>>(std::istream&, Json::Value&).
|
/// \see Json::operator>>(std::istream&, Json::Value&).
|
||||||
bool parse(std::istream& is, Value& root, bool collectComments = true);
|
bool parse(JSONCPP_ISTREAM& is, Value& root, bool collectComments = true);
|
||||||
|
|
||||||
|
/** \brief Returns a user friendly string that list errors in the parsed
|
||||||
|
* document.
|
||||||
|
* \return Formatted error message with the list of errors with their location
|
||||||
|
* in
|
||||||
|
* the parsed document. An empty string is returned if no error
|
||||||
|
* occurred
|
||||||
|
* during parsing.
|
||||||
|
* \deprecated Use getFormattedErrorMessages() instead (typo fix).
|
||||||
|
*/
|
||||||
|
JSONCPP_DEPRECATED("Use getFormattedErrorMessages() instead.")
|
||||||
|
JSONCPP_STRING getFormatedErrorMessages() const;
|
||||||
|
|
||||||
/** \brief Returns a user friendly string that list errors in the parsed
|
/** \brief Returns a user friendly string that list errors in the parsed
|
||||||
* document.
|
* document.
|
||||||
@@ -107,17 +123,7 @@ public:
|
|||||||
* occurred
|
* occurred
|
||||||
* during parsing.
|
* during parsing.
|
||||||
*/
|
*/
|
||||||
std::string getFormatedErrorMessages() const;
|
JSONCPP_STRING getFormattedErrorMessages() const;
|
||||||
|
|
||||||
/** \brief Returns a user friendly string that list errors in the parsed
|
|
||||||
* document.
|
|
||||||
* \return Formatted error message with the list of errors with their location
|
|
||||||
* in
|
|
||||||
* the parsed document. An empty string is returned if no error
|
|
||||||
* occurred
|
|
||||||
* during parsing.
|
|
||||||
*/
|
|
||||||
std::string getFormattedErrorMessages() const;
|
|
||||||
|
|
||||||
/** \brief Returns a vector of structured erros encounted while parsing.
|
/** \brief Returns a vector of structured erros encounted while parsing.
|
||||||
* \return A (possibly empty) vector of StructuredError objects. Currently
|
* \return A (possibly empty) vector of StructuredError objects. Currently
|
||||||
@@ -134,7 +140,7 @@ public:
|
|||||||
* \return \c true if the error was successfully added, \c false if the
|
* \return \c true if the error was successfully added, \c false if the
|
||||||
* Value offset exceeds the document size.
|
* Value offset exceeds the document size.
|
||||||
*/
|
*/
|
||||||
bool pushError(const Value& value, const std::string& message);
|
bool pushError(const Value& value, const JSONCPP_STRING& message);
|
||||||
|
|
||||||
/** \brief Add a semantic error message with extra context.
|
/** \brief Add a semantic error message with extra context.
|
||||||
* \param value JSON Value location associated with the error
|
* \param value JSON Value location associated with the error
|
||||||
@@ -143,7 +149,7 @@ public:
|
|||||||
* \return \c true if the error was successfully added, \c false if either
|
* \return \c true if the error was successfully added, \c false if either
|
||||||
* Value offset exceeds the document size.
|
* Value offset exceeds the document size.
|
||||||
*/
|
*/
|
||||||
bool pushError(const Value& value, const std::string& message, const Value& extra);
|
bool pushError(const Value& value, const JSONCPP_STRING& message, const Value& extra);
|
||||||
|
|
||||||
/** \brief Return whether there are any errors.
|
/** \brief Return whether there are any errors.
|
||||||
* \return \c true if there are no errors to report \c false if
|
* \return \c true if there are no errors to report \c false if
|
||||||
@@ -179,13 +185,12 @@ private:
|
|||||||
class ErrorInfo {
|
class ErrorInfo {
|
||||||
public:
|
public:
|
||||||
Token token_;
|
Token token_;
|
||||||
std::string message_;
|
JSONCPP_STRING message_;
|
||||||
Location extra_;
|
Location extra_;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::deque<ErrorInfo> Errors;
|
typedef std::deque<ErrorInfo> Errors;
|
||||||
|
|
||||||
bool expectToken(TokenType type, Token& token, const char* message);
|
|
||||||
bool readToken(Token& token);
|
bool readToken(Token& token);
|
||||||
void skipSpaces();
|
void skipSpaces();
|
||||||
bool match(Location pattern, int patternLength);
|
bool match(Location pattern, int patternLength);
|
||||||
@@ -200,7 +205,7 @@ private:
|
|||||||
bool decodeNumber(Token& token);
|
bool decodeNumber(Token& token);
|
||||||
bool decodeNumber(Token& token, Value& decoded);
|
bool decodeNumber(Token& token, Value& decoded);
|
||||||
bool decodeString(Token& token);
|
bool decodeString(Token& token);
|
||||||
bool decodeString(Token& token, std::string& decoded);
|
bool decodeString(Token& token, JSONCPP_STRING& decoded);
|
||||||
bool decodeDouble(Token& token);
|
bool decodeDouble(Token& token);
|
||||||
bool decodeDouble(Token& token, Value& decoded);
|
bool decodeDouble(Token& token, Value& decoded);
|
||||||
bool decodeUnicodeCodePoint(Token& token,
|
bool decodeUnicodeCodePoint(Token& token,
|
||||||
@@ -211,9 +216,9 @@ private:
|
|||||||
Location& current,
|
Location& current,
|
||||||
Location end,
|
Location end,
|
||||||
unsigned int& unicode);
|
unsigned int& unicode);
|
||||||
bool addError(const std::string& message, Token& token, Location extra = 0);
|
bool addError(const JSONCPP_STRING& message, Token& token, Location extra = 0);
|
||||||
bool recoverFromError(TokenType skipUntilToken);
|
bool recoverFromError(TokenType skipUntilToken);
|
||||||
bool addErrorAndRecover(const std::string& message,
|
bool addErrorAndRecover(const JSONCPP_STRING& message,
|
||||||
Token& token,
|
Token& token,
|
||||||
TokenType skipUntilToken);
|
TokenType skipUntilToken);
|
||||||
void skipUntilSpace();
|
void skipUntilSpace();
|
||||||
@@ -221,24 +226,154 @@ private:
|
|||||||
Char getNextChar();
|
Char getNextChar();
|
||||||
void
|
void
|
||||||
getLocationLineAndColumn(Location location, int& line, int& column) const;
|
getLocationLineAndColumn(Location location, int& line, int& column) const;
|
||||||
std::string getLocationLineAndColumn(Location location) const;
|
JSONCPP_STRING getLocationLineAndColumn(Location location) const;
|
||||||
void addComment(Location begin, Location end, CommentPlacement placement);
|
void addComment(Location begin, Location end, CommentPlacement placement);
|
||||||
void skipCommentTokens(Token& token);
|
void skipCommentTokens(Token& token);
|
||||||
|
|
||||||
|
static bool containsNewLine(Location begin, Location end);
|
||||||
|
static JSONCPP_STRING normalizeEOL(Location begin, Location end);
|
||||||
|
|
||||||
typedef std::stack<Value*> Nodes;
|
typedef std::stack<Value*> Nodes;
|
||||||
Nodes nodes_;
|
Nodes nodes_;
|
||||||
Errors errors_;
|
Errors errors_;
|
||||||
std::string document_;
|
JSONCPP_STRING document_;
|
||||||
Location begin_;
|
Location begin_;
|
||||||
Location end_;
|
Location end_;
|
||||||
Location current_;
|
Location current_;
|
||||||
Location lastValueEnd_;
|
Location lastValueEnd_;
|
||||||
Value* lastValue_;
|
Value* lastValue_;
|
||||||
std::string commentsBefore_;
|
JSONCPP_STRING commentsBefore_;
|
||||||
Features features_;
|
Features features_;
|
||||||
bool collectComments_;
|
bool collectComments_;
|
||||||
|
}; // Reader
|
||||||
|
|
||||||
|
/** Interface for reading JSON from a char array.
|
||||||
|
*/
|
||||||
|
class JSON_API CharReader {
|
||||||
|
public:
|
||||||
|
virtual ~CharReader() {}
|
||||||
|
/** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
|
||||||
|
document.
|
||||||
|
* The document must be a UTF-8 encoded string containing the document to read.
|
||||||
|
*
|
||||||
|
* \param beginDoc Pointer on the beginning of the UTF-8 encoded string of the
|
||||||
|
document to read.
|
||||||
|
* \param endDoc Pointer on the end of the UTF-8 encoded string of the
|
||||||
|
document to read.
|
||||||
|
* Must be >= beginDoc.
|
||||||
|
* \param root [out] Contains the root value of the document if it was
|
||||||
|
* successfully parsed.
|
||||||
|
* \param errs [out] Formatted error messages (if not NULL)
|
||||||
|
* a user friendly string that lists errors in the parsed
|
||||||
|
* document.
|
||||||
|
* \return \c true if the document was successfully parsed, \c false if an
|
||||||
|
error occurred.
|
||||||
|
*/
|
||||||
|
virtual bool parse(
|
||||||
|
char const* beginDoc, char const* endDoc,
|
||||||
|
Value* root, JSONCPP_STRING* errs) = 0;
|
||||||
|
|
||||||
|
class JSON_API Factory {
|
||||||
|
public:
|
||||||
|
virtual ~Factory() {}
|
||||||
|
/** \brief Allocate a CharReader via operator new().
|
||||||
|
* \throw std::exception if something goes wrong (e.g. invalid settings)
|
||||||
|
*/
|
||||||
|
virtual CharReader* newCharReader() const = 0;
|
||||||
|
}; // Factory
|
||||||
|
}; // CharReader
|
||||||
|
|
||||||
|
/** \brief Build a CharReader implementation.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
\code
|
||||||
|
using namespace Json;
|
||||||
|
CharReaderBuilder builder;
|
||||||
|
builder["collectComments"] = false;
|
||||||
|
Value value;
|
||||||
|
JSONCPP_STRING errs;
|
||||||
|
bool ok = parseFromStream(builder, std::cin, &value, &errs);
|
||||||
|
\endcode
|
||||||
|
*/
|
||||||
|
class JSON_API CharReaderBuilder : public CharReader::Factory {
|
||||||
|
public:
|
||||||
|
// Note: We use a Json::Value so that we can add data-members to this class
|
||||||
|
// without a major version bump.
|
||||||
|
/** Configuration of this builder.
|
||||||
|
These are case-sensitive.
|
||||||
|
Available settings (case-sensitive):
|
||||||
|
- `"collectComments": false or true`
|
||||||
|
- true to collect comment and allow writing them
|
||||||
|
back during serialization, false to discard comments.
|
||||||
|
This parameter is ignored if allowComments is false.
|
||||||
|
- `"allowComments": false or true`
|
||||||
|
- true if comments are allowed.
|
||||||
|
- `"strictRoot": false or true`
|
||||||
|
- true if root must be either an array or an object value
|
||||||
|
- `"allowDroppedNullPlaceholders": false or true`
|
||||||
|
- true if dropped null placeholders are allowed. (See StreamWriterBuilder.)
|
||||||
|
- `"allowNumericKeys": false or true`
|
||||||
|
- true if numeric object keys are allowed.
|
||||||
|
- `"allowSingleQuotes": false or true`
|
||||||
|
- true if '' are allowed for strings (both keys and values)
|
||||||
|
- `"stackLimit": integer`
|
||||||
|
- Exceeding stackLimit (recursive depth of `readValue()`) will
|
||||||
|
cause an exception.
|
||||||
|
- This is a security issue (seg-faults caused by deeply nested JSON),
|
||||||
|
so the default is low.
|
||||||
|
- `"failIfExtra": false or true`
|
||||||
|
- If true, `parse()` returns false when extra non-whitespace trails
|
||||||
|
the JSON value in the input string.
|
||||||
|
- `"rejectDupKeys": false or true`
|
||||||
|
- If true, `parse()` returns false when a key is duplicated within an object.
|
||||||
|
- `"allowSpecialFloats": false or true`
|
||||||
|
- If true, special float values (NaNs and infinities) are allowed
|
||||||
|
and their values are lossfree restorable.
|
||||||
|
|
||||||
|
You can examine 'settings_` yourself
|
||||||
|
to see the defaults. You can also write and read them just like any
|
||||||
|
JSON Value.
|
||||||
|
\sa setDefaults()
|
||||||
|
*/
|
||||||
|
Json::Value settings_;
|
||||||
|
|
||||||
|
CharReaderBuilder();
|
||||||
|
~CharReaderBuilder() JSONCPP_OVERRIDE;
|
||||||
|
|
||||||
|
CharReader* newCharReader() const JSONCPP_OVERRIDE;
|
||||||
|
|
||||||
|
/** \return true if 'settings' are legal and consistent;
|
||||||
|
* otherwise, indicate bad settings via 'invalid'.
|
||||||
|
*/
|
||||||
|
bool validate(Json::Value* invalid) const;
|
||||||
|
|
||||||
|
/** A simple way to update a specific setting.
|
||||||
|
*/
|
||||||
|
Value& operator[](JSONCPP_STRING key);
|
||||||
|
|
||||||
|
/** Called by ctor, but you can use this to reset settings_.
|
||||||
|
* \pre 'settings' != NULL (but Json::null is fine)
|
||||||
|
* \remark Defaults:
|
||||||
|
* \snippet src/lib_json/json_reader.cpp CharReaderBuilderDefaults
|
||||||
|
*/
|
||||||
|
static void setDefaults(Json::Value* settings);
|
||||||
|
/** Same as old Features::strictMode().
|
||||||
|
* \pre 'settings' != NULL (but Json::null is fine)
|
||||||
|
* \remark Defaults:
|
||||||
|
* \snippet src/lib_json/json_reader.cpp CharReaderBuilderStrictMode
|
||||||
|
*/
|
||||||
|
static void strictMode(Json::Value* settings);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Consume entire stream and use its begin/end.
|
||||||
|
* Someday we might have a real StreamReader, but for now this
|
||||||
|
* is convenient.
|
||||||
|
*/
|
||||||
|
bool JSON_API parseFromStream(
|
||||||
|
CharReader::Factory const&,
|
||||||
|
JSONCPP_ISTREAM&,
|
||||||
|
Value* root, std::string* errs);
|
||||||
|
|
||||||
/** \brief Read from 'sin' into 'root'.
|
/** \brief Read from 'sin' into 'root'.
|
||||||
|
|
||||||
Always keep comments from the input JSON.
|
Always keep comments from the input JSON.
|
||||||
@@ -263,10 +398,12 @@ private:
|
|||||||
\throw std::exception on parse error.
|
\throw std::exception on parse error.
|
||||||
\see Json::operator<<()
|
\see Json::operator<<()
|
||||||
*/
|
*/
|
||||||
JSON_API std::istream& operator>>(std::istream&, Value&);
|
JSON_API JSONCPP_ISTREAM& operator>>(JSONCPP_ISTREAM&, Value&);
|
||||||
|
|
||||||
} // namespace Json
|
} // namespace Json
|
||||||
|
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,14 +1,20 @@
|
|||||||
// DO NOT EDIT. This file is generated by CMake from "version"
|
// DO NOT EDIT. This file (and "version") is generated by CMake.
|
||||||
// and "version.h.in" files.
|
|
||||||
// Run CMake configure step to update it.
|
// Run CMake configure step to update it.
|
||||||
#ifndef JSON_VERSION_H_INCLUDED
|
#ifndef JSON_VERSION_H_INCLUDED
|
||||||
# define JSON_VERSION_H_INCLUDED
|
# define JSON_VERSION_H_INCLUDED
|
||||||
|
|
||||||
# define JSONCPP_VERSION_STRING "1.0.0"
|
# define JSONCPP_VERSION_STRING "1.8.2"
|
||||||
# define JSONCPP_VERSION_MAJOR 1
|
# define JSONCPP_VERSION_MAJOR 1
|
||||||
# define JSONCPP_VERSION_MINOR 0
|
# define JSONCPP_VERSION_MINOR 8
|
||||||
# define JSONCPP_VERSION_PATCH 0
|
# define JSONCPP_VERSION_PATCH 2
|
||||||
# define JSONCPP_VERSION_QUALIFIER
|
# define JSONCPP_VERSION_QUALIFIER
|
||||||
# define JSONCPP_VERSION_HEXA ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | (JSONCPP_VERSION_PATCH << 8))
|
# define JSONCPP_VERSION_HEXA ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | (JSONCPP_VERSION_PATCH << 8))
|
||||||
|
|
||||||
|
#ifdef JSONCPP_USING_SECURE_MEMORY
|
||||||
|
#undef JSONCPP_USING_SECURE_MEMORY
|
||||||
|
#endif
|
||||||
|
#define JSONCPP_USING_SECURE_MEMORY 0
|
||||||
|
// If non-zero, the library zeroes any memory that it has allocated before
|
||||||
|
// it frees its memory.
|
||||||
|
|
||||||
#endif // JSON_VERSION_H_INCLUDED
|
#endif // JSON_VERSION_H_INCLUDED
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2007-2010 Baptiste Lepilleur
|
// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
|
||||||
// Distributed under MIT license, or public domain if desired and
|
// Distributed under MIT license, or public domain if desired and
|
||||||
// recognized in your jurisdiction.
|
// recognized in your jurisdiction.
|
||||||
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
@@ -12,6 +12,7 @@
|
|||||||
#include <iosfwd>
|
#include <iosfwd>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <ostream>
|
||||||
|
|
||||||
// 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...
|
||||||
@@ -20,17 +21,131 @@
|
|||||||
#pragma warning(disable : 4251)
|
#pragma warning(disable : 4251)
|
||||||
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
||||||
|
|
||||||
|
#pragma pack(push, 8)
|
||||||
|
|
||||||
namespace Json {
|
namespace Json {
|
||||||
|
|
||||||
class Value;
|
class Value;
|
||||||
|
|
||||||
/** \brief Abstract class for writers.
|
/**
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
\code
|
||||||
|
using namespace Json;
|
||||||
|
void writeToStdout(StreamWriter::Factory const& factory, Value const& value) {
|
||||||
|
std::unique_ptr<StreamWriter> const writer(
|
||||||
|
factory.newStreamWriter());
|
||||||
|
writer->write(value, &std::cout);
|
||||||
|
std::cout << std::endl; // add lf and flush
|
||||||
|
}
|
||||||
|
\endcode
|
||||||
|
*/
|
||||||
|
class JSON_API StreamWriter {
|
||||||
|
protected:
|
||||||
|
JSONCPP_OSTREAM* sout_; // not owned; will not delete
|
||||||
|
public:
|
||||||
|
StreamWriter();
|
||||||
|
virtual ~StreamWriter();
|
||||||
|
/** Write Value into document as configured in sub-class.
|
||||||
|
Do not take ownership of sout, but maintain a reference during function.
|
||||||
|
\pre sout != NULL
|
||||||
|
\return zero on success (For now, we always return zero, so check the stream instead.)
|
||||||
|
\throw std::exception possibly, depending on configuration
|
||||||
|
*/
|
||||||
|
virtual int write(Value const& root, JSONCPP_OSTREAM* sout) = 0;
|
||||||
|
|
||||||
|
/** \brief A simple abstract factory.
|
||||||
|
*/
|
||||||
|
class JSON_API Factory {
|
||||||
|
public:
|
||||||
|
virtual ~Factory();
|
||||||
|
/** \brief Allocate a CharReader via operator new().
|
||||||
|
* \throw std::exception if something goes wrong (e.g. invalid settings)
|
||||||
|
*/
|
||||||
|
virtual StreamWriter* newStreamWriter() const = 0;
|
||||||
|
}; // Factory
|
||||||
|
}; // StreamWriter
|
||||||
|
|
||||||
|
/** \brief Write into stringstream, then return string, for convenience.
|
||||||
|
* A StreamWriter will be created from the factory, used, and then deleted.
|
||||||
*/
|
*/
|
||||||
class JSON_API Writer {
|
JSONCPP_STRING JSON_API writeString(StreamWriter::Factory const& factory, Value const& root);
|
||||||
|
|
||||||
|
|
||||||
|
/** \brief Build a StreamWriter implementation.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
\code
|
||||||
|
using namespace Json;
|
||||||
|
Value value = ...;
|
||||||
|
StreamWriterBuilder builder;
|
||||||
|
builder["commentStyle"] = "None";
|
||||||
|
builder["indentation"] = " "; // or whatever you like
|
||||||
|
std::unique_ptr<Json::StreamWriter> writer(
|
||||||
|
builder.newStreamWriter());
|
||||||
|
writer->write(value, &std::cout);
|
||||||
|
std::cout << std::endl; // add lf and flush
|
||||||
|
\endcode
|
||||||
|
*/
|
||||||
|
class JSON_API StreamWriterBuilder : public StreamWriter::Factory {
|
||||||
|
public:
|
||||||
|
// Note: We use a Json::Value so that we can add data-members to this class
|
||||||
|
// without a major version bump.
|
||||||
|
/** Configuration of this builder.
|
||||||
|
Available settings (case-sensitive):
|
||||||
|
- "commentStyle": "None" or "All"
|
||||||
|
- "indentation": "<anything>"
|
||||||
|
- "enableYAMLCompatibility": false or true
|
||||||
|
- slightly change the whitespace around colons
|
||||||
|
- "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
|
||||||
|
browser can handle the output just fine.
|
||||||
|
- "useSpecialFloats": false or true
|
||||||
|
- If true, outputs non-finite floating point values in the following way:
|
||||||
|
NaN values as "NaN", positive infinity as "Infinity", and negative infinity
|
||||||
|
as "-Infinity".
|
||||||
|
|
||||||
|
You can examine 'settings_` yourself
|
||||||
|
to see the defaults. You can also write and read them just like any
|
||||||
|
JSON Value.
|
||||||
|
\sa setDefaults()
|
||||||
|
*/
|
||||||
|
Json::Value settings_;
|
||||||
|
|
||||||
|
StreamWriterBuilder();
|
||||||
|
~StreamWriterBuilder() JSONCPP_OVERRIDE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \throw std::exception if something goes wrong (e.g. invalid settings)
|
||||||
|
*/
|
||||||
|
StreamWriter* newStreamWriter() const JSONCPP_OVERRIDE;
|
||||||
|
|
||||||
|
/** \return true if 'settings' are legal and consistent;
|
||||||
|
* otherwise, indicate bad settings via 'invalid'.
|
||||||
|
*/
|
||||||
|
bool validate(Json::Value* invalid) const;
|
||||||
|
/** A simple way to update a specific setting.
|
||||||
|
*/
|
||||||
|
Value& operator[](JSONCPP_STRING key);
|
||||||
|
|
||||||
|
/** Called by ctor, but you can use this to reset settings_.
|
||||||
|
* \pre 'settings' != NULL (but Json::null is fine)
|
||||||
|
* \remark Defaults:
|
||||||
|
* \snippet src/lib_json/json_writer.cpp StreamWriterBuilderDefaults
|
||||||
|
*/
|
||||||
|
static void setDefaults(Json::Value* settings);
|
||||||
|
};
|
||||||
|
|
||||||
|
/** \brief Abstract class for writers.
|
||||||
|
* \deprecated Use StreamWriter. (And really, this is an implementation detail.)
|
||||||
|
*/
|
||||||
|
class JSONCPP_DEPRECATED("Use StreamWriter instead") JSON_API Writer {
|
||||||
public:
|
public:
|
||||||
virtual ~Writer();
|
virtual ~Writer();
|
||||||
|
|
||||||
virtual std::string write(const Value& root) = 0;
|
virtual JSONCPP_STRING write(const Value& root) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** \brief Outputs a Value in <a HREF="http://www.json.org">JSON</a> format
|
/** \brief Outputs a Value in <a HREF="http://www.json.org">JSON</a> format
|
||||||
@@ -40,11 +155,13 @@ public:
|
|||||||
*consumption,
|
*consumption,
|
||||||
* but may be usefull to support feature such as RPC where bandwith is limited.
|
* but may be usefull to support feature such as RPC where bandwith is limited.
|
||||||
* \sa Reader, Value
|
* \sa Reader, Value
|
||||||
|
* \deprecated Use StreamWriterBuilder.
|
||||||
*/
|
*/
|
||||||
class JSON_API FastWriter : public Writer {
|
class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API FastWriter : public Writer {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FastWriter();
|
FastWriter();
|
||||||
virtual ~FastWriter() {}
|
~FastWriter() JSONCPP_OVERRIDE {}
|
||||||
|
|
||||||
void enableYAMLCompatibility();
|
void enableYAMLCompatibility();
|
||||||
|
|
||||||
@@ -58,12 +175,12 @@ public:
|
|||||||
void omitEndingLineFeed();
|
void omitEndingLineFeed();
|
||||||
|
|
||||||
public: // overridden from Writer
|
public: // overridden from Writer
|
||||||
virtual std::string write(const Value& root);
|
JSONCPP_STRING write(const Value& root) JSONCPP_OVERRIDE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void writeValue(const Value& value);
|
void writeValue(const Value& value);
|
||||||
|
|
||||||
std::string document_;
|
JSONCPP_STRING document_;
|
||||||
bool yamlCompatiblityEnabled_;
|
bool yamlCompatiblityEnabled_;
|
||||||
bool dropNullPlaceholders_;
|
bool dropNullPlaceholders_;
|
||||||
bool omitEndingLineFeed_;
|
bool omitEndingLineFeed_;
|
||||||
@@ -91,40 +208,41 @@ private:
|
|||||||
*#CommentPlacement.
|
*#CommentPlacement.
|
||||||
*
|
*
|
||||||
* \sa Reader, Value, Value::setComment()
|
* \sa Reader, Value, Value::setComment()
|
||||||
|
* \deprecated Use StreamWriterBuilder.
|
||||||
*/
|
*/
|
||||||
class JSON_API StyledWriter : public Writer {
|
class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API StyledWriter : public Writer {
|
||||||
public:
|
public:
|
||||||
StyledWriter();
|
StyledWriter();
|
||||||
virtual ~StyledWriter() {}
|
~StyledWriter() JSONCPP_OVERRIDE {}
|
||||||
|
|
||||||
public: // overridden from Writer
|
public: // overridden from Writer
|
||||||
/** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
|
/** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
|
||||||
* \param root Value to serialize.
|
* \param root Value to serialize.
|
||||||
* \return String containing the JSON document that represents the root value.
|
* \return String containing the JSON document that represents the root value.
|
||||||
*/
|
*/
|
||||||
virtual std::string write(const Value& root);
|
JSONCPP_STRING write(const Value& root) JSONCPP_OVERRIDE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void writeValue(const Value& value);
|
void writeValue(const Value& value);
|
||||||
void writeArrayValue(const Value& value);
|
void writeArrayValue(const Value& value);
|
||||||
bool isMultineArray(const Value& value);
|
bool isMultineArray(const Value& value);
|
||||||
void pushValue(const std::string& value);
|
void pushValue(const JSONCPP_STRING& value);
|
||||||
void writeIndent();
|
void writeIndent();
|
||||||
void writeWithIndent(const std::string& value);
|
void writeWithIndent(const JSONCPP_STRING& value);
|
||||||
void indent();
|
void indent();
|
||||||
void unindent();
|
void unindent();
|
||||||
void writeCommentBeforeValue(const Value& root);
|
void writeCommentBeforeValue(const Value& root);
|
||||||
void writeCommentAfterValueOnSameLine(const Value& root);
|
void writeCommentAfterValueOnSameLine(const Value& root);
|
||||||
bool hasCommentForValue(const Value& value);
|
bool hasCommentForValue(const Value& value);
|
||||||
static std::string normalizeEOL(const std::string& text);
|
static JSONCPP_STRING normalizeEOL(const JSONCPP_STRING& text);
|
||||||
|
|
||||||
typedef std::vector<std::string> ChildValues;
|
typedef std::vector<JSONCPP_STRING> ChildValues;
|
||||||
|
|
||||||
ChildValues childValues_;
|
ChildValues childValues_;
|
||||||
std::string document_;
|
JSONCPP_STRING document_;
|
||||||
std::string indentString_;
|
JSONCPP_STRING indentString_;
|
||||||
int rightMargin_;
|
unsigned int rightMargin_;
|
||||||
int indentSize_;
|
unsigned int indentSize_;
|
||||||
bool addChildValues_;
|
bool addChildValues_;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -151,10 +269,14 @@ private:
|
|||||||
#CommentPlacement.
|
#CommentPlacement.
|
||||||
*
|
*
|
||||||
* \sa Reader, Value, Value::setComment()
|
* \sa Reader, Value, Value::setComment()
|
||||||
|
* \deprecated Use StreamWriterBuilder.
|
||||||
*/
|
*/
|
||||||
class JSON_API StyledStreamWriter {
|
class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API StyledStreamWriter {
|
||||||
public:
|
public:
|
||||||
StyledStreamWriter(std::string indentation = "\t");
|
/**
|
||||||
|
* \param indentation Each level will be indented by this amount extra.
|
||||||
|
*/
|
||||||
|
StyledStreamWriter(JSONCPP_STRING indentation = "\t");
|
||||||
~StyledStreamWriter() {}
|
~StyledStreamWriter() {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -164,48 +286,51 @@ public:
|
|||||||
* \note There is no point in deriving from Writer, since write() should not
|
* \note There is no point in deriving from Writer, since write() should not
|
||||||
* return a value.
|
* return a value.
|
||||||
*/
|
*/
|
||||||
void write(std::ostream& out, const Value& root);
|
void write(JSONCPP_OSTREAM& out, const Value& root);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void writeValue(const Value& value);
|
void writeValue(const Value& value);
|
||||||
void writeArrayValue(const Value& value);
|
void writeArrayValue(const Value& value);
|
||||||
bool isMultineArray(const Value& value);
|
bool isMultineArray(const Value& value);
|
||||||
void pushValue(const std::string& value);
|
void pushValue(const JSONCPP_STRING& value);
|
||||||
void writeIndent();
|
void writeIndent();
|
||||||
void writeWithIndent(const std::string& value);
|
void writeWithIndent(const JSONCPP_STRING& value);
|
||||||
void indent();
|
void indent();
|
||||||
void unindent();
|
void unindent();
|
||||||
void writeCommentBeforeValue(const Value& root);
|
void writeCommentBeforeValue(const Value& root);
|
||||||
void writeCommentAfterValueOnSameLine(const Value& root);
|
void writeCommentAfterValueOnSameLine(const Value& root);
|
||||||
bool hasCommentForValue(const Value& value);
|
bool hasCommentForValue(const Value& value);
|
||||||
static std::string normalizeEOL(const std::string& text);
|
static JSONCPP_STRING normalizeEOL(const JSONCPP_STRING& text);
|
||||||
|
|
||||||
typedef std::vector<std::string> ChildValues;
|
typedef std::vector<JSONCPP_STRING> ChildValues;
|
||||||
|
|
||||||
ChildValues childValues_;
|
ChildValues childValues_;
|
||||||
std::ostream* document_;
|
JSONCPP_OSTREAM* document_;
|
||||||
std::string indentString_;
|
JSONCPP_STRING indentString_;
|
||||||
int rightMargin_;
|
unsigned int rightMargin_;
|
||||||
std::string indentation_;
|
JSONCPP_STRING indentation_;
|
||||||
bool addChildValues_;
|
bool addChildValues_ : 1;
|
||||||
|
bool indented_ : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined(JSON_HAS_INT64)
|
#if defined(JSON_HAS_INT64)
|
||||||
std::string JSON_API valueToString(Int value);
|
JSONCPP_STRING JSON_API valueToString(Int value);
|
||||||
std::string JSON_API valueToString(UInt value);
|
JSONCPP_STRING JSON_API valueToString(UInt value);
|
||||||
#endif // if defined(JSON_HAS_INT64)
|
#endif // if defined(JSON_HAS_INT64)
|
||||||
std::string JSON_API valueToString(LargestInt value);
|
JSONCPP_STRING JSON_API valueToString(LargestInt value);
|
||||||
std::string JSON_API valueToString(LargestUInt value);
|
JSONCPP_STRING JSON_API valueToString(LargestUInt value);
|
||||||
std::string JSON_API valueToString(double value);
|
JSONCPP_STRING JSON_API valueToString(double value);
|
||||||
std::string JSON_API valueToString(bool value);
|
JSONCPP_STRING JSON_API valueToString(bool value);
|
||||||
std::string JSON_API valueToQuotedString(const char* value);
|
JSONCPP_STRING JSON_API valueToQuotedString(const char* value);
|
||||||
|
|
||||||
/// \brief Output using the StyledStreamWriter.
|
/// \brief Output using the StyledStreamWriter.
|
||||||
/// \see Json::operator>>()
|
/// \see Json::operator>>()
|
||||||
JSON_API std::ostream& operator<<(std::ostream&, const Value& root);
|
JSON_API JSONCPP_OSTREAM& operator<<(JSONCPP_OSTREAM&, const Value& root);
|
||||||
|
|
||||||
} // namespace Json
|
} // namespace Json
|
||||||
|
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
||||||
|
|||||||
@@ -1,121 +0,0 @@
|
|||||||
// Copyright 2007-2010 Baptiste Lepilleur
|
|
||||||
// Distributed under MIT license, or public domain if desired and
|
|
||||||
// recognized in your jurisdiction.
|
|
||||||
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
|
||||||
|
|
||||||
#ifndef JSONCPP_BATCHALLOCATOR_H_INCLUDED
|
|
||||||
#define JSONCPP_BATCHALLOCATOR_H_INCLUDED
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
|
|
||||||
|
|
||||||
namespace Json {
|
|
||||||
|
|
||||||
/* Fast memory allocator.
|
|
||||||
*
|
|
||||||
* This memory allocator allocates memory for a batch of object (specified by
|
|
||||||
* the page size, the number of object in each page).
|
|
||||||
*
|
|
||||||
* It does not allow the destruction of a single object. All the allocated
|
|
||||||
* objects can be destroyed at once. The memory can be either released or reused
|
|
||||||
* for future allocation.
|
|
||||||
*
|
|
||||||
* The in-place new operator must be used to construct the object using the
|
|
||||||
* pointer returned by allocate.
|
|
||||||
*/
|
|
||||||
template <typename AllocatedType, const unsigned int objectPerAllocation>
|
|
||||||
class BatchAllocator {
|
|
||||||
public:
|
|
||||||
BatchAllocator(unsigned int objectsPerPage = 255)
|
|
||||||
: freeHead_(0), objectsPerPage_(objectsPerPage) {
|
|
||||||
// printf( "Size: %d => %s\n", sizeof(AllocatedType),
|
|
||||||
// typeid(AllocatedType).name() );
|
|
||||||
assert(sizeof(AllocatedType) * objectPerAllocation >=
|
|
||||||
sizeof(AllocatedType*)); // We must be able to store a slist in the
|
|
||||||
// object free space.
|
|
||||||
assert(objectsPerPage >= 16);
|
|
||||||
batches_ = allocateBatch(0); // allocated a dummy page
|
|
||||||
currentBatch_ = batches_;
|
|
||||||
}
|
|
||||||
|
|
||||||
~BatchAllocator() {
|
|
||||||
for (BatchInfo* batch = batches_; batch;) {
|
|
||||||
BatchInfo* nextBatch = batch->next_;
|
|
||||||
free(batch);
|
|
||||||
batch = nextBatch;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// allocate space for an array of objectPerAllocation object.
|
|
||||||
/// @warning it is the responsability of the caller to call objects
|
|
||||||
/// constructors.
|
|
||||||
AllocatedType* allocate() {
|
|
||||||
if (freeHead_) // returns node from free list.
|
|
||||||
{
|
|
||||||
AllocatedType* object = freeHead_;
|
|
||||||
freeHead_ = *(AllocatedType**)object;
|
|
||||||
return object;
|
|
||||||
}
|
|
||||||
if (currentBatch_->used_ == currentBatch_->end_) {
|
|
||||||
currentBatch_ = currentBatch_->next_;
|
|
||||||
while (currentBatch_ && currentBatch_->used_ == currentBatch_->end_)
|
|
||||||
currentBatch_ = currentBatch_->next_;
|
|
||||||
|
|
||||||
if (!currentBatch_) // no free batch found, allocate a new one
|
|
||||||
{
|
|
||||||
currentBatch_ = allocateBatch(objectsPerPage_);
|
|
||||||
currentBatch_->next_ = batches_; // insert at the head of the list
|
|
||||||
batches_ = currentBatch_;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
AllocatedType* allocated = currentBatch_->used_;
|
|
||||||
currentBatch_->used_ += objectPerAllocation;
|
|
||||||
return allocated;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Release the object.
|
|
||||||
/// @warning it is the responsability of the caller to actually destruct the
|
|
||||||
/// object.
|
|
||||||
void release(AllocatedType* object) {
|
|
||||||
assert(object != 0);
|
|
||||||
*(AllocatedType**)object = freeHead_;
|
|
||||||
freeHead_ = object;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
struct BatchInfo {
|
|
||||||
BatchInfo* next_;
|
|
||||||
AllocatedType* used_;
|
|
||||||
AllocatedType* end_;
|
|
||||||
AllocatedType buffer_[objectPerAllocation];
|
|
||||||
};
|
|
||||||
|
|
||||||
// disabled copy constructor and assignement operator.
|
|
||||||
BatchAllocator(const BatchAllocator&);
|
|
||||||
void operator=(const BatchAllocator&);
|
|
||||||
|
|
||||||
static BatchInfo* allocateBatch(unsigned int objectsPerPage) {
|
|
||||||
const unsigned int mallocSize =
|
|
||||||
sizeof(BatchInfo) - sizeof(AllocatedType) * objectPerAllocation +
|
|
||||||
sizeof(AllocatedType) * objectPerAllocation * objectsPerPage;
|
|
||||||
BatchInfo* batch = static_cast<BatchInfo*>(malloc(mallocSize));
|
|
||||||
batch->next_ = 0;
|
|
||||||
batch->used_ = batch->buffer_;
|
|
||||||
batch->end_ = batch->buffer_ + objectsPerPage;
|
|
||||||
return batch;
|
|
||||||
}
|
|
||||||
|
|
||||||
BatchInfo* batches_;
|
|
||||||
BatchInfo* currentBatch_;
|
|
||||||
/// Head of a single linked list within the allocated space of freeed object
|
|
||||||
AllocatedType* freeHead_;
|
|
||||||
unsigned int objectsPerPage_;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Json
|
|
||||||
|
|
||||||
#endif // ifndef JSONCPP_DOC_INCLUDE_IMPLEMENTATION
|
|
||||||
|
|
||||||
#endif // JSONCPP_BATCHALLOCATOR_H_INCLUDED
|
|
||||||
@@ -1,360 +0,0 @@
|
|||||||
// Copyright 2007-2010 Baptiste Lepilleur
|
|
||||||
// Distributed under MIT license, or public domain if desired and
|
|
||||||
// recognized in your jurisdiction.
|
|
||||||
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
|
||||||
|
|
||||||
// included by json_value.cpp
|
|
||||||
|
|
||||||
namespace Json {
|
|
||||||
|
|
||||||
// //////////////////////////////////////////////////////////////////
|
|
||||||
// //////////////////////////////////////////////////////////////////
|
|
||||||
// //////////////////////////////////////////////////////////////////
|
|
||||||
// class ValueInternalArray
|
|
||||||
// //////////////////////////////////////////////////////////////////
|
|
||||||
// //////////////////////////////////////////////////////////////////
|
|
||||||
// //////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
ValueArrayAllocator::~ValueArrayAllocator() {}
|
|
||||||
|
|
||||||
// //////////////////////////////////////////////////////////////////
|
|
||||||
// class DefaultValueArrayAllocator
|
|
||||||
// //////////////////////////////////////////////////////////////////
|
|
||||||
#ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
|
|
||||||
class DefaultValueArrayAllocator : public ValueArrayAllocator {
|
|
||||||
public: // overridden from ValueArrayAllocator
|
|
||||||
virtual ~DefaultValueArrayAllocator() {}
|
|
||||||
|
|
||||||
virtual ValueInternalArray* newArray() { return new ValueInternalArray(); }
|
|
||||||
|
|
||||||
virtual ValueInternalArray* newArrayCopy(const ValueInternalArray& other) {
|
|
||||||
return new ValueInternalArray(other);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void destructArray(ValueInternalArray* array) { delete array; }
|
|
||||||
|
|
||||||
virtual void
|
|
||||||
reallocateArrayPageIndex(Value**& indexes,
|
|
||||||
ValueInternalArray::PageIndex& indexCount,
|
|
||||||
ValueInternalArray::PageIndex minNewIndexCount) {
|
|
||||||
ValueInternalArray::PageIndex newIndexCount = (indexCount * 3) / 2 + 1;
|
|
||||||
if (minNewIndexCount > newIndexCount)
|
|
||||||
newIndexCount = minNewIndexCount;
|
|
||||||
void* newIndexes = realloc(indexes, sizeof(Value*) * newIndexCount);
|
|
||||||
JSON_ASSERT_MESSAGE(newIndexes, "Couldn't realloc.");
|
|
||||||
indexCount = newIndexCount;
|
|
||||||
indexes = static_cast<Value**>(newIndexes);
|
|
||||||
}
|
|
||||||
virtual void releaseArrayPageIndex(Value** indexes,
|
|
||||||
ValueInternalArray::PageIndex indexCount) {
|
|
||||||
if (indexes)
|
|
||||||
free(indexes);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual Value* allocateArrayPage() {
|
|
||||||
return static_cast<Value*>(
|
|
||||||
malloc(sizeof(Value) * ValueInternalArray::itemsPerPage));
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void releaseArrayPage(Value* value) {
|
|
||||||
if (value)
|
|
||||||
free(value);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#else // #ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
|
|
||||||
/// @todo make this thread-safe (lock when accessign batch allocator)
|
|
||||||
class DefaultValueArrayAllocator : public ValueArrayAllocator {
|
|
||||||
public: // overridden from ValueArrayAllocator
|
|
||||||
virtual ~DefaultValueArrayAllocator() {}
|
|
||||||
|
|
||||||
virtual ValueInternalArray* newArray() {
|
|
||||||
ValueInternalArray* array = arraysAllocator_.allocate();
|
|
||||||
new (array) ValueInternalArray(); // placement new
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ValueInternalArray* newArrayCopy(const ValueInternalArray& other) {
|
|
||||||
ValueInternalArray* array = arraysAllocator_.allocate();
|
|
||||||
new (array) ValueInternalArray(other); // placement new
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void destructArray(ValueInternalArray* array) {
|
|
||||||
if (array) {
|
|
||||||
array->~ValueInternalArray();
|
|
||||||
arraysAllocator_.release(array);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void
|
|
||||||
reallocateArrayPageIndex(Value**& indexes,
|
|
||||||
ValueInternalArray::PageIndex& indexCount,
|
|
||||||
ValueInternalArray::PageIndex minNewIndexCount) {
|
|
||||||
ValueInternalArray::PageIndex newIndexCount = (indexCount * 3) / 2 + 1;
|
|
||||||
if (minNewIndexCount > newIndexCount)
|
|
||||||
newIndexCount = minNewIndexCount;
|
|
||||||
void* newIndexes = realloc(indexes, sizeof(Value*) * newIndexCount);
|
|
||||||
JSON_ASSERT_MESSAGE(newIndexes, "Couldn't realloc.");
|
|
||||||
indexCount = newIndexCount;
|
|
||||||
indexes = static_cast<Value**>(newIndexes);
|
|
||||||
}
|
|
||||||
virtual void releaseArrayPageIndex(Value** indexes,
|
|
||||||
ValueInternalArray::PageIndex indexCount) {
|
|
||||||
if (indexes)
|
|
||||||
free(indexes);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual Value* allocateArrayPage() {
|
|
||||||
return static_cast<Value*>(pagesAllocator_.allocate());
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void releaseArrayPage(Value* value) {
|
|
||||||
if (value)
|
|
||||||
pagesAllocator_.release(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
BatchAllocator<ValueInternalArray, 1> arraysAllocator_;
|
|
||||||
BatchAllocator<Value, ValueInternalArray::itemsPerPage> pagesAllocator_;
|
|
||||||
};
|
|
||||||
#endif // #ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
|
|
||||||
|
|
||||||
static ValueArrayAllocator*& arrayAllocator() {
|
|
||||||
static DefaultValueArrayAllocator defaultAllocator;
|
|
||||||
static ValueArrayAllocator* arrayAllocator = &defaultAllocator;
|
|
||||||
return arrayAllocator;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct DummyArrayAllocatorInitializer {
|
|
||||||
DummyArrayAllocatorInitializer() {
|
|
||||||
arrayAllocator(); // ensure arrayAllocator() statics are initialized before
|
|
||||||
// main().
|
|
||||||
}
|
|
||||||
} dummyArrayAllocatorInitializer;
|
|
||||||
|
|
||||||
// //////////////////////////////////////////////////////////////////
|
|
||||||
// class ValueInternalArray
|
|
||||||
// //////////////////////////////////////////////////////////////////
|
|
||||||
bool ValueInternalArray::equals(const IteratorState& x,
|
|
||||||
const IteratorState& other) {
|
|
||||||
return x.array_ == other.array_ &&
|
|
||||||
x.currentItemIndex_ == other.currentItemIndex_ &&
|
|
||||||
x.currentPageIndex_ == other.currentPageIndex_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ValueInternalArray::increment(IteratorState& it) {
|
|
||||||
JSON_ASSERT_MESSAGE(
|
|
||||||
it.array_ && (it.currentPageIndex_ - it.array_->pages_) * itemsPerPage +
|
|
||||||
it.currentItemIndex_ !=
|
|
||||||
it.array_->size_,
|
|
||||||
"ValueInternalArray::increment(): moving iterator beyond end");
|
|
||||||
++(it.currentItemIndex_);
|
|
||||||
if (it.currentItemIndex_ == itemsPerPage) {
|
|
||||||
it.currentItemIndex_ = 0;
|
|
||||||
++(it.currentPageIndex_);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ValueInternalArray::decrement(IteratorState& it) {
|
|
||||||
JSON_ASSERT_MESSAGE(
|
|
||||||
it.array_ && it.currentPageIndex_ == it.array_->pages_ &&
|
|
||||||
it.currentItemIndex_ == 0,
|
|
||||||
"ValueInternalArray::decrement(): moving iterator beyond end");
|
|
||||||
if (it.currentItemIndex_ == 0) {
|
|
||||||
it.currentItemIndex_ = itemsPerPage - 1;
|
|
||||||
--(it.currentPageIndex_);
|
|
||||||
} else {
|
|
||||||
--(it.currentItemIndex_);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Value& ValueInternalArray::unsafeDereference(const IteratorState& it) {
|
|
||||||
return (*(it.currentPageIndex_))[it.currentItemIndex_];
|
|
||||||
}
|
|
||||||
|
|
||||||
Value& ValueInternalArray::dereference(const IteratorState& it) {
|
|
||||||
JSON_ASSERT_MESSAGE(
|
|
||||||
it.array_ && (it.currentPageIndex_ - it.array_->pages_) * itemsPerPage +
|
|
||||||
it.currentItemIndex_ <
|
|
||||||
it.array_->size_,
|
|
||||||
"ValueInternalArray::dereference(): dereferencing invalid iterator");
|
|
||||||
return unsafeDereference(it);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ValueInternalArray::makeBeginIterator(IteratorState& it) const {
|
|
||||||
it.array_ = const_cast<ValueInternalArray*>(this);
|
|
||||||
it.currentItemIndex_ = 0;
|
|
||||||
it.currentPageIndex_ = pages_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ValueInternalArray::makeIterator(IteratorState& it,
|
|
||||||
ArrayIndex index) const {
|
|
||||||
it.array_ = const_cast<ValueInternalArray*>(this);
|
|
||||||
it.currentItemIndex_ = index % itemsPerPage;
|
|
||||||
it.currentPageIndex_ = pages_ + index / itemsPerPage;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ValueInternalArray::makeEndIterator(IteratorState& it) const {
|
|
||||||
makeIterator(it, size_);
|
|
||||||
}
|
|
||||||
|
|
||||||
ValueInternalArray::ValueInternalArray() : pages_(0), size_(0), pageCount_(0) {}
|
|
||||||
|
|
||||||
ValueInternalArray::ValueInternalArray(const ValueInternalArray& other)
|
|
||||||
: pages_(0), size_(other.size_), pageCount_(0) {
|
|
||||||
PageIndex minNewPages = other.size_ / itemsPerPage;
|
|
||||||
arrayAllocator()->reallocateArrayPageIndex(pages_, pageCount_, minNewPages);
|
|
||||||
JSON_ASSERT_MESSAGE(pageCount_ >= minNewPages,
|
|
||||||
"ValueInternalArray::reserve(): bad reallocation");
|
|
||||||
IteratorState itOther;
|
|
||||||
other.makeBeginIterator(itOther);
|
|
||||||
Value* value;
|
|
||||||
for (ArrayIndex index = 0; index < size_; ++index, increment(itOther)) {
|
|
||||||
if (index % itemsPerPage == 0) {
|
|
||||||
PageIndex pageIndex = index / itemsPerPage;
|
|
||||||
value = arrayAllocator()->allocateArrayPage();
|
|
||||||
pages_[pageIndex] = value;
|
|
||||||
}
|
|
||||||
new (value) Value(dereference(itOther));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ValueInternalArray& ValueInternalArray::operator=(ValueInternalArray other) {
|
|
||||||
swap(other);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ValueInternalArray::~ValueInternalArray() {
|
|
||||||
// destroy all constructed items
|
|
||||||
IteratorState it;
|
|
||||||
IteratorState itEnd;
|
|
||||||
makeBeginIterator(it);
|
|
||||||
makeEndIterator(itEnd);
|
|
||||||
for (; !equals(it, itEnd); increment(it)) {
|
|
||||||
Value* value = &dereference(it);
|
|
||||||
value->~Value();
|
|
||||||
}
|
|
||||||
// release all pages
|
|
||||||
PageIndex lastPageIndex = size_ / itemsPerPage;
|
|
||||||
for (PageIndex pageIndex = 0; pageIndex < lastPageIndex; ++pageIndex)
|
|
||||||
arrayAllocator()->releaseArrayPage(pages_[pageIndex]);
|
|
||||||
// release pages index
|
|
||||||
arrayAllocator()->releaseArrayPageIndex(pages_, pageCount_);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ValueInternalArray::swap(ValueInternalArray& other) {
|
|
||||||
Value** tempPages = pages_;
|
|
||||||
pages_ = other.pages_;
|
|
||||||
other.pages_ = tempPages;
|
|
||||||
ArrayIndex tempSize = size_;
|
|
||||||
size_ = other.size_;
|
|
||||||
other.size_ = tempSize;
|
|
||||||
PageIndex tempPageCount = pageCount_;
|
|
||||||
pageCount_ = other.pageCount_;
|
|
||||||
other.pageCount_ = tempPageCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ValueInternalArray::clear() {
|
|
||||||
ValueInternalArray dummy;
|
|
||||||
swap(dummy);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ValueInternalArray::resize(ArrayIndex newSize) {
|
|
||||||
if (newSize == 0)
|
|
||||||
clear();
|
|
||||||
else if (newSize < size_) {
|
|
||||||
IteratorState it;
|
|
||||||
IteratorState itEnd;
|
|
||||||
makeIterator(it, newSize);
|
|
||||||
makeIterator(itEnd, size_);
|
|
||||||
for (; !equals(it, itEnd); increment(it)) {
|
|
||||||
Value* value = &dereference(it);
|
|
||||||
value->~Value();
|
|
||||||
}
|
|
||||||
PageIndex pageIndex = (newSize + itemsPerPage - 1) / itemsPerPage;
|
|
||||||
PageIndex lastPageIndex = size_ / itemsPerPage;
|
|
||||||
for (; pageIndex < lastPageIndex; ++pageIndex)
|
|
||||||
arrayAllocator()->releaseArrayPage(pages_[pageIndex]);
|
|
||||||
size_ = newSize;
|
|
||||||
} else if (newSize > size_)
|
|
||||||
resolveReference(newSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ValueInternalArray::makeIndexValid(ArrayIndex index) {
|
|
||||||
// Need to enlarge page index ?
|
|
||||||
if (index >= pageCount_ * itemsPerPage) {
|
|
||||||
PageIndex minNewPages = (index + 1) / itemsPerPage;
|
|
||||||
arrayAllocator()->reallocateArrayPageIndex(pages_, pageCount_, minNewPages);
|
|
||||||
JSON_ASSERT_MESSAGE(pageCount_ >= minNewPages,
|
|
||||||
"ValueInternalArray::reserve(): bad reallocation");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Need to allocate new pages ?
|
|
||||||
ArrayIndex nextPageIndex = (size_ % itemsPerPage) != 0
|
|
||||||
? size_ - (size_ % itemsPerPage) + itemsPerPage
|
|
||||||
: size_;
|
|
||||||
if (nextPageIndex <= index) {
|
|
||||||
PageIndex pageIndex = nextPageIndex / itemsPerPage;
|
|
||||||
PageIndex pageToAllocate = (index - nextPageIndex) / itemsPerPage + 1;
|
|
||||||
for (; pageToAllocate-- > 0; ++pageIndex)
|
|
||||||
pages_[pageIndex] = arrayAllocator()->allocateArrayPage();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize all new entries
|
|
||||||
IteratorState it;
|
|
||||||
IteratorState itEnd;
|
|
||||||
makeIterator(it, size_);
|
|
||||||
size_ = index + 1;
|
|
||||||
makeIterator(itEnd, size_);
|
|
||||||
for (; !equals(it, itEnd); increment(it)) {
|
|
||||||
Value* value = &dereference(it);
|
|
||||||
new (value) Value(); // Construct a default value using placement new
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Value& ValueInternalArray::resolveReference(ArrayIndex index) {
|
|
||||||
if (index >= size_)
|
|
||||||
makeIndexValid(index);
|
|
||||||
return pages_[index / itemsPerPage][index % itemsPerPage];
|
|
||||||
}
|
|
||||||
|
|
||||||
Value* ValueInternalArray::find(ArrayIndex index) const {
|
|
||||||
if (index >= size_)
|
|
||||||
return 0;
|
|
||||||
return &(pages_[index / itemsPerPage][index % itemsPerPage]);
|
|
||||||
}
|
|
||||||
|
|
||||||
ValueInternalArray::ArrayIndex ValueInternalArray::size() const {
|
|
||||||
return size_;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ValueInternalArray::distance(const IteratorState& x,
|
|
||||||
const IteratorState& y) {
|
|
||||||
return indexOf(y) - indexOf(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
ValueInternalArray::ArrayIndex
|
|
||||||
ValueInternalArray::indexOf(const IteratorState& iterator) {
|
|
||||||
if (!iterator.array_)
|
|
||||||
return ArrayIndex(-1);
|
|
||||||
return ArrayIndex((iterator.currentPageIndex_ - iterator.array_->pages_) *
|
|
||||||
itemsPerPage +
|
|
||||||
iterator.currentItemIndex_);
|
|
||||||
}
|
|
||||||
|
|
||||||
int ValueInternalArray::compare(const ValueInternalArray& other) const {
|
|
||||||
int sizeDiff(size_ - other.size_);
|
|
||||||
if (sizeDiff != 0)
|
|
||||||
return sizeDiff;
|
|
||||||
|
|
||||||
for (ArrayIndex index = 0; index < size_; ++index) {
|
|
||||||
int diff = pages_[index / itemsPerPage][index % itemsPerPage].compare(
|
|
||||||
other.pages_[index / itemsPerPage][index % itemsPerPage]);
|
|
||||||
if (diff != 0)
|
|
||||||
return diff;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Json
|
|
||||||
@@ -1,473 +0,0 @@
|
|||||||
// Copyright 2007-2010 Baptiste Lepilleur
|
|
||||||
// Distributed under MIT license, or public domain if desired and
|
|
||||||
// recognized in your jurisdiction.
|
|
||||||
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
|
||||||
|
|
||||||
// included by json_value.cpp
|
|
||||||
|
|
||||||
namespace Json {
|
|
||||||
|
|
||||||
// //////////////////////////////////////////////////////////////////
|
|
||||||
// //////////////////////////////////////////////////////////////////
|
|
||||||
// //////////////////////////////////////////////////////////////////
|
|
||||||
// class ValueInternalMap
|
|
||||||
// //////////////////////////////////////////////////////////////////
|
|
||||||
// //////////////////////////////////////////////////////////////////
|
|
||||||
// //////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
/** \internal MUST be safely initialized using memset( this, 0,
|
|
||||||
* sizeof(ValueInternalLink) );
|
|
||||||
* This optimization is used by the fast allocator.
|
|
||||||
*/
|
|
||||||
ValueInternalLink::ValueInternalLink() : previous_(0), next_(0) {}
|
|
||||||
|
|
||||||
ValueInternalLink::~ValueInternalLink() {
|
|
||||||
for (int index = 0; index < itemPerLink; ++index) {
|
|
||||||
if (!items_[index].isItemAvailable()) {
|
|
||||||
if (!items_[index].isMemberNameStatic())
|
|
||||||
free(keys_[index]);
|
|
||||||
} else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ValueMapAllocator::~ValueMapAllocator() {}
|
|
||||||
|
|
||||||
#ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
|
|
||||||
class DefaultValueMapAllocator : public ValueMapAllocator {
|
|
||||||
public: // overridden from ValueMapAllocator
|
|
||||||
virtual ValueInternalMap* newMap() { return new ValueInternalMap(); }
|
|
||||||
|
|
||||||
virtual ValueInternalMap* newMapCopy(const ValueInternalMap& other) {
|
|
||||||
return new ValueInternalMap(other);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void destructMap(ValueInternalMap* map) { delete map; }
|
|
||||||
|
|
||||||
virtual ValueInternalLink* allocateMapBuckets(unsigned int size) {
|
|
||||||
return new ValueInternalLink[size];
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void releaseMapBuckets(ValueInternalLink* links) { delete[] links; }
|
|
||||||
|
|
||||||
virtual ValueInternalLink* allocateMapLink() {
|
|
||||||
return new ValueInternalLink();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void releaseMapLink(ValueInternalLink* link) { delete link; }
|
|
||||||
};
|
|
||||||
#else
|
|
||||||
/// @todo make this thread-safe (lock when accessign batch allocator)
|
|
||||||
class DefaultValueMapAllocator : public ValueMapAllocator {
|
|
||||||
public: // overridden from ValueMapAllocator
|
|
||||||
virtual ValueInternalMap* newMap() {
|
|
||||||
ValueInternalMap* map = mapsAllocator_.allocate();
|
|
||||||
new (map) ValueInternalMap(); // placement new
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ValueInternalMap* newMapCopy(const ValueInternalMap& other) {
|
|
||||||
ValueInternalMap* map = mapsAllocator_.allocate();
|
|
||||||
new (map) ValueInternalMap(other); // placement new
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void destructMap(ValueInternalMap* map) {
|
|
||||||
if (map) {
|
|
||||||
map->~ValueInternalMap();
|
|
||||||
mapsAllocator_.release(map);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ValueInternalLink* allocateMapBuckets(unsigned int size) {
|
|
||||||
return new ValueInternalLink[size];
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void releaseMapBuckets(ValueInternalLink* links) { delete[] links; }
|
|
||||||
|
|
||||||
virtual ValueInternalLink* allocateMapLink() {
|
|
||||||
ValueInternalLink* link = linksAllocator_.allocate();
|
|
||||||
memset(link, 0, sizeof(ValueInternalLink));
|
|
||||||
return link;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void releaseMapLink(ValueInternalLink* link) {
|
|
||||||
link->~ValueInternalLink();
|
|
||||||
linksAllocator_.release(link);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
BatchAllocator<ValueInternalMap, 1> mapsAllocator_;
|
|
||||||
BatchAllocator<ValueInternalLink, 1> linksAllocator_;
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static ValueMapAllocator*& mapAllocator() {
|
|
||||||
static DefaultValueMapAllocator defaultAllocator;
|
|
||||||
static ValueMapAllocator* mapAllocator = &defaultAllocator;
|
|
||||||
return mapAllocator;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct DummyMapAllocatorInitializer {
|
|
||||||
DummyMapAllocatorInitializer() {
|
|
||||||
mapAllocator(); // ensure mapAllocator() statics are initialized before
|
|
||||||
// main().
|
|
||||||
}
|
|
||||||
} dummyMapAllocatorInitializer;
|
|
||||||
|
|
||||||
// h(K) = value * K >> w ; with w = 32 & K prime w.r.t. 2^32.
|
|
||||||
|
|
||||||
/*
|
|
||||||
use linked list hash map.
|
|
||||||
buckets array is a container.
|
|
||||||
linked list element contains 6 key/values. (memory = (16+4) * 6 + 4 = 124)
|
|
||||||
value have extra state: valid, available, deleted
|
|
||||||
*/
|
|
||||||
|
|
||||||
ValueInternalMap::ValueInternalMap()
|
|
||||||
: buckets_(0), tailLink_(0), bucketsSize_(0), itemCount_(0) {}
|
|
||||||
|
|
||||||
ValueInternalMap::ValueInternalMap(const ValueInternalMap& other)
|
|
||||||
: buckets_(0), tailLink_(0), bucketsSize_(0), itemCount_(0) {
|
|
||||||
reserve(other.itemCount_);
|
|
||||||
IteratorState it;
|
|
||||||
IteratorState itEnd;
|
|
||||||
other.makeBeginIterator(it);
|
|
||||||
other.makeEndIterator(itEnd);
|
|
||||||
for (; !equals(it, itEnd); increment(it)) {
|
|
||||||
bool isStatic;
|
|
||||||
const char* memberName = key(it, isStatic);
|
|
||||||
const Value& aValue = value(it);
|
|
||||||
resolveReference(memberName, isStatic) = aValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ValueInternalMap& ValueInternalMap::operator=(ValueInternalMap other) {
|
|
||||||
swap(other);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ValueInternalMap::~ValueInternalMap() {
|
|
||||||
if (buckets_) {
|
|
||||||
for (BucketIndex bucketIndex = 0; bucketIndex < bucketsSize_;
|
|
||||||
++bucketIndex) {
|
|
||||||
ValueInternalLink* link = buckets_[bucketIndex].next_;
|
|
||||||
while (link) {
|
|
||||||
ValueInternalLink* linkToRelease = link;
|
|
||||||
link = link->next_;
|
|
||||||
mapAllocator()->releaseMapLink(linkToRelease);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mapAllocator()->releaseMapBuckets(buckets_);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ValueInternalMap::swap(ValueInternalMap& other) {
|
|
||||||
ValueInternalLink* tempBuckets = buckets_;
|
|
||||||
buckets_ = other.buckets_;
|
|
||||||
other.buckets_ = tempBuckets;
|
|
||||||
ValueInternalLink* tempTailLink = tailLink_;
|
|
||||||
tailLink_ = other.tailLink_;
|
|
||||||
other.tailLink_ = tempTailLink;
|
|
||||||
BucketIndex tempBucketsSize = bucketsSize_;
|
|
||||||
bucketsSize_ = other.bucketsSize_;
|
|
||||||
other.bucketsSize_ = tempBucketsSize;
|
|
||||||
BucketIndex tempItemCount = itemCount_;
|
|
||||||
itemCount_ = other.itemCount_;
|
|
||||||
other.itemCount_ = tempItemCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ValueInternalMap::clear() {
|
|
||||||
ValueInternalMap dummy;
|
|
||||||
swap(dummy);
|
|
||||||
}
|
|
||||||
|
|
||||||
ValueInternalMap::BucketIndex ValueInternalMap::size() const {
|
|
||||||
return itemCount_;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ValueInternalMap::reserveDelta(BucketIndex growth) {
|
|
||||||
return reserve(itemCount_ + growth);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ValueInternalMap::reserve(BucketIndex newItemCount) {
|
|
||||||
if (!buckets_ && newItemCount > 0) {
|
|
||||||
buckets_ = mapAllocator()->allocateMapBuckets(1);
|
|
||||||
bucketsSize_ = 1;
|
|
||||||
tailLink_ = &buckets_[0];
|
|
||||||
}
|
|
||||||
// BucketIndex idealBucketCount = (newItemCount +
|
|
||||||
// ValueInternalLink::itemPerLink) / ValueInternalLink::itemPerLink;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Value* ValueInternalMap::find(const char* key) const {
|
|
||||||
if (!bucketsSize_)
|
|
||||||
return 0;
|
|
||||||
HashKey hashedKey = hash(key);
|
|
||||||
BucketIndex bucketIndex = hashedKey % bucketsSize_;
|
|
||||||
for (const ValueInternalLink* current = &buckets_[bucketIndex]; current != 0;
|
|
||||||
current = current->next_) {
|
|
||||||
for (BucketIndex index = 0; index < ValueInternalLink::itemPerLink;
|
|
||||||
++index) {
|
|
||||||
if (current->items_[index].isItemAvailable())
|
|
||||||
return 0;
|
|
||||||
if (strcmp(key, current->keys_[index]) == 0)
|
|
||||||
return ¤t->items_[index];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Value* ValueInternalMap::find(const char* key) {
|
|
||||||
const ValueInternalMap* constThis = this;
|
|
||||||
return const_cast<Value*>(constThis->find(key));
|
|
||||||
}
|
|
||||||
|
|
||||||
Value& ValueInternalMap::resolveReference(const char* key, bool isStatic) {
|
|
||||||
HashKey hashedKey = hash(key);
|
|
||||||
if (bucketsSize_) {
|
|
||||||
BucketIndex bucketIndex = hashedKey % bucketsSize_;
|
|
||||||
ValueInternalLink** previous = 0;
|
|
||||||
BucketIndex index;
|
|
||||||
for (ValueInternalLink* current = &buckets_[bucketIndex]; current != 0;
|
|
||||||
previous = ¤t->next_, current = current->next_) {
|
|
||||||
for (index = 0; index < ValueInternalLink::itemPerLink; ++index) {
|
|
||||||
if (current->items_[index].isItemAvailable())
|
|
||||||
return setNewItem(key, isStatic, current, index);
|
|
||||||
if (strcmp(key, current->keys_[index]) == 0)
|
|
||||||
return current->items_[index];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
reserveDelta(1);
|
|
||||||
return unsafeAdd(key, isStatic, hashedKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ValueInternalMap::remove(const char* key) {
|
|
||||||
HashKey hashedKey = hash(key);
|
|
||||||
if (!bucketsSize_)
|
|
||||||
return;
|
|
||||||
BucketIndex bucketIndex = hashedKey % bucketsSize_;
|
|
||||||
for (ValueInternalLink* link = &buckets_[bucketIndex]; link != 0;
|
|
||||||
link = link->next_) {
|
|
||||||
BucketIndex index;
|
|
||||||
for (index = 0; index < ValueInternalLink::itemPerLink; ++index) {
|
|
||||||
if (link->items_[index].isItemAvailable())
|
|
||||||
return;
|
|
||||||
if (strcmp(key, link->keys_[index]) == 0) {
|
|
||||||
doActualRemove(link, index, bucketIndex);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ValueInternalMap::doActualRemove(ValueInternalLink* link,
|
|
||||||
BucketIndex index,
|
|
||||||
BucketIndex bucketIndex) {
|
|
||||||
// find last item of the bucket and swap it with the 'removed' one.
|
|
||||||
// set removed items flags to 'available'.
|
|
||||||
// if last page only contains 'available' items, then desallocate it (it's
|
|
||||||
// empty)
|
|
||||||
ValueInternalLink*& lastLink = getLastLinkInBucket(index);
|
|
||||||
BucketIndex lastItemIndex = 1; // a link can never be empty, so start at 1
|
|
||||||
for (; lastItemIndex < ValueInternalLink::itemPerLink;
|
|
||||||
++lastItemIndex) // may be optimized with dicotomic search
|
|
||||||
{
|
|
||||||
if (lastLink->items_[lastItemIndex].isItemAvailable())
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
BucketIndex lastUsedIndex = lastItemIndex - 1;
|
|
||||||
Value* valueToDelete = &link->items_[index];
|
|
||||||
Value* valueToPreserve = &lastLink->items_[lastUsedIndex];
|
|
||||||
if (valueToDelete != valueToPreserve)
|
|
||||||
valueToDelete->swap(*valueToPreserve);
|
|
||||||
if (lastUsedIndex == 0) // page is now empty
|
|
||||||
{ // remove it from bucket linked list and delete it.
|
|
||||||
ValueInternalLink* linkPreviousToLast = lastLink->previous_;
|
|
||||||
if (linkPreviousToLast != 0) // can not deleted bucket link.
|
|
||||||
{
|
|
||||||
mapAllocator()->releaseMapLink(lastLink);
|
|
||||||
linkPreviousToLast->next_ = 0;
|
|
||||||
lastLink = linkPreviousToLast;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Value dummy;
|
|
||||||
valueToPreserve->swap(dummy); // restore deleted to default Value.
|
|
||||||
valueToPreserve->setItemUsed(false);
|
|
||||||
}
|
|
||||||
--itemCount_;
|
|
||||||
}
|
|
||||||
|
|
||||||
ValueInternalLink*&
|
|
||||||
ValueInternalMap::getLastLinkInBucket(BucketIndex bucketIndex) {
|
|
||||||
if (bucketIndex == bucketsSize_ - 1)
|
|
||||||
return tailLink_;
|
|
||||||
ValueInternalLink*& previous = buckets_[bucketIndex + 1].previous_;
|
|
||||||
if (!previous)
|
|
||||||
previous = &buckets_[bucketIndex];
|
|
||||||
return previous;
|
|
||||||
}
|
|
||||||
|
|
||||||
Value& ValueInternalMap::setNewItem(const char* key,
|
|
||||||
bool isStatic,
|
|
||||||
ValueInternalLink* link,
|
|
||||||
BucketIndex index) {
|
|
||||||
char* duplicatedKey = makeMemberName(key);
|
|
||||||
++itemCount_;
|
|
||||||
link->keys_[index] = duplicatedKey;
|
|
||||||
link->items_[index].setItemUsed();
|
|
||||||
link->items_[index].setMemberNameIsStatic(isStatic);
|
|
||||||
return link->items_[index]; // items already default constructed.
|
|
||||||
}
|
|
||||||
|
|
||||||
Value&
|
|
||||||
ValueInternalMap::unsafeAdd(const char* key, bool isStatic, HashKey hashedKey) {
|
|
||||||
JSON_ASSERT_MESSAGE(bucketsSize_ > 0,
|
|
||||||
"ValueInternalMap::unsafeAdd(): internal logic error.");
|
|
||||||
BucketIndex bucketIndex = hashedKey % bucketsSize_;
|
|
||||||
ValueInternalLink*& previousLink = getLastLinkInBucket(bucketIndex);
|
|
||||||
ValueInternalLink* link = previousLink;
|
|
||||||
BucketIndex index;
|
|
||||||
for (index = 0; index < ValueInternalLink::itemPerLink; ++index) {
|
|
||||||
if (link->items_[index].isItemAvailable())
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (index == ValueInternalLink::itemPerLink) // need to add a new page
|
|
||||||
{
|
|
||||||
ValueInternalLink* newLink = mapAllocator()->allocateMapLink();
|
|
||||||
index = 0;
|
|
||||||
link->next_ = newLink;
|
|
||||||
previousLink = newLink;
|
|
||||||
link = newLink;
|
|
||||||
}
|
|
||||||
return setNewItem(key, isStatic, link, index);
|
|
||||||
}
|
|
||||||
|
|
||||||
ValueInternalMap::HashKey ValueInternalMap::hash(const char* key) const {
|
|
||||||
HashKey hash = 0;
|
|
||||||
while (*key)
|
|
||||||
hash += *key++ * 37;
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ValueInternalMap::compare(const ValueInternalMap& other) const {
|
|
||||||
int sizeDiff(itemCount_ - other.itemCount_);
|
|
||||||
if (sizeDiff != 0)
|
|
||||||
return sizeDiff;
|
|
||||||
// Strict order guaranty is required. Compare all keys FIRST, then compare
|
|
||||||
// values.
|
|
||||||
IteratorState it;
|
|
||||||
IteratorState itEnd;
|
|
||||||
makeBeginIterator(it);
|
|
||||||
makeEndIterator(itEnd);
|
|
||||||
for (; !equals(it, itEnd); increment(it)) {
|
|
||||||
if (!other.find(key(it)))
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// All keys are equals, let's compare values
|
|
||||||
makeBeginIterator(it);
|
|
||||||
for (; !equals(it, itEnd); increment(it)) {
|
|
||||||
const Value* otherValue = other.find(key(it));
|
|
||||||
int valueDiff = value(it).compare(*otherValue);
|
|
||||||
if (valueDiff != 0)
|
|
||||||
return valueDiff;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ValueInternalMap::makeBeginIterator(IteratorState& it) const {
|
|
||||||
it.map_ = const_cast<ValueInternalMap*>(this);
|
|
||||||
it.bucketIndex_ = 0;
|
|
||||||
it.itemIndex_ = 0;
|
|
||||||
it.link_ = buckets_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ValueInternalMap::makeEndIterator(IteratorState& it) const {
|
|
||||||
it.map_ = const_cast<ValueInternalMap*>(this);
|
|
||||||
it.bucketIndex_ = bucketsSize_;
|
|
||||||
it.itemIndex_ = 0;
|
|
||||||
it.link_ = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ValueInternalMap::equals(const IteratorState& x,
|
|
||||||
const IteratorState& other) {
|
|
||||||
return x.map_ == other.map_ && x.bucketIndex_ == other.bucketIndex_ &&
|
|
||||||
x.link_ == other.link_ && x.itemIndex_ == other.itemIndex_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ValueInternalMap::incrementBucket(IteratorState& iterator) {
|
|
||||||
++iterator.bucketIndex_;
|
|
||||||
JSON_ASSERT_MESSAGE(
|
|
||||||
iterator.bucketIndex_ <= iterator.map_->bucketsSize_,
|
|
||||||
"ValueInternalMap::increment(): attempting to iterate beyond end.");
|
|
||||||
if (iterator.bucketIndex_ == iterator.map_->bucketsSize_)
|
|
||||||
iterator.link_ = 0;
|
|
||||||
else
|
|
||||||
iterator.link_ = &(iterator.map_->buckets_[iterator.bucketIndex_]);
|
|
||||||
iterator.itemIndex_ = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ValueInternalMap::increment(IteratorState& iterator) {
|
|
||||||
JSON_ASSERT_MESSAGE(iterator.map_,
|
|
||||||
"Attempting to iterator using invalid iterator.");
|
|
||||||
++iterator.itemIndex_;
|
|
||||||
if (iterator.itemIndex_ == ValueInternalLink::itemPerLink) {
|
|
||||||
JSON_ASSERT_MESSAGE(
|
|
||||||
iterator.link_ != 0,
|
|
||||||
"ValueInternalMap::increment(): attempting to iterate beyond end.");
|
|
||||||
iterator.link_ = iterator.link_->next_;
|
|
||||||
if (iterator.link_ == 0)
|
|
||||||
incrementBucket(iterator);
|
|
||||||
} else if (iterator.link_->items_[iterator.itemIndex_].isItemAvailable()) {
|
|
||||||
incrementBucket(iterator);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ValueInternalMap::decrement(IteratorState& iterator) {
|
|
||||||
if (iterator.itemIndex_ == 0) {
|
|
||||||
JSON_ASSERT_MESSAGE(iterator.map_,
|
|
||||||
"Attempting to iterate using invalid iterator.");
|
|
||||||
if (iterator.link_ == &iterator.map_->buckets_[iterator.bucketIndex_]) {
|
|
||||||
JSON_ASSERT_MESSAGE(iterator.bucketIndex_ > 0,
|
|
||||||
"Attempting to iterate beyond beginning.");
|
|
||||||
--(iterator.bucketIndex_);
|
|
||||||
}
|
|
||||||
iterator.link_ = iterator.link_->previous_;
|
|
||||||
iterator.itemIndex_ = ValueInternalLink::itemPerLink - 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* ValueInternalMap::key(const IteratorState& iterator) {
|
|
||||||
JSON_ASSERT_MESSAGE(iterator.link_,
|
|
||||||
"Attempting to iterate using invalid iterator.");
|
|
||||||
return iterator.link_->keys_[iterator.itemIndex_];
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* ValueInternalMap::key(const IteratorState& iterator,
|
|
||||||
bool& isStatic) {
|
|
||||||
JSON_ASSERT_MESSAGE(iterator.link_,
|
|
||||||
"Attempting to iterate using invalid iterator.");
|
|
||||||
isStatic = iterator.link_->items_[iterator.itemIndex_].isMemberNameStatic();
|
|
||||||
return iterator.link_->keys_[iterator.itemIndex_];
|
|
||||||
}
|
|
||||||
|
|
||||||
Value& ValueInternalMap::value(const IteratorState& iterator) {
|
|
||||||
JSON_ASSERT_MESSAGE(iterator.link_,
|
|
||||||
"Attempting to iterate using invalid iterator.");
|
|
||||||
return iterator.link_->items_[iterator.itemIndex_];
|
|
||||||
}
|
|
||||||
|
|
||||||
int ValueInternalMap::distance(const IteratorState& x, const IteratorState& y) {
|
|
||||||
int offset = 0;
|
|
||||||
IteratorState it = x;
|
|
||||||
while (!equals(it, y))
|
|
||||||
increment(it);
|
|
||||||
return offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Json
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2007-2010 Baptiste Lepilleur
|
// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
|
||||||
// Distributed under MIT license, or public domain if desired and
|
// Distributed under MIT license, or public domain if desired and
|
||||||
// recognized in your jurisdiction.
|
// recognized in your jurisdiction.
|
||||||
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
@@ -6,6 +6,16 @@
|
|||||||
#ifndef LIB_JSONCPP_JSON_TOOL_H_INCLUDED
|
#ifndef LIB_JSONCPP_JSON_TOOL_H_INCLUDED
|
||||||
#define LIB_JSONCPP_JSON_TOOL_H_INCLUDED
|
#define LIB_JSONCPP_JSON_TOOL_H_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
// Also support old flag NO_LOCALE_SUPPORT
|
||||||
|
#ifdef NO_LOCALE_SUPPORT
|
||||||
|
#define JSONCPP_NO_LOCALE_SUPPORT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef JSONCPP_NO_LOCALE_SUPPORT
|
||||||
|
#include <clocale>
|
||||||
|
#endif
|
||||||
|
|
||||||
/* This header provides common string manipulation support, such as UTF-8,
|
/* This header provides common string manipulation support, such as UTF-8,
|
||||||
* portable conversion from/to string...
|
* portable conversion from/to string...
|
||||||
*
|
*
|
||||||
@@ -13,10 +23,18 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
namespace Json {
|
namespace Json {
|
||||||
|
static char getDecimalPoint() {
|
||||||
|
#ifdef JSONCPP_NO_LOCALE_SUPPORT
|
||||||
|
return '\0';
|
||||||
|
#else
|
||||||
|
struct lconv* lc = localeconv();
|
||||||
|
return lc ? *(lc->decimal_point) : '\0';
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/// Converts a unicode code-point to UTF-8.
|
/// Converts a unicode code-point to UTF-8.
|
||||||
static inline std::string codePointToUTF8(unsigned int cp) {
|
static inline JSONCPP_STRING codePointToUTF8(unsigned int cp) {
|
||||||
std::string result;
|
JSONCPP_STRING result;
|
||||||
|
|
||||||
// based on description from http://en.wikipedia.org/wiki/UTF-8
|
// based on description from http://en.wikipedia.org/wiki/UTF-8
|
||||||
|
|
||||||
@@ -30,8 +48,8 @@ static inline std::string codePointToUTF8(unsigned int cp) {
|
|||||||
} else if (cp <= 0xFFFF) {
|
} else if (cp <= 0xFFFF) {
|
||||||
result.resize(3);
|
result.resize(3);
|
||||||
result[2] = static_cast<char>(0x80 | (0x3f & cp));
|
result[2] = static_cast<char>(0x80 | (0x3f & cp));
|
||||||
result[1] = 0x80 | static_cast<char>((0x3f & (cp >> 6)));
|
result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 6)));
|
||||||
result[0] = 0xE0 | static_cast<char>((0xf & (cp >> 12)));
|
result[0] = static_cast<char>(0xE0 | (0xf & (cp >> 12)));
|
||||||
} else if (cp <= 0x10FFFF) {
|
} else if (cp <= 0x10FFFF) {
|
||||||
result.resize(4);
|
result.resize(4);
|
||||||
result[3] = static_cast<char>(0x80 | (0x3f & cp));
|
result[3] = static_cast<char>(0x80 | (0x3f & cp));
|
||||||
@@ -43,7 +61,7 @@ static inline std::string codePointToUTF8(unsigned int cp) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if ch is a control character (in range [0,32[).
|
/// Returns true if ch is a control character (in range [1,31]).
|
||||||
static inline bool isControlCharacter(char ch) { return ch > 0 && ch <= 0x1F; }
|
static inline bool isControlCharacter(char ch) { return ch > 0 && ch <= 0x1F; }
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@@ -63,7 +81,7 @@ typedef char UIntToStringBuffer[uintToStringBufferSize];
|
|||||||
static inline void uintToString(LargestUInt value, char*& current) {
|
static inline void uintToString(LargestUInt value, char*& current) {
|
||||||
*--current = 0;
|
*--current = 0;
|
||||||
do {
|
do {
|
||||||
*--current = char(value % 10) + '0';
|
*--current = static_cast<char>(value % 10U + static_cast<unsigned>('0'));
|
||||||
value /= 10;
|
value /= 10;
|
||||||
} while (value != 0);
|
} while (value != 0);
|
||||||
}
|
}
|
||||||
@@ -82,6 +100,18 @@ static inline void fixNumericLocale(char* begin, char* end) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void fixNumericLocaleInput(char* begin, char* end) {
|
||||||
|
char decimalPoint = getDecimalPoint();
|
||||||
|
if (decimalPoint != '\0' && decimalPoint != '.') {
|
||||||
|
while (begin < end) {
|
||||||
|
if (*begin == '.') {
|
||||||
|
*begin = decimalPoint;
|
||||||
|
}
|
||||||
|
++begin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Json {
|
} // namespace Json {
|
||||||
|
|
||||||
#endif // LIB_JSONCPP_JSON_TOOL_H_INCLUDED
|
#endif // LIB_JSONCPP_JSON_TOOL_H_INCLUDED
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2007-2010 Baptiste Lepilleur
|
// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
|
||||||
// Distributed under MIT license, or public domain if desired and
|
// Distributed under MIT license, or public domain if desired and
|
||||||
// recognized in your jurisdiction.
|
// recognized in your jurisdiction.
|
||||||
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
@@ -16,68 +16,29 @@ namespace Json {
|
|||||||
// //////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
ValueIteratorBase::ValueIteratorBase()
|
ValueIteratorBase::ValueIteratorBase()
|
||||||
#ifndef JSON_VALUE_USE_INTERNAL_MAP
|
|
||||||
: current_(), isNull_(true) {
|
: current_(), isNull_(true) {
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
: isArray_(true), isNull_(true) {
|
|
||||||
iterator_.array_ = ValueInternalArray::IteratorState();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef JSON_VALUE_USE_INTERNAL_MAP
|
|
||||||
ValueIteratorBase::ValueIteratorBase(
|
ValueIteratorBase::ValueIteratorBase(
|
||||||
const Value::ObjectValues::iterator& current)
|
const Value::ObjectValues::iterator& current)
|
||||||
: current_(current), isNull_(false) {}
|
: current_(current), isNull_(false) {}
|
||||||
#else
|
|
||||||
ValueIteratorBase::ValueIteratorBase(
|
|
||||||
const ValueInternalArray::IteratorState& state)
|
|
||||||
: isArray_(true) {
|
|
||||||
iterator_.array_ = state;
|
|
||||||
}
|
|
||||||
|
|
||||||
ValueIteratorBase::ValueIteratorBase(
|
|
||||||
const ValueInternalMap::IteratorState& state)
|
|
||||||
: isArray_(false) {
|
|
||||||
iterator_.map_ = state;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Value& ValueIteratorBase::deref() const {
|
Value& ValueIteratorBase::deref() const {
|
||||||
#ifndef JSON_VALUE_USE_INTERNAL_MAP
|
|
||||||
return current_->second;
|
return current_->second;
|
||||||
#else
|
|
||||||
if (isArray_)
|
|
||||||
return ValueInternalArray::dereference(iterator_.array_);
|
|
||||||
return ValueInternalMap::value(iterator_.map_);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ValueIteratorBase::increment() {
|
void ValueIteratorBase::increment() {
|
||||||
#ifndef JSON_VALUE_USE_INTERNAL_MAP
|
|
||||||
++current_;
|
++current_;
|
||||||
#else
|
|
||||||
if (isArray_)
|
|
||||||
ValueInternalArray::increment(iterator_.array_);
|
|
||||||
ValueInternalMap::increment(iterator_.map_);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ValueIteratorBase::decrement() {
|
void ValueIteratorBase::decrement() {
|
||||||
#ifndef JSON_VALUE_USE_INTERNAL_MAP
|
|
||||||
--current_;
|
--current_;
|
||||||
#else
|
|
||||||
if (isArray_)
|
|
||||||
ValueInternalArray::decrement(iterator_.array_);
|
|
||||||
ValueInternalMap::decrement(iterator_.map_);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ValueIteratorBase::difference_type
|
ValueIteratorBase::difference_type
|
||||||
ValueIteratorBase::computeDistance(const SelfType& other) const {
|
ValueIteratorBase::computeDistance(const SelfType& other) const {
|
||||||
#ifndef JSON_VALUE_USE_INTERNAL_MAP
|
|
||||||
#ifdef JSON_USE_CPPTL_SMALLMAP
|
#ifdef JSON_USE_CPPTL_SMALLMAP
|
||||||
return current_ - other.current_;
|
return other.current_ - current_;
|
||||||
#else
|
#else
|
||||||
// Iterator for null value are initialized using the default
|
// Iterator for null value are initialized using the default
|
||||||
// constructor, which initialize current_ to the default
|
// constructor, which initialize current_ to the default
|
||||||
@@ -100,80 +61,58 @@ ValueIteratorBase::computeDistance(const SelfType& other) const {
|
|||||||
}
|
}
|
||||||
return myDistance;
|
return myDistance;
|
||||||
#endif
|
#endif
|
||||||
#else
|
|
||||||
if (isArray_)
|
|
||||||
return ValueInternalArray::distance(iterator_.array_,
|
|
||||||
other.iterator_.array_);
|
|
||||||
return ValueInternalMap::distance(iterator_.map_, other.iterator_.map_);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ValueIteratorBase::isEqual(const SelfType& other) const {
|
bool ValueIteratorBase::isEqual(const SelfType& other) const {
|
||||||
#ifndef JSON_VALUE_USE_INTERNAL_MAP
|
|
||||||
if (isNull_) {
|
if (isNull_) {
|
||||||
return other.isNull_;
|
return other.isNull_;
|
||||||
}
|
}
|
||||||
return current_ == other.current_;
|
return current_ == other.current_;
|
||||||
#else
|
|
||||||
if (isArray_)
|
|
||||||
return ValueInternalArray::equals(iterator_.array_, other.iterator_.array_);
|
|
||||||
return ValueInternalMap::equals(iterator_.map_, other.iterator_.map_);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ValueIteratorBase::copy(const SelfType& other) {
|
void ValueIteratorBase::copy(const SelfType& other) {
|
||||||
#ifndef JSON_VALUE_USE_INTERNAL_MAP
|
|
||||||
current_ = other.current_;
|
current_ = other.current_;
|
||||||
isNull_ = other.isNull_;
|
isNull_ = other.isNull_;
|
||||||
#else
|
|
||||||
if (isArray_)
|
|
||||||
iterator_.array_ = other.iterator_.array_;
|
|
||||||
iterator_.map_ = other.iterator_.map_;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Value ValueIteratorBase::key() const {
|
Value ValueIteratorBase::key() const {
|
||||||
#ifndef JSON_VALUE_USE_INTERNAL_MAP
|
|
||||||
const Value::CZString czstring = (*current_).first;
|
const Value::CZString czstring = (*current_).first;
|
||||||
if (czstring.c_str()) {
|
if (czstring.data()) {
|
||||||
if (czstring.isStaticString())
|
if (czstring.isStaticString())
|
||||||
return Value(StaticString(czstring.c_str()));
|
return Value(StaticString(czstring.data()));
|
||||||
return Value(czstring.c_str());
|
return Value(czstring.data(), czstring.data() + czstring.length());
|
||||||
}
|
}
|
||||||
return Value(czstring.index());
|
return Value(czstring.index());
|
||||||
#else
|
|
||||||
if (isArray_)
|
|
||||||
return Value(ValueInternalArray::indexOf(iterator_.array_));
|
|
||||||
bool isStatic;
|
|
||||||
const char* memberName = ValueInternalMap::key(iterator_.map_, isStatic);
|
|
||||||
if (isStatic)
|
|
||||||
return Value(StaticString(memberName));
|
|
||||||
return Value(memberName);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
UInt ValueIteratorBase::index() const {
|
UInt ValueIteratorBase::index() const {
|
||||||
#ifndef JSON_VALUE_USE_INTERNAL_MAP
|
|
||||||
const Value::CZString czstring = (*current_).first;
|
const Value::CZString czstring = (*current_).first;
|
||||||
if (!czstring.c_str())
|
if (!czstring.data())
|
||||||
return czstring.index();
|
return czstring.index();
|
||||||
return Value::UInt(-1);
|
return Value::UInt(-1);
|
||||||
#else
|
|
||||||
if (isArray_)
|
|
||||||
return Value::UInt(ValueInternalArray::indexOf(iterator_.array_));
|
|
||||||
return Value::UInt(-1);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* ValueIteratorBase::memberName() const {
|
JSONCPP_STRING ValueIteratorBase::name() const {
|
||||||
#ifndef JSON_VALUE_USE_INTERNAL_MAP
|
char const* keey;
|
||||||
const char* name = (*current_).first.c_str();
|
char const* end;
|
||||||
return name ? name : "";
|
keey = memberName(&end);
|
||||||
#else
|
if (!keey) return JSONCPP_STRING();
|
||||||
if (!isArray_)
|
return JSONCPP_STRING(keey, end);
|
||||||
return ValueInternalMap::key(iterator_.map_);
|
}
|
||||||
return "";
|
|
||||||
#endif
|
char const* ValueIteratorBase::memberName() const {
|
||||||
|
const char* cname = (*current_).first.data();
|
||||||
|
return cname ? cname : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
char const* ValueIteratorBase::memberName(char const** end) const {
|
||||||
|
const char* cname = (*current_).first.data();
|
||||||
|
if (!cname) {
|
||||||
|
*end = NULL;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
*end = cname + (*current_).first.length();
|
||||||
|
return cname;
|
||||||
}
|
}
|
||||||
|
|
||||||
// //////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////
|
||||||
@@ -186,19 +125,12 @@ const char* ValueIteratorBase::memberName() const {
|
|||||||
|
|
||||||
ValueConstIterator::ValueConstIterator() {}
|
ValueConstIterator::ValueConstIterator() {}
|
||||||
|
|
||||||
#ifndef JSON_VALUE_USE_INTERNAL_MAP
|
|
||||||
ValueConstIterator::ValueConstIterator(
|
ValueConstIterator::ValueConstIterator(
|
||||||
const Value::ObjectValues::iterator& current)
|
const Value::ObjectValues::iterator& current)
|
||||||
: ValueIteratorBase(current) {}
|
: ValueIteratorBase(current) {}
|
||||||
#else
|
|
||||||
ValueConstIterator::ValueConstIterator(
|
|
||||||
const ValueInternalArray::IteratorState& state)
|
|
||||||
: ValueIteratorBase(state) {}
|
|
||||||
|
|
||||||
ValueConstIterator::ValueConstIterator(
|
ValueConstIterator::ValueConstIterator(ValueIterator const& other)
|
||||||
const ValueInternalMap::IteratorState& state)
|
: ValueIteratorBase(other) {}
|
||||||
: ValueIteratorBase(state) {}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ValueConstIterator& ValueConstIterator::
|
ValueConstIterator& ValueConstIterator::
|
||||||
operator=(const ValueIteratorBase& other) {
|
operator=(const ValueIteratorBase& other) {
|
||||||
@@ -216,19 +148,13 @@ operator=(const ValueIteratorBase& other) {
|
|||||||
|
|
||||||
ValueIterator::ValueIterator() {}
|
ValueIterator::ValueIterator() {}
|
||||||
|
|
||||||
#ifndef JSON_VALUE_USE_INTERNAL_MAP
|
|
||||||
ValueIterator::ValueIterator(const Value::ObjectValues::iterator& current)
|
ValueIterator::ValueIterator(const Value::ObjectValues::iterator& current)
|
||||||
: ValueIteratorBase(current) {}
|
: ValueIteratorBase(current) {}
|
||||||
#else
|
|
||||||
ValueIterator::ValueIterator(const ValueInternalArray::IteratorState& state)
|
|
||||||
: ValueIteratorBase(state) {}
|
|
||||||
|
|
||||||
ValueIterator::ValueIterator(const ValueInternalMap::IteratorState& state)
|
|
||||||
: ValueIteratorBase(state) {}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ValueIterator::ValueIterator(const ValueConstIterator& other)
|
ValueIterator::ValueIterator(const ValueConstIterator& other)
|
||||||
: ValueIteratorBase(other) {}
|
: ValueIteratorBase(other) {
|
||||||
|
throwRuntimeError("ConstIterator to Iterator should never be allowed.");
|
||||||
|
}
|
||||||
|
|
||||||
ValueIterator::ValueIterator(const ValueIterator& other)
|
ValueIterator::ValueIterator(const ValueIterator& other)
|
||||||
: ValueIteratorBase(other) {}
|
: ValueIteratorBase(other) {}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user