Hide the std::pair inheritance in our result instances (#1396)

* Fixing issue 1243

* The tie must go.

* Having std::pair be a protected inheritance breaks on demand.

* Putting it back.

* You really want to use emplace.

* Fixing one botched test.

* Prettier test.

* Using safer code.

* Fixing unsafe code.

* Simplifying the fuzzer.

* Trying another way.

* Ok. It should work without exceptions.

* Removing trailing spaces.
This commit is contained in:
Daniel Lemire 2021-01-18 12:00:02 -05:00 committed by GitHub
parent 73063e2dab
commit 2a714f4e37
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 211 additions and 137 deletions

View File

@ -503,7 +503,7 @@ static void twitter_default_profile(State& state) {
for (dom::object tweet : doc["statuses"]) {
dom::object user = tweet["user"];
if (user["default_profile"]) {
default_users.insert(user["screen_name"]);
default_users.emplace(user["screen_name"]);
}
}
if (default_users.size() != 86) { return; }
@ -523,7 +523,7 @@ static void twitter_image_sizes(State& state) {
if (not (error = tweet["entities"]["media"].get(media))) {
for (dom::object image : media) {
for (auto size : image["sizes"].get<dom::object>()) {
image_sizes.insert({ size.value["w"], size.value["h"] });
image_sizes.emplace(size.value["w"], size.value["h"]);
}
}
}
@ -607,7 +607,7 @@ static void iterator_twitter_default_profile(State& state) {
// default_users.insert(user["screen_name"]);
if (!(iter.move_to_key("screen_name") && iter.is_string())) { return; }
default_users.insert(string_view(iter.get_string(), iter.get_string_length()));
default_users.emplace(iter.get_string(), iter.get_string_length());
}
if (!iter.up()) { return; } // back to user
}
@ -645,7 +645,7 @@ static void error_code_twitter_image_sizes(State& state) noexcept {
uint64_t width, height;
if ((error = size.value["w"].get(width))) { return; }
if ((error = size.value["h"].get(height))) { return; }
image_sizes.insert({ width, height });
image_sizes.emplace(width, height);
}
}
}
@ -699,7 +699,7 @@ static void iterator_twitter_image_sizes(State& state) {
if (!(iter.move_to_key("h")) && !iter.is_integer()) { return; }
uint64_t height = iter.get_integer();
if (!iter.up()) { return; } // back to size
image_sizes.insert({ width, height });
image_sizes.emplace(width, height);
} while (iter.next()); // next size
if (!iter.up()) { return; } // back to sizes

View File

@ -9,7 +9,7 @@ simdjson_never_inline
double bench(std::string filename, simdjson::padded_string& p) {
std::chrono::time_point<std::chrono::steady_clock> start_clock =
std::chrono::steady_clock::now();
simdjson::padded_string::load(filename).first.swap(p);
simdjson::padded_string::load(filename).value_unsafe().swap(p);
std::chrono::time_point<std::chrono::steady_clock> end_clock =
std::chrono::steady_clock::now();
std::chrono::duration<double> elapsed = end_clock - start_clock;

View File

@ -25,11 +25,12 @@ int main(int argc, char *argv[]) {
exit(1);
}
const char *filename = argv[1];
auto[p, err] = simdjson::padded_string::load(filename);
if (err) {
auto v = simdjson::padded_string::load(filename);
if (v.error()) {
std::cerr << "Could not load the file " << filename << std::endl;
return EXIT_FAILURE;
}
const simdjson::padded_string& p = v.value_unsafe();
if (test_baseline) {
std::wclog << "Baseline: Getline + normal parse... " << std::endl;
std::cout << "Gigabytes/second\t"

View File

@ -8,39 +8,48 @@
#include "NullBuffer.h"
// example from doc/basics.md#tree-walking-and-json-element-types
static void print_json(std::ostream& os, simdjson::dom::element element) {
/***
* Important: This function should compile without support for exceptions.
*/
static void print_json(std::ostream& os, simdjson::dom::element element) noexcept {
const char endl='\n';
switch (element.type()) {
case simdjson::dom::element_type::ARRAY:
os << "[";
for (simdjson::dom::element child : element.get<simdjson::dom::array>().first) {
print_json(os, child);
os << ",";
{
simdjson::dom::array array = element.get<simdjson::dom::array>().value_unsafe();
for (simdjson::dom::element child : array) {
print_json(os, child);
os << ",";
}
}
os << "]";
break;
case simdjson::dom::element_type::OBJECT:
os << "{";
for (simdjson::dom::key_value_pair field : element.get<simdjson::dom::object>().first) {
os << "\"" << field.key << "\": ";
print_json(os, field.value);
{
simdjson::dom::object object = element.get<simdjson::dom::object>().value_unsafe();
for (simdjson::dom::key_value_pair field : object) {
os << "\"" << field.key << "\": ";
print_json(os, field.value);
}
}
os << "}";
break;
case simdjson::dom::element_type::INT64:
os << element.get<int64_t>().first << endl;
os << element.get_int64().value_unsafe() << endl;
break;
case simdjson::dom::element_type::UINT64:
os << element.get<uint64_t>().first << endl;
os << element.get_uint64().value_unsafe() << endl;
break;
case simdjson::dom::element_type::DOUBLE:
os << element.get<double>().first << endl;
os << element.get_double().value_unsafe() << endl;
break;
case simdjson::dom::element_type::STRING:
os << element.get<std::string_view>().first << endl;
os << element.get_string().value_unsafe() << endl;
break;
case simdjson::dom::element_type::BOOL:
os << element.get<bool>().first << endl;
os << element.get_bool().value_unsafe() << endl;
break;
case simdjson::dom::element_type::NULL_VALUE:
os << "null" << endl;

View File

@ -92,6 +92,16 @@ simdjson_really_inline simdjson_result_base<T>::operator T&&() && noexcept(false
#endif // SIMDJSON_EXCEPTIONS
template<typename T>
simdjson_really_inline const T& simdjson_result_base<T>::value_unsafe() const& noexcept {
return this->first;
}
template<typename T>
simdjson_really_inline T&& simdjson_result_base<T>::value_unsafe() && noexcept {
return std::forward<T>(this->first);;
}
template<typename T>
simdjson_really_inline simdjson_result_base<T>::simdjson_result_base(T &&value, error_code error) noexcept
: std::pair<T, error_code>(std::forward<T>(value), error) {}
@ -150,6 +160,16 @@ simdjson_really_inline simdjson_result<T>::operator T&&() && noexcept(false) {
#endif // SIMDJSON_EXCEPTIONS
template<typename T>
simdjson_really_inline const T& simdjson_result<T>::value_unsafe() const& noexcept {
return internal::simdjson_result_base<T>::value_unsafe();
}
template<typename T>
simdjson_really_inline T&& simdjson_result<T>::value_unsafe() && noexcept {
return std::forward<internal::simdjson_result_base<T>>(*this).value_unsafe();
}
template<typename T>
simdjson_really_inline simdjson_result<T>::simdjson_result(T &&value, error_code error) noexcept
: internal::simdjson_result_base<T>(std::forward<T>(value), error) {}

View File

@ -97,7 +97,7 @@ namespace internal {
* Then any method returning simdjson_result<T> will be chainable with your methods.
*/
template<typename T>
struct simdjson_result_base : public std::pair<T, error_code> {
struct simdjson_result_base : protected std::pair<T, error_code> {
/**
* Create a new empty result with error = UNINITIALIZED.
@ -168,8 +168,20 @@ struct simdjson_result_base : public std::pair<T, error_code> {
* @throw simdjson_error if there was an error.
*/
simdjson_really_inline operator T&&() && noexcept(false);
#endif // SIMDJSON_EXCEPTIONS
/**
* Get the result value. This function is safe if and only
* the error() method returns a value that evoluates to false.
*/
simdjson_really_inline const T& value_unsafe() const& noexcept;
/**
* Take the result value (move it). This function is safe if and only
* the error() method returns a value that evoluates to false.
*/
simdjson_really_inline T&& value_unsafe() && noexcept;
}; // struct simdjson_result_base
} // namespace internal
@ -247,8 +259,20 @@ struct simdjson_result : public internal::simdjson_result_base<T> {
* @throw simdjson_error if there was an error.
*/
simdjson_really_inline operator T&&() && noexcept(false);
#endif // SIMDJSON_EXCEPTIONS
/**
* Get the result value. This function is safe if and only
* the error() method returns a value that evoluates to false.
*/
simdjson_really_inline const T& value_unsafe() const& noexcept;
/**
* Take the result value (move it). This function is safe if and only
* the error() method returns a value that evoluates to false.
*/
simdjson_really_inline T&& value_unsafe() && noexcept;
}; // struct simdjson_result
#ifndef SIMDJSON_DISABLE_DEPRECATED_API

View File

@ -35,7 +35,7 @@ simdjson_warn_unused simdjson_really_inline simdjson_result<document> parser::it
simdjson_warn_unused simdjson_really_inline simdjson_result<document> parser::iterate(const simdjson_result<padded_string> &result) & noexcept {
// We don't presently have a way to temporarily get a const T& from a simdjson_result<T> without throwing an exception
SIMDJSON_TRY( result.error() );
const padded_string &buf = result.first;
const padded_string &buf = result.value_unsafe();
return iterate(buf);
}

View File

@ -663,7 +663,7 @@ namespace dom_api_tests {
int i = 0;
for (auto [key, value] : object) {
ASSERT_EQUAL( key, expected_key[i] );
ASSERT_EQUAL( value.get<uint64_t>().first, expected_value[i] );
ASSERT_EQUAL( value.get<uint64_t>().value_unsafe(), expected_value[i] );
i++;
}
ASSERT_EQUAL( i*sizeof(uint64_t), sizeof(expected_value) );
@ -748,18 +748,18 @@ namespace dom_api_tests {
ASSERT_SUCCESS( parser.parse(json).get(array) );
auto iter = array.begin();
ASSERT_EQUAL( (*iter).get<uint64_t>().first, 0 );
ASSERT_EQUAL( (*iter).get<int64_t>().first, 0 );
ASSERT_EQUAL( (*iter).get<double>().first, 0 );
ASSERT_EQUAL( (*iter).get<uint64_t>().value_unsafe(), 0 );
ASSERT_EQUAL( (*iter).get<int64_t>().value_unsafe(), 0 );
ASSERT_EQUAL( (*iter).get<double>().value_unsafe(), 0 );
++iter;
ASSERT_EQUAL( (*iter).get<uint64_t>().first, 1 );
ASSERT_EQUAL( (*iter).get<int64_t>().first, 1 );
ASSERT_EQUAL( (*iter).get<double>().first, 1 );
ASSERT_EQUAL( (*iter).get<uint64_t>().value_unsafe(), 1 );
ASSERT_EQUAL( (*iter).get<int64_t>().value_unsafe(), 1 );
ASSERT_EQUAL( (*iter).get<double>().value_unsafe(), 1 );
++iter;
ASSERT_EQUAL( (*iter).get<int64_t>().first, -1 );
ASSERT_EQUAL( (*iter).get<double>().first, -1 );
ASSERT_EQUAL( (*iter).get<int64_t>().value_unsafe(), -1 );
ASSERT_EQUAL( (*iter).get<double>().value_unsafe(), -1 );
++iter;
ASSERT_EQUAL( (*iter).get<double>().first, 1.1 );
ASSERT_EQUAL( (*iter).get<double>().value_unsafe(), 1.1 );
return true;
}
@ -771,9 +771,9 @@ namespace dom_api_tests {
ASSERT_SUCCESS( parser.parse(json).get(array) );
auto val = array.begin();
ASSERT_EQUAL( (*val).get<bool>().first, true );
ASSERT_EQUAL( (*val).get<bool>().value_unsafe(), true );
++val;
ASSERT_EQUAL( (*val).get<bool>().first, false );
ASSERT_EQUAL( (*val).get<bool>().value_unsafe(), false );
return true;
}
@ -801,22 +801,23 @@ namespace dom_api_tests {
auto mylambda = [](dom::element e) { return int64_t(e); };
ASSERT_EQUAL( mylambda(node), 1 );
#endif
ASSERT_EQUAL( object["a"].get<uint64_t>().first, 1 );
ASSERT_EQUAL( object["b"].get<uint64_t>().first, 2 );
ASSERT_EQUAL( object["c/d"].get<uint64_t>().first, 3 );
ASSERT_EQUAL( object["a"].get<uint64_t>().value_unsafe(), 1 );
ASSERT_EQUAL( object["b"].get<uint64_t>().value_unsafe(), 2 );
ASSERT_EQUAL( object["c/d"].get<uint64_t>().value_unsafe(), 3 );
// Check all three again in backwards order, to ensure we can go backwards
ASSERT_EQUAL( object["c/d"].get<uint64_t>().first, 3 );
ASSERT_EQUAL( object["b"].get<uint64_t>().first, 2 );
ASSERT_EQUAL( object["a"].get<uint64_t>().first, 1 );
ASSERT_EQUAL( object["c/d"].get<uint64_t>().value_unsafe(), 3 );
ASSERT_EQUAL( object["b"].get<uint64_t>().value_unsafe(), 2 );
ASSERT_EQUAL( object["a"].get<uint64_t>().value_unsafe(), 1 );
simdjson::error_code error;
simdjson_unused element val;
#ifndef _LIBCPP_VERSION // should work everywhere but with libc++, must include the <ciso646> header.
std::tie(val,error) = object["d"];
ASSERT_ERROR( error, NO_SUCH_FIELD );
std::tie(std::ignore,error) = object["d"];
ASSERT_ERROR( error, NO_SUCH_FIELD );
#endif
// This is disabled, see https://github.com/simdjson/simdjson/issues/1243
//#ifndef _LIBCPP_VERSION // should work everywhere but with libc++, must include the <ciso646> header.
// std::tie(val,error) = object["d"];
// ASSERT_ERROR( error, NO_SUCH_FIELD );
// std::tie(std::ignore,error) = object["d"];
// ASSERT_ERROR( error, NO_SUCH_FIELD );
//#endif
// tie(val, error) = object["d"]; fails with "no viable overloaded '='" on Apple clang version 11.0.0 tie(val, error) = doc["d"];
object["d"].tie(val, error);
ASSERT_ERROR( error, NO_SUCH_FIELD );
@ -831,20 +832,20 @@ namespace dom_api_tests {
dom::parser parser;
dom::element doc;
ASSERT_SUCCESS( parser.parse(json).get(doc) );
ASSERT_EQUAL( doc["obj"]["a"].get<uint64_t>().first, 1);
ASSERT_EQUAL( doc["obj"]["a"].get<uint64_t>().value_unsafe(), 1);
object obj;
ASSERT_SUCCESS( doc.get(obj) );
ASSERT_EQUAL( obj["obj"]["a"].get<uint64_t>().first, 1);
ASSERT_EQUAL( obj["obj"]["a"].get<uint64_t>().value_unsafe(), 1);
ASSERT_SUCCESS( obj["obj"].get(obj) );
ASSERT_EQUAL( obj["a"].get<uint64_t>().first, 1 );
ASSERT_EQUAL( obj["b"].get<uint64_t>().first, 2 );
ASSERT_EQUAL( obj["c/d"].get<uint64_t>().first, 3 );
ASSERT_EQUAL( obj["a"].get<uint64_t>().value_unsafe(), 1 );
ASSERT_EQUAL( obj["b"].get<uint64_t>().value_unsafe(), 2 );
ASSERT_EQUAL( obj["c/d"].get<uint64_t>().value_unsafe(), 3 );
// Check all three again in backwards order, to ensure we can go backwards
ASSERT_EQUAL( obj["c/d"].get<uint64_t>().first, 3 );
ASSERT_EQUAL( obj["b"].get<uint64_t>().first, 2 );
ASSERT_EQUAL( obj["a"].get<uint64_t>().first, 1 );
ASSERT_EQUAL( obj["c/d"].get<uint64_t>().value_unsafe(), 3 );
ASSERT_EQUAL( obj["b"].get<uint64_t>().value_unsafe(), 2 );
ASSERT_EQUAL( obj["a"].get<uint64_t>().value_unsafe(), 1 );
simdjson_unused element val;
ASSERT_ERROR( doc["d"].get(val), NO_SUCH_FIELD);
@ -1062,6 +1063,24 @@ namespace dom_api_tests {
}
#endif
// https://github.com/simdjson/simdjson/issues/1243
bool unsafe_value_noexception() noexcept {
std::cout << "Running " << __func__ << std::endl;
string json(R"({ "foo": [1, 2, 3, 17, 22] })");
std::vector<uint64_t> expected_values = { 1, 2, 3, 17, 22 };
size_t index{0};
dom::parser parser;
auto elem = parser.parse(json)["foo"];
if (elem.error() || !elem.is_array()) { return false; }
auto myarray = elem.get_array().value_unsafe();
// for (auto child : elem.get_array().value_unsafe()) could be unsafe
for (auto child : myarray) {
if(!child.is_uint64()) { return false; }
if(index >= expected_values.size()) { return false; }
ASSERT_EQUAL( child.get_uint64().value_unsafe(), expected_values[index++]);
}
return true;
}
bool run() {
return
@ -1081,6 +1100,7 @@ namespace dom_api_tests {
twitter_count() &&
twitter_default_profile() &&
twitter_image_sizes() &&
unsafe_value_noexception() &&
#if SIMDJSON_EXCEPTIONS
object_iterator_exception() &&
array_iterator_exception() &&
@ -1135,7 +1155,7 @@ namespace type_tests {
cast_tester<T> tester;
std::cout << " test_cast<" << typeid(T).name() << "> expecting " << expected << std::endl;
// Grab the element out and check success
dom::element element = result.first;
dom::element element = result.value_unsafe();
RUN_TEST( tester.test_get_t(element, expected) );
RUN_TEST( tester.test_get_t(result, expected) );
@ -1160,7 +1180,7 @@ namespace type_tests {
cast_tester<T> tester;
std::cout << " test_cast<" << typeid(T).name() << ">" << std::endl;
// Grab the element out and check success
dom::element element = result.first;
dom::element element = result.value_unsafe();
RUN_TEST( tester.test_get_t(element) );
RUN_TEST( tester.test_get_t(result) );
@ -1186,7 +1206,7 @@ namespace type_tests {
template<typename T>
bool test_cast_error(simdjson_result<dom::element> result, simdjson::error_code expected_error) {
std::cout << " test_cast_error<" << typeid(T).name() << "> expecting error '" << expected_error << "'" << std::endl;
dom::element element = result.first;
dom::element element = result.value_unsafe();
cast_tester<T> tester;
@ -1208,7 +1228,7 @@ namespace type_tests {
bool test_type(simdjson_result<dom::element> result, dom::element_type expected_type) {
std::cout << " test_type() expecting " << expected_type << std::endl;
dom::element element = result.first;
dom::element element = result.value_unsafe();
dom::element_type actual_type;
auto error = result.type().get(actual_type);
ASSERT_SUCCESS(error);
@ -1238,7 +1258,7 @@ namespace type_tests {
bool test_is_null(simdjson_result<dom::element> result, bool expected_is_null) {
std::cout << " test_is_null() expecting " << expected_is_null << std::endl;
// Grab the element out and check success
dom::element element = result.first;
dom::element element = result.value_unsafe();
ASSERT_EQUAL(result.is_null(), expected_is_null);
ASSERT_EQUAL(element.is_null(), expected_is_null);

View File

@ -89,14 +89,14 @@ template<typename T>
bool cast_tester<T>::test_get_t(element element, T expected) {
auto actual = element.get<T>();
ASSERT_SUCCESS(actual.error());
return assert_equal(actual.first, expected);
return assert_equal(actual.value_unsafe(), expected);
}
template<typename T>
bool cast_tester<T>::test_get_t(simdjson_result<element> element, T expected) {
auto actual = element.get<T>();
ASSERT_SUCCESS(actual.error());
return assert_equal(actual.first, expected);
return assert_equal(actual.value_unsafe(), expected);
}
template<typename T>

View File

@ -18,7 +18,7 @@ namespace dom_api_tests {
for (auto [ field, error ] : object) {
ASSERT_SUCCESS(error);
ASSERT_EQUAL( field.key(), expected_key[i]);
ASSERT_EQUAL( field.value().get_uint64().first, expected_value[i] );
ASSERT_EQUAL( field.value().get_uint64().value_unsafe(), expected_value[i] );
i++;
}
ASSERT_EQUAL( i*sizeof(uint64_t), sizeof(expected_value) );
@ -30,7 +30,7 @@ namespace dom_api_tests {
for (auto [ field, error ] : object_result) {
ASSERT_SUCCESS(error);
ASSERT_EQUAL( field.key(), expected_key[i] );
ASSERT_EQUAL( field.value().get_uint64().first, expected_value[i] );
ASSERT_EQUAL( field.value().get_uint64().value_unsafe(), expected_value[i] );
i++;
}
ASSERT_EQUAL( i*sizeof(uint64_t), sizeof(expected_value) );
@ -870,11 +870,11 @@ namespace dom_api_tests {
ondemand::object object;
ASSERT_SUCCESS( doc_result.get(object) );
ASSERT_EQUAL( object["a"].get_uint64().first, 1 );
ASSERT_EQUAL( object["b"].get_uint64().first, 2 );
ASSERT_EQUAL( object["c/d"].get_uint64().first, 3 );
ASSERT_EQUAL( object["a"].get_uint64().value_unsafe(), 1 );
ASSERT_EQUAL( object["b"].get_uint64().value_unsafe(), 2 );
ASSERT_EQUAL( object["c/d"].get_uint64().value_unsafe(), 3 );
ASSERT_EQUAL( object["a"].get_uint64().first, 1 );
ASSERT_EQUAL( object["a"].get_uint64().value_unsafe(), 1 );
ASSERT_ERROR( object["d"], NO_SUCH_FIELD );
return true;
}));
@ -882,31 +882,31 @@ namespace dom_api_tests {
simdjson_result<ondemand::object> object;
object = doc_result.get_object();
ASSERT_EQUAL( object["a"].get_uint64().first, 1 );
ASSERT_EQUAL( object["b"].get_uint64().first, 2 );
ASSERT_EQUAL( object["c/d"].get_uint64().first, 3 );
ASSERT_EQUAL( object["a"].get_uint64().value_unsafe(), 1 );
ASSERT_EQUAL( object["b"].get_uint64().value_unsafe(), 2 );
ASSERT_EQUAL( object["c/d"].get_uint64().value_unsafe(), 3 );
ASSERT_EQUAL( object["a"].get_uint64().first, 1 );
ASSERT_EQUAL( object["a"].get_uint64().value_unsafe(), 1 );
ASSERT_ERROR( object["d"], NO_SUCH_FIELD );
return true;
}));
SUBTEST("ondemand::document", test_ondemand_doc(json, [&](auto doc_result) {
ondemand::document doc;
ASSERT_SUCCESS( std::move(doc_result).get(doc) );
ASSERT_EQUAL( doc["a"].get_uint64().first, 1 );
ASSERT_EQUAL( doc["b"].get_uint64().first, 2 );
ASSERT_EQUAL( doc["c/d"].get_uint64().first, 3 );
ASSERT_EQUAL( doc["a"].get_uint64().value_unsafe(), 1 );
ASSERT_EQUAL( doc["b"].get_uint64().value_unsafe(), 2 );
ASSERT_EQUAL( doc["c/d"].get_uint64().value_unsafe(), 3 );
ASSERT_EQUAL( doc["a"].get_uint64().first, 1 );
ASSERT_EQUAL( doc["a"].get_uint64().value_unsafe(), 1 );
ASSERT_ERROR( doc["d"], NO_SUCH_FIELD );
return true;
}));
SUBTEST("simdjson_result<ondemand::document>", test_ondemand_doc(json, [&](auto doc_result) {
ASSERT_EQUAL( doc_result["a"].get_uint64().first, 1 );
ASSERT_EQUAL( doc_result["b"].get_uint64().first, 2 );
ASSERT_EQUAL( doc_result["c/d"].get_uint64().first, 3 );
ASSERT_EQUAL( doc_result["a"].get_uint64().value_unsafe(), 1 );
ASSERT_EQUAL( doc_result["b"].get_uint64().value_unsafe(), 2 );
ASSERT_EQUAL( doc_result["c/d"].get_uint64().value_unsafe(), 3 );
ASSERT_EQUAL( doc_result["a"].get_uint64().first, 1 );
ASSERT_EQUAL( doc_result["a"].get_uint64().value_unsafe(), 1 );
ASSERT_ERROR( doc_result["d"], NO_SUCH_FIELD );
return true;
}));
@ -915,21 +915,21 @@ namespace dom_api_tests {
SUBTEST("ondemand::value", test_ondemand_doc(json, [&](auto doc_result) {
ondemand::value object;
ASSERT_SUCCESS( doc_result["outer"].get(object) );
ASSERT_EQUAL( object["a"].get_uint64().first, 1 );
ASSERT_EQUAL( object["b"].get_uint64().first, 2 );
ASSERT_EQUAL( object["c/d"].get_uint64().first, 3 );
ASSERT_EQUAL( object["a"].get_uint64().value_unsafe(), 1 );
ASSERT_EQUAL( object["b"].get_uint64().value_unsafe(), 2 );
ASSERT_EQUAL( object["c/d"].get_uint64().value_unsafe(), 3 );
ASSERT_EQUAL( object["a"].get_uint64().first, 1 );
ASSERT_EQUAL( object["a"].get_uint64().value_unsafe(), 1 );
ASSERT_ERROR( object["d"], NO_SUCH_FIELD );
return true;
}));
SUBTEST("simdjson_result<ondemand::value>", test_ondemand_doc(json, [&](auto doc_result) {
simdjson_result<ondemand::value> object = doc_result["outer"];
ASSERT_EQUAL( object["a"].get_uint64().first, 1 );
ASSERT_EQUAL( object["b"].get_uint64().first, 2 );
ASSERT_EQUAL( object["c/d"].get_uint64().first, 3 );
ASSERT_EQUAL( object["a"].get_uint64().value_unsafe(), 1 );
ASSERT_EQUAL( object["b"].get_uint64().value_unsafe(), 2 );
ASSERT_EQUAL( object["c/d"].get_uint64().value_unsafe(), 3 );
ASSERT_EQUAL( object["a"].get_uint64().first, 1 );
ASSERT_EQUAL( object["a"].get_uint64().value_unsafe(), 1 );
ASSERT_ERROR( object["d"], NO_SUCH_FIELD );
return true;
}));
@ -943,11 +943,11 @@ namespace dom_api_tests {
ondemand::object object;
ASSERT_SUCCESS( doc_result.get(object) );
ASSERT_EQUAL( object.find_field_unordered("a").get_uint64().first, 1 );
ASSERT_EQUAL( object.find_field_unordered("b").get_uint64().first, 2 );
ASSERT_EQUAL( object.find_field_unordered("c/d").get_uint64().first, 3 );
ASSERT_EQUAL( object.find_field_unordered("a").get_uint64().value_unsafe(), 1 );
ASSERT_EQUAL( object.find_field_unordered("b").get_uint64().value_unsafe(), 2 );
ASSERT_EQUAL( object.find_field_unordered("c/d").get_uint64().value_unsafe(), 3 );
ASSERT_EQUAL( object.find_field_unordered("a").get_uint64().first, 1 );
ASSERT_EQUAL( object.find_field_unordered("a").get_uint64().value_unsafe(), 1 );
ASSERT_ERROR( object.find_field_unordered("d"), NO_SUCH_FIELD );
return true;
}));
@ -955,31 +955,31 @@ namespace dom_api_tests {
simdjson_result<ondemand::object> object;
object = doc_result.get_object();
ASSERT_EQUAL( object.find_field_unordered("a").get_uint64().first, 1 );
ASSERT_EQUAL( object.find_field_unordered("b").get_uint64().first, 2 );
ASSERT_EQUAL( object.find_field_unordered("c/d").get_uint64().first, 3 );
ASSERT_EQUAL( object.find_field_unordered("a").get_uint64().value_unsafe(), 1 );
ASSERT_EQUAL( object.find_field_unordered("b").get_uint64().value_unsafe(), 2 );
ASSERT_EQUAL( object.find_field_unordered("c/d").get_uint64().value_unsafe(), 3 );
ASSERT_EQUAL( object.find_field_unordered("a").get_uint64().first, 1 );
ASSERT_EQUAL( object.find_field_unordered("a").get_uint64().value_unsafe(), 1 );
ASSERT_ERROR( object.find_field_unordered("d"), NO_SUCH_FIELD );
return true;
}));
SUBTEST("ondemand::document", test_ondemand_doc(json, [&](auto doc_result) {
ondemand::document doc;
ASSERT_SUCCESS( std::move(doc_result).get(doc) );
ASSERT_EQUAL( doc.find_field_unordered("a").get_uint64().first, 1 );
ASSERT_EQUAL( doc.find_field_unordered("b").get_uint64().first, 2 );
ASSERT_EQUAL( doc.find_field_unordered("c/d").get_uint64().first, 3 );
ASSERT_EQUAL( doc.find_field_unordered("a").get_uint64().value_unsafe(), 1 );
ASSERT_EQUAL( doc.find_field_unordered("b").get_uint64().value_unsafe(), 2 );
ASSERT_EQUAL( doc.find_field_unordered("c/d").get_uint64().value_unsafe(), 3 );
ASSERT_EQUAL( doc.find_field_unordered("a").get_uint64().first, 1 );
ASSERT_EQUAL( doc.find_field_unordered("a").get_uint64().value_unsafe(), 1 );
ASSERT_ERROR( doc.find_field_unordered("d"), NO_SUCH_FIELD );
return true;
}));
SUBTEST("simdjson_result<ondemand::document>", test_ondemand_doc(json, [&](auto doc_result) {
ASSERT_EQUAL( doc_result.find_field_unordered("a").get_uint64().first, 1 );
ASSERT_EQUAL( doc_result.find_field_unordered("b").get_uint64().first, 2 );
ASSERT_EQUAL( doc_result.find_field_unordered("c/d").get_uint64().first, 3 );
ASSERT_EQUAL( doc_result.find_field_unordered("a").get_uint64().value_unsafe(), 1 );
ASSERT_EQUAL( doc_result.find_field_unordered("b").get_uint64().value_unsafe(), 2 );
ASSERT_EQUAL( doc_result.find_field_unordered("c/d").get_uint64().value_unsafe(), 3 );
ASSERT_EQUAL( doc_result.find_field_unordered("a").get_uint64().first, 1 );
ASSERT_EQUAL( doc_result.find_field_unordered("a").get_uint64().value_unsafe(), 1 );
ASSERT_ERROR( doc_result.find_field_unordered("d"), NO_SUCH_FIELD );
return true;
}));
@ -988,21 +988,21 @@ namespace dom_api_tests {
SUBTEST("ondemand::value", test_ondemand_doc(json, [&](auto doc_result) {
ondemand::value object;
ASSERT_SUCCESS( doc_result.find_field_unordered("outer").get(object) );
ASSERT_EQUAL( object.find_field_unordered("a").get_uint64().first, 1 );
ASSERT_EQUAL( object.find_field_unordered("b").get_uint64().first, 2 );
ASSERT_EQUAL( object.find_field_unordered("c/d").get_uint64().first, 3 );
ASSERT_EQUAL( object.find_field_unordered("a").get_uint64().value_unsafe(), 1 );
ASSERT_EQUAL( object.find_field_unordered("b").get_uint64().value_unsafe(), 2 );
ASSERT_EQUAL( object.find_field_unordered("c/d").get_uint64().value_unsafe(), 3 );
ASSERT_EQUAL( object.find_field_unordered("a").get_uint64().first, 1 );
ASSERT_EQUAL( object.find_field_unordered("a").get_uint64().value_unsafe(), 1 );
ASSERT_ERROR( object.find_field_unordered("d"), NO_SUCH_FIELD );
return true;
}));
SUBTEST("simdjson_result<ondemand::value>", test_ondemand_doc(json, [&](auto doc_result) {
simdjson_result<ondemand::value> object = doc_result.find_field_unordered("outer");
ASSERT_EQUAL( object.find_field_unordered("a").get_uint64().first, 1 );
ASSERT_EQUAL( object.find_field_unordered("b").get_uint64().first, 2 );
ASSERT_EQUAL( object.find_field_unordered("c/d").get_uint64().first, 3 );
ASSERT_EQUAL( object.find_field_unordered("a").get_uint64().value_unsafe(), 1 );
ASSERT_EQUAL( object.find_field_unordered("b").get_uint64().value_unsafe(), 2 );
ASSERT_EQUAL( object.find_field_unordered("c/d").get_uint64().value_unsafe(), 3 );
ASSERT_EQUAL( object.find_field_unordered("a").get_uint64().first, 1 );
ASSERT_EQUAL( object.find_field_unordered("a").get_uint64().value_unsafe(), 1 );
ASSERT_ERROR( object.find_field_unordered("d"), NO_SUCH_FIELD );
return true;
}));
@ -1016,9 +1016,9 @@ namespace dom_api_tests {
ondemand::object object;
ASSERT_SUCCESS( doc_result.get(object) );
ASSERT_EQUAL( object.find_field("a").get_uint64().first, 1 );
ASSERT_EQUAL( object.find_field("b").get_uint64().first, 2 );
ASSERT_EQUAL( object.find_field("c/d").get_uint64().first, 3 );
ASSERT_EQUAL( object.find_field("a").get_uint64().value_unsafe(), 1 );
ASSERT_EQUAL( object.find_field("b").get_uint64().value_unsafe(), 2 );
ASSERT_EQUAL( object.find_field("c/d").get_uint64().value_unsafe(), 3 );
ASSERT_ERROR( object.find_field("a"), NO_SUCH_FIELD );
ASSERT_ERROR( object.find_field("d"), NO_SUCH_FIELD );
@ -1028,9 +1028,9 @@ namespace dom_api_tests {
simdjson_result<ondemand::object> object;
object = doc_result.get_object();
ASSERT_EQUAL( object.find_field("a").get_uint64().first, 1 );
ASSERT_EQUAL( object.find_field("b").get_uint64().first, 2 );
ASSERT_EQUAL( object.find_field("c/d").get_uint64().first, 3 );
ASSERT_EQUAL( object.find_field("a").get_uint64().value_unsafe(), 1 );
ASSERT_EQUAL( object.find_field("b").get_uint64().value_unsafe(), 2 );
ASSERT_EQUAL( object.find_field("c/d").get_uint64().value_unsafe(), 3 );
ASSERT_ERROR( object.find_field("a"), NO_SUCH_FIELD );
ASSERT_ERROR( object.find_field("d"), NO_SUCH_FIELD );
@ -1039,18 +1039,18 @@ namespace dom_api_tests {
SUBTEST("ondemand::document", test_ondemand_doc(json, [&](auto doc_result) {
ondemand::document doc;
ASSERT_SUCCESS( std::move(doc_result).get(doc) );
ASSERT_EQUAL( doc.find_field("a").get_uint64().first, 1 );
ASSERT_EQUAL( doc.find_field("b").get_uint64().first, 2 );
ASSERT_EQUAL( doc.find_field("c/d").get_uint64().first, 3 );
ASSERT_EQUAL( doc.find_field("a").get_uint64().value_unsafe(), 1 );
ASSERT_EQUAL( doc.find_field("b").get_uint64().value_unsafe(), 2 );
ASSERT_EQUAL( doc.find_field("c/d").get_uint64().value_unsafe(), 3 );
ASSERT_ERROR( doc.find_field("a"), NO_SUCH_FIELD );
ASSERT_ERROR( doc.find_field("d"), NO_SUCH_FIELD );
return true;
}));
SUBTEST("simdjson_result<ondemand::document>", test_ondemand_doc(json, [&](auto doc_result) {
ASSERT_EQUAL( doc_result.find_field("a").get_uint64().first, 1 );
ASSERT_EQUAL( doc_result.find_field("b").get_uint64().first, 2 );
ASSERT_EQUAL( doc_result.find_field("c/d").get_uint64().first, 3 );
ASSERT_EQUAL( doc_result.find_field("a").get_uint64().value_unsafe(), 1 );
ASSERT_EQUAL( doc_result.find_field("b").get_uint64().value_unsafe(), 2 );
ASSERT_EQUAL( doc_result.find_field("c/d").get_uint64().value_unsafe(), 3 );
ASSERT_ERROR( doc_result.find_field("a"), NO_SUCH_FIELD );
ASSERT_ERROR( doc_result.find_field("d"), NO_SUCH_FIELD );
@ -1061,9 +1061,9 @@ namespace dom_api_tests {
SUBTEST("ondemand::value", test_ondemand_doc(json, [&](auto doc_result) {
ondemand::value object;
ASSERT_SUCCESS( doc_result.find_field("outer").get(object) );
ASSERT_EQUAL( object.find_field("a").get_uint64().first, 1 );
ASSERT_EQUAL( object.find_field("b").get_uint64().first, 2 );
ASSERT_EQUAL( object.find_field("c/d").get_uint64().first, 3 );
ASSERT_EQUAL( object.find_field("a").get_uint64().value_unsafe(), 1 );
ASSERT_EQUAL( object.find_field("b").get_uint64().value_unsafe(), 2 );
ASSERT_EQUAL( object.find_field("c/d").get_uint64().value_unsafe(), 3 );
ASSERT_ERROR( object.find_field("a"), NO_SUCH_FIELD );
ASSERT_ERROR( object.find_field("d"), NO_SUCH_FIELD );
@ -1071,9 +1071,9 @@ namespace dom_api_tests {
}));
SUBTEST("simdjson_result<ondemand::value>", test_ondemand_doc(json, [&](auto doc_result) {
simdjson_result<ondemand::value> object = doc_result.find_field("outer");
ASSERT_EQUAL( object.find_field("a").get_uint64().first, 1 );
ASSERT_EQUAL( object.find_field("b").get_uint64().first, 2 );
ASSERT_EQUAL( object.find_field("c/d").get_uint64().first, 3 );
ASSERT_EQUAL( object.find_field("a").get_uint64().value_unsafe(), 1 );
ASSERT_EQUAL( object.find_field("b").get_uint64().value_unsafe(), 2 );
ASSERT_EQUAL( object.find_field("c/d").get_uint64().value_unsafe(), 3 );
ASSERT_ERROR( object.find_field("a"), NO_SUCH_FIELD );
ASSERT_ERROR( object.find_field("d"), NO_SUCH_FIELD );
@ -1086,35 +1086,35 @@ namespace dom_api_tests {
TEST_START();
auto json = R"({ "x": { "y": { "z": 2 } } }})"_padded;
SUBTEST("simdjson_result<ondemand::document>", test_ondemand_doc(json, [&](auto doc_result) {
ASSERT_EQUAL( doc_result["x"]["y"]["z"].get_uint64().first, 2 );
ASSERT_EQUAL( doc_result["x"]["y"]["z"].get_uint64().value_unsafe(), 2 );
return true;
}));
SUBTEST("ondemand::document", test_ondemand_doc(json, [&](auto doc_result) {
ondemand::document doc;
ASSERT_SUCCESS( std::move(doc_result).get(doc) );
ASSERT_EQUAL( doc["x"]["y"]["z"].get_uint64().first, 2 );
ASSERT_EQUAL( doc["x"]["y"]["z"].get_uint64().value_unsafe(), 2 );
return true;
}));
SUBTEST("simdjson_result<ondemand::object>", test_ondemand_doc(json, [&](auto doc_result) {
simdjson_result<ondemand::object> object = doc_result.get_object();
ASSERT_EQUAL( object["x"]["y"]["z"].get_uint64().first, 2 );
ASSERT_EQUAL( object["x"]["y"]["z"].get_uint64().value_unsafe(), 2 );
return true;
}));
SUBTEST("ondemand::object", test_ondemand_doc(json, [&](auto doc_result) {
ondemand::object object;
ASSERT_SUCCESS( doc_result.get(object) );
ASSERT_EQUAL( object["x"]["y"]["z"].get_uint64().first, 2 );
ASSERT_EQUAL( object["x"]["y"]["z"].get_uint64().value_unsafe(), 2 );
return true;
}));
SUBTEST("simdjson_result<ondemand::value>", test_ondemand_doc(json, [&](auto doc_result) {
simdjson_result<ondemand::value> x = doc_result["x"];
ASSERT_EQUAL( x["y"]["z"].get_uint64().first, 2 );
ASSERT_EQUAL( x["y"]["z"].get_uint64().value_unsafe(), 2 );
return true;
}));
SUBTEST("ondemand::value", test_ondemand_doc(json, [&](auto doc_result) {
ondemand::value x;
ASSERT_SUCCESS( doc_result["x"].get(x) );
ASSERT_EQUAL( x["y"]["z"].get_uint64().first, 2 );
ASSERT_EQUAL( x["y"]["z"].get_uint64().value_unsafe(), 2 );
return true;
}));
TEST_SUCCEED();