Merge branch 'hotwatermorning-master' with minor changes

This commit is contained in:
Tristan Penman 2016-01-29 17:59:27 -08:00
commit a1d330e285
15 changed files with 2309 additions and 5 deletions

View File

@ -8,6 +8,7 @@ else()
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
if(COMPILER_SUPPORTS_CXX11)
set(VALIJSON_CXX11_ADAPTERS_ARE_ENABLED 1)
message(STATUS "Building with C++11 support enabled")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -DVALIJSON_BUILD_CXX11_ADAPTERS=1")
else()
@ -29,6 +30,12 @@ add_library(jsoncpp
thirdparty/jsoncpp-0.9.4/src/lib_json/json_writer.cpp
)
if(VALIJSON_CXX11_ADAPTERS_ARE_ENABLED)
add_library(json11
thirdparty/json11-2016-01-26/json11.cpp
)
endif()
# Build local gtest
set(gtest_force_shared_crt ON)
add_subdirectory(thirdparty/gtest-1.7.0)
@ -43,6 +50,12 @@ include_directories(
${Boost_INCLUDE_DIRS}
)
if(VALIJSON_CXX11_ADAPTERS_ARE_ENABLED)
include_directories(
thirdparty/json11-2016-01-26
)
endif()
# Custom schema validation example
add_executable(custom_schema
examples/custom_schema.cpp
@ -53,8 +66,7 @@ add_executable(external_schema
examples/external_schema.cpp
)
# Unit tests executable
add_executable(test_suite
set(TEST_SOURCES
tests/test_adapter_comparison.cpp
tests/test_fetch_document_callback.cpp
tests/test_json_pointer.cpp
@ -64,7 +76,17 @@ add_executable(test_suite
tests/test_picojson_adapter.cpp
tests/test_validation_errors.cpp
tests/test_validator.cpp
)
)
if(VALIJSON_CXX11_ADAPTERS_ARE_ENABLED)
set(TEST_SOURCES
${TEST_SOURCES}
tests/test_json11_adapter.cpp
)
endif()
# Unit tests executable
add_executable(test_suite ${TEST_SOURCES})
# Definition for using picojson
set_target_properties(test_suite
@ -72,6 +94,9 @@ set_target_properties(test_suite
)
set(TEST_LIBS gtest gtest_main jsoncpp)
if(VALIJSON_CXX11_ADAPTERS_ARE_ENABLED)
set(TEST_LIBS ${TEST_LIBS} json11)
endif()
target_link_libraries(test_suite ${TEST_LIBS} ${Boost_LIBRARIES})
target_link_libraries(custom_schema ${Boost_LIBRARIES})

View File

@ -0,0 +1,676 @@
/**
* @file
*
* @brief Adapter implementation for the json11 parser library.
*
* Include this file in your program to enable support for json11.
*
* This file defines the following classes (not in this order):
* - Json11Adapter
* - Json11Array
* - Json11ArrayValueIterator
* - Json11FrozenValue
* - Json11Object
* - Json11ObjectMember
* - Json11ObjectMemberIterator
* - Json11Value
*
* Due to the dependencies that exist between these classes, the ordering of
* class declarations and definitions may be a bit confusing. The best place to
* start is Json11Adapter. This class definition is actually very small,
* since most of the functionality is inherited from the BasicAdapter class.
* Most of the classes in this file are provided as template arguments to the
* inherited BasicAdapter class.
*/
#ifndef __VALIJSON_ADAPTERS_JSON11_ADAPTER_HPP
#define __VALIJSON_ADAPTERS_JSON11_ADAPTER_HPP
#include <string>
#include <json11.hpp>
#include <boost/optional.hpp>
#include <boost/iterator/iterator_facade.hpp>
#include <valijson/adapters/adapter.hpp>
#include <valijson/adapters/basic_adapter.hpp>
#include <valijson/adapters/frozen_value.hpp>
namespace valijson {
namespace adapters {
class Json11Adapter;
class Json11ArrayValueIterator;
class Json11ObjectMemberIterator;
typedef std::pair<std::string, Json11Adapter> Json11ObjectMember;
/**
* @brief Light weight wrapper for a Json11 array value.
*
* This class is light weight wrapper for a Json11 array. It provides a
* minimum set of container functions and typedefs that allow it to be used as
* an iterable container.
*
* An instance of this class contains a single reference to the underlying
* Json11 value, assumed to be an array, so there is very little overhead
* associated with copy construction and passing by value.
*/
class Json11Array
{
public:
typedef Json11ArrayValueIterator const_iterator;
typedef Json11ArrayValueIterator iterator;
/// Construct a Json11Array referencing an empty array.
Json11Array()
: value(emptyArray()) { }
/**
* @brief Construct a Json11Array referencing a specific Json11
* value.
*
* @param value reference to a Json11 value
*
* Note that this constructor will throw an exception if the value is not
* an array.
*/
Json11Array(const json11::Json &value)
: value(value)
{
if (!value.is_array()) {
throw std::runtime_error("Value is not an array.");
}
}
/**
* @brief Return an iterator for the first element of the array.
*
* The iterator return by this function is effectively the iterator
* returned by the underlying Json11 implementation.
*/
Json11ArrayValueIterator begin() const;
/**
* @brief Return an iterator for one-past the last element of the array.
*
* The iterator return by this function is effectively the iterator
* returned by the underlying Json11 implementation.
*/
Json11ArrayValueIterator end() const;
/// Return the number of elements in the array
size_t size() const
{
return value.array_items().size();
}
private:
/**
* @brief Return a reference to a Json11 value that is an empty array.
*
* Note that the value returned by this function is a singleton.
*/
static const json11::Json & emptyArray()
{
static const json11::Json array((json11::Json::array()));
return array;
}
/// Reference to the contained value
const json11::Json &value;
};
/**
* @brief Light weight wrapper for a Json11 object.
*
* This class is light weight wrapper for a Json11 object. It provides a
* minimum set of container functions and typedefs that allow it to be used as
* an iterable container.
*
* An instance of this class contains a single reference to the underlying
* Json11 value, assumed to be an object, so there is very little overhead
* associated with copy construction and passing by value.
*/
class Json11Object
{
public:
typedef Json11ObjectMemberIterator const_iterator;
typedef Json11ObjectMemberIterator iterator;
/// Construct a Json11Object referencing an empty object singleton.
Json11Object()
: value(emptyObject()) { }
/**
* @brief Construct a Json11Object referencing a specific Json11
* value.
*
* @param value reference to a Json11 value
*
* Note that this constructor will throw an exception if the value is not
* an object.
*/
Json11Object(const json11::Json &value)
: value(value)
{
if (!value.is_object()) {
throw std::runtime_error("Value is not an object.");
}
}
/**
* @brief Return an iterator for this first object member
*
* The iterator return by this function is effectively a wrapper around
* the iterator value returned by the underlying Json11 implementation.
*/
Json11ObjectMemberIterator begin() const;
/**
* @brief Return an iterator for an invalid object member that indicates
* the end of the collection.
*
* The iterator return by this function is effectively a wrapper around
* the iterator value returned by the underlying Json11 implementation.
*/
Json11ObjectMemberIterator end() const;
/**
* @brief Return an iterator for the object member with the specified
* property name.
*
* If an object member with the specified name does not exist, the iterator
* returned will be the same as the iterator returned by the end() function.
*
* @param propertyName property name to search for
*/
Json11ObjectMemberIterator find(const std::string &propertyName) const;
/// Returns the number of members belonging to this object.
size_t size() const
{
return value.object_items().size();
}
private:
/**
* @brief Return a reference to a Json11 value that is empty object.
*
* Note that the value returned by this function is a singleton.
*/
static const json11::Json & emptyObject()
{
static const json11::Json object((json11::Json::object()));
return object;
}
/// Reference to the contained object
const json11::Json &value;
};
/**
* @brief Stores an independent copy of a Json11 value.
*
* This class allows a Json11 value to be stored independent of its original
* document. Json11 makes this easy to do, as it does not perform any
* custom memory management.
*
* @see FrozenValue
*/
class Json11FrozenValue: public FrozenValue
{
public:
/**
* @brief Make a copy of a Json11 value
*
* @param source the Json11 value to be copied
*/
Json11FrozenValue(const json11::Json &source)
: value(source) { }
virtual FrozenValue * clone() const
{
return new Json11FrozenValue(value);
}
virtual bool equalTo(const Adapter &other, bool strict) const;
private:
/// Stored Json11 value
json11::Json value;
};
/**
* @brief Light weight wrapper for a Json11 value.
*
* This class is passed as an argument to the BasicAdapter template class,
* and is used to provide access to a Json11 value. This class is responsible
* for the mechanics of actually reading a Json11 value, whereas the
* BasicAdapter class is responsible for the semantics of type comparisons
* and conversions.
*
* The functions that need to be provided by this class are defined implicitly
* by the implementation of the BasicAdapter template class.
*
* @see BasicAdapter
*/
class Json11Value
{
public:
/// Construct a wrapper for the empty object singleton
Json11Value()
: value(emptyObject()) { }
/// Construct a wrapper for a specific Json11 value
Json11Value(const json11::Json &value)
: value(value) { }
/**
* @brief Create a new Json11FrozenValue instance that contains the
* value referenced by this Json11Value instance.
*
* @returns pointer to a new Json11FrozenValue instance, belonging to the
* caller.
*/
FrozenValue * freeze() const
{
return new Json11FrozenValue(value);
}
/**
* @brief Optionally return a Json11Array instance.
*
* If the referenced Json11 value is an array, this function will return
* a boost::optional containing a Json11Array instance referencing the
* array.
*
* Otherwise it will return boost::none.
*/
boost::optional<Json11Array> getArrayOptional() const
{
if (value.is_array()) {
return boost::make_optional(Json11Array(value));
}
return boost::none;
}
/**
* @brief Retrieve the number of elements in the array
*
* If the referenced Json11 value is an array, this function will
* retrieve the number of elements in the array and store it in the output
* variable provided.
*
* @param result reference to size_t to set with result
*
* @returns true if the number of elements was retrieved, false otherwise.
*/
bool getArraySize(size_t &result) const
{
if (value.is_array()) {
result = value.array_items().size();
return true;
}
return false;
}
bool getBool(bool &result) const
{
if (value.is_bool()) {
result = value.bool_value();
return true;
}
return false;
}
bool getDouble(double &result) const
{
if (value.is_number()) {
result = value.number_value();
return true;
}
return false;
}
bool getInteger(int64_t &result) const
{
if(isInteger()) {
result = value.int_value();
return true;
}
return false;
}
/**
* @brief Optionally return a Json11Object instance.
*
* If the referenced Json11 value is an object, this function will return a
* boost::optional containing a Json11Object instance referencing the
* object.
*
* Otherwise it will return boost::none.
*/
boost::optional<Json11Object> getObjectOptional() const
{
if (value.is_object()) {
return boost::make_optional(Json11Object(value));
}
return boost::none;
}
/**
* @brief Retrieve the number of members in the object
*
* If the referenced Json11 value is an object, this function will
* retrieve the number of members in the object and store it in the output
* variable provided.
*
* @param result reference to size_t to set with result
*
* @returns true if the number of members was retrieved, false otherwise.
*/
bool getObjectSize(size_t &result) const
{
if (value.is_object()) {
result = value.object_items().size();
return true;
}
return false;
}
bool getString(std::string &result) const
{
if (value.is_string()) {
result = value.string_value();
return true;
}
return false;
}
static bool hasStrictTypes()
{
return true;
}
bool isArray() const
{
return value.is_array();
}
bool isBool() const
{
return value.is_bool();
}
bool isDouble() const
{
return value.is_number();
}
bool isInteger() const
{
return value.is_number()
&& value.int_value() == value.number_value();
}
bool isNull() const
{
return value.is_null();
}
bool isNumber() const
{
return value.is_number();
}
bool isObject() const
{
return value.is_object();
}
bool isString() const
{
return value.is_string();
}
private:
/// Return a reference to an empty object singleton
static const json11::Json & emptyObject()
{
static const json11::Json object((json11::Json::object()));
return object;
}
/// Reference to the contained Json11 value.
const json11::Json &value;
};
/**
* @brief An implementation of the Adapter interface supporting Json11.
*
* This class is defined in terms of the BasicAdapter template class, which
* helps to ensure that all of the Adapter implementations behave consistently.
*
* @see Adapter
* @see BasicAdapter
*/
class Json11Adapter:
public BasicAdapter<Json11Adapter,
Json11Array,
Json11ObjectMember,
Json11Object,
Json11Value>
{
public:
/// Construct a Json11Adapter that contains an empty object
Json11Adapter()
: BasicAdapter() { }
/// Construct a Json11Adapter containing a specific Json11 value
Json11Adapter(const json11::Json &value)
: BasicAdapter(value) { }
};
/**
* @brief Class for iterating over values held in a JSON array.
*
* This class provides a JSON array iterator that dereferences as an instance of
* Json11Adapter representing a value stored in the array. It has been
* implemented using the boost iterator_facade template.
*
* @see Json11Array
*/
class Json11ArrayValueIterator:
public boost::iterator_facade<
Json11ArrayValueIterator, // name of derived type
Json11Adapter, // value type
boost::bidirectional_traversal_tag, // bi-directional iterator
Json11Adapter> // type returned when dereferenced
{
public:
/**
* @brief Construct a new Json11ArrayValueIterator using an existing
* Json11 iterator.
*
* @param itr Json11 iterator to store
*/
Json11ArrayValueIterator(
const json11::Json::array::const_iterator &itr)
: itr(itr) { }
/// Returns a Json11Adapter that contains the value of the current
/// element.
Json11Adapter dereference() const
{
return Json11Adapter(*itr);
}
/**
* @brief Compare this iterator against another iterator.
*
* Note that this directly compares the iterators, not the underlying
* values, and assumes that two identical iterators will point to the same
* underlying object.
*
* @param other iterator to compare against
*
* @returns true if the iterators are equal, false otherwise.
*/
bool equal(const Json11ArrayValueIterator &other) const
{
return itr == other.itr;
}
void increment()
{
itr++;
}
void decrement()
{
itr--;
}
void advance(std::ptrdiff_t n)
{
itr += n;
}
private:
json11::Json::array::const_iterator itr;
};
/**
* @brief Class for iterating over the members belonging to a JSON object.
*
* This class provides a JSON object iterator that dereferences as an instance
* of Json11ObjectMember representing one of the members of the object. It
* has been implemented using the boost iterator_facade template.
*
* @see Json11Object
* @see Json11ObjectMember
*/
class Json11ObjectMemberIterator:
public boost::iterator_facade<
Json11ObjectMemberIterator, // name of derived type
Json11ObjectMember, // value type
boost::bidirectional_traversal_tag, // bi-directional iterator
Json11ObjectMember> // type returned when dereferenced
{
public:
/**
* @brief Construct an iterator from a Json11 iterator.
*
* @param itr Json11 iterator to store
*/
Json11ObjectMemberIterator(
const json11::Json::object::const_iterator &itr)
: itr(itr) { }
/**
* @brief Returns a Json11ObjectMember that contains the key and value
* belonging to the object member identified by the iterator.
*/
Json11ObjectMember dereference() const
{
return Json11ObjectMember(itr->first, itr->second);
}
/**
* @brief Compare this iterator with another iterator.
*
* Note that this directly compares the iterators, not the underlying
* values, and assumes that two identical iterators will point to the same
* underlying object.
*
* @param other Iterator to compare with
*
* @returns true if the underlying iterators are equal, false otherwise
*/
bool equal(const Json11ObjectMemberIterator &other) const
{
return itr == other.itr;
}
void increment()
{
itr++;
}
void decrement()
{
itr--;
}
private:
/// Iternal copy of the original Json11 iterator
json11::Json::object::const_iterator itr;
};
/// Specialisation of the AdapterTraits template struct for Json11Adapter.
template<>
struct AdapterTraits<valijson::adapters::Json11Adapter>
{
typedef json11::Json DocumentType;
static std::string adapterName()
{
return "Json11Adapter";
}
};
inline bool Json11FrozenValue::equalTo(const Adapter &other, bool strict) const
{
return Json11Adapter(value).equalTo(other, strict);
}
inline Json11ArrayValueIterator Json11Array::begin() const
{
return value.array_items().begin();
}
inline Json11ArrayValueIterator Json11Array::end() const
{
return value.array_items().end();
}
inline Json11ObjectMemberIterator Json11Object::begin() const
{
return value.object_items().begin();
}
inline Json11ObjectMemberIterator Json11Object::end() const
{
return value.object_items().end();
}
inline Json11ObjectMemberIterator Json11Object::find(
const std::string &propertyName) const
{
return value.object_items().find(propertyName);
}
} // namespace adapters
} // namespace valijson
#endif

View File

@ -0,0 +1,36 @@
#ifndef __VALIJSON_UTILS_JSON11_UTILS_HPP
#define __VALIJSON_UTILS_JSON11_UTILS_HPP
#include <json11.hpp>
#include <valijson/utils/file_utils.hpp>
namespace valijson {
namespace utils {
inline bool loadDocument(const std::string &path, json11::Json &document)
{
// Load schema JSON from file
std::string file;
if (!loadFile(path, file)) {
std::cerr << "Failed to load json from file '" << path << "'." << std::endl;
return false;
}
// Parse schema
std::string err;
document = json11::Json::parse(file, err);
if (!err.empty()) {
std::cerr << "json11 failed to parse the document:" << std::endl
<< "Parse error: " << err << std::endl;
return false;
}
return true;
}
} // namespace utils
} // namespace valijson
#endif

View File

@ -14,6 +14,11 @@
#include <valijson/utils/rapidjson_utils.hpp>
#include <valijson/utils/picojson_utils.hpp>
#ifdef VALIJSON_BUILD_CXX11_ADAPTERS
#include <valijson/adapters/json11_adapter.hpp>
#include <valijson/utils/json11_utils.hpp>
#endif // VALIJSON_BUILD_CXX11_ADAPTERS
#define TEST_DATA_DIR "../tests/data/documents/"
using valijson::adapters::AdapterTraits;
@ -234,3 +239,53 @@ TEST_F(TestAdapterComparison, RapidJsonCrtAllocVsRapidJsonCrtAlloc)
rapidjson::GenericValue<rapidjson::UTF8<>,
rapidjson::CrtAllocator> > >();
}
#ifdef VALIJSON_BUILD_CXX11_ADAPTERS
TEST_F(TestAdapterComparison, Json11VsJson11)
{
testComparison<
valijson::adapters::Json11Adapter,
valijson::adapters::Json11Adapter>();
}
TEST_F(TestAdapterComparison, Json11VsJsonCpp)
{
testComparison<
valijson::adapters::Json11Adapter,
valijson::adapters::JsonCppAdapter>();
}
TEST_F(TestAdapterComparison, Json11VsRapidJson)
{
testComparison<
valijson::adapters::Json11Adapter,
valijson::adapters::RapidJsonAdapter>();
}
TEST_F(TestAdapterComparison, Json11VsRapidJsonCrtAlloc)
{
testComparison<
valijson::adapters::Json11Adapter,
valijson::adapters::GenericRapidJsonAdapter<
rapidjson::GenericValue<rapidjson::UTF8<>,
rapidjson::CrtAllocator> > >();
}
TEST_F(TestAdapterComparison, Json11VsPicoJson)
{
testComparison<
valijson::adapters::Json11Adapter,
valijson::adapters::PicoJsonAdapter>();
}
TEST_F(TestAdapterComparison, Json11VsPropertyTree)
{
testComparison<
valijson::adapters::Json11Adapter,
valijson::adapters::PropertyTreeAdapter>();
}
#endif // VALIJSON_BUILD_CXX11_ADAPTERS

View File

@ -0,0 +1,90 @@
#ifdef VALIJSON_BUILD_CXX11_ADAPTERS
#include <boost/foreach.hpp>
#include <boost/lexical_cast.hpp>
#include <gtest/gtest.h>
#include <valijson/adapters/json11_adapter.hpp>
class TestJson11Adapter : public testing::Test
{
};
TEST_F(TestJson11Adapter, BasicArrayIteration)
{
const unsigned int numElements = 10;
// Create a Json11 document that consists of an array of numbers
json11::Json::array array;
for (unsigned int i = 0; i < numElements; i++) {
json11::Json value(static_cast<double>(i));
array.push_back(value);
}
json11::Json document(array);
// Ensure that wrapping the document preserves the array and does not allow
// it to be cast to other types
valijson::adapters::Json11Adapter adapter(document);
ASSERT_NO_THROW( adapter.getArray() );
ASSERT_ANY_THROW( adapter.getBool() );
ASSERT_ANY_THROW( adapter.getDouble() );
ASSERT_ANY_THROW( adapter.getObject() );
ASSERT_ANY_THROW( adapter.getString() );
// Ensure that the array contains the expected number of elements
EXPECT_EQ( numElements, adapter.getArray().size() );
// Ensure that the elements are returned in the order they were inserted
unsigned int expectedValue = 0;
BOOST_FOREACH( const valijson::adapters::Json11Adapter value, adapter.getArray() ) {
ASSERT_TRUE( value.isNumber() );
EXPECT_EQ( double(expectedValue), value.getDouble() );
expectedValue++;
}
// Ensure that the correct number of elements were iterated over
EXPECT_EQ(numElements, expectedValue);
}
TEST_F(TestJson11Adapter, BasicObjectIteration)
{
const unsigned int numElements = 10;
// Create a DropBoxJson11 document that consists of an object that maps numeric
// strings their corresponding numeric values
json11::Json::object object;
for (unsigned int i = 0; i < numElements; i++) {
std::string name(boost::lexical_cast<std::string>(i));
object[name] = json11::Json(static_cast<double>(i));
}
json11::Json document(object);
// Ensure that wrapping the document preserves the object and does not
// allow it to be cast to other types
valijson::adapters::Json11Adapter adapter(document);
ASSERT_NO_THROW( adapter.getObject() );
ASSERT_ANY_THROW( adapter.getArray() );
ASSERT_ANY_THROW( adapter.getBool() );
ASSERT_ANY_THROW( adapter.getDouble() );
ASSERT_ANY_THROW( adapter.getString() );
// Ensure that the object contains the expected number of members
EXPECT_EQ( numElements, adapter.getObject().size() );
// Ensure that the members are returned in the order they were inserted
unsigned int expectedValue = 0;
BOOST_FOREACH( const valijson::adapters::Json11Adapter::ObjectMember member, adapter.getObject() ) {
ASSERT_TRUE( member.second.isNumber() );
EXPECT_EQ( boost::lexical_cast<std::string>(expectedValue), member.first );
EXPECT_EQ( double(expectedValue), member.second.getDouble() );
expectedValue++;
}
// Ensure that the correct number of elements were iterated over
EXPECT_EQ( numElements, expectedValue );
}
#endif // VALIJSON_BUILD_CXX11_ADAPTERS

View File

@ -18,6 +18,11 @@
#include <valijson/validation_results.hpp>
#include <valijson/validator.hpp>
#ifdef VALIJSON_BUILD_CXX11_ADAPTERS
#include <valijson/adapters/json11_adapter.hpp>
#include <valijson/utils/json11_utils.hpp>
#endif // VALIJSON_BUILD_CXX11_ADAPTERS
#define TEST_SUITE_DIR "../thirdparty/JSON-Schema-Test-Suite/tests/"
using valijson::adapters::AdapterTraits;
@ -116,6 +121,9 @@ protected:
processTestFile<valijson::adapters::JsonCppAdapter>(testFile, version);
processTestFile<valijson::adapters::RapidJsonAdapter>(testFile, version);
processTestFile<valijson::adapters::PicoJsonAdapter>(testFile, version);
#ifdef VALIJSON_BUILD_CXX11_ADAPTERS
processTestFile<valijson::adapters::Json11Adapter>(testFile, version);
#endif // VALIJSON_BUILD_CXX11_ADAPTERS
}
void processDraft3TestFile(const std::string &testFile)

View File

@ -0,0 +1 @@
test

View File

@ -0,0 +1,21 @@
project(json11)
cmake_minimum_required(VERSION 2.8)
enable_testing()
add_definitions(
-std=c++11
-fno-rtti
-fno-exceptions
-Wall
-Wextra
-Werror)
set(json11_SRCS json11.cpp)
add_library(json11 STATIC ${json11_SRCS})
add_test(json11_test json11_test)
add_executable(json11_test ${json11_SRCS} test.cpp)

View File

@ -0,0 +1,19 @@
Copyright (c) 2013 Dropbox, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

7
thirdparty/json11-2016-01-26/Makefile vendored Normal file
View File

@ -0,0 +1,7 @@
test: json11.cpp json11.hpp test.cpp
$(CXX) -O -std=c++11 json11.cpp test.cpp -o test -fno-rtti -fno-exceptions
clean:
if [ -e test ]; then rm test; fi
.PHONY: clean

42
thirdparty/json11-2016-01-26/README.md vendored Normal file
View File

@ -0,0 +1,42 @@
json11
------
json11 is a tiny JSON library for C++11, providing JSON parsing and serialization.
The core object provided by the library is json11::Json. A Json object represents any JSON
value: null, bool, number (int or double), string (std::string), array (std::vector), or
object (std::map).
Json objects act like values. They can be assigned, copied, moved, compared for equality or
order, and so on. There are also helper methods Json::dump, to serialize a Json to a string, and
Json::parse (static) to parse a std::string as a Json object.
It's easy to make a JSON object with C++11's new initializer syntax:
Json my_json = Json::object {
{ "key1", "value1" },
{ "key2", false },
{ "key3", Json::array { 1, 2, 3 } },
};
std::string json_str = my_json.dump();
There are also implicit constructors that allow standard and user-defined types to be
automatically converted to JSON. For example:
class Point {
public:
int x;
int y;
Point (int x, int y) : x(x), y(y) {}
Json to_json() const { return Json::array { x, y }; }
};
std::vector<Point> points = { { 1, 2 }, { 10, 20 }, { 100, 200 } };
std::string points_json = Json(points).dump();
JSON values can have their values queried and inspected:
Json json = Json::array { Json::object { { "k", "v" } } };
std::string str = json[0]["k"].string_value();
More documentation is still to come. For now, see json11.hpp.

769
thirdparty/json11-2016-01-26/json11.cpp vendored Normal file
View File

@ -0,0 +1,769 @@
/* Copyright (c) 2013 Dropbox, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "json11.hpp"
#include <cassert>
#include <cmath>
#include <cstdlib>
#include <cstdio>
#include <limits>
namespace json11 {
static const int max_depth = 200;
using std::string;
using std::vector;
using std::map;
using std::make_shared;
using std::initializer_list;
using std::move;
/* * * * * * * * * * * * * * * * * * * *
* Serialization
*/
static void dump(std::nullptr_t, string &out) {
out += "null";
}
static void dump(double value, string &out) {
if (std::isfinite(value)) {
char buf[32];
snprintf(buf, sizeof buf, "%.17g", value);
out += buf;
} else {
out += "null";
}
}
static void dump(int value, string &out) {
char buf[32];
snprintf(buf, sizeof buf, "%d", value);
out += buf;
}
static void dump(bool value, string &out) {
out += value ? "true" : "false";
}
static void dump(const string &value, string &out) {
out += '"';
for (size_t i = 0; i < value.length(); i++) {
const char ch = value[i];
if (ch == '\\') {
out += "\\\\";
} else if (ch == '"') {
out += "\\\"";
} else if (ch == '\b') {
out += "\\b";
} else if (ch == '\f') {
out += "\\f";
} else if (ch == '\n') {
out += "\\n";
} else if (ch == '\r') {
out += "\\r";
} else if (ch == '\t') {
out += "\\t";
} else if (static_cast<uint8_t>(ch) <= 0x1f) {
char buf[8];
snprintf(buf, sizeof buf, "\\u%04x", ch);
out += buf;
} else if (static_cast<uint8_t>(ch) == 0xe2 && static_cast<uint8_t>(value[i+1]) == 0x80
&& static_cast<uint8_t>(value[i+2]) == 0xa8) {
out += "\\u2028";
i += 2;
} else if (static_cast<uint8_t>(ch) == 0xe2 && static_cast<uint8_t>(value[i+1]) == 0x80
&& static_cast<uint8_t>(value[i+2]) == 0xa9) {
out += "\\u2029";
i += 2;
} else {
out += ch;
}
}
out += '"';
}
static void dump(const Json::array &values, string &out) {
bool first = true;
out += "[";
for (const auto &value : values) {
if (!first)
out += ", ";
value.dump(out);
first = false;
}
out += "]";
}
static void dump(const Json::object &values, string &out) {
bool first = true;
out += "{";
for (const auto &kv : values) {
if (!first)
out += ", ";
dump(kv.first, out);
out += ": ";
kv.second.dump(out);
first = false;
}
out += "}";
}
void Json::dump(string &out) const {
m_ptr->dump(out);
}
/* * * * * * * * * * * * * * * * * * * *
* Value wrappers
*/
template <Json::Type tag, typename T>
class Value : public JsonValue {
protected:
// Constructors
explicit Value(const T &value) : m_value(value) {}
explicit Value(T &&value) : m_value(move(value)) {}
// Get type tag
Json::Type type() const override {
return tag;
}
// Comparisons
bool equals(const JsonValue * other) const override {
return m_value == static_cast<const Value<tag, T> *>(other)->m_value;
}
bool less(const JsonValue * other) const override {
return m_value < static_cast<const Value<tag, T> *>(other)->m_value;
}
const T m_value;
void dump(string &out) const override { json11::dump(m_value, out); }
};
class JsonDouble final : public Value<Json::NUMBER, double> {
double number_value() const override { return m_value; }
int int_value() const override { return static_cast<int>(m_value); }
bool equals(const JsonValue * other) const override { return m_value == other->number_value(); }
bool less(const JsonValue * other) const override { return m_value < other->number_value(); }
public:
explicit JsonDouble(double value) : Value(value) {}
};
class JsonInt final : public Value<Json::NUMBER, int> {
double number_value() const override { return m_value; }
int int_value() const override { return m_value; }
bool equals(const JsonValue * other) const override { return m_value == other->number_value(); }
bool less(const JsonValue * other) const override { return m_value < other->number_value(); }
public:
explicit JsonInt(int value) : Value(value) {}
};
class JsonBoolean final : public Value<Json::BOOL, bool> {
bool bool_value() const override { return m_value; }
public:
explicit JsonBoolean(bool value) : Value(value) {}
};
class JsonString final : public Value<Json::STRING, string> {
const string &string_value() const override { return m_value; }
public:
explicit JsonString(const string &value) : Value(value) {}
explicit JsonString(string &&value) : Value(move(value)) {}
};
class JsonArray final : public Value<Json::ARRAY, Json::array> {
const Json::array &array_items() const override { return m_value; }
const Json & operator[](size_t i) const override;
public:
explicit JsonArray(const Json::array &value) : Value(value) {}
explicit JsonArray(Json::array &&value) : Value(move(value)) {}
};
class JsonObject final : public Value<Json::OBJECT, Json::object> {
const Json::object &object_items() const override { return m_value; }
const Json & operator[](const string &key) const override;
public:
explicit JsonObject(const Json::object &value) : Value(value) {}
explicit JsonObject(Json::object &&value) : Value(move(value)) {}
};
class JsonNull final : public Value<Json::NUL, std::nullptr_t> {
public:
JsonNull() : Value(nullptr) {}
};
/* * * * * * * * * * * * * * * * * * * *
* Static globals - static-init-safe
*/
struct Statics {
const std::shared_ptr<JsonValue> null = make_shared<JsonNull>();
const std::shared_ptr<JsonValue> t = make_shared<JsonBoolean>(true);
const std::shared_ptr<JsonValue> f = make_shared<JsonBoolean>(false);
const string empty_string;
const vector<Json> empty_vector;
const map<string, Json> empty_map;
Statics() {}
};
static const Statics & statics() {
static const Statics s {};
return s;
}
static const Json & static_null() {
// This has to be separate, not in Statics, because Json() accesses statics().null.
static const Json json_null;
return json_null;
}
/* * * * * * * * * * * * * * * * * * * *
* Constructors
*/
Json::Json() noexcept : m_ptr(statics().null) {}
Json::Json(std::nullptr_t) noexcept : m_ptr(statics().null) {}
Json::Json(double value) : m_ptr(make_shared<JsonDouble>(value)) {}
Json::Json(int value) : m_ptr(make_shared<JsonInt>(value)) {}
Json::Json(bool value) : m_ptr(value ? statics().t : statics().f) {}
Json::Json(const string &value) : m_ptr(make_shared<JsonString>(value)) {}
Json::Json(string &&value) : m_ptr(make_shared<JsonString>(move(value))) {}
Json::Json(const char * value) : m_ptr(make_shared<JsonString>(value)) {}
Json::Json(const Json::array &values) : m_ptr(make_shared<JsonArray>(values)) {}
Json::Json(Json::array &&values) : m_ptr(make_shared<JsonArray>(move(values))) {}
Json::Json(const Json::object &values) : m_ptr(make_shared<JsonObject>(values)) {}
Json::Json(Json::object &&values) : m_ptr(make_shared<JsonObject>(move(values))) {}
/* * * * * * * * * * * * * * * * * * * *
* Accessors
*/
Json::Type Json::type() const { return m_ptr->type(); }
double Json::number_value() const { return m_ptr->number_value(); }
int Json::int_value() const { return m_ptr->int_value(); }
bool Json::bool_value() const { return m_ptr->bool_value(); }
const string & Json::string_value() const { return m_ptr->string_value(); }
const vector<Json> & Json::array_items() const { return m_ptr->array_items(); }
const map<string, Json> & Json::object_items() const { return m_ptr->object_items(); }
const Json & Json::operator[] (size_t i) const { return (*m_ptr)[i]; }
const Json & Json::operator[] (const string &key) const { return (*m_ptr)[key]; }
double JsonValue::number_value() const { return 0; }
int JsonValue::int_value() const { return 0; }
bool JsonValue::bool_value() const { return false; }
const string & JsonValue::string_value() const { return statics().empty_string; }
const vector<Json> & JsonValue::array_items() const { return statics().empty_vector; }
const map<string, Json> & JsonValue::object_items() const { return statics().empty_map; }
const Json & JsonValue::operator[] (size_t) const { return static_null(); }
const Json & JsonValue::operator[] (const string &) const { return static_null(); }
const Json & JsonObject::operator[] (const string &key) const {
auto iter = m_value.find(key);
return (iter == m_value.end()) ? static_null() : iter->second;
}
const Json & JsonArray::operator[] (size_t i) const {
if (i >= m_value.size()) return static_null();
else return m_value[i];
}
/* * * * * * * * * * * * * * * * * * * *
* Comparison
*/
bool Json::operator== (const Json &other) const {
if (m_ptr->type() != other.m_ptr->type())
return false;
return m_ptr->equals(other.m_ptr.get());
}
bool Json::operator< (const Json &other) const {
if (m_ptr->type() != other.m_ptr->type())
return m_ptr->type() < other.m_ptr->type();
return m_ptr->less(other.m_ptr.get());
}
/* * * * * * * * * * * * * * * * * * * *
* Parsing
*/
/* esc(c)
*
* Format char c suitable for printing in an error message.
*/
static inline string esc(char c) {
char buf[12];
if (static_cast<uint8_t>(c) >= 0x20 && static_cast<uint8_t>(c) <= 0x7f) {
snprintf(buf, sizeof buf, "'%c' (%d)", c, c);
} else {
snprintf(buf, sizeof buf, "(%d)", c);
}
return string(buf);
}
static inline bool in_range(long x, long lower, long upper) {
return (x >= lower && x <= upper);
}
/* JsonParser
*
* Object that tracks all state of an in-progress parse.
*/
struct JsonParser {
/* State
*/
const string &str;
size_t i;
string &err;
bool failed;
const JsonParse strategy;
/* fail(msg, err_ret = Json())
*
* Mark this parse as failed.
*/
Json fail(string &&msg) {
return fail(move(msg), Json());
}
template <typename T>
T fail(string &&msg, const T err_ret) {
if (!failed)
err = std::move(msg);
failed = true;
return err_ret;
}
/* consume_whitespace()
*
* Advance until the current character is non-whitespace.
*/
void consume_whitespace() {
while (str[i] == ' ' || str[i] == '\r' || str[i] == '\n' || str[i] == '\t')
i++;
}
/* consume_comment()
*
* Advance comments (c-style inline and multiline).
*/
bool consume_comment() {
bool comment_found = false;
if (str[i] == '/') {
i++;
if (i == str.size())
return fail("unexpected end of input inside comment", 0);
if (str[i] == '/') { // inline comment
i++;
if (i == str.size())
return fail("unexpected end of input inside inline comment", 0);
// advance until next line
while (str[i] != '\n') {
i++;
if (i == str.size())
return fail("unexpected end of input inside inline comment", 0);
}
comment_found = true;
}
else if (str[i] == '*') { // multiline comment
i++;
if (i > str.size()-2)
return fail("unexpected end of input inside multi-line comment", 0);
// advance until closing tokens
while (!(str[i] == '*' && str[i+1] == '/')) {
i++;
if (i > str.size()-2)
return fail(
"unexpected end of input inside multi-line comment", 0);
}
i += 2;
if (i == str.size())
return fail(
"unexpected end of input inside multi-line comment", 0);
comment_found = true;
}
else
return fail("malformed comment", 0);
}
return comment_found;
}
/* consume_garbage()
*
* Advance until the current character is non-whitespace and non-comment.
*/
void consume_garbage() {
consume_whitespace();
if(strategy == JsonParse::COMMENTS) {
bool comment_found = false;
do {
comment_found = consume_comment();
consume_whitespace();
}
while(comment_found);
}
}
/* get_next_token()
*
* Return the next non-whitespace character. If the end of the input is reached,
* flag an error and return 0.
*/
char get_next_token() {
consume_garbage();
if (i == str.size())
return fail("unexpected end of input", 0);
return str[i++];
}
/* encode_utf8(pt, out)
*
* Encode pt as UTF-8 and add it to out.
*/
void encode_utf8(long pt, string & out) {
if (pt < 0)
return;
if (pt < 0x80) {
out += static_cast<char>(pt);
} else if (pt < 0x800) {
out += static_cast<char>((pt >> 6) | 0xC0);
out += static_cast<char>((pt & 0x3F) | 0x80);
} else if (pt < 0x10000) {
out += static_cast<char>((pt >> 12) | 0xE0);
out += static_cast<char>(((pt >> 6) & 0x3F) | 0x80);
out += static_cast<char>((pt & 0x3F) | 0x80);
} else {
out += static_cast<char>((pt >> 18) | 0xF0);
out += static_cast<char>(((pt >> 12) & 0x3F) | 0x80);
out += static_cast<char>(((pt >> 6) & 0x3F) | 0x80);
out += static_cast<char>((pt & 0x3F) | 0x80);
}
}
/* parse_string()
*
* Parse a string, starting at the current position.
*/
string parse_string() {
string out;
long last_escaped_codepoint = -1;
while (true) {
if (i == str.size())
return fail("unexpected end of input in string", "");
char ch = str[i++];
if (ch == '"') {
encode_utf8(last_escaped_codepoint, out);
return out;
}
if (in_range(ch, 0, 0x1f))
return fail("unescaped " + esc(ch) + " in string", "");
// The usual case: non-escaped characters
if (ch != '\\') {
encode_utf8(last_escaped_codepoint, out);
last_escaped_codepoint = -1;
out += ch;
continue;
}
// Handle escapes
if (i == str.size())
return fail("unexpected end of input in string", "");
ch = str[i++];
if (ch == 'u') {
// Extract 4-byte escape sequence
string esc = str.substr(i, 4);
// Explicitly check length of the substring. The following loop
// relies on std::string returning the terminating NUL when
// accessing str[length]. Checking here reduces brittleness.
if (esc.length() < 4) {
return fail("bad \\u escape: " + esc, "");
}
for (int j = 0; j < 4; j++) {
if (!in_range(esc[j], 'a', 'f') && !in_range(esc[j], 'A', 'F')
&& !in_range(esc[j], '0', '9'))
return fail("bad \\u escape: " + esc, "");
}
long codepoint = strtol(esc.data(), nullptr, 16);
// JSON specifies that characters outside the BMP shall be encoded as a pair
// of 4-hex-digit \u escapes encoding their surrogate pair components. Check
// whether we're in the middle of such a beast: the previous codepoint was an
// escaped lead (high) surrogate, and this is a trail (low) surrogate.
if (in_range(last_escaped_codepoint, 0xD800, 0xDBFF)
&& in_range(codepoint, 0xDC00, 0xDFFF)) {
// Reassemble the two surrogate pairs into one astral-plane character, per
// the UTF-16 algorithm.
encode_utf8((((last_escaped_codepoint - 0xD800) << 10)
| (codepoint - 0xDC00)) + 0x10000, out);
last_escaped_codepoint = -1;
} else {
encode_utf8(last_escaped_codepoint, out);
last_escaped_codepoint = codepoint;
}
i += 4;
continue;
}
encode_utf8(last_escaped_codepoint, out);
last_escaped_codepoint = -1;
if (ch == 'b') {
out += '\b';
} else if (ch == 'f') {
out += '\f';
} else if (ch == 'n') {
out += '\n';
} else if (ch == 'r') {
out += '\r';
} else if (ch == 't') {
out += '\t';
} else if (ch == '"' || ch == '\\' || ch == '/') {
out += ch;
} else {
return fail("invalid escape character " + esc(ch), "");
}
}
}
/* parse_number()
*
* Parse a double.
*/
Json parse_number() {
size_t start_pos = i;
if (str[i] == '-')
i++;
// Integer part
if (str[i] == '0') {
i++;
if (in_range(str[i], '0', '9'))
return fail("leading 0s not permitted in numbers");
} else if (in_range(str[i], '1', '9')) {
i++;
while (in_range(str[i], '0', '9'))
i++;
} else {
return fail("invalid " + esc(str[i]) + " in number");
}
if (str[i] != '.' && str[i] != 'e' && str[i] != 'E'
&& (i - start_pos) <= static_cast<size_t>(std::numeric_limits<int>::digits10)) {
return std::atoi(str.c_str() + start_pos);
}
// Decimal part
if (str[i] == '.') {
i++;
if (!in_range(str[i], '0', '9'))
return fail("at least one digit required in fractional part");
while (in_range(str[i], '0', '9'))
i++;
}
// Exponent part
if (str[i] == 'e' || str[i] == 'E') {
i++;
if (str[i] == '+' || str[i] == '-')
i++;
if (!in_range(str[i], '0', '9'))
return fail("at least one digit required in exponent");
while (in_range(str[i], '0', '9'))
i++;
}
return std::strtod(str.c_str() + start_pos, nullptr);
}
/* expect(str, res)
*
* Expect that 'str' starts at the character that was just read. If it does, advance
* the input and return res. If not, flag an error.
*/
Json expect(const string &expected, Json res) {
assert(i != 0);
i--;
if (str.compare(i, expected.length(), expected) == 0) {
i += expected.length();
return res;
} else {
return fail("parse error: expected " + expected + ", got " + str.substr(i, expected.length()));
}
}
/* parse_json()
*
* Parse a JSON object.
*/
Json parse_json(int depth) {
if (depth > max_depth) {
return fail("exceeded maximum nesting depth");
}
char ch = get_next_token();
if (failed)
return Json();
if (ch == '-' || (ch >= '0' && ch <= '9')) {
i--;
return parse_number();
}
if (ch == 't')
return expect("true", true);
if (ch == 'f')
return expect("false", false);
if (ch == 'n')
return expect("null", Json());
if (ch == '"')
return parse_string();
if (ch == '{') {
map<string, Json> data;
ch = get_next_token();
if (ch == '}')
return data;
while (1) {
if (ch != '"')
return fail("expected '\"' in object, got " + esc(ch));
string key = parse_string();
if (failed)
return Json();
ch = get_next_token();
if (ch != ':')
return fail("expected ':' in object, got " + esc(ch));
data[std::move(key)] = parse_json(depth + 1);
if (failed)
return Json();
ch = get_next_token();
if (ch == '}')
break;
if (ch != ',')
return fail("expected ',' in object, got " + esc(ch));
ch = get_next_token();
}
return data;
}
if (ch == '[') {
vector<Json> data;
ch = get_next_token();
if (ch == ']')
return data;
while (1) {
i--;
data.push_back(parse_json(depth + 1));
if (failed)
return Json();
ch = get_next_token();
if (ch == ']')
break;
if (ch != ',')
return fail("expected ',' in list, got " + esc(ch));
ch = get_next_token();
(void)ch;
}
return data;
}
return fail("expected value, got " + esc(ch));
}
};
Json Json::parse(const string &in, string &err, JsonParse strategy) {
JsonParser parser { in, 0, err, false, strategy };
Json result = parser.parse_json(0);
// Check for any trailing garbage
parser.consume_garbage();
if (parser.i != in.size())
return parser.fail("unexpected trailing " + esc(in[parser.i]));
return result;
}
// Documented in json11.hpp
vector<Json> Json::parse_multi(const string &in,
string &err,
JsonParse strategy) {
JsonParser parser { in, 0, err, false, strategy };
vector<Json> json_vec;
while (parser.i != in.size() && !parser.failed) {
json_vec.push_back(parser.parse_json(0));
// Check for another object
parser.consume_garbage();
}
return json_vec;
}
/* * * * * * * * * * * * * * * * * * * *
* Shape-checking
*/
bool Json::has_shape(const shape & types, string & err) const {
if (!is_object()) {
err = "expected JSON object, got " + dump();
return false;
}
for (auto & item : types) {
if ((*this)[item.first].type() != item.second) {
err = "bad type for " + item.first + " in " + dump();
return false;
}
}
return true;
}
} // namespace json11

211
thirdparty/json11-2016-01-26/json11.hpp vendored Normal file
View File

@ -0,0 +1,211 @@
/* json11
*
* json11 is a tiny JSON library for C++11, providing JSON parsing and serialization.
*
* The core object provided by the library is json11::Json. A Json object represents any JSON
* value: null, bool, number (int or double), string (std::string), array (std::vector), or
* object (std::map).
*
* Json objects act like values: they can be assigned, copied, moved, compared for equality or
* order, etc. There are also helper methods Json::dump, to serialize a Json to a string, and
* Json::parse (static) to parse a std::string as a Json object.
*
* Internally, the various types of Json object are represented by the JsonValue class
* hierarchy.
*
* A note on numbers - JSON specifies the syntax of number formatting but not its semantics,
* so some JSON implementations distinguish between integers and floating-point numbers, while
* some don't. In json11, we choose the latter. Because some JSON implementations (namely
* Javascript itself) treat all numbers as the same type, distinguishing the two leads
* to JSON that will be *silently* changed by a round-trip through those implementations.
* Dangerous! To avoid that risk, json11 stores all numbers as double internally, but also
* provides integer helpers.
*
* Fortunately, double-precision IEEE754 ('double') can precisely store any integer in the
* range +/-2^53, which includes every 'int' on most systems. (Timestamps often use int64
* or long long to avoid the Y2038K problem; a double storing microseconds since some epoch
* will be exact for +/- 275 years.)
*/
/* Copyright (c) 2013 Dropbox, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#pragma once
#include <string>
#include <vector>
#include <map>
#include <memory>
#include <initializer_list>
namespace json11 {
enum JsonParse {
STANDARD, COMMENTS
};
class JsonValue;
class Json final {
public:
// Types
enum Type {
NUL, NUMBER, BOOL, STRING, ARRAY, OBJECT
};
// Array and object typedefs
typedef std::vector<Json> array;
typedef std::map<std::string, Json> object;
// Constructors for the various types of JSON value.
Json() noexcept; // NUL
Json(std::nullptr_t) noexcept; // NUL
Json(double value); // NUMBER
Json(int value); // NUMBER
Json(bool value); // BOOL
Json(const std::string &value); // STRING
Json(std::string &&value); // STRING
Json(const char * value); // STRING
Json(const array &values); // ARRAY
Json(array &&values); // ARRAY
Json(const object &values); // OBJECT
Json(object &&values); // OBJECT
// Implicit constructor: anything with a to_json() function.
template <class T, class = decltype(&T::to_json)>
Json(const T & t) : Json(t.to_json()) {}
// Implicit constructor: map-like objects (std::map, std::unordered_map, etc)
template <class M, typename std::enable_if<
std::is_constructible<std::string, typename M::key_type>::value
&& std::is_constructible<Json, typename M::mapped_type>::value,
int>::type = 0>
Json(const M & m) : Json(object(m.begin(), m.end())) {}
// Implicit constructor: vector-like objects (std::list, std::vector, std::set, etc)
template <class V, typename std::enable_if<
std::is_constructible<Json, typename V::value_type>::value,
int>::type = 0>
Json(const V & v) : Json(array(v.begin(), v.end())) {}
// This prevents Json(some_pointer) from accidentally producing a bool. Use
// Json(bool(some_pointer)) if that behavior is desired.
Json(void *) = delete;
// Accessors
Type type() const;
bool is_null() const { return type() == NUL; }
bool is_number() const { return type() == NUMBER; }
bool is_bool() const { return type() == BOOL; }
bool is_string() const { return type() == STRING; }
bool is_array() const { return type() == ARRAY; }
bool is_object() const { return type() == OBJECT; }
// Return the enclosed value if this is a number, 0 otherwise. Note that json11 does not
// distinguish between integer and non-integer numbers - number_value() and int_value()
// can both be applied to a NUMBER-typed object.
double number_value() const;
int int_value() const;
// Return the enclosed value if this is a boolean, false otherwise.
bool bool_value() const;
// Return the enclosed string if this is a string, "" otherwise.
const std::string &string_value() const;
// Return the enclosed std::vector if this is an array, or an empty vector otherwise.
const array &array_items() const;
// Return the enclosed std::map if this is an object, or an empty map otherwise.
const object &object_items() const;
// Return a reference to arr[i] if this is an array, Json() otherwise.
const Json & operator[](size_t i) const;
// Return a reference to obj[key] if this is an object, Json() otherwise.
const Json & operator[](const std::string &key) const;
// Serialize.
void dump(std::string &out) const;
std::string dump() const {
std::string out;
dump(out);
return out;
}
// Parse. If parse fails, return Json() and assign an error message to err.
static Json parse(const std::string & in,
std::string & err,
JsonParse strategy = JsonParse::STANDARD);
static Json parse(const char * in,
std::string & err,
JsonParse strategy = JsonParse::STANDARD) {
if (in) {
return parse(std::string(in), err, strategy);
} else {
err = "null input";
return nullptr;
}
}
// Parse multiple objects, concatenated or separated by whitespace
static std::vector<Json> parse_multi(
const std::string & in,
std::string & err,
JsonParse strategy = JsonParse::STANDARD);
bool operator== (const Json &rhs) const;
bool operator< (const Json &rhs) const;
bool operator!= (const Json &rhs) const { return !(*this == rhs); }
bool operator<= (const Json &rhs) const { return !(rhs < *this); }
bool operator> (const Json &rhs) const { return (rhs < *this); }
bool operator>= (const Json &rhs) const { return !(*this < rhs); }
/* has_shape(types, err)
*
* Return true if this is a JSON object and, for each item in types, has a field of
* the given type. If not, return false and set err to a descriptive message.
*/
typedef std::initializer_list<std::pair<std::string, Type>> shape;
bool has_shape(const shape & types, std::string & err) const;
private:
std::shared_ptr<JsonValue> m_ptr;
};
// Internal class hierarchy - JsonValue objects are not exposed to users of this API.
class JsonValue {
protected:
friend class Json;
friend class JsonInt;
friend class JsonDouble;
virtual Json::Type type() const = 0;
virtual bool equals(const JsonValue * other) const = 0;
virtual bool less(const JsonValue * other) const = 0;
virtual void dump(std::string &out) const = 0;
virtual double number_value() const;
virtual int int_value() const;
virtual bool bool_value() const;
virtual const std::string &string_value() const;
virtual const Json::array &array_items() const;
virtual const Json &operator[](size_t i) const;
virtual const Json::object &object_items() const;
virtual const Json &operator[](const std::string &key) const;
virtual ~JsonValue() {}
};
} // namespace json11

205
thirdparty/json11-2016-01-26/test.cpp vendored Normal file
View File

@ -0,0 +1,205 @@
#include <string>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <sstream>
#include "json11.hpp"
#include <cassert>
#include <list>
#include <set>
#include <unordered_map>
using namespace json11;
using std::string;
// Check that Json has the properties we want.
#include <type_traits>
#define CHECK_TRAIT(x) static_assert(std::x::value, #x)
CHECK_TRAIT(is_nothrow_constructible<Json>);
CHECK_TRAIT(is_nothrow_default_constructible<Json>);
CHECK_TRAIT(is_copy_constructible<Json>);
CHECK_TRAIT(is_nothrow_move_constructible<Json>);
CHECK_TRAIT(is_copy_assignable<Json>);
CHECK_TRAIT(is_nothrow_move_assignable<Json>);
CHECK_TRAIT(is_nothrow_destructible<Json>);
void parse_from_stdin() {
string buf;
string line;
while (std::getline(std::cin, line)) {
buf += line + "\n";
}
string err;
auto json = Json::parse(buf, err);
if (!err.empty()) {
printf("Failed: %s\n", err.c_str());
} else {
printf("Result: %s\n", json.dump().c_str());
}
}
int main(int argc, char **argv) {
if (argc == 2 && argv[1] == string("--stdin")) {
parse_from_stdin();
return 0;
}
const string simple_test =
R"({"k1":"v1", "k2":42, "k3":["a",123,true,false,null]})";
string err;
auto json = Json::parse(simple_test, err);
std::cout << "k1: " << json["k1"].string_value() << "\n";
std::cout << "k3: " << json["k3"].dump() << "\n";
for (auto &k : json["k3"].array_items()) {
std::cout << " - " << k.dump() << "\n";
}
const string comment_test = R"({
// comment /* with nested comment */
"a": 1,
// comment
// continued
"b": "text",
/* multi
line
comment */
// and single-line comment
"c": [1, 2, 3]
})";
string err_comment;
auto json_comment = Json::parse(
comment_test, err_comment, JsonParse::COMMENTS);
if (!err_comment.empty()) {
printf("Failed: %s\n", err_comment.c_str());
} else {
printf("Result: %s\n", json_comment.dump().c_str());
}
string failing_comment_test = R"({
/* bad comment
"a": 1,
})";
string err_failing_comment;
auto json_failing_comment = Json::parse(
failing_comment_test, err_failing_comment, JsonParse::COMMENTS);
if (!err_failing_comment.empty()) {
printf("Failed: %s\n", err_failing_comment.c_str());
} else {
printf("Result: %s\n", json_failing_comment.dump().c_str());
}
failing_comment_test = R"({
/ / bad comment })";
json_failing_comment = Json::parse(
failing_comment_test, err_failing_comment, JsonParse::COMMENTS);
if (!err_failing_comment.empty()) {
printf("Failed: %s\n", err_failing_comment.c_str());
} else {
printf("Result: %s\n", json_failing_comment.dump().c_str());
}
failing_comment_test = R"({// bad comment })";
json_failing_comment = Json::parse(
failing_comment_test, err_failing_comment, JsonParse::COMMENTS);
if (!err_failing_comment.empty()) {
printf("Failed: %s\n", err_failing_comment.c_str());
} else {
printf("Result: %s\n", json_failing_comment.dump().c_str());
}
failing_comment_test = R"({
"a": 1
}/)";
json_failing_comment = Json::parse(
failing_comment_test, err_failing_comment, JsonParse::COMMENTS);
if (!err_failing_comment.empty()) {
printf("Failed: %s\n", err_failing_comment.c_str());
} else {
printf("Result: %s\n", json_failing_comment.dump().c_str());
}
failing_comment_test = R"({/* bad
comment *})";
json_failing_comment = Json::parse(
failing_comment_test, err_failing_comment, JsonParse::COMMENTS);
if (!err_failing_comment.empty()) {
printf("Failed: %s\n", err_failing_comment.c_str());
} else {
printf("Result: %s\n", json_failing_comment.dump().c_str());
}
std::list<int> l1 { 1, 2, 3 };
std::vector<int> l2 { 1, 2, 3 };
std::set<int> l3 { 1, 2, 3 };
assert(Json(l1) == Json(l2));
assert(Json(l2) == Json(l3));
std::map<string, string> m1 { { "k1", "v1" }, { "k2", "v2" } };
std::unordered_map<string, string> m2 { { "k1", "v1" }, { "k2", "v2" } };
assert(Json(m1) == Json(m2));
// Json literals
Json obj = Json::object({
{ "k1", "v1" },
{ "k2", 42.0 },
{ "k3", Json::array({ "a", 123.0, true, false, nullptr }) },
});
std::cout << "obj: " << obj.dump() << "\n";
assert(Json("a").number_value() == 0);
assert(Json("a").string_value() == "a");
assert(Json().number_value() == 0);
assert(obj == json);
assert(Json(42) == Json(42.0));
assert(Json(42) != Json(42.1));
const string unicode_escape_test =
R"([ "blah\ud83d\udca9blah\ud83dblah\udca9blah\u0000blah\u1234" ])";
const char utf8[] = "blah" "\xf0\x9f\x92\xa9" "blah" "\xed\xa0\xbd" "blah"
"\xed\xb2\xa9" "blah" "\0" "blah" "\xe1\x88\xb4";
Json uni = Json::parse(unicode_escape_test, err);
assert(uni[0].string_value().size() == (sizeof utf8) - 1);
assert(std::memcmp(uni[0].string_value().data(), utf8, sizeof utf8) == 0);
// Demonstrates the behavior change in Xcode 7 / Clang 3.7 described
// here: https://llvm.org/bugs/show_bug.cgi?id=23812
Json nested_array = Json::array { Json::array { 1, 2, 3 } };
assert(nested_array.is_array());
assert(nested_array.array_items().size() == 1);
assert(nested_array.array_items()[0].is_array());
assert(nested_array.array_items()[0].array_items().size() == 3);
Json my_json = Json::object {
{ "key1", "value1" },
{ "key2", false },
{ "key3", Json::array { 1, 2, 3 } },
};
std::string json_str = my_json.dump();
printf("%s\n", json_str.c_str());
class Point {
public:
int x;
int y;
Point (int x, int y) : x(x), y(y) {}
Json to_json() const { return Json::array { x, y }; }
};
std::vector<Point> points = { { 1, 2 }, { 10, 20 }, { 100, 200 } };
std::string points_json = Json(points).dump();
printf("%s\n", points_json.c_str());
}

View File

@ -10,6 +10,9 @@
6A477F8517D6BCBB0013571C /* libboost_regex-mt.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 6A477F8417D6BCBB0013571C /* libboost_regex-mt.dylib */; };
6A477F8617D6EA000013571C /* libboost_regex-mt.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 6A477F8417D6BCBB0013571C /* libboost_regex-mt.dylib */; };
6A506D201AF88E5D00C2C818 /* test_json_pointer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6A506D1F1AF88E5D00C2C818 /* test_json_pointer.cpp */; };
6A5C5D2A1C5B13D4004F40ED /* test_json11_adapter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6A5C5D291C5B13D4004F40ED /* test_json11_adapter.cpp */; };
6A5C5D4B1C5B1525004F40ED /* json11.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6A5C5D411C5B1511004F40ED /* json11.cpp */; };
6A5C5D4E1C5B1554004F40ED /* libjson11.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 6A5C5D471C5B151F004F40ED /* libjson11.a */; };
6A725F4517F61D7000D6B2FF /* test_validation_errors.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6A725F4317F61B5100D6B2FF /* test_validation_errors.cpp */; };
6A725F4617F6404100D6B2FF /* test_adapter_comparison.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6AB8FEB117E6DF9A0028E147 /* test_adapter_comparison.cpp */; };
6A725F4717F6404100D6B2FF /* test_jsoncpp_adapter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6AB8FE9217E6BE770028E147 /* test_jsoncpp_adapter.cpp */; };
@ -30,6 +33,13 @@
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
6A5C5D4C1C5B1539004F40ED /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 6AC78AC517C5FBBC00674114 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 6A5C5D461C5B151F004F40ED;
remoteInfo = json11;
};
6AEFECCF1AB53F6D00275614 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 6AC78AC517C5FBBC00674114 /* Project object */;
@ -56,6 +66,13 @@
6A506D1C1AF884E100C2C818 /* rfc6901-json-pointer.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = "rfc6901-json-pointer.txt"; sourceTree = "<group>"; };
6A506D1E1AF88D8700C2C818 /* json_pointer.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; name = json_pointer.hpp; path = internal/json_pointer.hpp; sourceTree = "<group>"; };
6A506D1F1AF88E5D00C2C818 /* test_json_pointer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = test_json_pointer.cpp; sourceTree = "<group>"; };
6A5C5D261C5B139B004F40ED /* json11_adapter.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = json11_adapter.hpp; sourceTree = "<group>"; };
6A5C5D271C5B13AB004F40ED /* json11_utils.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = json11_utils.hpp; sourceTree = "<group>"; };
6A5C5D281C5B13C3004F40ED /* picojson_utils.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = picojson_utils.hpp; sourceTree = "<group>"; };
6A5C5D291C5B13D4004F40ED /* test_json11_adapter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = test_json11_adapter.cpp; sourceTree = "<group>"; };
6A5C5D411C5B1511004F40ED /* json11.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = json11.cpp; sourceTree = "<group>"; };
6A5C5D421C5B1511004F40ED /* json11.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = json11.hpp; sourceTree = "<group>"; };
6A5C5D471C5B151F004F40ED /* libjson11.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libjson11.a; sourceTree = BUILT_PRODUCTS_DIR; };
6A6962F81C1C113F00089239 /* folderInteger.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = folderInteger.json; sourceTree = "<group>"; };
6A6962F91C1C113F00089239 /* integer.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = integer.json; sourceTree = "<group>"; };
6A6962FA1C1C113F00089239 /* subSchemas.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = subSchemas.json; sourceTree = "<group>"; };
@ -252,6 +269,13 @@
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
6A5C5D441C5B151F004F40ED /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
6AB8FE8C17E6A57E0028E147 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
@ -264,6 +288,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
6A5C5D4E1C5B1554004F40ED /* libjson11.a in Frameworks */,
6AEFECD11AB53F7600275614 /* libjsoncpp.a in Frameworks */,
6A477F8517D6BCBB0013571C /* libboost_regex-mt.dylib in Frameworks */,
);
@ -340,6 +365,15 @@
name = internal;
sourceTree = "<group>";
};
6A5C5D401C5B14BC004F40ED /* json11-2016-01-26 */ = {
isa = PBXGroup;
children = (
6A5C5D411C5B1511004F40ED /* json11.cpp */,
6A5C5D421C5B1511004F40ED /* json11.hpp */,
);
path = "json11-2016-01-26";
sourceTree = "<group>";
};
6A6962F61C1C113F00089239 /* remotes */ = {
isa = PBXGroup;
children = (
@ -560,7 +594,9 @@
isa = PBXGroup;
children = (
6AB8FEBB17E6EF910028E147 /* file_utils.hpp */,
6A5C5D271C5B13AB004F40ED /* json11_utils.hpp */,
6AB8FEBC17E6EF9A0028E147 /* jsoncpp_utils.hpp */,
6A5C5D281C5B13C3004F40ED /* picojson_utils.hpp */,
6AB8FEBD17E77C360028E147 /* property_tree_utils.hpp */,
6A869A3017CD8A92006864FA /* rapidjson_utils.hpp */,
6A9E1855194D486C003F1C4C /* utf8_utils.hpp */,
@ -637,6 +673,7 @@
isa = PBXGroup;
children = (
6AF70AC218FE71F600342325 /* gtest-1.7.0 */,
6A5C5D401C5B14BC004F40ED /* json11-2016-01-26 */,
6AA334801AB5100700F1928B /* jsoncpp-0.9.4 */,
6A8699E517CD8641006864FA /* JSON-Schema-Test-Suite */,
6AC18CEC17CC851000FE0EC9 /* rapidjson-0.1 */,
@ -699,6 +736,7 @@
6AB8FEB117E6DF9A0028E147 /* test_adapter_comparison.cpp */,
6AA8A5DA17F8BDCA002728A0 /* test_fetch_document_callback.cpp */,
6A506D1F1AF88E5D00C2C818 /* test_json_pointer.cpp */,
6A5C5D291C5B13D4004F40ED /* test_json11_adapter.cpp */,
6AB8FE9217E6BE770028E147 /* test_jsoncpp_adapter.cpp */,
6AA822FE1C3F38D4007103A7 /* test_picojson_adapter.cpp */,
6AB8FEC417E92B100028E147 /* test_property_tree_adapter.cpp */,
@ -732,6 +770,7 @@
6AC18D4117CC899800FE0EC9 /* test_suite */,
6AB8FE9117E6A57E0028E147 /* custom_schema */,
6AEFECC81AB53F1000275614 /* libjsoncpp.a */,
6A5C5D471C5B151F004F40ED /* libjson11.a */,
);
name = Products;
sourceTree = "<group>";
@ -778,6 +817,7 @@
6AC18C1917CC2DDC00FE0EC9 /* adapter.hpp */,
6AB8FEBE17E7F9420028E147 /* basic_adapter.hpp */,
6AC18C1717CC1BE100FE0EC9 /* frozen_value.hpp */,
6A5C5D261C5B139B004F40ED /* json11_adapter.hpp */,
6AC78BE017C5FC6A00674114 /* jsoncpp_adapter.hpp */,
6AAF16D21BC744BE002CB1AF /* picojson_adapter.hpp */,
6AC78BE117C5FC6A00674114 /* property_tree_adapter.hpp */,
@ -873,6 +913,13 @@
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
6A5C5D451C5B151F004F40ED /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
6AEFECC61AB53F1000275614 /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
@ -883,6 +930,23 @@
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
6A5C5D461C5B151F004F40ED /* json11 */ = {
isa = PBXNativeTarget;
buildConfigurationList = 6A5C5D481C5B151F004F40ED /* Build configuration list for PBXNativeTarget "json11" */;
buildPhases = (
6A5C5D431C5B151F004F40ED /* Sources */,
6A5C5D441C5B151F004F40ED /* Frameworks */,
6A5C5D451C5B151F004F40ED /* Headers */,
);
buildRules = (
);
dependencies = (
);
name = json11;
productName = json11;
productReference = 6A5C5D471C5B151F004F40ED /* libjson11.a */;
productType = "com.apple.product-type.library.static";
};
6AB8FE8817E6A57E0028E147 /* custom_schema */ = {
isa = PBXNativeTarget;
buildConfigurationList = 6AB8FE8E17E6A57E0028E147 /* Build configuration list for PBXNativeTarget "custom_schema" */;
@ -909,6 +973,7 @@
buildRules = (
);
dependencies = (
6A5C5D4D1C5B1539004F40ED /* PBXTargetDependency */,
6AEFECD01AB53F6D00275614 /* PBXTargetDependency */,
);
name = test_suite;
@ -958,6 +1023,9 @@
LastUpgradeCheck = 0720;
ORGANIZATIONNAME = "Tristan Penman";
TargetAttributes = {
6A5C5D461C5B151F004F40ED = {
CreatedOnToolsVersion = 7.2;
};
6AEFECC71AB53F1000275614 = {
CreatedOnToolsVersion = 6.2;
};
@ -979,11 +1047,20 @@
6AC78ACC17C5FBBC00674114 /* external_schema */,
6AC18D4017CC899800FE0EC9 /* test_suite */,
6AEFECC71AB53F1000275614 /* jsoncpp */,
6A5C5D461C5B151F004F40ED /* json11 */,
);
};
/* End PBXProject section */
/* Begin PBXSourcesBuildPhase section */
6A5C5D431C5B151F004F40ED /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
6A5C5D4B1C5B1525004F40ED /* json11.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
6AB8FE8917E6A57E0028E147 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
@ -1003,6 +1080,7 @@
6A725F4717F6404100D6B2FF /* test_jsoncpp_adapter.cpp in Sources */,
6A725F4817F6404100D6B2FF /* test_property_tree_adapter.cpp in Sources */,
6AD3490118FF56FB004BDEE7 /* gtest_main.cc in Sources */,
6A5C5D2A1C5B13D4004F40ED /* test_json11_adapter.cpp in Sources */,
6AA822FF1C3F38D4007103A7 /* test_picojson_adapter.cpp in Sources */,
6A506D201AF88E5D00C2C818 /* test_json_pointer.cpp in Sources */,
6A725F4917F6404100D6B2FF /* test_rapidjson_adapter.cpp in Sources */,
@ -1031,6 +1109,11 @@
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
6A5C5D4D1C5B1539004F40ED /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 6A5C5D461C5B151F004F40ED /* json11 */;
targetProxy = 6A5C5D4C1C5B1539004F40ED /* PBXContainerItemProxy */;
};
6AEFECD01AB53F6D00275614 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 6AEFECC71AB53F1000275614 /* jsoncpp */;
@ -1039,6 +1122,52 @@
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
6A5C5D491C5B151F004F40ED /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CODE_SIGN_IDENTITY = "-";
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
EXECUTABLE_PREFIX = lib;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
MTL_ENABLE_DEBUG_INFO = YES;
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
};
6A5C5D4A1C5B151F004F40ED /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CODE_SIGN_IDENTITY = "-";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
EXECUTABLE_PREFIX = lib;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
MTL_ENABLE_DEBUG_INFO = NO;
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
};
6AB8FE8F17E6A57E0028E147 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
@ -1075,10 +1204,12 @@
GTEST_USE_OWN_TR1_TUPLE,
GTEST_HAS_PARAM_TEST,
PICOJSON_USE_INT64,
VALIJSON_BUILD_CXX11_ADAPTERS,
);
HEADER_SEARCH_PATHS = (
"../thirdparty/gtest-1.7.0/include",
"../thirdparty/gtest-1.7.0",
"../thirdparty/json11-2016-01-26",
"../thirdparty/jsoncpp-0.9.4/include",
"../thirdparty/picojson-1.3.0",
"../thirdparty/rapidjson-0.1/include",
@ -1098,10 +1229,12 @@
GTEST_USE_OWN_TR1_TUPLE,
GTEST_HAS_PARAM_TEST,
PICOJSON_USE_INT64,
VALIJSON_BUILD_CXX11_ADAPTERS,
);
HEADER_SEARCH_PATHS = (
"../thirdparty/gtest-1.7.0/include",
"../thirdparty/gtest-1.7.0",
"../thirdparty/json11-2016-01-26",
"../thirdparty/jsoncpp-0.9.4/include",
"../thirdparty/picojson-1.3.0",
"../thirdparty/rapidjson-0.1/include",
@ -1125,7 +1258,6 @@
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
@ -1158,7 +1290,6 @@
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
@ -1249,6 +1380,14 @@
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
6A5C5D481C5B151F004F40ED /* Build configuration list for PBXNativeTarget "json11" */ = {
isa = XCConfigurationList;
buildConfigurations = (
6A5C5D491C5B151F004F40ED /* Debug */,
6A5C5D4A1C5B151F004F40ED /* Release */,
);
defaultConfigurationIsVisible = 0;
};
6AB8FE8E17E6A57E0028E147 /* Build configuration list for PBXNativeTarget "custom_schema" */ = {
isa = XCConfigurationList;
buildConfigurations = (