Support picojson library

This commit is contained in:
Hiroyuki Kobayashi 2015-05-09 00:24:29 +09:00
parent e13784c58a
commit 24d993dcd2
21 changed files with 2851 additions and 1 deletions

View File

@ -23,6 +23,7 @@ include_directories(
thirdparty/gtest-1.7.0/include
thirdparty/jsoncpp-0.9.4/include
thirdparty/rapidjson-0.1/include
thirdparty/picojson-1.3.0
${Boost_INCLUDE_DIRS}
)
@ -44,11 +45,17 @@ add_executable(test_suite
tests/test_jsoncpp_adapter.cpp
tests/test_property_tree_adapter.cpp
tests/test_rapidjson_adapter.cpp
tests/test_picojson_adapter.cpp
tests/test_uri_resolution.cpp
tests/test_validation_errors.cpp
tests/test_validator.cpp
)
# Definition for using picojson
set_target_properties(test_suite
PROPERTIES COMPILE_DEFINITIONS "PICOJSON_USE_INT64"
)
set(TEST_LIBS gtest gtest_main jsoncpp)
target_link_libraries(test_suite ${TEST_LIBS} ${Boost_LIBRARIES})

View File

@ -23,11 +23,12 @@ Required:
Later versions of boost (up to 1.57) are also known to work correctly.
Valijson supports JSON documents loaded using JsonCpp, RapidJson and Boost Property Tree. It has been tested against the following versions of these libraries:
Valijson supports JSON documents loaded using JsonCpp, RapidJson, Boost Property Tree and PicoJSON. It has been tested against the following versions of these libraries:
- [boost::property_tree 1.54](http://www.boost.org/doc/libs/1_54_0/doc/html/boost_propertytree/synopsis.html)
- [jsoncpp 0.9.4](https://github.com/open-source-parsers/jsoncpp/archive/0.9.4.tar.gz)
- [rapidjson 0.1](https://code.google.com/p/rapidjson/downloads/detail?name=rapidjson-0.1.zip)
- [PicoJSON 1.3.0](https://github.com/kazuho/picojson/archive/v1.3.0.tar.gz)
Version of JsonCpp going back to 0.5.0 should also work correctly, but versions from 1.0 onwards have not yet been tested.

View File

@ -0,0 +1,691 @@
/**
* @file
*
* @brief Adapter implementation for the PicoJson parser library.
*
* Include this file in your program to enable support for PicoJson.
*
* This file defines the following classes (not in this order):
* - PicoJsonAdapter
* - PicoJsonArray
* - PicoJsonArrayValueIterator
* - PicoJsonFrozenValue
* - PicoJsonObject
* - PicoJsonObjectMember
* - PicoJsonObjectMemberIterator
* - PicoJsonValue
*
* 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 PicoJsonAdapter. 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_PICOJSON_ADAPTER_HPP
#define __VALIJSON_ADAPTERS_PICOJSON_ADAPTER_HPP
#include <string>
#include <boost/bind.hpp>
#include <boost/optional.hpp>
#include <boost/iterator/iterator_facade.hpp>
#include <picojson.h>
#include <valijson/adapters/adapter.hpp>
#include <valijson/adapters/basic_adapter.hpp>
#include <valijson/adapters/frozen_value.hpp>
namespace valijson {
namespace adapters {
class PicoJsonAdapter;
class PicoJsonArrayValueIterator;
class PicoJsonObjectMemberIterator;
typedef std::pair<std::string, PicoJsonAdapter> PicoJsonObjectMember;
/**
* @brief Light weight wrapper for a PicoJson array value.
*
* This class is light weight wrapper for a PicoJson 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
* PicoJson value, assumed to be an array, so there is very little overhead
* associated with copy construction and passing by value.
*/
class PicoJsonArray
{
public:
typedef PicoJsonArrayValueIterator const_iterator;
typedef PicoJsonArrayValueIterator iterator;
/// Construct a PicoJsonArray referencing an empty array.
PicoJsonArray()
: value(emptyArray()) { }
/**
* @brief Construct a PicoJsonArray referencing a specific PicoJson
* value.
*
* @param value reference to a PicoJson value
*
* Note that this constructor will throw an exception if the value is not
* an array.
*/
PicoJsonArray(const picojson::value &value)
: value(value)
{
if (!value.is<picojson::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 PicoJson implementation.
*/
PicoJsonArrayValueIterator 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 PicoJson implementation.
*/
PicoJsonArrayValueIterator end() const;
/// Return the number of elements in the array
size_t size() const
{
const picojson::array &array = value.get<picojson::array>();
return array.size();
}
private:
/**
* @brief Return a reference to a PicoJson value that is an empty array.
*
* Note that the value returned by this function is a singleton.
*/
static const picojson::value & emptyArray()
{
static const picojson::value array(picojson::array_type, false);
return array;
}
/// Reference to the contained value
const picojson::value &value;
};
/**
* @brief Light weight wrapper for a PicoJson object.
*
* This class is light weight wrapper for a PicoJson 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
* PicoJson value, assumed to be an object, so there is very little overhead
* associated with copy construction and passing by value.
*/
class PicoJsonObject
{
public:
typedef PicoJsonObjectMemberIterator const_iterator;
typedef PicoJsonObjectMemberIterator iterator;
/// Construct a PicoJsonObject referencing an empty object singleton.
PicoJsonObject()
: value(emptyObject()) { }
/**
* @brief Construct a PicoJsonObject referencing a specific PicoJson
* value.
*
* @param value reference to a PicoJson value
*
* Note that this constructor will throw an exception if the value is not
* an object.
*/
PicoJsonObject(const picojson::value &value)
: value(value)
{
if (!value.is<picojson::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 PicoJson implementation.
*/
PicoJsonObjectMemberIterator 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 PicoJson implementation.
*/
PicoJsonObjectMemberIterator 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 property property name to search for
*/
PicoJsonObjectMemberIterator find(const std::string &propertyName) const;
/// Returns the number of members belonging to this object.
size_t size() const
{
const picojson::object &object = value.get<picojson::object>();
return object.size();
}
private:
/**
* @brief Return a reference to a PicoJson value that is empty object.
*
* Note that the value returned by this function is a singleton.
*/
static const picojson::value & emptyObject()
{
static const picojson::value object(picojson::object_type, false);
return object;
}
/// Reference to the contained object
const picojson::value &value;
};
/**
* @brief Stores an independent copy of a PicoJson value.
*
* This class allows a PicoJson value to be stored independent of its original
* document. PicoJson makes this easy to do, as it does not perform any
* custom memory management.
*
* @see FrozenValue
*/
class PicoJsonFrozenValue: public FrozenValue
{
public:
/**
* @brief Make a copy of a PicoJson value
*
* @param source the PicoJson value to be copied
*/
PicoJsonFrozenValue(const picojson::value &source)
: value(source) { }
virtual FrozenValue * clone() const
{
return new PicoJsonFrozenValue(value);
}
virtual bool equalTo(const Adapter &other, bool strict) const;
private:
/// Stored PicoJson value
picojson::value value;
};
/**
* @brief Light weight wrapper for a PicoJson value.
*
* This class is passed as an argument to the BasicAdapter template class,
* and is used to provide access to a PicoJson value. This class is responsible
* for the mechanics of actually reading a PicoJson 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 PicoJsonValue
{
public:
/// Construct a wrapper for the empty object singleton
PicoJsonValue()
: value(emptyObject()) { }
/// Construct a wrapper for a specific PicoJson value
PicoJsonValue(const picojson::value &value)
: value(value) { }
/**
* @brief Create a new PicoJsonFrozenValue instance that contains the
* value referenced by this PicoJsonValue instance.
*
* @returns pointer to a new PicoJsonFrozenValue instance, belonging to the
* caller.
*/
FrozenValue * freeze() const
{
return new PicoJsonFrozenValue(value);
}
/**
* @brief Optionally return a PicoJsonArray instance.
*
* If the referenced PicoJson value is an array, this function will return
* a boost::optional containing a PicoJsonArray instance referencing the
* array.
*
* Otherwise it will return boost::none.
*/
boost::optional<PicoJsonArray> getArrayOptional() const
{
if (value.is<picojson::array>()) {
return boost::make_optional(PicoJsonArray(value));
}
return boost::none;
}
/**
* @brief Retrieve the number of elements in the array
*
* If the referenced PicoJson 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<picojson::array>()) {
const picojson::array& array = value.get<picojson::array>();
result = array.size();
return true;
}
return false;
}
bool getBool(bool &result) const
{
if (value.is<bool>()) {
result = value.get<bool>();
return true;
}
return false;
}
bool getDouble(double &result) const
{
if (value.is<double>()) {
result = value.get<double>();
return true;
}
return false;
}
bool getInteger(int64_t &result) const
{
if (value.is<int64_t>()) {
result = value.get<int64_t>();
return true;
}
return false;
}
/**
* @brief Optionally return a PicoJsonObject instance.
*
* If the referenced PicoJson value is an object, this function will return a
* boost::optional containing a PicoJsonObject instance referencing the
* object.
*
* Otherwise it will return boost::none.
*/
boost::optional<PicoJsonObject> getObjectOptional() const
{
if (value.is<picojson::object>()) {
return boost::make_optional(PicoJsonObject(value));
}
return boost::none;
}
/**
* @brief Retrieve the number of members in the object
*
* If the referenced PicoJson 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<picojson::object>()) {
const picojson::object &object = value.get<picojson::object>();
result = object.size();
return true;
}
return false;
}
bool getString(std::string &result) const
{
if (value.is<std::string>()) {
result = value.get<std::string>();
return true;
}
return false;
}
static bool hasStrictTypes()
{
return true;
}
bool isArray() const
{
return value.is<picojson::array>();
}
bool isBool() const
{
return value.is<bool>();
}
bool isDouble() const
{
if (value.is<int64_t>()) {
return false;
}
return value.is<double>();
}
bool isInteger() const
{
return value.is<int64_t>();
}
bool isNull() const
{
return value.is<picojson::null>();
}
bool isNumber() const
{
return value.is<double>();
}
bool isObject() const
{
return value.is<picojson::object>();
}
bool isString() const
{
return value.is<std::string>();
}
private:
/// Return a reference to an empty object singleton
static const picojson::value & emptyObject()
{
static const picojson::value object(picojson::object_type, false);
return object;
}
/// Reference to the contained PicoJson value.
const picojson::value &value;
};
/**
* @brief An implementation of the Adapter interface supporting PicoJson.
*
* 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 PicoJsonAdapter:
public BasicAdapter<PicoJsonAdapter,
PicoJsonArray,
PicoJsonObjectMember,
PicoJsonObject,
PicoJsonValue>
{
public:
/// Construct a PicoJsonAdapter that contains an empty object
PicoJsonAdapter()
: BasicAdapter() { }
/// Construct a PicoJsonAdapter containing a specific PicoJson value
PicoJsonAdapter(const picojson::value &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
* PicoJsonAdapter representing a value stored in the array. It has been
* implemented using the boost iterator_facade template.
*
* @see PicoJsonArray
*/
class PicoJsonArrayValueIterator:
public boost::iterator_facade<
PicoJsonArrayValueIterator, // name of derived type
PicoJsonAdapter, // value type
boost::bidirectional_traversal_tag, // bi-directional iterator
PicoJsonAdapter> // type returned when dereferenced
{
public:
/**
* @brief Construct a new PicoJsonArrayValueIterator using an existing
* PicoJson iterator.
*
* @param itr PicoJson iterator to store
*/
PicoJsonArrayValueIterator(
const picojson::array::const_iterator &itr)
: itr(itr) { }
/// Returns a PicoJsonAdapter that contains the value of the current
/// element.
PicoJsonAdapter dereference() const
{
return PicoJsonAdapter(*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 rhs iterator to compare against
*
* @returns true if the iterators are equal, false otherwise.
*/
bool equal(const PicoJsonArrayValueIterator &other) const
{
return itr == other.itr;
}
void increment()
{
itr++;
}
void decrement()
{
itr--;
}
void advance(std::ptrdiff_t n)
{
itr += n;
}
private:
picojson::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 PicoJsonObjectMember representing one of the members of the object. It
* has been implemented using the boost iterator_facade template.
*
* @see PicoJsonObject
* @see PicoJsonObjectMember
*/
class PicoJsonObjectMemberIterator:
public boost::iterator_facade<
PicoJsonObjectMemberIterator, // name of derived type
PicoJsonObjectMember, // value type
boost::bidirectional_traversal_tag, // bi-directional iterator
PicoJsonObjectMember> // type returned when dereferenced
{
public:
/**
* @brief Construct an iterator from a PicoJson iterator.
*
* @param itr PicoJson iterator to store
*/
PicoJsonObjectMemberIterator(
const picojson::object::const_iterator &itr)
: itr(itr) { }
/**
* @brief Returns a PicoJsonObjectMember that contains the key and value
* belonging to the object member identified by the iterator.
*/
PicoJsonObjectMember dereference() const
{
return PicoJsonObjectMember(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 rhs Iterator to compare with
*
* @returns true if the underlying iterators are equal, false otherwise
*/
bool equal(const PicoJsonObjectMemberIterator &other) const
{
return itr == other.itr;
}
void increment()
{
itr++;
}
void decrement()
{
itr--;
}
private:
/// Iternal copy of the original PicoJson iterator
picojson::object::const_iterator itr;
};
/// Specialisation of the AdapterTraits template struct for PicoJsonAdapter.
template<>
struct AdapterTraits<valijson::adapters::PicoJsonAdapter>
{
typedef picojson::value DocumentType;
static std::string adapterName()
{
return "PicoJsonAdapter";
}
};
inline bool PicoJsonFrozenValue::equalTo(const Adapter &other, bool strict) const
{
return PicoJsonAdapter(value).equalTo(other, strict);
}
inline PicoJsonArrayValueIterator PicoJsonArray::begin() const
{
const picojson::array &array = value.get<picojson::array>();
return array.begin();
}
inline PicoJsonArrayValueIterator PicoJsonArray::end() const
{
const picojson::array &array = value.get<picojson::array>();
return array.end();
}
inline PicoJsonObjectMemberIterator PicoJsonObject::begin() const
{
const picojson::object &object = value.get<picojson::object>();
return object.begin();
}
inline PicoJsonObjectMemberIterator PicoJsonObject::end() const
{
const picojson::object &object = value.get<picojson::object>();
return object.end();
}
inline PicoJsonObjectMemberIterator PicoJsonObject::find(
const std::string &propertyName) const
{
const picojson::object &object = value.get<picojson::object>();
return object.find(propertyName);
}
} // namespace adapters
} // namespace valijson
#endif

View File

@ -0,0 +1,34 @@
#ifndef __VALIJSON_UTILS_PICOJSON_UTILS_HPP
#define __VALIJSON_UTILS_PICOJSON_UTILS_HPP
#include <picojson.h>
#include <valijson/utils/file_utils.hpp>
namespace valijson {
namespace utils {
inline bool loadDocument(const std::string &path, picojson::value &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 = picojson::parse(document, file);
if (!err.empty()) {
std::cerr << "PicoJson failed to parse the document:" << std::endl
<< "Parse error: " << err << std::endl;
return false;
}
return true;
}
} // namespace utils
} // namespace valijson
#endif

View File

@ -6,9 +6,11 @@
#include <valijson/adapters/jsoncpp_adapter.hpp>
#include <valijson/adapters/property_tree_adapter.hpp>
#include <valijson/adapters/rapidjson_adapter.hpp>
#include <valijson/adapters/picojson_adapter.hpp>
#include <valijson/utils/jsoncpp_utils.hpp>
#include <valijson/utils/property_tree_utils.hpp>
#include <valijson/utils/rapidjson_utils.hpp>
#include <valijson/utils/picojson_utils.hpp>
#define TEST_DATA_DIR "../tests/data/documents/"
@ -135,6 +137,13 @@ TEST_F(TestAdapterComparison, JsonCppVsRapidJson)
valijson::adapters::RapidJsonAdapter>();
}
TEST_F(TestAdapterComparison, JsonCppVsPicoJson)
{
testComparison<
valijson::adapters::JsonCppAdapter,
valijson::adapters::PicoJsonAdapter>();
}
TEST_F(TestAdapterComparison, PropertyTreeVsPropertyTree)
{
testComparison<
@ -149,9 +158,30 @@ TEST_F(TestAdapterComparison, PropertyTreeVsRapidJson)
valijson::adapters::RapidJsonAdapter>();
}
TEST_F(TestAdapterComparison, PropertyTreeVsPicoJson)
{
testComparison<
valijson::adapters::PropertyTreeAdapter,
valijson::adapters::PicoJsonAdapter>();
}
TEST_F(TestAdapterComparison, RapidJsonVsRapidJson)
{
testComparison<
valijson::adapters::RapidJsonAdapter,
valijson::adapters::RapidJsonAdapter>();
}
TEST_F(TestAdapterComparison, RapidJsonVsPicoJson)
{
testComparison<
valijson::adapters::RapidJsonAdapter,
valijson::adapters::PicoJsonAdapter>();
}
TEST_F(TestAdapterComparison, PicoJsonVsPicoJson)
{
testComparison<
valijson::adapters::PicoJsonAdapter,
valijson::adapters::PicoJsonAdapter>();
}

View File

@ -0,0 +1,85 @@
#include <boost/foreach.hpp>
#include <boost/lexical_cast.hpp>
#include <gtest/gtest.h>
#include <valijson/adapters/picojson_adapter.hpp>
class TestPicoJsonAdapter : public testing::Test
{
};
TEST_F(TestPicoJsonAdapter, BasicArrayIteration)
{
const unsigned int numElements = 10;
// Create a picojson document that consists of an array of numbers
picojson::array array;
for (unsigned int i = 0; i < numElements; i++) {
picojson::value value(static_cast<double>(i));
array.push_back(value);
}
picojson::value document(array);
// Ensure that wrapping the document preserves the array and does not allow
// it to be cast to other types
valijson::adapters::PicoJsonAdapter 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::PicoJsonAdapter 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(TestPicoJsonAdapter, BasicObjectIteration)
{
const unsigned int numElements = 10;
// Create a picojson document that consists of an object that maps numeric
// strings their corresponding numeric values
picojson::object object;
for (unsigned int i = 0; i < numElements; i++) {
std::string name(boost::lexical_cast<std::string>(i));
object[name] = picojson::value(static_cast<double>(i));
}
picojson::value document(object);
// Ensure that wrapping the document preserves the object and does not
// allow it to be cast to other types
valijson::adapters::PicoJsonAdapter 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::PicoJsonAdapter::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 );
}

View File

@ -7,8 +7,10 @@
#include <valijson/adapters/jsoncpp_adapter.hpp>
#include <valijson/adapters/rapidjson_adapter.hpp>
#include <valijson/adapters/picojson_adapter.hpp>
#include <valijson/utils/jsoncpp_utils.hpp>
#include <valijson/utils/rapidjson_utils.hpp>
#include <valijson/utils/picojson_utils.hpp>
#include <valijson/schema.hpp>
#include <valijson/schema_parser.hpp>
#include <valijson/validation_results.hpp>
@ -111,6 +113,7 @@ protected:
{
processTestFile<valijson::adapters::JsonCppAdapter>(testFile, version);
processTestFile<valijson::adapters::RapidJsonAdapter>(testFile, version);
processTestFile<valijson::adapters::PicoJsonAdapter>(testFile, version);
}
void processDraft3TestFile(const std::string &testFile)

4
thirdparty/picojson-1.3.0/.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
*~
a.out
test-core
test-core-int64

0
thirdparty/picojson-1.3.0/.gitmodules vendored Normal file
View File

8
thirdparty/picojson-1.3.0/.travis.yml vendored Normal file
View File

@ -0,0 +1,8 @@
language: cpp
compiler:
- clang
- gcc
script:
- make test

25
thirdparty/picojson-1.3.0/Changes vendored Normal file
View File

@ -0,0 +1,25 @@
Revision history for picojson
1.3.0 2015-02-25 13:05:00+0900
- `make check` is now synonym of `make test` (#62)
- operator= is now safe when part of LHS is being assigned, as well as exception-safe (#66)
1.2.1 2014-12-16 15:33:00+0900
- bundle the contents of `picotest/` (#61)
1.2.0 2014-12-15 16:20:00+0900
- `make install` to install picojson.h (#58)
- two-argument `picojson::parse()` for ease-of-use (#57)
1.1.1 2014-06-25 10:35:00+0900
- tweaks to suppress compiler errors / warning (#38 #39)
- clarify the licenses of the files in exmaple/ (#42)
1.1 2014-06-16 12:57:00+0900
- added experimental support for int64 type (#34)
- by default, throw std::runtime_error instead of using assert for runtime errors (#33)
- refine compatibility regarding the use of isinf/isnan (#29, #36)
- remove `.get<int>()` (#35)
1.0 2014-06-05 12:54:00+0900
- initial release with a version number

25
thirdparty/picojson-1.3.0/LICENSE vendored Normal file
View File

@ -0,0 +1,25 @@
Copyright 2009-2010 Cybozu Labs, Inc.
Copyright 2011-2014 Kazuho Oku
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

26
thirdparty/picojson-1.3.0/Makefile vendored Normal file
View File

@ -0,0 +1,26 @@
prefix=/usr/local
includedir=$(prefix)/include
check: test
test: test-core test-core-int64
./test-core
./test-core-int64
test-core: test.cc picotest/picotest.c picotest/picotest.h
$(CXX) -Wall test.cc picotest/picotest.c -o $@
test-core-int64: test.cc picotest/picotest.c picotest/picotest.h
$(CXX) -Wall -DPICOJSON_USE_INT64 test.cc picotest/picotest.c -o $@
clean:
rm -f test-core test-core-int64
install:
install -d $(DESTDIR)$(includedir)
install -p -m 0644 picojson.h $(DESTDIR)$(includedir)
uninstall:
rm -f $(DESTDIR)$(includedir)/picojson.h
.PHONY: test check clean install uninstall

195
thirdparty/picojson-1.3.0/README.mkdn vendored Normal file
View File

@ -0,0 +1,195 @@
# PicoJSON - a C++ JSON parser / serializer
Copyright &copy; 2009-2010 Cybozu Labs, Inc.
Copyright &copy; 2011-2015 Kazuho Oku
Licensed under [2-clause BSD license](http://opensource.org/licenses/BSD-2-Clause)
## Version
1.3.0 [![Build Status](https://travis-ci.org/kazuho/picojson.svg?branch=rel/1.3.0)](https://travis-ci.org/kazuho/picojson)
## Introduction
PicoJSON is a tiny JSON parser / serializer for C++ with following properties:
- header-file only
- no external dependencies (only uses standard C++ libraries)
- STL-frendly (arrays are represented by using std::vector, objects are std::map)
- provides both pull interface and streaming (event-based) interface
## Reading JSON using the pull interface
There are several ways to use the pull (DOM-like) interface of picojson.
The easiest way is to use the two-argument `parse` function.
```
std::string json = "[ \"hello JSON\" ]";
picojson::value v;
std::string err = picojson::parse(v, json);
if (! err.empty()) {
std:cerr << err << std::endl;
}
```
Four-argument `parse` function accepts a pair of iterators, and returns the end position of the input.
```
const char* json = "{\"a\":1}";
picojson::value v;
std::string err;
const char* json_end = picojson::parse(v, json, json + strlen(json), &err);
if (! err.empty()) {
std::cerr << err << std::endl;
}
```
```
std::istream_iterator input(std::cin);
picojson::value v;
std::string err;
input = picojson::parse(v, input, std::istream_iterator(), &err);
if (! err.empty()) {
std::cerr << err << std::endl;
}
```
It is also possible to use the `>>` operator to parse the input, however this interface is not thread-safe.
```
picosjon::value v;
std::cin >> v;
std::string err = picojson::get_last_error();
```
## Accessing the values
Values of a JSON object is represented as instances of picojson::value class.
<pre>
namespace picojson {
class value {
...
public:
typedef std::vector&lt;value&gt; array;
typedef std::map&lt;std::string, value&gt; object;
value(); // create a null object
explicit value(bool b); // create a boolean object
explicit value(double n); // create a number object
explicit value(const std::string& s); // create a string object
explicit value(const array& a); // create an array object
explicit value(const object& o); // create an "object"
bool is&lt;picojson::null&gt;() const; // check if the object is "null"
bool is&lt;bool&gt;() const; // check if the object is a boolean
const bool& get&lt;bool&gt;() const; // const accessor (usable only if the object is a boolean)
bool& get&lt;bool&gt;(); // non-const accessor (usable only if the object is a boolean)
bool is&lt;double&gt;() const; // check if the object is a number
const double& get&lt;double&gt;() const; // const accessor (usable only if the object is a number)
double& get&lt;double&gt;(); // non-const accessor (usable only if the object is a number)
bool is&lt;std::string&gt;() const; // check if the object is a string
const std::string& get&lt;std::string&gt;() const;
// const accessor (usable only if the object is a string)
std::string& get&lt;std::string&gt;(); // non-const accessor (usable only if the object is a string)
bool is&lt;array&gt;() const; // check if the object is an array
const array& get&lt;array&gt;() const; // const accessor (usable only if the object is an array)
array& get&lt;array&gt;(); // non-const accessor (usable only if the object is an array)
bool is&lt;object&gt;() const; // check if the object is an "object"
const object& get&lt;object&gt;() const; // const accessor (usable only if the object is an object)
object& get&lt;object&gt;(); // non-const accessor (usable only if the object is an array)
bool evaluate_as_boolean() const; // evaluates the object as a boolean
std::string serialize() const; // returns the object in JSON representation
template<typename Iter> void serialize(Iter os) const;
// serializes the object in JSON representation through an output iterator
std::string to_str() const; // returns the object in string (for casual use)
};
}
</pre>
The code below parses a JSON string and prints the contents of the object.
<pre>
picojson::value v;
// parse the input
std::cin &gt;&gt; v;
std::string err = picojson::get_last_error();
if (! err.empty()) {
std::cerr &lt;&lt; err &lt;&lt; std::endl;
exit(1);
}
// check if the type of the value is "object"
if (! v.is&lt;picojson::object&gt;()) {
std::cerr &lt;&lt; "JSON is not an object" &lt;&lt; std::endl;
exit(2);
}
// obtain a const reference to the map, and print the contents
const picojson::value::object& obj = v.get&lt;picojson::object&gt;();
for (picojson::value::object::const_iterator i = obj.begin();
i != obj.end();
++i) {
std::cout &lt;&lt; i-&gt;first &lt;&lt; ': ' &lt;&lt; i-&gt;second.to_str() &lt;&lt; std::endl;
}
</pre>
Please note that the type check is mandatory; do not forget to check the type of the object by calling is&lt;type&gt;() before accessing the value by calling get&lt;type&gt;().
## Reading JSON using the streaming (event-driven) interface
Please refer to the implementation of picojson::default_parse_context and picojson::null_parse_context. There is also an example (examples/streaming.cc) .
## Serializing to JSON
Instances of the picojson::value class can be serialized in three ways, to ostream, to std::string, or to an output iterator.
<pre>
picojson::value v;
...
std::cout &lt;&lt; v;
</pre>
<pre>
picojson::value v;
...
std::string json = v.serialize();
</pre>
<pre>
picojson::value v;
...
v.serialize(std::ostream_iterator(std::cout));
</pre>
## Experimental support for int64_t
Experimental suport for int64_t becomes available if the code is compiled with preprocessor macro `PICOJSON_USE_INT64`.
Turning on the feature will cause following changes to picojson:
- new constructor `picojson::value(int64_t)` is defined
- `is<int64_t>()` and `get<int64_t>()` become available
- numerics in JSON within the bounds of int64_t and not using `.` nor `e`/`E` are considered as int64 type
- the values are also avaliable as `double`s as well (i.e. all values which are `.is<int64_t>() == true` are also `.is<double>() == true`)
- int64 values are converted to double once `get<double>()` is called
Enabling the feature should not cause compatibility problem with code that do not use the feature.
## Further reading
Examples can be found in the <i>examples</i> directory, and on the [Wiki](https://github.com/kazuho/picojson/wiki). Please add your favorite examples to the Wiki.

View File

@ -0,0 +1,110 @@
/*
* Copyright 2009-2010 Cybozu Labs, Inc.
* Copyright 2011-2014 Kazuho Oku
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <curl/curl.h>
#include "../picojson.h"
typedef struct {
char* data; // response data from server
size_t size; // response size of data
} MEMFILE;
MEMFILE*
memfopen() {
MEMFILE* mf = (MEMFILE*) malloc(sizeof(MEMFILE));
mf->data = NULL;
mf->size = 0;
return mf;
}
void
memfclose(MEMFILE* mf) {
if (mf->data) free(mf->data);
free(mf);
}
size_t
memfwrite(char* ptr, size_t size, size_t nmemb, void* stream) {
MEMFILE* mf = (MEMFILE*) stream;
int block = size * nmemb;
if (!mf->data)
mf->data = (char*) malloc(block);
else
mf->data = (char*) realloc(mf->data, mf->size + block);
if (mf->data) {
memcpy(mf->data + mf->size, ptr, block);
mf->size += block;
}
return block;
}
char*
memfstrdup(MEMFILE* mf) {
char* buf = (char*)malloc(mf->size + 1);
memcpy(buf, mf->data, mf->size);
buf[mf->size] = 0;
return buf;
}
using namespace std;
using namespace picojson;
int
main(int argc, char* argv[]) {
char error[256];
MEMFILE* mf = memfopen();
CURL* curl = curl_easy_init();
curl_easy_setopt(curl, CURLOPT_URL, "https://api.github.com/repos/kazuho/picojson/issues");
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
curl_easy_setopt(curl, CURLOPT_USERAGENT, "curl");
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, &error);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, memfwrite);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, mf);
if (curl_easy_perform(curl) != CURLE_OK) {
cerr << error << endl;
} else {
value v;
string err;
parse(v, mf->data, mf->data + mf->size, &err);
if (err.empty()) {
array arr = v.get<array>();
array::iterator it;
for (it = arr.begin(); it != arr.end(); it++) {
object obj = it->get<object>();
cout << "#" << obj["number"].to_str() << ": " << obj["title"].to_str() << endl;
cout << " " << obj["html_url"].to_str() << endl << endl;
}
} else {
cerr << err << endl;
}
}
curl_easy_cleanup(curl);
memfclose(mf);
return 0;
}

View File

@ -0,0 +1,70 @@
/*
* Copyright 2009-2010 Cybozu Labs, Inc.
* Copyright 2011-2014 Kazuho Oku
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "../picojson.h"
int main(void)
{
picojson::value v;
// read json value from stream
std::cin >> v;
if (std::cin.fail()) {
std::cerr << picojson::get_last_error() << std::endl;
return 1;
}
// dump json object
std::cout << "---- dump input ----" << std::endl;
std::cout << v << std::endl;
// accessors
std::cout << "---- analyzing input ----" << std::endl;
if (v.is<picojson::null>()) {
std::cout << "input is null" << std::endl;
} else if (v.is<bool>()) {
std::cout << "input is " << (v.get<bool>() ? "true" : "false") << std::endl;
} else if (v.is<double>()) {
std::cout << "input is " << v.get<double>() << std::endl;
} else if (v.is<std::string>()) {
std::cout << "input is " << v.get<std::string>() << std::endl;
} else if (v.is<picojson::array>()) {
std::cout << "input is an array" << std::endl;
const picojson::array& a = v.get<picojson::array>();
for (picojson::array::const_iterator i = a.begin(); i != a.end(); ++i) {
std::cout << " " << *i << std::endl;
}
} else if (v.is<picojson::object>()) {
std::cout << "input is an object" << std::endl;
const picojson::object& o = v.get<picojson::object>();
for (picojson::object::const_iterator i = o.begin(); i != o.end(); ++i) {
std::cout << i->first << " " << i->second << std::endl;
}
}
return 0;
}

View File

@ -0,0 +1,76 @@
/*
* Copyright 2009-2010 Cybozu Labs, Inc.
* Copyright 2011-2014 Kazuho Oku
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <iostream>
#include <iterator>
#include "../picojson.h"
// this example reads a array of hashes (each item representing a 2D point),
// and prints the x and y values to stdout
namespace {
class root_context : public picojson::deny_parse_context {
public:
bool parse_array_start() {
return true; // only allow array as root
}
template <typename Iter> bool parse_array_item(picojson::input<Iter>& in, size_t) {
picojson::value item;
// parse the array item
picojson::default_parse_context ctx(&item);
if (! picojson::_parse(ctx, in)) {
return false;
}
// assert that the array item is a hash
if (! item.is<picojson::object>()) {
return false;
}
// print x and y
std::cout << item.get("x") << ',' << item.get("y").to_str()
<< std::endl;
return true;
}
};
}
int main(void)
{
root_context ctx;
std::string err;
picojson::_parse(ctx, std::istream_iterator<char>(std::cin),
std::istream_iterator<char>(), &err);
if (! err.empty()) {
std::cerr << err << std::endl;
return 1;
}
return 0;
}

1010
thirdparty/picojson-1.3.0/picojson.h vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,99 @@
/*
* Copyright (c) 2014 DeNA Co., Ltd.
*
* 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 <stdarg.h>
#include <stdio.h>
#include <string.h>
#include "picotest.h"
struct test_t {
int num_tests;
int failed;
};
struct test_t main_tests, *cur_tests = &main_tests;
static int test_level = 0;
static void indent(void)
{
int i;
for (i = 0; i != test_level; ++i)
printf(" ");
}
__attribute__((format (printf, 1, 2)))
void note(const char *fmt, ...)
{
va_list arg;
indent();
printf("# ");
va_start(arg, fmt);
vprintf(fmt, arg);
va_end(arg);
printf("\n");
}
__attribute__((format (printf, 2, 3)))
void _ok(int cond, const char *fmt, ...)
{
va_list arg;
if (! cond)
cur_tests->failed = 1;
indent();
printf("%s %d - ", cond ? "ok" : "not ok", ++cur_tests->num_tests);
va_start(arg, fmt);
vprintf(fmt, arg);
va_end(arg);
printf("\n");
}
int done_testing(void)
{
indent();
printf("1..%d\n", cur_tests->num_tests);
return cur_tests->failed;
}
void subtest(const char *name, void (*cb)(void))
{
struct test_t test = {}, *parent_tests;
parent_tests = cur_tests;
cur_tests = &test;
++test_level;
note("Subtest: %s", name);
cb();
done_testing();
--test_level;
cur_tests = parent_tests;
if (test.failed)
cur_tests->failed = 1;
_ok(! test.failed, "%s", name);
}

View File

@ -0,0 +1,39 @@
/*
* Copyright (c) 2014 DeNA Co., Ltd.
*
* 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.
*/
#ifndef picotest_h
#define picotest_h
#ifdef __cplusplus
extern "C" {
#endif
void note(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
void _ok(int cond, const char *fmt, ...) __attribute__((format (printf, 2, 3)));
#define ok(cond) _ok(cond, "%s %d", __FILE__, __LINE__)
int done_testing(void);
void subtest(const char *name, void (*cb)(void));
#ifdef __cplusplus
}
#endif
#endif

312
thirdparty/picojson-1.3.0/test.cc vendored Normal file
View File

@ -0,0 +1,312 @@
/*
* Copyright 2009-2010 Cybozu Labs, Inc.
* Copyright 2011-2014 Kazuho Oku, Yasuhiro Matsumoto, Shigeo Mitsunari
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "picojson.h"
#include "picotest/picotest.h"
#ifdef _MSC_VER
#pragma warning(disable : 4127) // conditional expression is constant
#endif
using namespace std;
#define is(x, y, name) _ok((x) == (y), name)
#include <algorithm>
#include <sstream>
#include <float.h>
#include <limits.h>
int main(void)
{
#if PICOJSON_USE_LOCALE
setlocale(LC_ALL, "");
#endif
// constructors
#define TEST(expr, expected) \
is(picojson::value expr .serialize(), string(expected), "picojson::value" #expr)
TEST( (true), "true");
TEST( (false), "false");
TEST( (42.0), "42");
TEST( (string("hello")), "\"hello\"");
TEST( ("hello"), "\"hello\"");
TEST( ("hello", 4), "\"hell\"");
{
double a = 1;
for (int i = 0; i < 1024; i++) {
picojson::value vi(a);
std::stringstream ss;
ss << vi;
picojson::value vo;
ss >> vo;
double b = vo.get<double>();
if ((i < 53 && a != b) || fabs(a - b) / b > 1e-8) {
printf("ng i=%d a=%.18e b=%.18e\n", i, a, b);
}
a *= 2;
}
}
#undef TEST
#define TEST(in, type, cmp, serialize_test) { \
picojson::value v; \
const char* s = in; \
string err = picojson::parse(v, s, s + strlen(s)); \
_ok(err.empty(), in " no error"); \
_ok(v.is<type>(), in " check type"); \
is(v.get<type>(), static_cast<type>(cmp), in " correct output"); \
is(*s, '\0', in " read to eof"); \
if (serialize_test) { \
is(v.serialize(), string(in), in " serialize"); \
} \
}
TEST("false", bool, false, true);
TEST("true", bool, true, true);
TEST("90.5", double, 90.5, false);
TEST("1.7976931348623157e+308", double, DBL_MAX, false);
TEST("\"hello\"", string, string("hello"), true);
TEST("\"\\\"\\\\\\/\\b\\f\\n\\r\\t\"", string, string("\"\\/\b\f\n\r\t"),
true);
TEST("\"\\u0061\\u30af\\u30ea\\u30b9\"", string,
string("a\xe3\x82\xaf\xe3\x83\xaa\xe3\x82\xb9"), false);
TEST("\"\\ud840\\udc0b\"", string, string("\xf0\xa0\x80\x8b"), false);
#ifdef PICOJSON_USE_INT64
TEST("0", int64_t, 0, true);
TEST("-9223372036854775808", int64_t, std::numeric_limits<int64_t>::min(), true);
TEST("9223372036854775807", int64_t, std::numeric_limits<int64_t>::max(), true);
#endif
#undef TEST
#define TEST(type, expr) { \
picojson::value v; \
const char *s = expr; \
string err = picojson::parse(v, s, s + strlen(s)); \
_ok(err.empty(), "empty " #type " no error"); \
_ok(v.is<picojson::type>(), "empty " #type " check type"); \
_ok(v.get<picojson::type>().empty(), "check " #type " array size"); \
}
TEST(array, "[]");
TEST(object, "{}");
#undef TEST
{
picojson::value v;
const char *s = "[1,true,\"hello\"]";
string err = picojson::parse(v, s, s + strlen(s));
_ok(err.empty(), "array no error");
_ok(v.is<picojson::array>(), "array check type");
is(v.get<picojson::array>().size(), size_t(3), "check array size");
_ok(v.contains(0), "check contains array[0]");
_ok(v.get(0).is<double>(), "check array[0] type");
is(v.get(0).get<double>(), 1.0, "check array[0] value");
_ok(v.contains(1), "check contains array[1]");
_ok(v.get(1).is<bool>(), "check array[1] type");
_ok(v.get(1).get<bool>(), "check array[1] value");
_ok(v.contains(2), "check contains array[2]");
_ok(v.get(2).is<string>(), "check array[2] type");
is(v.get(2).get<string>(), string("hello"), "check array[2] value");
_ok(!v.contains(3), "check not contains array[3]");
}
{
picojson::value v;
const char *s = "{ \"a\": true }";
string err = picojson::parse(v, s, s + strlen(s));
_ok(err.empty(), "object no error");
_ok(v.is<picojson::object>(), "object check type");
is(v.get<picojson::object>().size(), size_t(1), "check object size");
_ok(v.contains("a"), "check contains property");
_ok(v.get("a").is<bool>(), "check bool property exists");
is(v.get("a").get<bool>(), true, "check bool property value");
is(v.serialize(), string("{\"a\":true}"), "serialize object");
_ok(!v.contains("z"), "check not contains property");
}
#define TEST(json, msg) do { \
picojson::value v; \
const char *s = json; \
string err = picojson::parse(v, s, s + strlen(s)); \
is(err, string("syntax error at line " msg), msg); \
} while (0)
TEST("falsoa", "1 near: oa");
TEST("{]", "1 near: ]");
TEST("\n\bbell", "2 near: bell");
TEST("\"abc\nd\"", "1 near: ");
#undef TEST
{
picojson::value v1, v2;
const char *s;
string err;
s = "{ \"b\": true, \"a\": [1,2,\"three\"], \"d\": 2 }";
err = picojson::parse(v1, s, s + strlen(s));
s = "{ \"d\": 2.0, \"b\": true, \"a\": [1,2,\"three\"] }";
err = picojson::parse(v2, s, s + strlen(s));
_ok((v1 == v2), "check == operator in deep comparison");
}
{
picojson::value v1, v2;
const char *s;
string err;
s = "{ \"b\": true, \"a\": [1,2,\"three\"], \"d\": 2 }";
err = picojson::parse(v1, s, s + strlen(s));
s = "{ \"d\": 2.0, \"a\": [1,\"three\"], \"b\": true }";
err = picojson::parse(v2, s, s + strlen(s));
_ok((v1 != v2), "check != operator for array in deep comparison");
}
{
picojson::value v1, v2;
const char *s;
string err;
s = "{ \"b\": true, \"a\": [1,2,\"three\"], \"d\": 2 }";
err = picojson::parse(v1, s, s + strlen(s));
s = "{ \"d\": 2.0, \"a\": [1,2,\"three\"], \"b\": false }";
err = picojson::parse(v2, s, s + strlen(s));
_ok((v1 != v2), "check != operator for object in deep comparison");
}
{
picojson::value v1, v2;
const char *s;
string err;
s = "{ \"b\": true, \"a\": [1,2,\"three\"], \"d\": 2 }";
err = picojson::parse(v1, s, s + strlen(s));
picojson::object& o = v1.get<picojson::object>();
o.erase("b");
picojson::array& a = o["a"].get<picojson::array>();
picojson::array::iterator i;
i = std::remove(a.begin(), a.end(), picojson::value(std::string("three")));
a.erase(i, a.end());
s = "{ \"a\": [1,2], \"d\": 2 }";
err = picojson::parse(v2, s, s + strlen(s));
_ok((v1 == v2), "check erase()");
}
_ok(picojson::value(3.0).serialize() == "3",
"integral number should be serialized as a integer");
{
const char* s = "{ \"a\": [1,2], \"d\": 2 }";
picojson::null_parse_context ctx;
string err;
picojson::_parse(ctx, s, s + strlen(s), &err);
_ok(err.empty(), "null_parse_context");
}
{
picojson::value v1, v2;
v1 = picojson::value(true);
swap(v1, v2);
_ok(v1.is<picojson::null>(), "swap (null)");
_ok(v2.get<bool>() == true, "swap (bool)");
v1 = picojson::value("a");
v2 = picojson::value(1.0);
swap(v1, v2);
_ok(v1.get<double>() == 1.0, "swap (dobule)");
_ok(v2.get<string>() == "a", "swap (string)");
v1 = picojson::value(picojson::object());
v2 = picojson::value(picojson::array());
swap(v1, v2);
_ok(v1.is<picojson::array>(), "swap (array)");
_ok(v2.is<picojson::object>(), "swap (object)");
}
{
picojson::value v;
const char *s = "{ \"a\": 1, \"b\": [ 2, { \"b1\": \"abc\" } ], \"c\": {}, \"d\": [] }";
string err;
err = picojson::parse(v, s, s + strlen(s));
_ok(err.empty(), "parse test data for prettifying output");
_ok(v.serialize() == "{\"a\":1,\"b\":[2,{\"b1\":\"abc\"}],\"c\":{},\"d\":[]}", "non-prettifying output");
_ok(v.serialize(true) == "{\n \"a\": 1,\n \"b\": [\n 2,\n {\n \"b1\": \"abc\"\n }\n ],\n \"c\": {},\n \"d\": []\n}\n", "prettifying output");
}
try {
picojson::value v(std::numeric_limits<double>::quiet_NaN());
_ok(false, "should not accept NaN");
} catch (std::overflow_error e) {
_ok(true, "should not accept NaN");
}
try {
picojson::value v(std::numeric_limits<double>::infinity());
_ok(false, "should not accept infinity");
} catch (std::overflow_error e) {
_ok(true, "should not accept infinity");
}
try {
picojson::value v(123.);
_ok(! v.is<bool>(), "is<wrong_type>() should return false");
v.get<bool>();
_ok(false, "get<wrong_type>() should raise an error");
} catch (std::runtime_error e) {
_ok(true, "get<wrong_type>() should raise an error");
}
#ifdef PICOJSON_USE_INT64
{
picojson::value v1((int64_t)123);
_ok(v1.is<int64_t>(), "is int64_t");
_ok(v1.is<double>(), "is double as well");
_ok(v1.serialize() == "123", "serialize the value");
_ok(v1.get<int64_t>() == 123, "value is correct as int64_t");
_ok(v1.get<double>(), "value is correct as double");
_ok(! v1.is<int64_t>(), "is no more int64_type once get<double>() is called");
_ok(v1.is<double>(), "and is still a double");
const char *s = "-9223372036854775809";
_ok(picojson::parse(v1, s, s + strlen(s)).empty(), "parse underflowing int64_t");
_ok(! v1.is<int64_t>(), "underflowing int is not int64_t");
_ok(v1.is<double>(), "underflowing int is double");
_ok(v1.get<double>() + 9.22337203685478e+18 < 65536, "double value is somewhat correct");
}
#endif
{
picojson::value v;
std::string err = picojson::parse(v, "[ 1, \"abc\" ]");
_ok(err.empty(), "simple API no error");
_ok(v.is<picojson::array>(), "simple API return type is array");
is(v.get<picojson::array>().size(), 2, "simple API array size");
_ok(v.get<picojson::array>()[0].is<double>(), "simple API type #0");
is(v.get<picojson::array>()[0].get<double>(), 1, "simple API value #0");
_ok(v.get<picojson::array>()[1].is<std::string>(), "simple API type #1");
is(v.get<picojson::array>()[1].get<std::string>(), "abc", "simple API value #1");
}
return done_testing();
}