Let us try to check with the exceptions disabled. (#707)
* Tweaking code so that we can run all tests with exceptions off. * Removing SIMDJSON_DISABLE_EXCEPTIONS
This commit is contained in:
parent
efd706528b
commit
6d7c77ddc1
|
@ -92,7 +92,16 @@ jobs:
|
|||
executor: clang6
|
||||
environment: { CMAKE_TEST_FLAGS: -DSIMDJSON_ENABLE_THREADS=ON }
|
||||
steps: [ init_clang6, cmake_test ]
|
||||
|
||||
gcc-avx-noexcept:
|
||||
description: Build, run tests and check performance on GCC 7 and AVX 2 *without* threads
|
||||
executor: gcc7
|
||||
environment: { CMAKE_TEST_FLAGS: -DSIMDJSON_DISABLE_EXCEPTIONS=ON }
|
||||
steps: [ cmake_test ]
|
||||
clang-avx-noexcept:
|
||||
description: Build, run tests and check performance on Clang 6 and AVX 2 with threads
|
||||
executor: clang6
|
||||
environment: { CMAKE_TEST_FLAGS: -DSIMDJSON_DISABLE_EXCEPTIONS=ON }
|
||||
steps: [ init_clang6, cmake_test ]
|
||||
gcc9-avx:
|
||||
description: Build, run tests and check performance on GCC 9 and AVX 2
|
||||
executor: gcc9
|
||||
|
@ -197,6 +206,8 @@ workflows:
|
|||
version: 2.1
|
||||
build_and_test:
|
||||
jobs:
|
||||
- gcc-avx-noexcept
|
||||
- clang-avx-noexcept
|
||||
- gcc9-avx
|
||||
- gcc8-avx
|
||||
- gcc-avx
|
||||
|
|
|
@ -65,23 +65,30 @@ void print_vec(const std::vector<int64_t> &v) {
|
|||
|
||||
void simdjson_recurse(std::vector<int64_t> & v, simdjson::dom::element element) {
|
||||
if (element.is<simdjson::dom::array>()) {
|
||||
auto array = element.get<simdjson::dom::array>();
|
||||
simdjson::dom::array array;
|
||||
simdjson::error_code error;
|
||||
element.get<simdjson::dom::array>().tie(array, error);
|
||||
for (auto child : array) {
|
||||
if (child.is<simdjson::dom::array>() || child.is<simdjson::dom::object>()) {
|
||||
simdjson_recurse(v, child);
|
||||
}
|
||||
}
|
||||
} else if (element.is<simdjson::dom::object>()) {
|
||||
auto object = element.get<simdjson::dom::object>();
|
||||
simdjson::dom::object object;
|
||||
simdjson::error_code error;
|
||||
element.get<simdjson::dom::object>().tie(object, error);
|
||||
for (auto [key, value] : object) {
|
||||
if((key.size() == 4) && (memcmp(key.data(), "user", 4) == 0)) {
|
||||
// we are in an object under the key "user"
|
||||
if(value.is<simdjson::dom::object>()) {
|
||||
auto child_object = value.get<simdjson::dom::object>();
|
||||
simdjson::dom::object child_object;
|
||||
value.get<simdjson::dom::object>().tie(child_object, error);
|
||||
for (auto [child_key, child_value] : child_object) {
|
||||
if((child_key.size() == 2) && (memcmp(child_key.data(), "id", 2) == 0)) {
|
||||
if(child_value.is<int64_t>()) {
|
||||
v.push_back(child_value.get<int64_t>());
|
||||
int64_t x;
|
||||
child_value.get<int64_t>().tie(x, error);
|
||||
v.push_back(x);
|
||||
}
|
||||
}
|
||||
if (child_value.is<simdjson::dom::array>() || child_value.is<simdjson::dom::object>()) {
|
||||
|
@ -111,9 +118,13 @@ __attribute__((noinline)) std::vector<int64_t>
|
|||
simdjson_compute_stats(const simdjson::padded_string &p) {
|
||||
std::vector<int64_t> answer;
|
||||
simdjson::dom::parser parser;
|
||||
simdjson::dom::element doc = parser.parse(p);
|
||||
simdjson_recurse(answer, doc);
|
||||
remove_duplicates(answer);
|
||||
simdjson::dom::element doc;
|
||||
simdjson::error_code error;
|
||||
parser.parse(p).tie(doc, error);
|
||||
if(!error) {
|
||||
simdjson_recurse(answer, doc);
|
||||
remove_duplicates(answer);
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
|
||||
|
@ -373,7 +384,8 @@ int main(int argc, char *argv[]) {
|
|||
BEST_TIME("sasjon (just parse) ", sasjon_just_parse(p), false, , repeat,
|
||||
volume, !just_data);
|
||||
simdjson::dom::parser parser;
|
||||
simdjson::dom::element doc = parser.parse(p);
|
||||
simdjson::dom::element doc;
|
||||
parser.parse(p).tie(doc, error);
|
||||
BEST_TIME("simdjson (just dom) ", simdjson_just_dom(doc).size(), size,
|
||||
, repeat, volume, !just_data);
|
||||
char *buffer = (char *)malloc(p.size() + 1);
|
||||
|
|
|
@ -54,7 +54,10 @@ really_inline void simdjson_process_atom(stat_t &s,
|
|||
if (element.is<double>()) {
|
||||
s.number_count++;
|
||||
} else if (element.is<bool>()) {
|
||||
if (element.get<bool>()) {
|
||||
simdjson::error_code err;
|
||||
bool v;
|
||||
element.get<bool>().tie(v,err);
|
||||
if (v) {
|
||||
s.true_count++;
|
||||
} else {
|
||||
s.false_count++;
|
||||
|
|
|
@ -29,7 +29,8 @@ std::string exec(const char* cmd) {
|
|||
std::string result;
|
||||
std::unique_ptr<FILE, decltype(&closepipe)> pipe(popen(cmd, "r"), closepipe);
|
||||
if (!pipe) {
|
||||
throw std::runtime_error("popen() failed!");
|
||||
std::cerr << "popen() failed!" << std::endl;
|
||||
abort();
|
||||
}
|
||||
while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) {
|
||||
result += buffer.data();
|
||||
|
|
|
@ -52,7 +52,10 @@ really_inline void simdjson_process_atom(stat_t &s,
|
|||
} else if(element.is<double>()) {
|
||||
s.float_count++;
|
||||
} else if (element.is<bool>()) {
|
||||
if (element.get<bool>()) {
|
||||
simdjson::error_code err;
|
||||
bool v;
|
||||
element.get<bool>().tie(v,err);
|
||||
if (v) {
|
||||
s.true_count++;
|
||||
} else {
|
||||
s.false_count++;
|
||||
|
|
|
@ -190,6 +190,29 @@ behavior.
|
|||
> parser.parse(json).tie(doc, error); // <-- Assigns to doc and error just like "auto [doc, error]"
|
||||
> ```
|
||||
|
||||
|
||||
We can write a "quick start" example where we attempt to parse a file and access some data, without triggering exceptions:
|
||||
|
||||
```C++
|
||||
#include "simdjson.h"
|
||||
|
||||
int main(void) {
|
||||
simdjson::dom::parser parser;
|
||||
simdjson::dom::element tweets;
|
||||
simdjson::error_code error;
|
||||
parser.load("twitter.json").tie(tweets,error);
|
||||
if (error) { std::cerr << error << std::endl; return EXIT_FAILURE; }
|
||||
simdjson::dom::element res;
|
||||
|
||||
tweets["search_metadata"]["count"].tie(res,error);
|
||||
if(error) {
|
||||
std::cerr << "could not access keys" << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
std::cout << res << " results." << std::endl;
|
||||
}
|
||||
```
|
||||
|
||||
### Error Handling Example
|
||||
|
||||
This is how the example in "Using the Parsed JSON" could be written using only error code checking:
|
||||
|
|
|
@ -1,2 +1,6 @@
|
|||
add_executable(quickstart quickstart.cpp)
|
||||
target_link_libraries(quickstart PRIVATE simdjson)
|
||||
if(SIMDJSON_EXCEPTIONS)
|
||||
add_executable(quickstart quickstart.cpp)
|
||||
target_link_libraries(quickstart PRIVATE simdjson)
|
||||
endif()
|
||||
add_executable(quickstart_noexceptions quickstart_noexceptions.cpp)
|
||||
target_link_libraries(quickstart_noexceptions PRIVATE simdjson)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "simdjson.h"
|
||||
|
||||
int main(void) {
|
||||
simdjson::dom::parser parser;
|
||||
simdjson::dom::element tweets = parser.load("twitter.json");
|
||||
std::cout << tweets["search_metadata"]["count"] << " results." << std::endl;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
#include "simdjson.h"
|
||||
|
||||
int main(void) {
|
||||
simdjson::dom::parser parser;
|
||||
simdjson::dom::element tweets;
|
||||
simdjson::error_code error;
|
||||
parser.load("twitter.json").tie(tweets,error);
|
||||
if (error) { std::cerr << error << std::endl; return EXIT_FAILURE; }
|
||||
simdjson::dom::element res;
|
||||
|
||||
tweets["search_metadata"]["count"].tie(res,error);
|
||||
if(error) {
|
||||
std::cerr << "could not access keys" << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
std::cout << res << " results." << std::endl;
|
||||
}
|
||||
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
// example from doc/basics.md#tree-walking-and-json-element-types
|
||||
static void print_json(std::ostream& os, simdjson::dom::element element) {
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
const char endl='\n';
|
||||
switch (element.type()) {
|
||||
case simdjson::dom::element_type::ARRAY:
|
||||
|
@ -46,9 +47,10 @@ static void print_json(std::ostream& os, simdjson::dom::element element) {
|
|||
os << "null" << endl;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
|
||||
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
try {
|
||||
simdjson::dom::parser pj;
|
||||
auto elem=pj.parse(Data, Size);
|
||||
|
@ -58,6 +60,6 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
|
|||
print_json(os,v);
|
||||
} catch (...) {
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#include "NullBuffer.h"
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
|
||||
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
try {
|
||||
simdjson::dom::parser pj;
|
||||
auto elem=pj.parse(Data, Size);
|
||||
|
@ -16,5 +16,6 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
|
|||
UNUSED auto dumpstatus=v.dump_raw_tape(os);
|
||||
} catch (...) {
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
|
|||
auto end = begin + Size;
|
||||
|
||||
std::string str(begin, end);
|
||||
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
try {
|
||||
simdjson::dom::parser parser;
|
||||
simdjson::dom::element doc = parser.parse(str);
|
||||
|
@ -17,5 +17,6 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
|
|||
} catch (...) {
|
||||
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -3,12 +3,13 @@
|
|||
#include <cstdint>
|
||||
#include <string>
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
|
||||
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
try {
|
||||
simdjson::dom::parser pj;
|
||||
auto result=pj.parse(Data, Size);
|
||||
UNUSED auto v=result.value();
|
||||
}catch(...) {
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
|
||||
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
try {
|
||||
simdjson::dom::parser pj;
|
||||
auto elem=pj.parse(Data, Size);
|
||||
|
@ -15,5 +15,6 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
|
|||
os<<elem;
|
||||
} catch (...) {
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -41,6 +41,9 @@ option(SIMDJSON_EXCEPTIONS "Enable simdjson's exception-throwing interface" ON)
|
|||
if(NOT SIMDJSON_EXCEPTIONS)
|
||||
message(STATUS "simdjson exception interface turned off. Code that does not check error codes will not compile.")
|
||||
target_compile_definitions(simdjson-headers INTERFACE SIMDJSON_EXCEPTIONS=0)
|
||||
if(UNIX)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions")
|
||||
endif(UNIX)
|
||||
endif()
|
||||
|
||||
option(SIMDJSON_ENABLE_THREADS "Enable threaded operation" ON)
|
||||
|
|
|
@ -73,18 +73,24 @@ endfunction(add_compile_test)
|
|||
|
||||
# Don't add the tests if we're on VS2017 or older; they don't succeed.
|
||||
if(NOT (MSVC AND MSVC_VERSION LESS 1920))
|
||||
if(SIMDJSON_EXCEPTIONS)
|
||||
add_compile_test(readme_examples readme_examples.cpp quicktests)
|
||||
set_property(
|
||||
TEST readme_examples
|
||||
APPEND PROPERTY LABELS quicktests
|
||||
)
|
||||
endif()
|
||||
add_compile_test(readme_examples_noexceptions readme_examples_noexceptions.cpp quicktests)
|
||||
|
||||
# Compile tests that *should fail*
|
||||
add_compile_test(readme_examples_will_fail_with_exceptions_off readme_examples.cpp)
|
||||
target_compile_definitions(readme_examples_will_fail_with_exceptions_off PRIVATE SIMDJSON_EXCEPTIONS=0)
|
||||
set_tests_properties(readme_examples_will_fail_with_exceptions_off PROPERTIES WILL_FAIL TRUE)
|
||||
|
||||
set_property(
|
||||
TEST readme_examples readme_examples_noexceptions readme_examples_will_fail_with_exceptions_off
|
||||
TEST readme_examples_noexceptions readme_examples_will_fail_with_exceptions_off
|
||||
APPEND PROPERTY LABELS quicktests
|
||||
)
|
||||
|
||||
endif()
|
||||
|
||||
|
||||
|
|
|
@ -258,7 +258,14 @@ namespace document_tests {
|
|||
"}"_padded;
|
||||
simdjson::dom::parser parser;
|
||||
std::ostringstream myStream;
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
myStream << parser.parse(json);
|
||||
#else
|
||||
simdjson::dom::element doc;
|
||||
simdjson::error_code error;
|
||||
parser.parse(json).tie(doc, error);
|
||||
myStream << doc;
|
||||
#endif
|
||||
std::string newjson = myStream.str();
|
||||
if(static_cast<std::string>(json) != newjson) {
|
||||
std::cout << "serialized json differs!" << std::endl;
|
||||
|
@ -1280,7 +1287,6 @@ namespace type_tests {
|
|||
// T() == expected
|
||||
actual = T(result);
|
||||
ASSERT_EQUAL(actual, expected);
|
||||
|
||||
actual = T(element);
|
||||
ASSERT_EQUAL(actual, expected);
|
||||
|
||||
|
@ -1309,6 +1315,7 @@ namespace type_tests {
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
bool test_cast(simdjson_result<dom::element> result) {
|
||||
std::cout << " test_cast<" << typeid(T).name() << "> expecting success" << std::endl;
|
||||
|
@ -1369,7 +1376,6 @@ namespace type_tests {
|
|||
bool test_cast(simdjson_result<dom::element> result, simdjson::error_code expected_error) {
|
||||
std::cout << " test_cast<" << typeid(T).name() << "> expecting error '" << expected_error << "'" << std::endl;
|
||||
dom::element element = result.first;
|
||||
|
||||
// get<T>() == expected
|
||||
T actual;
|
||||
simdjson::error_code error;
|
||||
|
@ -1428,7 +1434,6 @@ 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_type actual_type;
|
||||
simdjson::error_code error;
|
||||
result.type().tie(actual_type, error);
|
||||
|
@ -1460,7 +1465,6 @@ namespace type_tests {
|
|||
std::cout << " test_is_null() expecting " << expected_is_null << std::endl;
|
||||
// Grab the element out and check success
|
||||
dom::element element = result.first;
|
||||
|
||||
bool actual_is_null;
|
||||
simdjson::error_code error;
|
||||
result.is_null().tie(actual_is_null, error);
|
||||
|
@ -1549,7 +1553,6 @@ namespace type_tests {
|
|||
|
||||
dom::parser parser;
|
||||
simdjson_result<dom::element> result = parser.parse(ALL_TYPES_JSON)[key];
|
||||
|
||||
return true
|
||||
&& test_type(result, dom::element_type::INT64)
|
||||
&& test_cast<dom::array>(result, INCORRECT_TYPE)
|
||||
|
@ -1589,7 +1592,6 @@ namespace type_tests {
|
|||
|
||||
dom::parser parser;
|
||||
simdjson_result<dom::element> result = parser.parse(ALL_TYPES_JSON)[key];
|
||||
|
||||
return true
|
||||
&& test_type(result, dom::element_type::DOUBLE)
|
||||
&& test_cast<dom::array>(result, INCORRECT_TYPE)
|
||||
|
|
|
@ -96,12 +96,15 @@ void recurse(simdjson::dom::element element, stat_t &s, size_t depth) {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
simdjson::error_code error;
|
||||
if (element.is<double>()) {
|
||||
s.float_count++;
|
||||
} else if (element.is<int64_t>()) {
|
||||
s.integer_count++;
|
||||
} else if (element.is<bool>()) {
|
||||
if (element.get<bool>()) {
|
||||
bool v;
|
||||
element.get<bool>().tie(v,error);
|
||||
if (v) {
|
||||
s.true_count++;
|
||||
} else {
|
||||
s.false_count++;
|
||||
|
@ -110,15 +113,19 @@ void recurse(simdjson::dom::element element, stat_t &s, size_t depth) {
|
|||
s.null_count++;
|
||||
} else if (element.is<std::string_view>()) {
|
||||
s.string_count++;
|
||||
if (is_ascii(element.get<std::string_view>())) {
|
||||
std::string_view v;
|
||||
element.get<std::string_view>().tie(v,error);
|
||||
if (is_ascii(v)) {
|
||||
s.ascii_string_count++;
|
||||
}
|
||||
const std::string_view strval = element.get<std::string_view>();
|
||||
std::string_view strval;
|
||||
element.get<std::string_view>().tie(strval, error);
|
||||
if (strval.size() > s.string_maximum_length) {
|
||||
s.string_maximum_length = strval.size();
|
||||
}
|
||||
} else {
|
||||
throw std::runtime_error("unrecognized node.");
|
||||
std::cerr << "unrecognized node." << std::endl;
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue