Replace x.get<T>() with x.get(v) or T(x)
This commit is contained in:
parent
1b1a122b1f
commit
6fa5abcd7e
|
@ -407,7 +407,7 @@ static void iterator_twitter_default_profile(State& state) {
|
||||||
set<string_view> default_users;
|
set<string_view> default_users;
|
||||||
ParsedJson::Iterator iter(pj);
|
ParsedJson::Iterator iter(pj);
|
||||||
|
|
||||||
// for (dom::object tweet : doc["statuses"].get<dom::array>()) {
|
// for (dom::object tweet : doc["statuses"]) {
|
||||||
if (!(iter.move_to_key("statuses") && iter.is_array())) { return; }
|
if (!(iter.move_to_key("statuses") && iter.is_array())) { return; }
|
||||||
if (iter.down()) { // first status
|
if (iter.down()) { // first status
|
||||||
do {
|
do {
|
||||||
|
@ -480,7 +480,7 @@ static void iterator_twitter_image_sizes(State& state) {
|
||||||
set<tuple<uint64_t, uint64_t>> image_sizes;
|
set<tuple<uint64_t, uint64_t>> image_sizes;
|
||||||
ParsedJson::Iterator iter(pj);
|
ParsedJson::Iterator iter(pj);
|
||||||
|
|
||||||
// for (dom::object tweet : doc["statuses"].get<dom::array>()) {
|
// for (dom::object tweet : doc["statuses"]) {
|
||||||
if (!(iter.move_to_key("statuses") && iter.is_array())) { return; }
|
if (!(iter.move_to_key("statuses") && iter.is_array())) { return; }
|
||||||
if (iter.down()) { // first status
|
if (iter.down()) { // first status
|
||||||
do {
|
do {
|
||||||
|
@ -492,7 +492,7 @@ static void iterator_twitter_image_sizes(State& state) {
|
||||||
if (iter.move_to_key("media")) {
|
if (iter.move_to_key("media")) {
|
||||||
if (!iter.is_array()) { return; }
|
if (!iter.is_array()) { return; }
|
||||||
|
|
||||||
// for (dom::object image : media.get<dom::array>()) {
|
// for (dom::object image : media) {
|
||||||
if (iter.down()) { // first media
|
if (iter.down()) { // first media
|
||||||
do {
|
do {
|
||||||
|
|
||||||
|
|
|
@ -40,17 +40,18 @@ void print_vec(const std::vector<int64_t> &v) {
|
||||||
|
|
||||||
// simdjson_recurse below come be implemented like so but it is slow:
|
// simdjson_recurse below come be implemented like so but it is slow:
|
||||||
/*void simdjson_recurse(std::vector<int64_t> & v, simdjson::dom::element element) {
|
/*void simdjson_recurse(std::vector<int64_t> & v, simdjson::dom::element element) {
|
||||||
if (element.is<simdjson::dom::array>()) {
|
error_code error;
|
||||||
auto [array, array_error] = element.get<simdjson::dom::array>();
|
if (element.is_array()) {
|
||||||
|
dom::array array;
|
||||||
|
error = element.get(array);
|
||||||
for (auto child : array) {
|
for (auto child : array) {
|
||||||
if (child.is<simdjson::dom::array>() || child.is<simdjson::dom::object>()) {
|
if (child.is<simdjson::dom::array>() || child.is<simdjson::dom::object>()) {
|
||||||
simdjson_recurse(v, child);
|
simdjson_recurse(v, child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (element.is<simdjson::dom::object>()) {
|
} else if (element.is_object()) {
|
||||||
auto [object, error] = element.get<simdjson::dom::object>();
|
|
||||||
int64_t id;
|
int64_t id;
|
||||||
error = object["user"]["id"].get(id);
|
error = element["user"]["id"].get(id);
|
||||||
if(!error) {
|
if(!error) {
|
||||||
v.push_back(id);
|
v.push_back(id);
|
||||||
}
|
}
|
||||||
|
|
|
@ -154,11 +154,11 @@ static void GenStatPlus(Stat &stat, const dom::element &v) {
|
||||||
break;
|
break;
|
||||||
case dom::element_type::STRING: {
|
case dom::element_type::STRING: {
|
||||||
stat.stringCount++;
|
stat.stringCount++;
|
||||||
std::string_view sv = v.get<std::string_view>();
|
auto sv = std::string_view(v);
|
||||||
stat.stringLength += sv.size();
|
stat.stringLength += sv.size();
|
||||||
} break;
|
} break;
|
||||||
case dom::element_type::BOOL:
|
case dom::element_type::BOOL:
|
||||||
if (v.get<bool>()) {
|
if (bool(v)) {
|
||||||
stat.trueCount++;
|
stat.trueCount++;
|
||||||
} else {
|
} else {
|
||||||
stat.falseCount++;
|
stat.falseCount++;
|
||||||
|
|
|
@ -164,7 +164,7 @@ And another one:
|
||||||
auto abstract_json = R"(
|
auto abstract_json = R"(
|
||||||
{ "str" : { "123" : {"abc" : 3.14 } } } )"_padded;
|
{ "str" : { "123" : {"abc" : 3.14 } } } )"_padded;
|
||||||
dom::parser parser;
|
dom::parser parser;
|
||||||
double v = parser.parse(abstract_json)["str"]["123"]["abc"].get<double>();
|
double v = parser.parse(abstract_json)["str"]["123"]["abc"];
|
||||||
cout << "number: " << v << endl;
|
cout << "number: " << v << endl;
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -191,14 +191,13 @@ Though it does not validate the JSON input, it will detect when the document end
|
||||||
C++17 Support
|
C++17 Support
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
While the simdjson library can be used in any project using C++ 11 and above, it has special support
|
While the simdjson library can be used in any project using C++ 11 and above, field iteration has special support C++ 17's destructuring syntax. For example:
|
||||||
for C++ 17. The APIs for field iteration and error handling in particular are designed to work
|
|
||||||
nicely with C++17's destructuring syntax. For example:
|
|
||||||
|
|
||||||
```c++
|
```c++
|
||||||
dom::parser parser;
|
|
||||||
padded_string json = R"( { "foo": 1, "bar": 2 } )"_padded;
|
padded_string json = R"( { "foo": 1, "bar": 2 } )"_padded;
|
||||||
auto [object, error] = parser.parse(json).get<dom::object>();
|
dom::parser parser;
|
||||||
|
dom::object object;
|
||||||
|
auto error = parser.parse(json).get(object);
|
||||||
if (error) { cerr << error << endl; return; }
|
if (error) { cerr << error << endl; return; }
|
||||||
for (auto [key, value] : object) {
|
for (auto [key, value] : object) {
|
||||||
cout << key << " = " << value << endl;
|
cout << key << " = " << value << endl;
|
||||||
|
@ -209,11 +208,10 @@ For comparison, here is the C++ 11 version of the same code:
|
||||||
|
|
||||||
```c++
|
```c++
|
||||||
// C++ 11 version for comparison
|
// C++ 11 version for comparison
|
||||||
dom::parser parser;
|
|
||||||
padded_string json = R"( { "foo": 1, "bar": 2 } )"_padded;
|
padded_string json = R"( { "foo": 1, "bar": 2 } )"_padded;
|
||||||
simdjson::error_code error;
|
dom::parser parser;
|
||||||
dom::object object;
|
dom::object object;
|
||||||
error = parser.parse(json).get(object);
|
auto error = parser.parse(json).get(object);
|
||||||
if (!error) { cerr << error << endl; return; }
|
if (!error) { cerr << error << endl; return; }
|
||||||
for (dom::key_value_pair field : object) {
|
for (dom::key_value_pair field : object) {
|
||||||
cout << field.key << " = " << field.value << endl;
|
cout << field.key << " = " << field.value << endl;
|
||||||
|
@ -378,8 +376,7 @@ And another one:
|
||||||
cout << "number: " << v << endl;
|
cout << "number: " << v << endl;
|
||||||
```
|
```
|
||||||
|
|
||||||
Notice how we can string several operation (`parser.parse(abstract_json)["str"]["123"]["abc"].get<double>()`) and only check for the error once, a strategy we call *error chaining*.
|
Notice how we can string several operations (`parser.parse(abstract_json)["str"]["123"]["abc"].get(v)`) and only check for the error once, a strategy we call *error chaining*.
|
||||||
|
|
||||||
|
|
||||||
The next two functions will take as input a JSON document containing an array with a single element, either a string or a number. They return true upon success.
|
The next two functions will take as input a JSON document containing an array with a single element, either a string or a number. They return true upon success.
|
||||||
|
|
||||||
|
|
|
@ -336,8 +336,8 @@ public:
|
||||||
* The key will be matched against **unescaped** JSON:
|
* The key will be matched against **unescaped** JSON:
|
||||||
*
|
*
|
||||||
* dom::parser parser;
|
* dom::parser parser;
|
||||||
* parser.parse(R"({ "a\n": 1 })")["a\n"].get<uint64_t>().value == 1
|
* parser.parse(R"({ "a\n": 1 })")["a\n"].get<uint64_t>().first == 1
|
||||||
* parser.parse(R"({ "a\n": 1 })")["a\\n"].get<uint64_t>().error == NO_SUCH_FIELD
|
* parser.parse(R"({ "a\n": 1 })")["a\\n"].get<uint64_t>().error() == NO_SUCH_FIELD
|
||||||
*
|
*
|
||||||
* @return The value associated with this field, or:
|
* @return The value associated with this field, or:
|
||||||
* - NO_SUCH_FIELD if the field does not exist in the object
|
* - NO_SUCH_FIELD if the field does not exist in the object
|
||||||
|
@ -351,8 +351,8 @@ public:
|
||||||
* The key will be matched against **unescaped** JSON:
|
* The key will be matched against **unescaped** JSON:
|
||||||
*
|
*
|
||||||
* dom::parser parser;
|
* dom::parser parser;
|
||||||
* parser.parse(R"({ "a\n": 1 })")["a\n"].get<uint64_t>().value == 1
|
* parser.parse(R"({ "a\n": 1 })")["a\n"].get<uint64_t>().first == 1
|
||||||
* parser.parse(R"({ "a\n": 1 })")["a\\n"].get<uint64_t>().error == NO_SUCH_FIELD
|
* parser.parse(R"({ "a\n": 1 })")["a\\n"].get<uint64_t>().error() == NO_SUCH_FIELD
|
||||||
*
|
*
|
||||||
* @return The value associated with this field, or:
|
* @return The value associated with this field, or:
|
||||||
* - NO_SUCH_FIELD if the field does not exist in the object
|
* - NO_SUCH_FIELD if the field does not exist in the object
|
||||||
|
@ -391,8 +391,8 @@ public:
|
||||||
* The key will be matched against **unescaped** JSON:
|
* The key will be matched against **unescaped** JSON:
|
||||||
*
|
*
|
||||||
* dom::parser parser;
|
* dom::parser parser;
|
||||||
* parser.parse(R"({ "a\n": 1 })")["a\n"].get<uint64_t>().value == 1
|
* parser.parse(R"({ "a\n": 1 })")["a\n"].get<uint64_t>().first == 1
|
||||||
* parser.parse(R"({ "a\n": 1 })")["a\\n"].get<uint64_t>().error == NO_SUCH_FIELD
|
* parser.parse(R"({ "a\n": 1 })")["a\\n"].get<uint64_t>().error() == NO_SUCH_FIELD
|
||||||
*
|
*
|
||||||
* @return The value associated with this field, or:
|
* @return The value associated with this field, or:
|
||||||
* - NO_SUCH_FIELD if the field does not exist in the object
|
* - NO_SUCH_FIELD if the field does not exist in the object
|
||||||
|
|
|
@ -101,8 +101,8 @@ public:
|
||||||
* The key will be matched against **unescaped** JSON:
|
* The key will be matched against **unescaped** JSON:
|
||||||
*
|
*
|
||||||
* dom::parser parser;
|
* dom::parser parser;
|
||||||
* parser.parse(R"({ "a\n": 1 })")["a\n"].get<uint64_t>().value == 1
|
* parser.parse(R"({ "a\n": 1 })")["a\n"].get<uint64_t>().first == 1
|
||||||
* parser.parse(R"({ "a\n": 1 })")["a\\n"].get<uint64_t>().error == NO_SUCH_FIELD
|
* parser.parse(R"({ "a\n": 1 })")["a\\n"].get<uint64_t>().error() == NO_SUCH_FIELD
|
||||||
*
|
*
|
||||||
* This function has linear-time complexity: the keys are checked one by one.
|
* This function has linear-time complexity: the keys are checked one by one.
|
||||||
*
|
*
|
||||||
|
@ -118,8 +118,8 @@ public:
|
||||||
* The key will be matched against **unescaped** JSON:
|
* The key will be matched against **unescaped** JSON:
|
||||||
*
|
*
|
||||||
* dom::parser parser;
|
* dom::parser parser;
|
||||||
* parser.parse(R"({ "a\n": 1 })")["a\n"].get<uint64_t>().value == 1
|
* parser.parse(R"({ "a\n": 1 })")["a\n"].get<uint64_t>().first == 1
|
||||||
* parser.parse(R"({ "a\n": 1 })")["a\\n"].get<uint64_t>().error == NO_SUCH_FIELD
|
* parser.parse(R"({ "a\n": 1 })")["a\\n"].get<uint64_t>().error() == NO_SUCH_FIELD
|
||||||
*
|
*
|
||||||
* This function has linear-time complexity: the keys are checked one by one.
|
* This function has linear-time complexity: the keys are checked one by one.
|
||||||
*
|
*
|
||||||
|
@ -151,8 +151,8 @@ public:
|
||||||
* The key will be matched against **unescaped** JSON:
|
* The key will be matched against **unescaped** JSON:
|
||||||
*
|
*
|
||||||
* dom::parser parser;
|
* dom::parser parser;
|
||||||
* parser.parse(R"({ "a\n": 1 })")["a\n"].get<uint64_t>().value == 1
|
* parser.parse(R"({ "a\n": 1 })")["a\n"].get<uint64_t>().first == 1
|
||||||
* parser.parse(R"({ "a\n": 1 })")["a\\n"].get<uint64_t>().error == NO_SUCH_FIELD
|
* parser.parse(R"({ "a\n": 1 })")["a\\n"].get<uint64_t>().error() == NO_SUCH_FIELD
|
||||||
*
|
*
|
||||||
* This function has linear-time complexity: the keys are checked one by one.
|
* This function has linear-time complexity: the keys are checked one by one.
|
||||||
*
|
*
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
#include "cast_tester.h"
|
#include "cast_tester.h"
|
||||||
#include "test_macros.h"
|
#include "test_macros.h"
|
||||||
|
|
||||||
|
const size_t AMAZON_CELLPHONES_NDJSON_DOC_COUNT = 793;
|
||||||
|
|
||||||
namespace number_tests {
|
namespace number_tests {
|
||||||
|
|
||||||
// ulp distance
|
// ulp distance
|
||||||
|
@ -39,8 +41,8 @@ namespace number_tests {
|
||||||
for (int m = 10; m < 20; m++) {
|
for (int m = 10; m < 20; m++) {
|
||||||
for (int i = -1024; i < 1024; i++) {
|
for (int i = -1024; i < 1024; i++) {
|
||||||
auto str = std::to_string(i);
|
auto str = std::to_string(i);
|
||||||
auto [actual, error] = parser.parse(str).get<int64_t>();
|
int64_t actual;
|
||||||
if (error) { std::cerr << error << std::endl; return false; }
|
ASSERT_SUCCESS(parser.parse(str).get(actual));
|
||||||
if (actual != i) {
|
if (actual != i) {
|
||||||
std::cerr << "JSON '" << str << "' parsed to " << actual << " instead of " << i << std::endl;
|
std::cerr << "JSON '" << str << "' parsed to " << actual << " instead of " << i << std::endl;
|
||||||
return false;
|
return false;
|
||||||
|
@ -60,7 +62,8 @@ namespace number_tests {
|
||||||
size_t n = snprintf(buf, sizeof(buf), "%.*e", std::numeric_limits<double>::max_digits10 - 1, expected);
|
size_t n = snprintf(buf, sizeof(buf), "%.*e", std::numeric_limits<double>::max_digits10 - 1, expected);
|
||||||
if (n >= sizeof(buf)) { abort(); }
|
if (n >= sizeof(buf)) { abort(); }
|
||||||
fflush(NULL);
|
fflush(NULL);
|
||||||
auto [actual, error] = parser.parse(buf, n).get<double>();
|
double actual;
|
||||||
|
auto error = parser.parse(buf, n).get(actual);
|
||||||
if (error) { std::cerr << error << std::endl; return false; }
|
if (error) { std::cerr << error << std::endl; return false; }
|
||||||
uint64_t ulp = f64_ulp_dist(actual,expected);
|
uint64_t ulp = f64_ulp_dist(actual,expected);
|
||||||
if(ulp > maxulp) maxulp = ulp;
|
if(ulp > maxulp) maxulp = ulp;
|
||||||
|
@ -154,7 +157,8 @@ namespace number_tests {
|
||||||
if (n >= sizeof(buf)) { abort(); }
|
if (n >= sizeof(buf)) { abort(); }
|
||||||
fflush(NULL);
|
fflush(NULL);
|
||||||
|
|
||||||
auto [actual, error] = parser.parse(buf, n).get<double>();
|
double actual;
|
||||||
|
auto error = parser.parse(buf, n).get(actual);
|
||||||
if (error) { std::cerr << error << std::endl; return false; }
|
if (error) { std::cerr << error << std::endl; return false; }
|
||||||
double expected = ((i >= -307) ? testing_power_of_ten[i + 307]: std::pow(10, i));
|
double expected = ((i >= -307) ? testing_power_of_ten[i + 307]: std::pow(10, i));
|
||||||
int ulp = (int) f64_ulp_dist(actual, expected);
|
int ulp = (int) f64_ulp_dist(actual, expected);
|
||||||
|
@ -229,41 +233,27 @@ namespace document_tests {
|
||||||
std::cout << __func__ << std::endl;
|
std::cout << __func__ << std::endl;
|
||||||
simdjson::padded_string smalljson = "[1,2,3]"_padded;
|
simdjson::padded_string smalljson = "[1,2,3]"_padded;
|
||||||
simdjson::dom::parser parser;
|
simdjson::dom::parser parser;
|
||||||
auto [doc, error] = parser.parse(smalljson).get<simdjson::dom::array>();
|
simdjson::dom::array array;
|
||||||
if (error) {
|
ASSERT_SUCCESS( parser.parse(smalljson).get(array) );
|
||||||
printf("This json should be valid %s.\n", smalljson.data());
|
ASSERT_EQUAL( array.size(), 3 );
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if(doc.size() != 3) {
|
|
||||||
printf("This json should have size three but found %zu : %s.\n", doc.size(), smalljson.data());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool count_object_example() {
|
bool count_object_example() {
|
||||||
std::cout << __func__ << std::endl;
|
std::cout << __func__ << std::endl;
|
||||||
simdjson::padded_string smalljson = "{\"1\":1,\"2\":1,\"3\":1}"_padded;
|
simdjson::padded_string smalljson = "{\"1\":1,\"2\":1,\"3\":1}"_padded;
|
||||||
simdjson::dom::parser parser;
|
simdjson::dom::parser parser;
|
||||||
auto [doc, error] = parser.parse(smalljson).get<simdjson::dom::object>();
|
simdjson::dom::object object;
|
||||||
if (error) {
|
ASSERT_SUCCESS( parser.parse(smalljson).get(object) );
|
||||||
printf("This json should be valid %s.\n", smalljson.data());
|
ASSERT_EQUAL( object.size(), 3 );
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if(doc.size() != 3) {
|
|
||||||
printf("This json should have size three but found %zu : %s.\n", doc.size(), smalljson.data());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool padded_with_open_bracket() {
|
bool padded_with_open_bracket() {
|
||||||
std::cout << __func__ << std::endl;
|
std::cout << __func__ << std::endl;
|
||||||
simdjson::dom::parser parser;
|
simdjson::dom::parser parser;
|
||||||
// This is an invalid document padded with open braces.
|
// This is an invalid document padded with open braces.
|
||||||
auto error1 = parser.parse("[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[", 2, false).error();
|
ASSERT_ERROR( parser.parse("[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[", 2, false).error(), simdjson::TAPE_ERROR);
|
||||||
if (!error1) { std::cerr << "We expected an error but got: " << error1 << std::endl; return false; }
|
|
||||||
// This is a valid document padded with open braces.
|
// This is a valid document padded with open braces.
|
||||||
auto error2 = parser.parse("[][[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[", 2, false).error();
|
ASSERT_SUCCESS( parser.parse("[][[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[", 2, false).error() );
|
||||||
if (error2) { std::cerr << "Error: " << error2 << std::endl; return false; }
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// returns true if successful
|
// returns true if successful
|
||||||
|
@ -524,16 +514,9 @@ namespace document_stream_tests {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto [keyid, error2] = doc["id"].get<int64_t>();
|
int64_t keyid;
|
||||||
if (error2) {
|
ASSERT_SUCCESS( doc["id"].get(keyid) );
|
||||||
printf("Error getting id as int64 on document %zd at batch size %zu: %s\n", count, batch_size, simdjson::error_message(error2));
|
ASSERT_EQUAL( keyid, int64_t(count) );
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (keyid != int64_t(count)) {
|
|
||||||
printf("key does not match %" PRId64 ", expected %zd on document %zd at batch size %zu\n", keyid, count, count, batch_size);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
@ -576,23 +559,13 @@ namespace document_stream_tests {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto [keyid, error2] = doc["id"].get<int64_t>();
|
int64_t keyid;
|
||||||
if (error2) {
|
ASSERT_SUCCESS( doc["id"].get(keyid) );
|
||||||
printf("Error getting id as int64 on document %zd at batch size %zu: %s\n", count, batch_size, simdjson::error_message(error2));
|
ASSERT_EQUAL( keyid, int64_t(count) );
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (keyid != int64_t(count)) {
|
|
||||||
printf("key does not match %" PRId64 ", expected %zd on document %zd at batch size %zu\n", keyid, count, count, batch_size);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
if(count != n_records) {
|
ASSERT_EQUAL( count, n_records )
|
||||||
printf("Found wrong number of documents %zd, expected %zd at batch size %zu\n", count, n_records, batch_size);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
printf("ok\n");
|
printf("ok\n");
|
||||||
return true;
|
return true;
|
||||||
|
@ -662,10 +635,10 @@ namespace parse_api_tests {
|
||||||
simdjson::dom::document_stream stream;
|
simdjson::dom::document_stream stream;
|
||||||
ASSERT_SUCCESS( parser.parse_many(EMPTY_NDJSON).get(stream) );
|
ASSERT_SUCCESS( parser.parse_many(EMPTY_NDJSON).get(stream) );
|
||||||
for (auto doc : stream) {
|
for (auto doc : stream) {
|
||||||
if (doc.error()) { cerr << "Error in parse_many: " << doc.error() << endl; return false; }
|
ASSERT_SUCCESS(doc.error());
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
if (count != 0) { cerr << "parse_many returned " << count << " documents, expected 0" << endl; return false; }
|
ASSERT_EQUAL(count, 0);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -682,22 +655,21 @@ namespace parse_api_tests {
|
||||||
simdjson::dom::document_stream stream;
|
simdjson::dom::document_stream stream;
|
||||||
ASSERT_SUCCESS( parser.parse_many(empty_batches_ndjson, BATCH_SIZE*16).get(stream) );
|
ASSERT_SUCCESS( parser.parse_many(empty_batches_ndjson, BATCH_SIZE*16).get(stream) );
|
||||||
for (auto [doc, error] : stream) {
|
for (auto [doc, error] : stream) {
|
||||||
if (error) { cerr << "Error in parse_many: " << error << endl; return false; }
|
ASSERT_SUCCESS(error);
|
||||||
count++;
|
count++;
|
||||||
auto [val, val_error] = doc.get<uint64_t>();
|
uint64_t val;
|
||||||
if (val_error) { cerr << "Document is not an unsigned int: " << val_error << endl; return false; }
|
ASSERT_SUCCESS( doc.get(val) );
|
||||||
if (val != count) { cerr << "Expected document #" << count << " to equal " << count << ", but got " << val << " instead!" << endl; return false; }
|
ASSERT_EQUAL( val, count );
|
||||||
}
|
}
|
||||||
if (count != 3) { cerr << "parse_many returned " << count << " documents, expected 0" << endl; return false; }
|
ASSERT_EQUAL(count, 3);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool parser_load() {
|
bool parser_load() {
|
||||||
std::cout << "Running " << __func__ << " on " << TWITTER_JSON << std::endl;
|
std::cout << "Running " << __func__ << " on " << TWITTER_JSON << std::endl;
|
||||||
dom::parser parser;
|
dom::parser parser;
|
||||||
auto [doc, error] = parser.load(TWITTER_JSON);
|
dom::object object;
|
||||||
if (error) { cerr << error << endl; return false; }
|
ASSERT_SUCCESS( parser.load(TWITTER_JSON).get(object) );
|
||||||
if (!doc.is<dom::object>()) { cerr << "Document did not parse as an object" << endl; return false; }
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool parser_load_many() {
|
bool parser_load_many() {
|
||||||
|
@ -707,21 +679,19 @@ namespace parse_api_tests {
|
||||||
simdjson::dom::document_stream stream;
|
simdjson::dom::document_stream stream;
|
||||||
ASSERT_SUCCESS( parser.load_many(AMAZON_CELLPHONES_NDJSON).get(stream) );
|
ASSERT_SUCCESS( parser.load_many(AMAZON_CELLPHONES_NDJSON).get(stream) );
|
||||||
for (auto [doc, error] : stream) {
|
for (auto [doc, error] : stream) {
|
||||||
if (error) { cerr << error << endl; return false; }
|
ASSERT_SUCCESS( error );
|
||||||
|
|
||||||
dom::array arr;
|
dom::array arr;
|
||||||
error = doc.get(arr); // let us get the array
|
ASSERT_SUCCESS( doc.get(arr) ); // let us get the array
|
||||||
if (error) { cerr << error << endl; return false; }
|
ASSERT_EQUAL(arr.size(), 9);
|
||||||
|
|
||||||
if(arr.size() != 9) { cerr << "bad array size"<< endl; return false; }
|
size_t arr_count = 0;
|
||||||
|
for (auto v : arr) { arr_count++; (void)v; }
|
||||||
size_t c = 0;
|
ASSERT_EQUAL(arr_count, 9);
|
||||||
for(auto v : arr) { c++; (void)v; }
|
|
||||||
if(c != 9) { cerr << "mismatched array size"<< endl; return false; }
|
|
||||||
|
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
if (count != 793) { cerr << "Expected 793 documents, but load_many loaded " << count << " documents." << endl; return false; }
|
ASSERT_EQUAL(count, AMAZON_CELLPHONES_NDJSON_DOC_COUNT);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -735,18 +705,16 @@ namespace parse_api_tests {
|
||||||
if (error) { cerr << error << endl; return false; }
|
if (error) { cerr << error << endl; return false; }
|
||||||
|
|
||||||
dom::array arr;
|
dom::array arr;
|
||||||
error = doc.get(arr); // let us get the array
|
ASSERT_SUCCESS( doc.get(arr) );
|
||||||
if (error) { cerr << error << endl; return false; }
|
ASSERT_EQUAL( arr.size(), 9 );
|
||||||
|
|
||||||
if(arr.size() != 9) { cerr << "bad array size"<< endl; return false; }
|
size_t arr_count = 0;
|
||||||
|
for (auto v : arr) { arr_count++; (void)v; }
|
||||||
size_t c = 0;
|
ASSERT_EQUAL( arr_count, 9 );
|
||||||
for(auto v : arr) { c++; (void)v; }
|
|
||||||
if(c != 9) { cerr << "mismatched array size"<< endl; return false; }
|
|
||||||
|
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
if (count != 793) { cerr << "Expected 793 documents, but load_many loaded " << count << " documents." << endl; return false; }
|
ASSERT_EQUAL( count, AMAZON_CELLPHONES_NDJSON_DOC_COUNT );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
SIMDJSON_POP_DISABLE_WARNINGS
|
SIMDJSON_POP_DISABLE_WARNINGS
|
||||||
|
@ -756,45 +724,39 @@ namespace parse_api_tests {
|
||||||
bool parser_parse_exception() {
|
bool parser_parse_exception() {
|
||||||
std::cout << "Running " << __func__ << std::endl;
|
std::cout << "Running " << __func__ << std::endl;
|
||||||
dom::parser parser;
|
dom::parser parser;
|
||||||
element doc = parser.parse(BASIC_JSON);
|
UNUSED dom::array array = parser.parse(BASIC_JSON);
|
||||||
if (!doc.is<dom::array>()) { cerr << "Document did not parse as an array" << endl; return false; }
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool parser_parse_many_exception() {
|
bool parser_parse_many_exception() {
|
||||||
std::cout << "Running " << __func__ << std::endl;
|
std::cout << "Running " << __func__ << std::endl;
|
||||||
dom::parser parser;
|
dom::parser parser;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (const element doc : parser.parse_many(BASIC_NDJSON)) {
|
for (UNUSED dom::array doc : parser.parse_many(BASIC_NDJSON)) {
|
||||||
if (!doc.is<dom::array>()) { cerr << "Document did not parse as an array" << endl; return false; }
|
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
if (count != 2) { cerr << "parse_many returned " << count << " documents, expected 2" << endl; return false; }
|
ASSERT_EQUAL(count, 2);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool parser_load_exception() {
|
bool parser_load_exception() {
|
||||||
std::cout << "Running " << __func__ << std::endl;
|
std::cout << "Running " << __func__ << std::endl;
|
||||||
dom::parser parser;
|
dom::parser parser;
|
||||||
const element doc = parser.load(TWITTER_JSON);
|
size_t count = 0;
|
||||||
if (!doc.is<dom::object>()) { cerr << "Document did not parse as an object" << endl; return false; }
|
dom::object object = parser.load(TWITTER_JSON);
|
||||||
size_t c = 0;
|
for (UNUSED auto field : object) {
|
||||||
dom::object obj = doc.get<dom::object>().value(); // let us get the object
|
count++;
|
||||||
for (auto x : obj) {
|
|
||||||
c++;
|
|
||||||
(void) x;
|
|
||||||
}
|
}
|
||||||
if(c != obj.size()) { cerr << "Mismatched size" << endl; return false; }
|
ASSERT_EQUAL( count, object.size() );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool parser_load_many_exception() {
|
bool parser_load_many_exception() {
|
||||||
std::cout << "Running " << __func__ << std::endl;
|
std::cout << "Running " << __func__ << std::endl;
|
||||||
dom::parser parser;
|
dom::parser parser;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (const element doc : parser.load_many(AMAZON_CELLPHONES_NDJSON)) {
|
for (UNUSED dom::array doc : parser.load_many(AMAZON_CELLPHONES_NDJSON)) {
|
||||||
if (!doc.is<dom::array>()) { cerr << "Document did not parse as an array" << endl; return false; }
|
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
if (count != 793) { cerr << "Expected 1 document, but load_many loaded " << count << " documents." << endl; return false; }
|
ASSERT_EQUAL( count, AMAZON_CELLPHONES_NDJSON_DOC_COUNT );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -933,16 +895,17 @@ namespace dom_api_tests {
|
||||||
string json(R"({ "a": 1, "b": 2, "c": 3 })");
|
string json(R"({ "a": 1, "b": 2, "c": 3 })");
|
||||||
const char* expected_key[] = { "a", "b", "c" };
|
const char* expected_key[] = { "a", "b", "c" };
|
||||||
uint64_t expected_value[] = { 1, 2, 3 };
|
uint64_t expected_value[] = { 1, 2, 3 };
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
dom::parser parser;
|
dom::parser parser;
|
||||||
auto [object, error] = parser.parse(json).get<dom::object>();
|
dom::object object;
|
||||||
if (error) { cerr << "Error: " << error << endl; return false; }
|
ASSERT_SUCCESS( parser.parse(json).get(object) );
|
||||||
|
int i = 0;
|
||||||
for (auto [key, value] : object) {
|
for (auto [key, value] : object) {
|
||||||
if (key != expected_key[i] || value.get<uint64_t>().first != expected_value[i]) { cerr << "Expected " << expected_key[i] << " = " << expected_value[i] << ", got " << key << "=" << value << endl; return false; }
|
ASSERT_EQUAL( key, expected_key[i] );
|
||||||
|
ASSERT_EQUAL( value.get<uint64_t>().value(), expected_value[i] );
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
if (i*sizeof(uint64_t) != sizeof(expected_value)) { cout << "Expected " << sizeof(expected_value) << " values, got " << i << endl; return false; }
|
ASSERT_EQUAL( i*sizeof(uint64_t), sizeof(expected_value) );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -950,16 +913,18 @@ namespace dom_api_tests {
|
||||||
std::cout << "Running " << __func__ << std::endl;
|
std::cout << "Running " << __func__ << std::endl;
|
||||||
string json(R"([ 1, 10, 100 ])");
|
string json(R"([ 1, 10, 100 ])");
|
||||||
uint64_t expected_value[] = { 1, 10, 100 };
|
uint64_t expected_value[] = { 1, 10, 100 };
|
||||||
int i=0;
|
|
||||||
|
|
||||||
dom::parser parser;
|
dom::parser parser;
|
||||||
auto [array, error] = parser.parse(json).get<dom::array>();
|
dom::array array;
|
||||||
if (error) { cerr << "Error: " << error << endl; return false; }
|
ASSERT_SUCCESS( parser.parse(json).get(array) );
|
||||||
|
int i=0;
|
||||||
for (auto value : array) {
|
for (auto value : array) {
|
||||||
if (value.get<uint64_t>().first != expected_value[i]) { cerr << "Expected " << expected_value[i] << ", got " << value << endl; return false; }
|
uint64_t v;
|
||||||
|
ASSERT_SUCCESS( value.get(v) );
|
||||||
|
ASSERT_EQUAL( v, expected_value[i] );
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
if (i*sizeof(uint64_t) != sizeof(expected_value)) { cout << "Expected " << sizeof(expected_value) << " values, got " << i << endl; return false; }
|
ASSERT_EQUAL( i*sizeof(uint64_t), sizeof(expected_value) );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -969,13 +934,13 @@ namespace dom_api_tests {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
dom::parser parser;
|
dom::parser parser;
|
||||||
auto [object, error] = parser.parse(json).get<dom::object>();
|
dom::object object;
|
||||||
if (error) { cerr << "Error: " << error << endl; return false; }
|
ASSERT_SUCCESS( parser.parse(json).get(object) );
|
||||||
for (auto [key, value] : object) {
|
for (UNUSED auto field : object) {
|
||||||
cout << "Unexpected " << key << " = " << value << endl;
|
TEST_FAIL("Unexpected field");
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
if (i > 0) { cout << "Expected 0 values, got " << i << endl; return false; }
|
ASSERT_EQUAL(i, 0);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -985,13 +950,13 @@ namespace dom_api_tests {
|
||||||
int i=0;
|
int i=0;
|
||||||
|
|
||||||
dom::parser parser;
|
dom::parser parser;
|
||||||
auto [array, error] = parser.parse(json).get<dom::array>();
|
dom::array array;
|
||||||
if (error) { cerr << "Error: " << error << endl; return false; }
|
ASSERT_SUCCESS( parser.parse(json).get(array) );
|
||||||
for (auto value : array) {
|
for (UNUSED auto value : array) {
|
||||||
cout << "Unexpected value " << value << endl;
|
TEST_FAIL("Unexpected value");
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
if (i > 0) { cout << "Expected 0 values, got " << i << endl; return false; }
|
ASSERT_EQUAL(i, 0);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -999,13 +964,18 @@ namespace dom_api_tests {
|
||||||
std::cout << "Running " << __func__ << std::endl;
|
std::cout << "Running " << __func__ << std::endl;
|
||||||
string json(R"([ "hi", "has backslash\\" ])");
|
string json(R"([ "hi", "has backslash\\" ])");
|
||||||
dom::parser parser;
|
dom::parser parser;
|
||||||
auto [array, error] = parser.parse(json).get<dom::array>();
|
dom::array array;
|
||||||
if (error) { cerr << "Error: " << error << endl; return false; }
|
ASSERT_SUCCESS( parser.parse(json).get(array) );
|
||||||
auto val = array.begin();
|
|
||||||
|
auto iter = array.begin();
|
||||||
|
std::string_view val;
|
||||||
|
ASSERT_SUCCESS( (*iter).get(val) );
|
||||||
|
ASSERT_EQUAL( val, "hi" );
|
||||||
|
|
||||||
|
++iter;
|
||||||
|
ASSERT_SUCCESS( (*iter).get(val) );
|
||||||
|
ASSERT_EQUAL( val, "has backslash\\" );
|
||||||
|
|
||||||
if ((*val).get<std::string_view>().first != "hi") { cerr << "Expected value to be \"hi\", was " << (*val).get<std::string_view>().first << endl; return false; }
|
|
||||||
++val;
|
|
||||||
if ((*val).get<std::string_view>().first != "has backslash\\") { cerr << "Expected string_view(\"has backslash\\\\\") to be \"has backslash\\\", was " << (*val).get<std::string_view>().first << endl; return false; }
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1013,22 +983,22 @@ namespace dom_api_tests {
|
||||||
std::cout << "Running " << __func__ << std::endl;
|
std::cout << "Running " << __func__ << std::endl;
|
||||||
string json(R"([ 0, 1, -1, 1.1 ])");
|
string json(R"([ 0, 1, -1, 1.1 ])");
|
||||||
dom::parser parser;
|
dom::parser parser;
|
||||||
auto [array, error] = parser.parse(json).get<dom::array>();
|
dom::array array;
|
||||||
if (error) { cerr << "Error: " << error << endl; return false; }
|
ASSERT_SUCCESS( parser.parse(json).get(array) );
|
||||||
auto val = array.begin();
|
|
||||||
|
|
||||||
if ((*val).get<uint64_t>().first != 0) { cerr << "Expected uint64_t(0) to be 0, was " << (*val) << endl; return false; }
|
auto iter = array.begin();
|
||||||
if ((*val).get<int64_t>().first != 0) { cerr << "Expected int64_t(0) to be 0, was " << (*val).get<int64_t>().first << endl; return false; }
|
ASSERT_EQUAL( (*iter).get<uint64_t>().value(), 0 );
|
||||||
if ((*val).get<double>().first != 0) { cerr << "Expected double(0) to be 0, was " << (*val).get<double>().first << endl; return false; }
|
ASSERT_EQUAL( (*iter).get<int64_t>().value(), 0 );
|
||||||
++val;
|
ASSERT_EQUAL( (*iter).get<double>().value(), 0 );
|
||||||
if ((*val).get<uint64_t>().first != 1) { cerr << "Expected uint64_t(1) to be 1, was " << (*val) << endl; return false; }
|
++iter;
|
||||||
if ((*val).get<int64_t>().first != 1) { cerr << "Expected int64_t(1) to be 1, was " << (*val).get<int64_t>().first << endl; return false; }
|
ASSERT_EQUAL( (*iter).get<uint64_t>().value(), 1 );
|
||||||
if ((*val).get<double>().first != 1) { cerr << "Expected double(1) to be 1, was " << (*val).get<double>().first << endl; return false; }
|
ASSERT_EQUAL( (*iter).get<int64_t>().value(), 1 );
|
||||||
++val;
|
ASSERT_EQUAL( (*iter).get<double>().value(), 1 );
|
||||||
if ((*val).get<int64_t>().first != -1) { cerr << "Expected int64_t(-1) to be -1, was " << (*val).get<int64_t>().first << endl; return false; }
|
++iter;
|
||||||
if ((*val).get<double>().first != -1) { cerr << "Expected double(-1) to be -1, was " << (*val).get<double>().first << endl; return false; }
|
ASSERT_EQUAL( (*iter).get<int64_t>().value(), -1 );
|
||||||
++val;
|
ASSERT_EQUAL( (*iter).get<double>().value(), -1 );
|
||||||
if ((*val).get<double>().first != 1.1) { cerr << "Expected double(1.1) to be 1.1, was " << (*val).get<double>().first << endl; return false; }
|
++iter;
|
||||||
|
ASSERT_EQUAL( (*iter).get<double>().value(), 1.1 );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1036,13 +1006,13 @@ namespace dom_api_tests {
|
||||||
std::cout << "Running " << __func__ << std::endl;
|
std::cout << "Running " << __func__ << std::endl;
|
||||||
string json(R"([ true, false ])");
|
string json(R"([ true, false ])");
|
||||||
dom::parser parser;
|
dom::parser parser;
|
||||||
auto [array, error] = parser.parse(json).get<dom::array>();
|
dom::array array;
|
||||||
if (error) { cerr << "Error: " << error << endl; return false; }
|
ASSERT_SUCCESS( parser.parse(json).get(array) );
|
||||||
auto val = array.begin();
|
|
||||||
|
|
||||||
if ((*val).get<bool>().first != true) { cerr << "Expected bool(true) to be true, was " << (*val) << endl; return false; }
|
auto val = array.begin();
|
||||||
|
ASSERT_EQUAL( (*val).get<bool>().first, true );
|
||||||
++val;
|
++val;
|
||||||
if ((*val).get<bool>().first != false) { cerr << "Expected bool(false) to be false, was " << (*val) << endl; return false; }
|
ASSERT_EQUAL( (*val).get<bool>().first, false );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1050,10 +1020,11 @@ namespace dom_api_tests {
|
||||||
std::cout << "Running " << __func__ << std::endl;
|
std::cout << "Running " << __func__ << std::endl;
|
||||||
string json(R"([ null ])");
|
string json(R"([ null ])");
|
||||||
dom::parser parser;
|
dom::parser parser;
|
||||||
auto [array, error] = parser.parse(json).get<dom::array>();
|
dom::array array;
|
||||||
if (error) { cerr << "Error: " << error << endl; return false; }
|
ASSERT_SUCCESS( parser.parse(json).get(array) );
|
||||||
|
|
||||||
auto val = array.begin();
|
auto val = array.begin();
|
||||||
if (!(*val).is_null()) { cerr << "Expected null to be null!" << endl; return false; }
|
ASSERT_EQUAL( !(*val).is_null(), 0 );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1061,27 +1032,29 @@ namespace dom_api_tests {
|
||||||
std::cout << "Running " << __func__ << std::endl;
|
std::cout << "Running " << __func__ << std::endl;
|
||||||
string json(R"({ "a": 1, "b": 2, "c/d": 3})");
|
string json(R"({ "a": 1, "b": 2, "c/d": 3})");
|
||||||
dom::parser parser;
|
dom::parser parser;
|
||||||
auto [doc, error] = parser.parse(json);
|
dom::object object;
|
||||||
if (doc["a"].get<uint64_t>().first != 1) { cerr << "Expected uint64_t(doc[\"a\"]) to be 1, was " << doc["a"].first << endl; return false; }
|
ASSERT_SUCCESS( parser.parse(json).get(object) );
|
||||||
if (doc["b"].get<uint64_t>().first != 2) { cerr << "Expected uint64_t(doc[\"b\"]) to be 2, was " << doc["b"].first << endl; return false; }
|
ASSERT_EQUAL( object["a"].get<uint64_t>().first, 1 );
|
||||||
if (doc["c/d"].get<uint64_t>().first != 3) { cerr << "Expected uint64_t(doc[\"c/d\"]) to be 3, was " << doc["c"].first << endl; return false; }
|
ASSERT_EQUAL( object["b"].get<uint64_t>().first, 2 );
|
||||||
|
ASSERT_EQUAL( object["c/d"].get<uint64_t>().first, 3 );
|
||||||
// Check all three again in backwards order, to ensure we can go backwards
|
// Check all three again in backwards order, to ensure we can go backwards
|
||||||
if (doc["c/d"].get<uint64_t>().first != 3) { cerr << "Expected uint64_t(doc[\"c/d\"]) to be 3, was " << doc["c"].first << endl; return false; }
|
ASSERT_EQUAL( object["c/d"].get<uint64_t>().first, 3 );
|
||||||
if (doc["b"].get<uint64_t>().first != 2) { cerr << "Expected uint64_t(doc[\"b\"]) to be 2, was " << doc["b"].first << endl; return false; }
|
ASSERT_EQUAL( object["b"].get<uint64_t>().first, 2 );
|
||||||
if (doc["a"].get<uint64_t>().first != 1) { cerr << "Expected uint64_t(doc[\"a\"]) to be 1, was " << doc["a"].first << endl; return false; }
|
ASSERT_EQUAL( object["a"].get<uint64_t>().first, 1 );
|
||||||
|
|
||||||
|
simdjson::error_code error;
|
||||||
UNUSED element val;
|
UNUSED element val;
|
||||||
#ifndef _LIBCPP_VERSION // should work everywhere but with libc++, must include the <ciso646> header.
|
#ifndef _LIBCPP_VERSION // should work everywhere but with libc++, must include the <ciso646> header.
|
||||||
std::tie(val,error) = doc["d"];
|
std::tie(val,error) = object["d"];
|
||||||
if (error != simdjson::NO_SUCH_FIELD) { cerr << "Expected NO_SUCH_FIELD error for uint64_t(doc[\"d\"]), got " << error << endl; return false; }
|
ASSERT_ERROR( error, NO_SUCH_FIELD );
|
||||||
std::tie(std::ignore,error) = doc["d"];
|
std::tie(std::ignore,error) = object["d"];
|
||||||
if (error != simdjson::NO_SUCH_FIELD) { cerr << "Expected NO_SUCH_FIELD error for uint64_t(doc[\"d\"]), got " << error << endl; return false; }
|
ASSERT_ERROR( error, NO_SUCH_FIELD );
|
||||||
#endif
|
#endif
|
||||||
// tie(val, error) = doc["d"]; fails with "no viable overloaded '='" on Apple clang version 11.0.0 tie(val, error) = doc["d"];
|
// tie(val, error) = object["d"]; fails with "no viable overloaded '='" on Apple clang version 11.0.0 tie(val, error) = doc["d"];
|
||||||
doc["d"].tie(val, error);
|
object["d"].tie(val, error);
|
||||||
if (error != simdjson::NO_SUCH_FIELD) { cerr << "Expected NO_SUCH_FIELD error for uint64_t(doc[\"d\"]), got " << error << endl; return false; }
|
ASSERT_ERROR( error, NO_SUCH_FIELD );
|
||||||
if (doc["d"].get(val) != simdjson::NO_SUCH_FIELD) { cerr << "Expected NO_SUCH_FIELD error for uint64_t(doc[\"d\"]), got " << error << endl; return false; }
|
ASSERT_ERROR( object["d"].get(val), NO_SUCH_FIELD );
|
||||||
if (doc["d"].error() != simdjson::NO_SUCH_FIELD) { cerr << "Expected NO_SUCH_FIELD error for uint64_t(doc[\"d\"]), got " << error << endl; return false; }
|
ASSERT_ERROR( object["d"].error(), NO_SUCH_FIELD );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1089,26 +1062,25 @@ namespace dom_api_tests {
|
||||||
std::cout << "Running " << __func__ << std::endl;
|
std::cout << "Running " << __func__ << std::endl;
|
||||||
string json(R"({ "obj": { "a": 1, "b": 2, "c/d": 3 } })");
|
string json(R"({ "obj": { "a": 1, "b": 2, "c/d": 3 } })");
|
||||||
dom::parser parser;
|
dom::parser parser;
|
||||||
auto [doc, error] = parser.parse(json);
|
dom::element doc;
|
||||||
if (error) { cerr << "Error: " << error << endl; return false; }
|
ASSERT_SUCCESS( parser.parse(json).get(doc) );
|
||||||
if (doc["obj"]["a"].get<uint64_t>().first != 1) { cerr << "Expected uint64_t(doc[\"obj\"][\"a\"]) to be 1, was " << doc["obj"]["a"].first << endl; return false; }
|
ASSERT_EQUAL( doc["obj"]["a"].get<uint64_t>().first, 1);
|
||||||
|
|
||||||
object obj;
|
object obj;
|
||||||
error = doc.get(obj);
|
ASSERT_SUCCESS( doc.get(obj) );
|
||||||
if (error) { cerr << "Error: " << error << endl; return false; }
|
ASSERT_EQUAL( obj["obj"]["a"].get<uint64_t>().first, 1);
|
||||||
if (obj["obj"]["a"].get<uint64_t>().first != 1) { cerr << "Expected uint64_t(doc[\"obj\"][\"a\"]) to be 1, was " << doc["obj"]["a"].first << endl; return false; }
|
|
||||||
|
|
||||||
error = obj["obj"].get(obj);
|
ASSERT_SUCCESS( obj["obj"].get(obj) );
|
||||||
if (obj["a"].get<uint64_t>().first != 1) { cerr << "Expected uint64_t(obj[\"a\"]) to be 1, was " << obj["a"].first << endl; return false; }
|
ASSERT_EQUAL( obj["a"].get<uint64_t>().first, 1 );
|
||||||
if (obj["b"].get<uint64_t>().first != 2) { cerr << "Expected uint64_t(obj[\"b\"]) to be 2, was " << obj["b"].first << endl; return false; }
|
ASSERT_EQUAL( obj["b"].get<uint64_t>().first, 2 );
|
||||||
if (obj["c/d"].get<uint64_t>().first != 3) { cerr << "Expected uint64_t(obj[\"c\"]) to be 3, was " << obj["c"].first << endl; return false; }
|
ASSERT_EQUAL( obj["c/d"].get<uint64_t>().first, 3 );
|
||||||
// Check all three again in backwards order, to ensure we can go backwards
|
// Check all three again in backwards order, to ensure we can go backwards
|
||||||
if (obj["c/d"].get<uint64_t>().first != 3) { cerr << "Expected uint64_t(obj[\"c\"]) to be 3, was " << obj["c"].first << endl; return false; }
|
ASSERT_EQUAL( obj["c/d"].get<uint64_t>().first, 3 );
|
||||||
if (obj["b"].get<uint64_t>().first != 2) { cerr << "Expected uint64_t(obj[\"b\"]) to be 2, was " << obj["b"].first << endl; return false; }
|
ASSERT_EQUAL( obj["b"].get<uint64_t>().first, 2 );
|
||||||
if (obj["a"].get<uint64_t>().first != 1) { cerr << "Expected uint64_t(obj[\"a\"]) to be 1, was " << obj["a"].first << endl; return false; }
|
ASSERT_EQUAL( obj["a"].get<uint64_t>().first, 1 );
|
||||||
|
|
||||||
UNUSED element val;
|
UNUSED element val;
|
||||||
if (doc["d"].get(val) != simdjson::NO_SUCH_FIELD) { cerr << "Expected NO_SUCH_FIELD error for uint64_t(obj[\"d\"]), got " << error << endl; return false; }
|
ASSERT_ERROR( doc["d"].get(val), NO_SUCH_FIELD);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1116,9 +1088,9 @@ namespace dom_api_tests {
|
||||||
std::cout << "Running " << __func__ << std::endl;
|
std::cout << "Running " << __func__ << std::endl;
|
||||||
// Prints the number of results in twitter.json
|
// Prints the number of results in twitter.json
|
||||||
dom::parser parser;
|
dom::parser parser;
|
||||||
auto [result_count, error] = parser.load(TWITTER_JSON)["search_metadata"]["count"].get<uint64_t>();
|
uint64_t result_count;
|
||||||
if (error) { cerr << "Error: " << error << endl; return false; }
|
ASSERT_SUCCESS( parser.load(TWITTER_JSON)["search_metadata"]["count"].get(result_count) );
|
||||||
if (result_count != 100) { cerr << "Expected twitter.json[metadata_count][count] = 100, got " << result_count << endl; return false; }
|
ASSERT_EQUAL( result_count, 100 );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1128,20 +1100,19 @@ namespace dom_api_tests {
|
||||||
set<string_view> default_users;
|
set<string_view> default_users;
|
||||||
dom::parser parser;
|
dom::parser parser;
|
||||||
dom::array tweets;
|
dom::array tweets;
|
||||||
auto error = parser.load(TWITTER_JSON)["statuses"].get(tweets);
|
ASSERT_SUCCESS( parser.load(TWITTER_JSON)["statuses"].get(tweets) );
|
||||||
if (error) { cerr << "Error: " << error << endl; return false; }
|
|
||||||
for (auto tweet : tweets) {
|
for (auto tweet : tweets) {
|
||||||
object user;
|
object user;
|
||||||
if ((error = tweet["user"].get(user))) { cerr << "Error: " << error << endl; return false; }
|
ASSERT_SUCCESS( tweet["user"].get(user) );
|
||||||
bool default_profile;
|
bool default_profile;
|
||||||
if ((error = user["default_profile"].get(default_profile))) { cerr << "Error: " << error << endl; return false; }
|
ASSERT_SUCCESS( user["default_profile"].get(default_profile) );
|
||||||
if (default_profile) {
|
if (default_profile) {
|
||||||
std::string_view screen_name;
|
std::string_view screen_name;
|
||||||
if ((error = user["screen_name"].get(screen_name))) { cerr << "Error: " << error << endl; return false; }
|
ASSERT_SUCCESS( user["screen_name"].get(screen_name) );
|
||||||
default_users.insert(screen_name);
|
default_users.insert(screen_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (default_users.size() != 86) { cerr << "Expected twitter.json[statuses][user] to contain 86 default_profile users, got " << default_users.size() << endl; return false; }
|
ASSERT_EQUAL( default_users.size(), 86 );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1149,26 +1120,26 @@ namespace dom_api_tests {
|
||||||
std::cout << "Running " << __func__ << std::endl;
|
std::cout << "Running " << __func__ << std::endl;
|
||||||
// Print image names and sizes
|
// Print image names and sizes
|
||||||
set<pair<uint64_t, uint64_t>> image_sizes;
|
set<pair<uint64_t, uint64_t>> image_sizes;
|
||||||
|
simdjson::error_code error;
|
||||||
dom::parser parser;
|
dom::parser parser;
|
||||||
dom::array tweets;
|
dom::array tweets;
|
||||||
auto error = parser.load(TWITTER_JSON)["statuses"].get(tweets);
|
ASSERT_SUCCESS( parser.load(TWITTER_JSON)["statuses"].get(tweets) );
|
||||||
if (error) { cerr << "Error: " << error << endl; return false; }
|
|
||||||
for (auto tweet : tweets) {
|
for (auto tweet : tweets) {
|
||||||
dom::array media;
|
dom::array media;
|
||||||
if (not (error = tweet["entities"]["media"].get(media))) {
|
if (not (error = tweet["entities"]["media"].get(media))) {
|
||||||
for (auto image : media) {
|
for (auto image : media) {
|
||||||
object sizes;
|
object sizes;
|
||||||
if ((error = image["sizes"].get(sizes))) { cerr << "Error: " << error << endl; return false; }
|
ASSERT_SUCCESS( image["sizes"].get(sizes) );
|
||||||
for (auto size : sizes) {
|
for (auto size : sizes) {
|
||||||
uint64_t width, height;
|
uint64_t width, height;
|
||||||
if ((error = size.value["w"].get(width))) { cerr << "Error: " << error << endl; return false; }
|
ASSERT_SUCCESS( size.value["w"].get(width) );
|
||||||
if ((error = size.value["h"].get(height))) { cerr << "Error: " << error << endl; return false; }
|
ASSERT_SUCCESS( size.value["h"].get(height) );
|
||||||
image_sizes.insert(make_pair(width, height));
|
image_sizes.insert(make_pair(width, height));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (image_sizes.size() != 15) { cerr << "Expected twitter.json[statuses][entities][media][sizes] to contain 15 different sizes, got " << image_sizes.size() << endl; return false; }
|
ASSERT_EQUAL( image_sizes.size(), 15 );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1182,12 +1153,12 @@ namespace dom_api_tests {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
dom::parser parser;
|
dom::parser parser;
|
||||||
element doc = parser.parse(json);
|
for (auto [key, value] : dom::object(parser.parse(json))) {
|
||||||
for (auto [key, value] : doc.get<dom::object>()) {
|
ASSERT_EQUAL( key, expected_key[i]);
|
||||||
if (key != expected_key[i] || uint64_t(value) != expected_value[i]) { cerr << "Expected " << expected_key[i] << " = " << expected_value[i] << ", got " << key << "=" << uint64_t(value) << endl; return false; }
|
ASSERT_EQUAL( uint64_t(value), expected_value[i] );
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
if (i*sizeof(uint64_t) != sizeof(expected_value)) { cout << "Expected " << sizeof(expected_value) << " values, got " << i << endl; return false; }
|
ASSERT_EQUAL( i*sizeof(uint64_t), sizeof(expected_value) );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1198,69 +1169,61 @@ namespace dom_api_tests {
|
||||||
int i=0;
|
int i=0;
|
||||||
|
|
||||||
dom::parser parser;
|
dom::parser parser;
|
||||||
element doc = parser.parse(json);
|
for (uint64_t value : parser.parse(json)) {
|
||||||
for (uint64_t value : doc.get<dom::array>()) {
|
ASSERT_EQUAL( value, expected_value[i] );
|
||||||
if (value != expected_value[i]) { cerr << "Expected " << expected_value[i] << ", got " << value << endl; return false; }
|
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
if (i*sizeof(uint64_t) != sizeof(expected_value)) { cout << "Expected " << sizeof(expected_value) << " values, got " << i << endl; return false; }
|
ASSERT_EQUAL( i*sizeof(uint64_t), sizeof(expected_value) );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool string_value_exception() {
|
bool string_value_exception() {
|
||||||
std::cout << "Running " << __func__ << std::endl;
|
std::cout << "Running " << __func__ << std::endl;
|
||||||
string json(R"([ "hi", "has backslash\\" ])");
|
|
||||||
dom::parser parser;
|
dom::parser parser;
|
||||||
auto val = parser.parse(json).get<dom::array>().begin();
|
ASSERT_EQUAL( (const char *)parser.parse(R"("hi")"_padded), "hi" );
|
||||||
|
ASSERT_EQUAL( string_view(parser.parse(R"("hi")"_padded)), "hi" );
|
||||||
if (strcmp((const char*)*val, "hi")) { cerr << "Expected const char*(\"hi\") to be \"hi\", was " << (const char*)*val << endl; return false; }
|
ASSERT_EQUAL( (const char *)parser.parse(R"("has backslash\\")"_padded), "has backslash\\");
|
||||||
if (string_view(*val) != "hi") { cerr << "Expected string_view(\"hi\") to be \"hi\", was " << string_view(*val) << endl; return false; }
|
ASSERT_EQUAL( string_view(parser.parse(R"("has backslash\\")"_padded)), "has backslash\\" );
|
||||||
++val;
|
|
||||||
if (strcmp((const char*)*val, "has backslash\\")) { cerr << "Expected const char*(\"has backslash\\\\\") to be \"has backslash\\\", was " << (const char*)*val << endl; return false; }
|
|
||||||
if (string_view(*val) != "has backslash\\") { cerr << "Expected string_view(\"has backslash\\\\\") to be \"has backslash\\\", was " << string_view(*val) << endl; return false; }
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool numeric_values_exception() {
|
bool numeric_values_exception() {
|
||||||
std::cout << "Running " << __func__ << std::endl;
|
std::cout << "Running " << __func__ << std::endl;
|
||||||
string json(R"([ 0, 1, -1, 1.1 ])");
|
|
||||||
dom::parser parser;
|
dom::parser parser;
|
||||||
auto val = parser.parse(json).get<dom::array>().begin();
|
|
||||||
|
|
||||||
if (uint64_t(*val) != 0) { cerr << "Expected uint64_t(0) to be 0, was " << uint64_t(*val) << endl; return false; }
|
ASSERT_EQUAL( uint64_t(parser.parse("0"_padded)), 0);
|
||||||
if (int64_t(*val) != 0) { cerr << "Expected int64_t(0) to be 0, was " << int64_t(*val) << endl; return false; }
|
ASSERT_EQUAL( int64_t(parser.parse("0"_padded)), 0);
|
||||||
if (double(*val) != 0) { cerr << "Expected double(0) to be 0, was " << double(*val) << endl; return false; }
|
ASSERT_EQUAL( double(parser.parse("0"_padded)), 0);
|
||||||
++val;
|
|
||||||
if (uint64_t(*val) != 1) { cerr << "Expected uint64_t(1) to be 1, was " << uint64_t(*val) << endl; return false; }
|
ASSERT_EQUAL( uint64_t(parser.parse("1"_padded)), 1);
|
||||||
if (int64_t(*val) != 1) { cerr << "Expected int64_t(1) to be 1, was " << int64_t(*val) << endl; return false; }
|
ASSERT_EQUAL( int64_t(parser.parse("1"_padded)), 1);
|
||||||
if (double(*val) != 1) { cerr << "Expected double(1) to be 1, was " << double(*val) << endl; return false; }
|
ASSERT_EQUAL( double(parser.parse("1"_padded)), 1);
|
||||||
++val;
|
|
||||||
if (int64_t(*val) != -1) { cerr << "Expected int64_t(-1) to be -1, was " << int64_t(*val) << endl; return false; }
|
ASSERT_EQUAL( int64_t(parser.parse("-1"_padded)), -1);
|
||||||
if (double(*val) != -1) { cerr << "Expected double(-1) to be -1, was " << double(*val) << endl; return false; }
|
ASSERT_EQUAL( double(parser.parse("-1"_padded)), -1);
|
||||||
++val;
|
|
||||||
if (double(*val) != 1.1) { cerr << "Expected double(1.1) to be 1.1, was " << double(*val) << endl; return false; }
|
ASSERT_EQUAL( double(parser.parse("1.1"_padded)), 1.1);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool boolean_values_exception() {
|
bool boolean_values_exception() {
|
||||||
std::cout << "Running " << __func__ << std::endl;
|
std::cout << "Running " << __func__ << std::endl;
|
||||||
string json(R"([ true, false ])");
|
|
||||||
dom::parser parser;
|
dom::parser parser;
|
||||||
auto val = parser.parse(json).get<dom::array>().begin();
|
|
||||||
|
|
||||||
if (bool(*val) != true) { cerr << "Expected bool(true) to be true, was " << bool(*val) << endl; return false; }
|
ASSERT_EQUAL( bool(parser.parse("true"_padded)), true);
|
||||||
++val;
|
|
||||||
if (bool(*val) != false) { cerr << "Expected bool(false) to be false, was " << bool(*val) << endl; return false; }
|
ASSERT_EQUAL( bool(parser.parse("false"_padded)), false);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool null_value_exception() {
|
bool null_value_exception() {
|
||||||
std::cout << "Running " << __func__ << std::endl;
|
std::cout << "Running " << __func__ << std::endl;
|
||||||
string json(R"([ null ])");
|
|
||||||
dom::parser parser;
|
dom::parser parser;
|
||||||
auto val = parser.parse(json).get<dom::array>().begin();
|
|
||||||
|
|
||||||
if (!(*val).is_null()) { cerr << "Expected null to be null!" << endl; return false; }
|
ASSERT_EQUAL( bool(parser.parse("null"_padded).is_null()), true );
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1268,8 +1231,10 @@ namespace dom_api_tests {
|
||||||
std::cout << "Running " << __func__ << std::endl;
|
std::cout << "Running " << __func__ << std::endl;
|
||||||
string json(R"({ "a": 1, "b": 2, "c": 3})");
|
string json(R"({ "a": 1, "b": 2, "c": 3})");
|
||||||
dom::parser parser;
|
dom::parser parser;
|
||||||
element doc = parser.parse(json);
|
auto obj = parser.parse(json);
|
||||||
if (uint64_t(doc["a"]) != 1) { cerr << "Expected uint64_t(doc[\"a\"]) to be 1, was " << uint64_t(doc["a"]) << endl; return false; }
|
|
||||||
|
ASSERT_EQUAL(uint64_t(obj["a"]), 1);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1278,7 +1243,9 @@ namespace dom_api_tests {
|
||||||
string json(R"({ "obj": { "a": 1, "b": 2, "c": 3 } })");
|
string json(R"({ "obj": { "a": 1, "b": 2, "c": 3 } })");
|
||||||
dom::parser parser;
|
dom::parser parser;
|
||||||
object obj = parser.parse(json)["obj"];
|
object obj = parser.parse(json)["obj"];
|
||||||
if (uint64_t(obj["a"]) != 1) { cerr << "Expected uint64_t(doc[\"a\"]) to be 1, was " << uint64_t(obj["a"]) << endl; return false; }
|
|
||||||
|
ASSERT_EQUAL( uint64_t(obj["a"]), 1);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1313,18 +1280,17 @@ namespace dom_api_tests {
|
||||||
// Print image names and sizes
|
// Print image names and sizes
|
||||||
set<pair<uint64_t, uint64_t>> image_sizes;
|
set<pair<uint64_t, uint64_t>> image_sizes;
|
||||||
dom::parser parser;
|
dom::parser parser;
|
||||||
element doc = parser.load(TWITTER_JSON);
|
for (object tweet : parser.load(TWITTER_JSON)["statuses"]) {
|
||||||
for (object tweet : doc["statuses"].get<dom::array>()) {
|
auto media = tweet["entities"]["media"];
|
||||||
auto [media, not_found] = tweet["entities"]["media"];
|
if (!media.error()) {
|
||||||
if (!not_found) {
|
for (object image : media) {
|
||||||
for (object image : media.get<dom::array>()) {
|
for (auto size : object(image["sizes"])) {
|
||||||
for (auto size : image["sizes"].get<dom::object>()) {
|
|
||||||
image_sizes.insert(make_pair(size.value["w"], size.value["h"]));
|
image_sizes.insert(make_pair(size.value["w"], size.value["h"]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (image_sizes.size() != 15) { cerr << "Expected twitter.json[statuses][entities][media][sizes] to contain 15 different sizes, got " << image_sizes.size() << endl; return false; }
|
ASSERT_EQUAL( image_sizes.size(), 15 );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1721,21 +1687,10 @@ namespace minify_tests {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
size_t newlength{};
|
size_t newlength{};
|
||||||
auto error = simdjson::minify(input, length, buffer.get(), newlength);
|
ASSERT_SUCCESS( simdjson::minify(input, length, buffer.get(), newlength) );
|
||||||
if(error != simdjson::SUCCESS) {
|
ASSERT_EQUAL( newlength, expected_length);
|
||||||
std::cerr << "error " << error << std::endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// memcmp
|
|
||||||
if(newlength != expected_length) {
|
|
||||||
std::cerr << "lengths do not match " << std::endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
for(size_t i = 0; i < newlength; i++) {
|
for(size_t i = 0; i < newlength; i++) {
|
||||||
if(buffer.get()[i] != expected[i]) {
|
ASSERT_EQUAL( buffer.get()[i], expected[i]);
|
||||||
std::cerr << "Inputs do not match (but same length) " << std::endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1785,8 +1740,8 @@ namespace format_tests {
|
||||||
bool print_parser_parse() {
|
bool print_parser_parse() {
|
||||||
std::cout << "Running " << __func__ << std::endl;
|
std::cout << "Running " << __func__ << std::endl;
|
||||||
dom::parser parser;
|
dom::parser parser;
|
||||||
auto [doc, error] = parser.parse(DOCUMENT);
|
dom::element doc;
|
||||||
if (error) { cerr << error << endl; return false; }
|
ASSERT_SUCCESS( parser.parse(DOCUMENT).get(doc) );
|
||||||
ostringstream s;
|
ostringstream s;
|
||||||
s << doc;
|
s << doc;
|
||||||
return assert_minified(s);
|
return assert_minified(s);
|
||||||
|
@ -1794,8 +1749,8 @@ namespace format_tests {
|
||||||
bool print_minify_parser_parse() {
|
bool print_minify_parser_parse() {
|
||||||
std::cout << "Running " << __func__ << std::endl;
|
std::cout << "Running " << __func__ << std::endl;
|
||||||
dom::parser parser;
|
dom::parser parser;
|
||||||
auto [doc, error] = parser.parse(DOCUMENT);
|
dom::element doc;
|
||||||
if (error) { cerr << error << endl; return false; }
|
ASSERT_SUCCESS( parser.parse(DOCUMENT).get(doc) );
|
||||||
ostringstream s;
|
ostringstream s;
|
||||||
s << minify(doc);
|
s << minify(doc);
|
||||||
return assert_minified(s);
|
return assert_minified(s);
|
||||||
|
@ -1804,8 +1759,8 @@ namespace format_tests {
|
||||||
bool print_element() {
|
bool print_element() {
|
||||||
std::cout << "Running " << __func__ << std::endl;
|
std::cout << "Running " << __func__ << std::endl;
|
||||||
dom::parser parser;
|
dom::parser parser;
|
||||||
auto [value, error] = parser.parse(DOCUMENT)["foo"];
|
dom::element value;
|
||||||
if (error) { cerr << error << endl; return false; }
|
ASSERT_SUCCESS( parser.parse(DOCUMENT)["foo"].get(value) );
|
||||||
ostringstream s;
|
ostringstream s;
|
||||||
s << value;
|
s << value;
|
||||||
return assert_minified(s, "1");
|
return assert_minified(s, "1");
|
||||||
|
@ -1813,8 +1768,8 @@ namespace format_tests {
|
||||||
bool print_minify_element() {
|
bool print_minify_element() {
|
||||||
std::cout << "Running " << __func__ << std::endl;
|
std::cout << "Running " << __func__ << std::endl;
|
||||||
dom::parser parser;
|
dom::parser parser;
|
||||||
auto [value, error] = parser.parse(DOCUMENT)["foo"];
|
dom::element value;
|
||||||
if (error) { cerr << error << endl; return false; }
|
ASSERT_SUCCESS( parser.parse(DOCUMENT)["foo"].get(value) );
|
||||||
ostringstream s;
|
ostringstream s;
|
||||||
s << minify(value);
|
s << minify(value);
|
||||||
return assert_minified(s, "1");
|
return assert_minified(s, "1");
|
||||||
|
@ -1823,38 +1778,38 @@ namespace format_tests {
|
||||||
bool print_array() {
|
bool print_array() {
|
||||||
std::cout << "Running " << __func__ << std::endl;
|
std::cout << "Running " << __func__ << std::endl;
|
||||||
dom::parser parser;
|
dom::parser parser;
|
||||||
auto [value, error] = parser.parse(DOCUMENT)["bar"].get<dom::array>();
|
dom::array array;
|
||||||
if (error) { cerr << error << endl; return false; }
|
ASSERT_SUCCESS( parser.parse(DOCUMENT)["bar"].get(array) );
|
||||||
ostringstream s;
|
ostringstream s;
|
||||||
s << value;
|
s << array;
|
||||||
return assert_minified(s, "[1,2,3]");
|
return assert_minified(s, "[1,2,3]");
|
||||||
}
|
}
|
||||||
bool print_minify_array() {
|
bool print_minify_array() {
|
||||||
std::cout << "Running " << __func__ << std::endl;
|
std::cout << "Running " << __func__ << std::endl;
|
||||||
dom::parser parser;
|
dom::parser parser;
|
||||||
auto [value, error] = parser.parse(DOCUMENT)["bar"].get<dom::array>();
|
dom::array array;
|
||||||
if (error) { cerr << error << endl; return false; }
|
ASSERT_SUCCESS( parser.parse(DOCUMENT)["bar"].get(array) );
|
||||||
ostringstream s;
|
ostringstream s;
|
||||||
s << minify(value);
|
s << minify(array);
|
||||||
return assert_minified(s, "[1,2,3]");
|
return assert_minified(s, "[1,2,3]");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool print_object() {
|
bool print_object() {
|
||||||
std::cout << "Running " << __func__ << std::endl;
|
std::cout << "Running " << __func__ << std::endl;
|
||||||
dom::parser parser;
|
dom::parser parser;
|
||||||
auto [value, error] = parser.parse(DOCUMENT)["baz"].get<dom::object>();
|
dom::object object;
|
||||||
if (error) { cerr << error << endl; return false; }
|
ASSERT_SUCCESS( parser.parse(DOCUMENT)["baz"].get(object) );
|
||||||
ostringstream s;
|
ostringstream s;
|
||||||
s << value;
|
s << object;
|
||||||
return assert_minified(s, R"({"a":1,"b":2,"c":3})");
|
return assert_minified(s, R"({"a":1,"b":2,"c":3})");
|
||||||
}
|
}
|
||||||
bool print_minify_object() {
|
bool print_minify_object() {
|
||||||
std::cout << "Running " << __func__ << std::endl;
|
std::cout << "Running " << __func__ << std::endl;
|
||||||
dom::parser parser;
|
dom::parser parser;
|
||||||
auto [value, error] = parser.parse(DOCUMENT)["baz"].get<dom::object>();
|
dom::object object;
|
||||||
if (error) { cerr << error << endl; return false; }
|
ASSERT_SUCCESS( parser.parse(DOCUMENT)["baz"].get(object) );
|
||||||
ostringstream s;
|
ostringstream s;
|
||||||
s << minify(value);
|
s << minify(object);
|
||||||
return assert_minified(s, R"({"a":1,"b":2,"c":3})");
|
return assert_minified(s, R"({"a":1,"b":2,"c":3})");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1878,25 +1833,22 @@ namespace format_tests {
|
||||||
bool print_element_result_exception() {
|
bool print_element_result_exception() {
|
||||||
std::cout << "Running " << __func__ << std::endl;
|
std::cout << "Running " << __func__ << std::endl;
|
||||||
dom::parser parser;
|
dom::parser parser;
|
||||||
element doc = parser.parse(DOCUMENT);
|
|
||||||
ostringstream s;
|
ostringstream s;
|
||||||
s << doc["foo"];
|
s << parser.parse(DOCUMENT)["foo"];
|
||||||
return assert_minified(s, "1");
|
return assert_minified(s, "1");
|
||||||
}
|
}
|
||||||
bool print_minify_element_result_exception() {
|
bool print_minify_element_result_exception() {
|
||||||
std::cout << "Running " << __func__ << std::endl;
|
std::cout << "Running " << __func__ << std::endl;
|
||||||
dom::parser parser;
|
dom::parser parser;
|
||||||
element doc = parser.parse(DOCUMENT);
|
|
||||||
ostringstream s;
|
ostringstream s;
|
||||||
s << minify(doc["foo"]);
|
s << minify(parser.parse(DOCUMENT)["foo"]);
|
||||||
return assert_minified(s, "1");
|
return assert_minified(s, "1");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool print_element_exception() {
|
bool print_element_exception() {
|
||||||
std::cout << "Running " << __func__ << std::endl;
|
std::cout << "Running " << __func__ << std::endl;
|
||||||
dom::parser parser;
|
dom::parser parser;
|
||||||
element doc = parser.parse(DOCUMENT);
|
element value = parser.parse(DOCUMENT)["foo"];
|
||||||
element value = doc["foo"];
|
|
||||||
ostringstream s;
|
ostringstream s;
|
||||||
s << value;
|
s << value;
|
||||||
return assert_minified(s, "1");
|
return assert_minified(s, "1");
|
||||||
|
@ -1904,8 +1856,7 @@ namespace format_tests {
|
||||||
bool print_minify_element_exception() {
|
bool print_minify_element_exception() {
|
||||||
std::cout << "Running " << __func__ << std::endl;
|
std::cout << "Running " << __func__ << std::endl;
|
||||||
dom::parser parser;
|
dom::parser parser;
|
||||||
element doc = parser.parse(DOCUMENT);
|
element value = parser.parse(DOCUMENT)["foo"];
|
||||||
element value = doc["foo"];
|
|
||||||
ostringstream s;
|
ostringstream s;
|
||||||
s << minify(value);
|
s << minify(value);
|
||||||
return assert_minified(s, "1");
|
return assert_minified(s, "1");
|
||||||
|
@ -1914,66 +1865,64 @@ namespace format_tests {
|
||||||
bool print_array_result_exception() {
|
bool print_array_result_exception() {
|
||||||
std::cout << "Running " << __func__ << std::endl;
|
std::cout << "Running " << __func__ << std::endl;
|
||||||
dom::parser parser;
|
dom::parser parser;
|
||||||
element doc = parser.parse(DOCUMENT);
|
|
||||||
ostringstream s;
|
ostringstream s;
|
||||||
s << doc["bar"].get<dom::array>();
|
s << parser.parse(DOCUMENT)["bar"].get<dom::array>();
|
||||||
return assert_minified(s, "[1,2,3]");
|
return assert_minified(s, "[1,2,3]");
|
||||||
}
|
}
|
||||||
bool print_minify_array_result_exception() {
|
bool print_minify_array_result_exception() {
|
||||||
std::cout << "Running " << __func__ << std::endl;
|
std::cout << "Running " << __func__ << std::endl;
|
||||||
dom::parser parser;
|
dom::parser parser;
|
||||||
element doc = parser.parse(DOCUMENT);
|
|
||||||
ostringstream s;
|
ostringstream s;
|
||||||
s << minify(doc["bar"].get<dom::array>());
|
s << minify(parser.parse(DOCUMENT)["bar"].get<dom::array>());
|
||||||
return assert_minified(s, "[1,2,3]");
|
return assert_minified(s, "[1,2,3]");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool print_object_result_exception() {
|
bool print_object_result_exception() {
|
||||||
std::cout << "Running " << __func__ << std::endl;
|
std::cout << "Running " << __func__ << std::endl;
|
||||||
dom::parser parser;
|
dom::parser parser;
|
||||||
element doc = parser.parse(DOCUMENT);
|
|
||||||
ostringstream s;
|
ostringstream s;
|
||||||
s << doc["baz"].get<dom::object>();
|
s << parser.parse(DOCUMENT)["baz"].get<dom::object>();
|
||||||
return assert_minified(s, R"({"a":1,"b":2,"c":3})");
|
return assert_minified(s, R"({"a":1,"b":2,"c":3})");
|
||||||
}
|
}
|
||||||
bool print_minify_object_result_exception() {
|
bool print_minify_object_result_exception() {
|
||||||
std::cout << "Running " << __func__ << std::endl;
|
std::cout << "Running " << __func__ << std::endl;
|
||||||
dom::parser parser;
|
dom::parser parser;
|
||||||
element doc = parser.parse(DOCUMENT);
|
|
||||||
ostringstream s;
|
ostringstream s;
|
||||||
s << minify(doc["baz"].get<dom::object>());
|
s << minify(parser.parse(DOCUMENT)["baz"].get<dom::object>());
|
||||||
return assert_minified(s, R"({"a":1,"b":2,"c":3})");
|
return assert_minified(s, R"({"a":1,"b":2,"c":3})");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool print_array_exception() {
|
bool print_array_exception() {
|
||||||
std::cout << "Running " << __func__ << std::endl;
|
std::cout << "Running " << __func__ << std::endl;
|
||||||
dom::parser parser;
|
dom::parser parser;
|
||||||
|
dom::array array = parser.parse(DOCUMENT)["bar"];
|
||||||
ostringstream s;
|
ostringstream s;
|
||||||
s << parser.parse(DOCUMENT)["bar"];
|
s << array;
|
||||||
return assert_minified(s, "[1,2,3]");
|
return assert_minified(s, "[1,2,3]");
|
||||||
}
|
}
|
||||||
bool print_minify_array_exception() {
|
bool print_minify_array_exception() {
|
||||||
std::cout << "Running " << __func__ << std::endl;
|
std::cout << "Running " << __func__ << std::endl;
|
||||||
dom::parser parser;
|
dom::parser parser;
|
||||||
|
dom::array array = parser.parse(DOCUMENT)["bar"];
|
||||||
ostringstream s;
|
ostringstream s;
|
||||||
s << minify(parser.parse(DOCUMENT)["bar"]);
|
s << minify(array);
|
||||||
return assert_minified(s, "[1,2,3]");
|
return assert_minified(s, "[1,2,3]");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool print_object_exception() {
|
bool print_object_exception() {
|
||||||
std::cout << "Running " << __func__ << std::endl;
|
std::cout << "Running " << __func__ << std::endl;
|
||||||
dom::parser parser;
|
dom::parser parser;
|
||||||
|
dom::object object = parser.parse(DOCUMENT)["baz"];
|
||||||
ostringstream s;
|
ostringstream s;
|
||||||
s << parser.parse(DOCUMENT)["baz"];
|
s << object;
|
||||||
return assert_minified(s, R"({"a":1,"b":2,"c":3})");
|
return assert_minified(s, R"({"a":1,"b":2,"c":3})");
|
||||||
}
|
}
|
||||||
bool print_minify_object_exception() {
|
bool print_minify_object_exception() {
|
||||||
std::cout << "Running " << __func__ << std::endl;
|
std::cout << "Running " << __func__ << std::endl;
|
||||||
dom::parser parser;
|
dom::parser parser;
|
||||||
element doc = parser.parse(DOCUMENT);
|
dom::object object = parser.parse(DOCUMENT)["baz"];
|
||||||
object value = doc["baz"];
|
|
||||||
ostringstream s;
|
ostringstream s;
|
||||||
s << minify(value);
|
s << minify(object);
|
||||||
return assert_minified(s, R"({"a":1,"b":2,"c":3})");
|
return assert_minified(s, R"({"a":1,"b":2,"c":3})");
|
||||||
}
|
}
|
||||||
#endif // SIMDJSON_EXCEPTIONS
|
#endif // SIMDJSON_EXCEPTIONS
|
||||||
|
|
|
@ -46,15 +46,16 @@ namespace parser_load {
|
||||||
ASSERT_SUCCESS(parser.parse_many(DOC).get(docs));
|
ASSERT_SUCCESS(parser.parse_many(DOC).get(docs));
|
||||||
for (auto doc : docs) {
|
for (auto doc : docs) {
|
||||||
count++;
|
count++;
|
||||||
auto [val, error] = doc.get<uint64_t>();
|
uint64_t val;
|
||||||
|
auto error = doc.get(val);
|
||||||
if (count == 3) {
|
if (count == 3) {
|
||||||
ASSERT_ERROR(error, TAPE_ERROR);
|
ASSERT_ERROR(error, TAPE_ERROR);
|
||||||
} else {
|
} else {
|
||||||
if (error) { TEST_FAIL(error); }
|
ASSERT_SUCCESS(error);
|
||||||
if (val != count) { cerr << "FAIL: expected " << count << ", got " << val << endl; return false; }
|
ASSERT_EQUAL(val, count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (count != 3) { cerr << "FAIL: expected 2 documents and 1 error, got " << count << " total things" << endl; return false; }
|
ASSERT_EQUAL(count, 3);
|
||||||
TEST_SUCCEED();
|
TEST_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,7 +70,7 @@ namespace parser_load {
|
||||||
count++;
|
count++;
|
||||||
ASSERT_ERROR(doc.error(), TAPE_ERROR);
|
ASSERT_ERROR(doc.error(), TAPE_ERROR);
|
||||||
}
|
}
|
||||||
if (count != 1) { cerr << "FAIL: expected no documents and 1 error, got " << count << " total things" << endl; return false; }
|
ASSERT_EQUAL(count, 1);
|
||||||
TEST_SUCCEED();
|
TEST_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,36 +83,34 @@ namespace parser_load {
|
||||||
ASSERT_SUCCESS(parser.parse_many(DOC).get(docs));
|
ASSERT_SUCCESS(parser.parse_many(DOC).get(docs));
|
||||||
for (auto doc : docs) {
|
for (auto doc : docs) {
|
||||||
count++;
|
count++;
|
||||||
auto [val, error] = doc.get<uint64_t>();
|
uint64_t val;
|
||||||
|
auto error = doc.get(val);
|
||||||
if (count == 3) {
|
if (count == 3) {
|
||||||
ASSERT_ERROR(error, TAPE_ERROR);
|
ASSERT_ERROR(error, TAPE_ERROR);
|
||||||
} else {
|
} else {
|
||||||
if (error) { TEST_FAIL(error); }
|
ASSERT_SUCCESS(error);
|
||||||
if (val != count) { cerr << "FAIL: expected " << count << ", got " << val << endl; return false; }
|
ASSERT_EQUAL(val, count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (count != 3) { cerr << "FAIL: expected 2 documents and 1 error, got " << count << " total things" << endl; return false; }
|
ASSERT_EQUAL(count, 3);
|
||||||
TEST_SUCCEED();
|
TEST_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool parser_load_nonexistent() {
|
bool parser_load_nonexistent() {
|
||||||
TEST_START();
|
TEST_START();
|
||||||
dom::parser parser;
|
dom::parser parser;
|
||||||
auto error = parser.load(NONEXISTENT_FILE).error();
|
ASSERT_ERROR( parser.load(NONEXISTENT_FILE).error(), IO_ERROR );
|
||||||
ASSERT_ERROR(error, IO_ERROR);
|
|
||||||
TEST_SUCCEED();
|
TEST_SUCCEED();
|
||||||
}
|
}
|
||||||
bool parser_load_many_nonexistent() {
|
bool parser_load_many_nonexistent() {
|
||||||
TEST_START();
|
TEST_START();
|
||||||
dom::parser parser;
|
dom::parser parser;
|
||||||
dom::document_stream stream;
|
ASSERT_ERROR( parser.load_many(NONEXISTENT_FILE).error(), IO_ERROR );
|
||||||
ASSERT_ERROR(parser.load_many(NONEXISTENT_FILE).get(stream), IO_ERROR);
|
|
||||||
TEST_SUCCEED();
|
TEST_SUCCEED();
|
||||||
}
|
}
|
||||||
bool padded_string_load_nonexistent() {
|
bool padded_string_load_nonexistent() {
|
||||||
TEST_START();
|
TEST_START();
|
||||||
auto error = padded_string::load(NONEXISTENT_FILE).error();
|
ASSERT_ERROR(padded_string::load(NONEXISTENT_FILE).error(), IO_ERROR);
|
||||||
ASSERT_ERROR(error, IO_ERROR);
|
|
||||||
TEST_SUCCEED();
|
TEST_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,16 +118,17 @@ namespace parser_load {
|
||||||
TEST_START();
|
TEST_START();
|
||||||
dom::parser parser;
|
dom::parser parser;
|
||||||
UNUSED uint64_t foo;
|
UNUSED uint64_t foo;
|
||||||
ASSERT_ERROR( parser.load(NONEXISTENT_FILE)["foo"].get(foo) , IO_ERROR);
|
ASSERT_ERROR( parser.load(NONEXISTENT_FILE)["foo"].get(foo), IO_ERROR);
|
||||||
TEST_SUCCEED();
|
TEST_SUCCEED();
|
||||||
}
|
}
|
||||||
bool parser_load_many_chain() {
|
bool parser_load_many_chain() {
|
||||||
TEST_START();
|
TEST_START();
|
||||||
dom::parser parser;
|
dom::parser parser;
|
||||||
dom::document_stream stream;
|
UNUSED dom::document_stream stream;
|
||||||
ASSERT_ERROR( parser.load_many(NONEXISTENT_FILE).get(stream) , IO_ERROR );
|
ASSERT_ERROR( parser.load_many(NONEXISTENT_FILE).get(stream), IO_ERROR );
|
||||||
TEST_SUCCEED();
|
TEST_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool run() {
|
bool run() {
|
||||||
return true
|
return true
|
||||||
&& parser_load_capacity()
|
&& parser_load_capacity()
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
#include "simdjson.h"
|
#include "simdjson.h"
|
||||||
|
#include "test_macros.h"
|
||||||
|
|
||||||
// we define our own asserts to get around NDEBUG
|
// we define our own asserts to get around NDEBUG
|
||||||
#ifndef ASSERT
|
#ifndef ASSERT
|
||||||
|
@ -29,44 +30,43 @@ template <typename T> static const std::string make_json(T value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static void parse_and_validate(const std::string src, T expected) {
|
static bool parse_and_validate(const std::string src, T expected) {
|
||||||
std::cout << "src: " << src << ", ";
|
std::cout << "src: " << src << ", ";
|
||||||
const padded_string pstr{src};
|
const padded_string pstr{src};
|
||||||
simdjson::dom::parser parser;
|
simdjson::dom::parser parser;
|
||||||
|
|
||||||
bool result;
|
|
||||||
if constexpr (std::is_same<int64_t, T>::value) {
|
if constexpr (std::is_same<int64_t, T>::value) {
|
||||||
auto [actual, error] = parser.parse(pstr).get<dom::object>()["key"].get<int64_t>();
|
int64_t actual;
|
||||||
if (error) { std::cerr << error << std::endl; abort(); }
|
ASSERT_SUCCESS( parser.parse(pstr)["key"].get(actual) );
|
||||||
result = (expected == actual);
|
std::cout << std::boolalpha << "test: " << (expected == actual) << std::endl;
|
||||||
|
ASSERT_EQUAL( expected, actual );
|
||||||
} else {
|
} else {
|
||||||
auto [actual, error] = parser.parse(pstr).get<dom::object>()["key"].get<uint64_t>();
|
uint64_t actual;
|
||||||
if (error) { std::cerr << error << std::endl; abort(); }
|
ASSERT_SUCCESS( parser.parse(pstr)["key"].get(actual) );
|
||||||
result = (expected == actual);
|
std::cout << std::boolalpha << "test: " << (expected == actual) << std::endl;
|
||||||
}
|
ASSERT_EQUAL( expected, actual );
|
||||||
std::cout << std::boolalpha << "test: " << result << std::endl;
|
|
||||||
if(!result) {
|
|
||||||
std::cerr << "bug detected" << std::endl;
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool parse_and_check_signed(const std::string src) {
|
static bool parse_and_check_signed(const std::string src) {
|
||||||
std::cout << "src: " << src << ", expecting signed" << std::endl;
|
std::cout << "src: " << src << ", expecting signed" << std::endl;
|
||||||
const padded_string pstr{src};
|
const padded_string pstr{src};
|
||||||
simdjson::dom::parser parser;
|
simdjson::dom::parser parser;
|
||||||
auto [value, error] = parser.parse(pstr).get<dom::object>()["key"];
|
simdjson::dom::element value;
|
||||||
if (error) { std::cerr << error << std::endl; abort(); }
|
ASSERT_SUCCESS( parser.parse(pstr).get<dom::object>()["key"].get(value) );
|
||||||
return value.is<int64_t>();
|
ASSERT_EQUAL( value.is<int64_t>(), true );
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool parse_and_check_unsigned(const std::string src) {
|
static bool parse_and_check_unsigned(const std::string src) {
|
||||||
std::cout << "src: " << src << ", expecting signed" << std::endl;
|
std::cout << "src: " << src << ", expecting signed" << std::endl;
|
||||||
const padded_string pstr{src};
|
const padded_string pstr{src};
|
||||||
simdjson::dom::parser parser;
|
simdjson::dom::parser parser;
|
||||||
auto [value, error] = parser.parse(pstr).get<dom::object>()["key"];
|
simdjson::dom::element value;
|
||||||
if (error) { std::cerr << error << std::endl; abort(); }
|
ASSERT_SUCCESS( parser.parse(pstr).get<dom::object>()["key"].get(value) );
|
||||||
return value.is<uint64_t>();
|
ASSERT_EQUAL( value.is<uint64_t>(), true );
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
|
@ -75,21 +75,21 @@ int main() {
|
||||||
constexpr auto int64_min = numeric_limits<int64_t>::lowest();
|
constexpr auto int64_min = numeric_limits<int64_t>::lowest();
|
||||||
constexpr auto uint64_max = numeric_limits<uint64_t>::max();
|
constexpr auto uint64_max = numeric_limits<uint64_t>::max();
|
||||||
constexpr auto uint64_min = numeric_limits<uint64_t>::lowest();
|
constexpr auto uint64_min = numeric_limits<uint64_t>::lowest();
|
||||||
parse_and_validate(make_json(int64_max), int64_max);
|
|
||||||
parse_and_validate(make_json(int64_min), int64_min);
|
|
||||||
parse_and_validate(make_json(uint64_max), uint64_max);
|
|
||||||
parse_and_validate(make_json(uint64_min), uint64_min);
|
|
||||||
constexpr auto int64_max_plus1 = static_cast<uint64_t>(int64_max) + 1;
|
constexpr auto int64_max_plus1 = static_cast<uint64_t>(int64_max) + 1;
|
||||||
parse_and_validate(make_json(int64_max_plus1), int64_max_plus1);
|
if (true
|
||||||
if(!parse_and_check_signed(make_json(int64_max))) {
|
&& parse_and_validate(make_json(int64_max), int64_max)
|
||||||
std::cerr << "bug: large signed integers should be represented as signed integers" << std::endl;
|
&& parse_and_validate(make_json(uint64_max), uint64_max)
|
||||||
return EXIT_FAILURE;
|
&& parse_and_validate(make_json(uint64_min), uint64_min)
|
||||||
|
&& parse_and_validate(make_json(int64_min), int64_min)
|
||||||
|
&& parse_and_validate(make_json(uint64_max), uint64_max)
|
||||||
|
&& parse_and_validate(make_json(uint64_min), uint64_min)
|
||||||
|
&& parse_and_validate(make_json(int64_max_plus1), int64_max_plus1)
|
||||||
|
&& parse_and_check_signed(make_json(int64_max))
|
||||||
|
&& parse_and_check_unsigned(make_json(uint64_max))
|
||||||
|
) {
|
||||||
|
std::cout << "All ok." << std::endl;
|
||||||
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
if(!parse_and_check_unsigned(make_json(uint64_max))) {
|
return EXIT_FAILURE;
|
||||||
std::cerr << "bug: a large unsigned integers is not represented as an unsigned integer" << std::endl;
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
std::cout << "All ok." << std::endl;
|
|
||||||
return EXIT_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include "simdjson.h"
|
#include "simdjson.h"
|
||||||
|
#include "test_macros.h"
|
||||||
|
|
||||||
// we define our own asserts to get around NDEBUG
|
// we define our own asserts to get around NDEBUG
|
||||||
#ifndef ASSERT
|
#ifndef ASSERT
|
||||||
|
@ -35,49 +36,46 @@ const padded_string TEST_JSON = R"(
|
||||||
bool json_pointer_success_test(const char *json_pointer, std::string_view expected_value) {
|
bool json_pointer_success_test(const char *json_pointer, std::string_view expected_value) {
|
||||||
std::cout << "Running successful JSON pointer test '" << json_pointer << "' ..." << std::endl;
|
std::cout << "Running successful JSON pointer test '" << json_pointer << "' ..." << std::endl;
|
||||||
dom::parser parser;
|
dom::parser parser;
|
||||||
auto [value, error] = parser.parse(TEST_JSON).at(json_pointer).get<std::string_view>();
|
std::string_view value;
|
||||||
if (error) { std::cerr << "Unexpected Error: " << error << std::endl; return false; }
|
ASSERT_SUCCESS( parser.parse(TEST_JSON).at(json_pointer).get(value) );
|
||||||
ASSERT(value == expected_value);
|
ASSERT_EQUAL(value, expected_value);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool json_pointer_success_test(const char *json_pointer) {
|
bool json_pointer_success_test(const char *json_pointer) {
|
||||||
std::cout << "Running successful JSON pointer test '" << json_pointer << "' ..." << std::endl;
|
std::cout << "Running successful JSON pointer test '" << json_pointer << "' ..." << std::endl;
|
||||||
dom::parser parser;
|
dom::parser parser;
|
||||||
auto error = parser.parse(TEST_JSON).at(json_pointer).error();
|
ASSERT_SUCCESS( parser.parse(TEST_JSON).at(json_pointer).error() );
|
||||||
if (error) { std::cerr << "Unexpected Error: " << error << std::endl; return false; }
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool json_pointer_failure_test(const char *json_pointer, error_code expected_failure_test) {
|
bool json_pointer_failure_test(const char *json_pointer, error_code expected_error) {
|
||||||
std::cout << "Running invalid JSON pointer test '" << json_pointer << "' ..." << std::endl;
|
std::cout << "Running invalid JSON pointer test '" << json_pointer << "' ..." << std::endl;
|
||||||
dom::parser parser;
|
dom::parser parser;
|
||||||
auto error = parser.parse(TEST_JSON).at(json_pointer).error();
|
ASSERT_ERROR(parser.parse(TEST_JSON).at(json_pointer).error(), expected_error);
|
||||||
ASSERT(error == expected_failure_test);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
if (
|
if (true
|
||||||
json_pointer_success_test("") &&
|
&& json_pointer_success_test("")
|
||||||
json_pointer_success_test("~1~001abc") &&
|
&& json_pointer_success_test("~1~001abc")
|
||||||
json_pointer_success_test("~1~001abc/1") &&
|
&& json_pointer_success_test("~1~001abc/1")
|
||||||
json_pointer_success_test("~1~001abc/1/\\\" 0") &&
|
&& json_pointer_success_test("~1~001abc/1/\\\" 0")
|
||||||
json_pointer_success_test("~1~001abc/1/\\\" 0/0", "value0") &&
|
&& json_pointer_success_test("~1~001abc/1/\\\" 0/0", "value0")
|
||||||
json_pointer_success_test("~1~001abc/1/\\\" 0/1", "value1") &&
|
&& json_pointer_success_test("~1~001abc/1/\\\" 0/1", "value1")
|
||||||
json_pointer_failure_test("~1~001abc/1/\\\" 0/2", INDEX_OUT_OF_BOUNDS) && // index actually out of bounds
|
&& json_pointer_failure_test("~1~001abc/1/\\\" 0/2", INDEX_OUT_OF_BOUNDS) // index actually out of bounds
|
||||||
json_pointer_success_test("arr") && // get array
|
&& json_pointer_success_test("arr") // get array
|
||||||
json_pointer_failure_test("arr/0", INDEX_OUT_OF_BOUNDS) && // array index 0 out of bounds on empty array
|
&& json_pointer_failure_test("arr/0", INDEX_OUT_OF_BOUNDS) // array index 0 out of bounds on empty array
|
||||||
json_pointer_success_test("~1~001abc") && // get object
|
&& json_pointer_success_test("~1~001abc") // get object
|
||||||
json_pointer_success_test("0", "0 ok") && // object index with integer-ish key
|
&& json_pointer_success_test("0", "0 ok") // object index with integer-ish key
|
||||||
json_pointer_success_test("01", "01 ok") && // object index with key that would be an invalid integer
|
&& json_pointer_success_test("01", "01 ok") // object index with key that would be an invalid integer
|
||||||
json_pointer_success_test("", "empty ok") && // object index with empty key
|
&& json_pointer_success_test("", "empty ok") // object index with empty key
|
||||||
json_pointer_failure_test("~01abc", NO_SUCH_FIELD) && // Test that we don't try to compare the literal key
|
&& json_pointer_failure_test("~01abc", NO_SUCH_FIELD) // Test that we don't try to compare the literal key
|
||||||
json_pointer_failure_test("~1~001abc/01", INVALID_JSON_POINTER) && // Leading 0 in integer index
|
&& json_pointer_failure_test("~1~001abc/01", INVALID_JSON_POINTER) // Leading 0 in integer index
|
||||||
json_pointer_failure_test("~1~001abc/", INVALID_JSON_POINTER) && // Empty index to array
|
&& json_pointer_failure_test("~1~001abc/", INVALID_JSON_POINTER) // Empty index to array
|
||||||
json_pointer_failure_test("~1~001abc/-", INDEX_OUT_OF_BOUNDS) && // End index is always out of bounds
|
&& json_pointer_failure_test("~1~001abc/-", INDEX_OUT_OF_BOUNDS) // End index is always out of bounds
|
||||||
true
|
|
||||||
) {
|
) {
|
||||||
std::cout << "Success!" << std::endl;
|
std::cout << "Success!" << std::endl;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -88,7 +88,7 @@ void basics_dom_4() {
|
||||||
auto abstract_json = R"(
|
auto abstract_json = R"(
|
||||||
{ "str" : { "123" : {"abc" : 3.14 } } } )"_padded;
|
{ "str" : { "123" : {"abc" : 3.14 } } } )"_padded;
|
||||||
dom::parser parser;
|
dom::parser parser;
|
||||||
double v = parser.parse(abstract_json)["str"]["123"]["abc"].get<double>();
|
double v = parser.parse(abstract_json)["str"]["123"]["abc"];
|
||||||
cout << "number: " << v << endl;
|
cout << "number: " << v << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,9 +141,10 @@ namespace treewalk_1 {
|
||||||
|
|
||||||
#ifdef SIMDJSON_CPLUSPLUS17
|
#ifdef SIMDJSON_CPLUSPLUS17
|
||||||
void basics_cpp17_1() {
|
void basics_cpp17_1() {
|
||||||
dom::parser parser;
|
|
||||||
padded_string json = R"( { "foo": 1, "bar": 2 } )"_padded;
|
padded_string json = R"( { "foo": 1, "bar": 2 } )"_padded;
|
||||||
auto [object, error] = parser.parse(json).get<dom::object>();
|
dom::parser parser;
|
||||||
|
dom::object object;
|
||||||
|
auto error = parser.parse(json).get(object);
|
||||||
if (error) { cerr << error << endl; return; }
|
if (error) { cerr << error << endl; return; }
|
||||||
for (auto [key, value] : object) {
|
for (auto [key, value] : object) {
|
||||||
cout << key << " = " << value << endl;
|
cout << key << " = " << value << endl;
|
||||||
|
@ -153,11 +154,10 @@ void basics_cpp17_1() {
|
||||||
|
|
||||||
void basics_cpp17_2() {
|
void basics_cpp17_2() {
|
||||||
// C++ 11 version for comparison
|
// C++ 11 version for comparison
|
||||||
dom::parser parser;
|
|
||||||
padded_string json = R"( { "foo": 1, "bar": 2 } )"_padded;
|
padded_string json = R"( { "foo": 1, "bar": 2 } )"_padded;
|
||||||
simdjson::error_code error;
|
dom::parser parser;
|
||||||
dom::object object;
|
dom::object object;
|
||||||
error = parser.parse(json).get(object);
|
auto error = parser.parse(json).get(object);
|
||||||
if (!error) { cerr << error << endl; return; }
|
if (!error) { cerr << error << endl; return; }
|
||||||
for (dom::key_value_pair field : object) {
|
for (dom::key_value_pair field : object) {
|
||||||
cout << field.key << " = " << field.value << endl;
|
cout << field.key << " = " << field.value << endl;
|
||||||
|
|
|
@ -18,17 +18,25 @@ const char *SMALLDEMO_JSON = SIMDJSON_BENCHMARK_SMALLDATA_DIR "smalldemo.json";
|
||||||
const char *TRUENULL_JSON = SIMDJSON_BENCHMARK_SMALLDATA_DIR "truenull.json";
|
const char *TRUENULL_JSON = SIMDJSON_BENCHMARK_SMALLDATA_DIR "truenull.json";
|
||||||
|
|
||||||
// For the ASSERT_EQUAL macro
|
// For the ASSERT_EQUAL macro
|
||||||
template<typename T>
|
template<typename T, typename S>
|
||||||
bool equals_expected(T actual, T expected) {
|
bool equals_expected(T actual, S expected) {
|
||||||
return actual == expected;
|
return actual == T(expected);
|
||||||
}
|
}
|
||||||
template<>
|
template<>
|
||||||
bool equals_expected<const char *>(const char *actual, const char *expected) {
|
bool equals_expected<const char *, const char *>(const char *actual, const char *expected) {
|
||||||
return !strcmp(actual, expected);
|
return !strcmp(actual, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define TEST_START() { cout << "Running " << __func__ << " ..." << endl; }
|
#define TEST_START() { cout << "Running " << __func__ << " ..." << endl; }
|
||||||
#define ASSERT_EQUAL(ACTUAL, EXPECTED) do { auto _actual = (ACTUAL); auto _expected = (EXPECTED); if (!equals_expected(_actual, _expected)) { std::cerr << "Expected " << #ACTUAL << " to be " << _expected << ", got " << _actual << " instead!" << std::endl; return false; } } while(0);
|
#define ASSERT_EQUAL(ACTUAL, EXPECTED) \
|
||||||
|
do { \
|
||||||
|
auto _actual = (ACTUAL); \
|
||||||
|
auto _expected = (EXPECTED); \
|
||||||
|
if (!equals_expected(_actual, _expected)) { \
|
||||||
|
std::cerr << "Expected " << (#ACTUAL) << " to be " << _expected << ", got " << _actual << " instead!" << std::endl; \
|
||||||
|
return false; \
|
||||||
|
} \
|
||||||
|
} while(0);
|
||||||
#define ASSERT_ERROR(ACTUAL, EXPECTED) do { auto _actual = (ACTUAL); auto _expected = (EXPECTED); if (_actual != _expected) { std::cerr << "FAIL: Unexpected error \"" << _actual << "\" (expected \"" << _expected << "\")" << std::endl; return false; } } while (0);
|
#define ASSERT_ERROR(ACTUAL, EXPECTED) do { auto _actual = (ACTUAL); auto _expected = (EXPECTED); if (_actual != _expected) { std::cerr << "FAIL: Unexpected error \"" << _actual << "\" (expected \"" << _expected << "\")" << std::endl; return false; } } while (0);
|
||||||
#define ASSERT(RESULT, MESSAGE) if (!(RESULT)) { std::cerr << MESSAGE << std::endl; return false; }
|
#define ASSERT(RESULT, MESSAGE) if (!(RESULT)) { std::cerr << MESSAGE << std::endl; return false; }
|
||||||
#define RUN_TEST(RESULT) if (!RESULT) { return false; }
|
#define RUN_TEST(RESULT) if (!RESULT) { return false; }
|
||||||
|
|
Loading…
Reference in New Issue