Switch to submodule for picojson

This commit is contained in:
Tristan Penman 2022-08-30 11:41:15 +12:00
parent c0ce4cde7e
commit 2cef1a6538
17 changed files with 5 additions and 2000 deletions

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "thirdparty/picojson"]
path = thirdparty/picojson
url = https://github.com/tristanpenman/picojson.git

View File

@ -95,7 +95,7 @@ include_directories(include SYSTEM
thirdparty/json11-ec4e452
thirdparty/jsoncpp-1.9.5/include
thirdparty/rapidjson-48fbd8c/include
thirdparty/picojson-1.3.0
thirdparty/picojson
thirdparty/nlohmann-json-3.1.2
thirdparty/yaml-cpp-0.7.0/include
)

1
thirdparty/picojson vendored Submodule

@ -0,0 +1 @@
Subproject commit 9dfda04e89c28a9e602ce9ef626dd9b6acbc6e60

View File

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

View File

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

View File

@ -1,25 +0,0 @@
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

View File

@ -1,25 +0,0 @@
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.

View File

@ -1,26 +0,0 @@
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

View File

@ -1,195 +0,0 @@
# 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

@ -1,110 +0,0 @@
/*
* 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

@ -1,70 +0,0 @@
/*
* 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

@ -1,76 +0,0 @@
/*
* 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;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,99 +0,0 @@
/*
* 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

@ -1,39 +0,0 @@
/*
* 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

View File

@ -1,312 +0,0 @@
/*
* 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();
}