Guarding first/second access. (#1688)
* Guarding first/second access. * Correcting our own usage. * Adding more documentation.
This commit is contained in:
parent
06643fc9f5
commit
19902abaf8
|
@ -871,6 +871,30 @@ bool parse() {
|
|||
```
|
||||
|
||||
|
||||
The following examples illustrates how to iterate through the content of an object without
|
||||
having to handle exceptions.
|
||||
```c++
|
||||
auto json = R"({"k\u0065y": 1})"_padded;
|
||||
ondemand::parser parser;
|
||||
ondemand::document doc;
|
||||
auto error = parser.iterate(json).get(doc);
|
||||
if(error) { return false; }
|
||||
ondemand::object object;
|
||||
error = doc.get_object().get(object);
|
||||
if(error) { return false; }
|
||||
for(auto field : object) {
|
||||
ondemand::raw_json_string keyv;
|
||||
error = field.key().get(keyv);
|
||||
if(error) { return false; }
|
||||
if(keyv == "key") {
|
||||
uint64_t intvalue;
|
||||
error = field.value().get(intvalue);
|
||||
if(error) { return false; }
|
||||
std::cout << intvalue;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Disabling Exceptions
|
||||
|
||||
The simdjson can be build with exceptions entirely disabled. It checks the `__cpp_exceptions` macro at compile time. Even if exceptions are enabled in your compiler, you may still disable exceptions specifically for simdjson, by setting `SIMDJSON_EXCEPTIONS` to `0` (false) at compile-time when building the simdjson library. If you are building with CMake, to ensure you don't write any code that uses exceptions, you compile with `SIMDJSON_EXCEPTIONS=OFF`. For example, if including the project via cmake:
|
||||
|
|
|
@ -115,9 +115,10 @@ struct implementation_simdjson_result_base {
|
|||
* the error() method returns a value that evaluates to false.
|
||||
*/
|
||||
simdjson_really_inline T&& value_unsafe() && noexcept;
|
||||
|
||||
T first{};
|
||||
error_code second{UNINITIALIZED};
|
||||
protected:
|
||||
/** users should never directly access first and second. **/
|
||||
T first{}; /** Users should never directly access 'first'. **/
|
||||
error_code second{UNINITIALIZED}; /** Users should never directly access 'second'. **/
|
||||
}; // struct implementation_simdjson_result_base
|
||||
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
|
|
|
@ -17,3 +17,4 @@ endfunction(add_dual_compile_test)
|
|||
add_dual_compile_test(iterate_char_star)
|
||||
add_dual_compile_test(iterate_string_view)
|
||||
add_dual_compile_test(iterate_temporary_buffer)
|
||||
add_dual_compile_test(first_second_access)
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
|
||||
#include <iostream>
|
||||
#include "simdjson.h"
|
||||
|
||||
using namespace simdjson;
|
||||
|
||||
int main() {
|
||||
auto json = "1"_padded;
|
||||
ondemand::parser parser;
|
||||
ondemand::document doc;
|
||||
auto error = parser.iterate(json).get(doc);
|
||||
if(error) { return EXIT_FAILURE; }
|
||||
simdjson_result<ondemand::value> query = doc.at_pointer("/");
|
||||
#if COMPILATION_TEST_USE_FAILING_CODE
|
||||
if(query.second == simdjson::SUCCESS) {
|
||||
std::cout << "success" << std::endl;
|
||||
std::cout << query.first << std::endl;
|
||||
}
|
||||
#else
|
||||
ondemand::value val;
|
||||
error = query.get(val);
|
||||
if(error == simdjson::SUCCESS) {
|
||||
std::cout << "success" << std::endl;
|
||||
std::cout << val << std::endl;
|
||||
}
|
||||
#endif
|
||||
return EXIT_SUCCESS;
|
||||
}
|
|
@ -416,9 +416,10 @@ namespace array_tests {
|
|||
}
|
||||
// Break after using first value in child object
|
||||
case 3: {
|
||||
for (auto [ child_field, error ] : value.get_object()) {
|
||||
ASSERT_SUCCESS(error);
|
||||
ASSERT_EQUAL(child_field.key(), "x");
|
||||
for (auto child_field : value.get_object()) {
|
||||
ondemand::raw_json_string k;
|
||||
ASSERT_SUCCESS( child_field.key().get(k) );
|
||||
ASSERT_EQUAL(k, "x");
|
||||
uint64_t x;
|
||||
ASSERT_SUCCESS( child_field.value().get(x) );
|
||||
ASSERT_EQUAL(x, 3);
|
||||
|
@ -430,9 +431,10 @@ namespace array_tests {
|
|||
|
||||
// Break without using first value in child object
|
||||
case 4: {
|
||||
for (auto [ child_field, error ] : value.get_object()) {
|
||||
ASSERT_SUCCESS(error);
|
||||
ASSERT_EQUAL(child_field.key(), "x");
|
||||
for (auto child_field : value.get_object()) {
|
||||
ondemand::raw_json_string k;
|
||||
ASSERT_SUCCESS( child_field.key().get(k) );
|
||||
ASSERT_EQUAL(k, "x");
|
||||
break;
|
||||
}
|
||||
std::cout << " - After reaching (but not using) first value in child object ..." << std::endl;
|
||||
|
@ -457,8 +459,7 @@ namespace array_tests {
|
|||
|
||||
// Break after first value in child array
|
||||
case 7: {
|
||||
for (auto [ child_value, error ] : value) {
|
||||
ASSERT_SUCCESS(error);
|
||||
for (auto child_value : value) {
|
||||
uint64_t x;
|
||||
ASSERT_SUCCESS( child_value.get(x) );
|
||||
ASSERT_EQUAL( x, 7 );
|
||||
|
|
|
@ -17,7 +17,7 @@ namespace object_error_tests {
|
|||
ASSERT_ERROR(actual_error, expected_error[count - N]);
|
||||
} else {
|
||||
ASSERT_SUCCESS(actual_error);
|
||||
ASSERT_EQUAL(field.key().first, expected_key[count]);
|
||||
ASSERT_EQUAL(field.key().value_unsafe(), expected_key[count]);
|
||||
ASSERT_EQUAL(actual, expected[count]);
|
||||
}
|
||||
count++;
|
||||
|
|
|
@ -203,9 +203,9 @@ namespace object_tests {
|
|||
ASSERT_RESULT( doc_result.type(), json_type::object );
|
||||
ASSERT_SUCCESS( doc_result.get(object) );
|
||||
size_t i = 0;
|
||||
for (auto [ field, error ] : object) {
|
||||
ASSERT_SUCCESS(error);
|
||||
ASSERT_EQUAL( field.key(), expected_key[i]);
|
||||
for (auto field : object) {
|
||||
ASSERT_SUCCESS( field.key().error() );
|
||||
ASSERT_EQUAL( field.key().value_unsafe(), expected_key[i]);
|
||||
ASSERT_EQUAL( field.value().get_uint64().value_unsafe(), expected_value[i] );
|
||||
i++;
|
||||
}
|
||||
|
@ -217,9 +217,9 @@ namespace object_tests {
|
|||
ASSERT_RESULT( doc_result.type(), json_type::object );
|
||||
ASSERT_SUCCESS( doc_result.get(object) );
|
||||
size_t i = 0;
|
||||
for (auto [ field, error ] : object) {
|
||||
ASSERT_SUCCESS(error);
|
||||
ASSERT_EQUAL( field.key(), expected_key[i]);
|
||||
for (auto field : object) {
|
||||
ASSERT_SUCCESS( field.error() );
|
||||
ASSERT_EQUAL( field.key().value_unsafe(), expected_key[i]);
|
||||
ASSERT_EQUAL( field.value().get_uint64().value_unsafe(), expected_value[i] );
|
||||
i++;
|
||||
}
|
||||
|
@ -228,9 +228,9 @@ namespace object_tests {
|
|||
ASSERT_RESULT( doc_result.type(), json_type::object );
|
||||
ASSERT_SUCCESS( doc_result.get(object) );
|
||||
i = 0;
|
||||
for (auto [ field, error ] : object) {
|
||||
ASSERT_SUCCESS(error);
|
||||
ASSERT_EQUAL( field.key(), expected_key[i]);
|
||||
for (auto field : object) {
|
||||
ASSERT_SUCCESS( field.error() );
|
||||
ASSERT_EQUAL( field.key().value_unsafe(), expected_key[i]);
|
||||
ASSERT_EQUAL( field.value().get_uint64().value_unsafe(), expected_value[i] );
|
||||
i++;
|
||||
}
|
||||
|
@ -240,9 +240,9 @@ namespace object_tests {
|
|||
SUBTEST("simdjson_result<ondemand::object>", test_ondemand_doc(json, [&](auto doc_result) {
|
||||
simdjson_result<ondemand::object> object_result = doc_result.get_object();
|
||||
size_t i = 0;
|
||||
for (auto [ field, error ] : object_result) {
|
||||
ASSERT_SUCCESS(error);
|
||||
ASSERT_EQUAL( field.key(), expected_key[i] );
|
||||
for (auto field : object_result) {
|
||||
ASSERT_SUCCESS( field.error() );
|
||||
ASSERT_EQUAL( field.key().value_unsafe(), expected_key[i]);
|
||||
ASSERT_EQUAL( field.value().get_uint64().value_unsafe(), expected_value[i] );
|
||||
i++;
|
||||
}
|
||||
|
@ -297,9 +297,9 @@ namespace object_tests {
|
|||
case 3: {
|
||||
ASSERT_EQUAL(key, "object_break");
|
||||
|
||||
for (auto [ child_field, error ] : field.value().get_object()) {
|
||||
ASSERT_SUCCESS(error);
|
||||
ASSERT_EQUAL(child_field.key(), "x");
|
||||
for (auto child_field : field.value().get_object()) {
|
||||
ASSERT_SUCCESS( child_field.error() );
|
||||
ASSERT_EQUAL(child_field.key().value_unsafe(), "x");
|
||||
uint64_t x;
|
||||
ASSERT_SUCCESS( child_field.value().get(x) );
|
||||
ASSERT_EQUAL(x, 3);
|
||||
|
@ -313,9 +313,9 @@ namespace object_tests {
|
|||
case 4: {
|
||||
ASSERT_EQUAL(key, "object_break_unused");
|
||||
|
||||
for (auto [ child_field, error ] : field.value().get_object()) {
|
||||
ASSERT_SUCCESS(error);
|
||||
ASSERT_EQUAL(child_field.key(), "x");
|
||||
for (auto child_field : field.value().get_object()) {
|
||||
ASSERT_SUCCESS(child_field.error());
|
||||
ASSERT_EQUAL(child_field.key().value_unsafe(), "x");
|
||||
break;
|
||||
}
|
||||
std::cout << " - After reaching (but not using) first value in child object ..." << std::endl;
|
||||
|
@ -576,17 +576,15 @@ namespace object_tests {
|
|||
ASSERT_RESULT( doc_result.type(), json_type::object );
|
||||
ASSERT_SUCCESS( doc_result.get(object) );
|
||||
size_t i = 0;
|
||||
for (auto [ field, error ] : object) {
|
||||
for (auto field : object) {
|
||||
(void)field;
|
||||
(void)error;
|
||||
i++;
|
||||
}
|
||||
ASSERT_EQUAL( i, 0 );
|
||||
doc_result.rewind();
|
||||
i = 0;
|
||||
for (auto [ field, error ] : object) {
|
||||
for (auto field : object) {
|
||||
(void)field;
|
||||
(void)error;
|
||||
i++;
|
||||
}
|
||||
ASSERT_EQUAL( i, 0 );
|
||||
|
|
|
@ -345,6 +345,59 @@ int using_the_parsed_json_6_process() {
|
|||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
bool exception_free_object_loop() {
|
||||
auto json = R"({"k\u0065y": 1})"_padded;
|
||||
ondemand::parser parser;
|
||||
ondemand::document doc;
|
||||
auto error = parser.iterate(json).get(doc);
|
||||
if(error) { return false; }
|
||||
ondemand::object object;
|
||||
error = doc.get_object().get(object);
|
||||
if(error) { return false; }
|
||||
for(auto field : object) {
|
||||
std::string_view keyv;
|
||||
error = field.unescaped_key().get(keyv);
|
||||
if(error) { return false; }
|
||||
if(keyv == "key") {
|
||||
uint64_t intvalue;
|
||||
error = field.value().get(intvalue);
|
||||
if(error) { return false; }
|
||||
std::cout << intvalue;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool exception_free_object_loop_no_escape() {
|
||||
auto json = R"({"k\u0065y": 1})"_padded;
|
||||
ondemand::parser parser;
|
||||
ondemand::document doc;
|
||||
auto error = parser.iterate(json).get(doc);
|
||||
if(error) { return false; }
|
||||
ondemand::object object;
|
||||
error = doc.get_object().get(object);
|
||||
if(error) { return false; }
|
||||
for(auto field : object) {
|
||||
ondemand::raw_json_string keyv;
|
||||
error = field.key().get(keyv);
|
||||
/**
|
||||
* If you need to escape the keys, you can do
|
||||
* std::string_view keyv;
|
||||
* error = field.unescaped_key().get(keyv);
|
||||
*/
|
||||
if(error) { return false; }
|
||||
if(keyv == "key") {
|
||||
uint64_t intvalue;
|
||||
error = field.value().get(intvalue);
|
||||
if(error) { return false; }
|
||||
std::cout << intvalue;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool using_the_parsed_json_6() {
|
||||
TEST_START();
|
||||
ASSERT_EQUAL(using_the_parsed_json_6_process(), EXIT_SUCCESS);
|
||||
|
|
Loading…
Reference in New Issue