Merge pull request #643 from simdjson/jkeiser/get

Replace as_X and is_X with get<T> and is<T>
This commit is contained in:
John Keiser 2020-03-28 16:46:05 -07:00 committed by GitHub
commit d4f4608dab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 280 additions and 365 deletions

View File

@ -25,6 +25,8 @@ static void twitter_count(State& state) {
}
BENCHMARK(twitter_count);
SIMDJSON_PUSH_DISABLE_WARNINGS
SIMDJSON_DISABLE_DEPRECATED_WARNING
static void iterator_twitter_count(State& state) {
// Prints the number of results in twitter.json
padded_string json = padded_string::load(JSON_TEST_PATH);
@ -41,6 +43,7 @@ static void iterator_twitter_count(State& state) {
}
}
BENCHMARK(iterator_twitter_count);
SIMDJSON_POP_DISABLE_WARNINGS
static void twitter_default_profile(State& state) {
// Count unique users with a default profile.
@ -48,7 +51,7 @@ static void twitter_default_profile(State& state) {
dom::element doc = parser.load(JSON_TEST_PATH);
for (auto _ : state) {
set<string_view> default_users;
for (dom::object tweet : doc["statuses"].as_array()) {
for (dom::object tweet : doc["statuses"].get<dom::array>()) {
dom::object user = tweet["user"];
if (user["default_profile"]) {
default_users.insert(user["screen_name"]);
@ -65,11 +68,11 @@ static void twitter_image_sizes(State& state) {
dom::element doc = parser.load(JSON_TEST_PATH);
for (auto _ : state) {
set<tuple<uint64_t, uint64_t>> image_sizes;
for (dom::object tweet : doc["statuses"].as_array()) {
for (dom::object tweet : doc["statuses"].get<dom::array>()) {
auto [media, not_found] = tweet["entities"]["media"];
if (!not_found) {
for (dom::object image : media.as_array()) {
for (auto [key, size] : image["sizes"].as_object()) {
for (dom::object image : media.get<dom::array>()) {
for (auto [key, size] : image["sizes"].get<dom::object>()) {
image_sizes.insert({ size["w"], size["h"] });
}
}
@ -87,7 +90,7 @@ static void error_code_twitter_count(State& state) noexcept {
dom::parser parser;
dom::element doc = parser.load(JSON_TEST_PATH);
for (auto _ : state) {
auto [value, error] = doc["search_metadata"]["count"].as_uint64_t();
auto [value, error] = doc["search_metadata"]["count"].get<uint64_t>();
if (error) { return; }
if (value != 100) { return; }
}
@ -101,15 +104,15 @@ static void error_code_twitter_default_profile(State& state) noexcept {
for (auto _ : state) {
set<string_view> default_users;
auto [tweets, error] = doc["statuses"].as_array();
auto [tweets, error] = doc["statuses"].get<dom::array>();
if (error) { return; }
for (dom::element tweet : tweets) {
auto [user, error2] = tweet["user"].as_object();
auto [user, error2] = tweet["user"].get<dom::object>();
if (error2) { return; }
auto [default_profile, error3] = user["default_profile"].as_bool();
auto [default_profile, error3] = user["default_profile"].get<bool>();
if (error3) { return; }
if (default_profile) {
auto [screen_name, error4] = user["screen_name"].as_string();
auto [screen_name, error4] = user["screen_name"].get<std::string_view>();
if (error4) { return; }
default_users.insert(screen_name);
}
@ -120,6 +123,8 @@ static void error_code_twitter_default_profile(State& state) noexcept {
}
BENCHMARK(error_code_twitter_default_profile);
SIMDJSON_PUSH_DISABLE_WARNINGS
SIMDJSON_DISABLE_DEPRECATED_WARNING
static void iterator_twitter_default_profile(State& state) {
// Count unique users with a default profile.
padded_string json = padded_string::load(JSON_TEST_PATH);
@ -128,7 +133,7 @@ static void iterator_twitter_default_profile(State& state) {
set<string_view> default_users;
ParsedJson::Iterator iter(pj);
// for (dom::object tweet : doc["statuses"].as_array()) {
// for (dom::object tweet : doc["statuses"].get<dom::array>()) {
if (!(iter.move_to_key("statuses") && iter.is_array())) { return; }
if (iter.down()) { // first status
do {
@ -156,6 +161,7 @@ static void iterator_twitter_default_profile(State& state) {
if (default_users.size() != 86) { return; }
}
}
SIMDJSON_POP_DISABLE_WARNINGS
BENCHMARK(iterator_twitter_default_profile);
static void error_code_twitter_image_sizes(State& state) noexcept {
@ -164,17 +170,17 @@ static void error_code_twitter_image_sizes(State& state) noexcept {
dom::element doc = parser.load(JSON_TEST_PATH);
for (auto _ : state) {
set<tuple<uint64_t, uint64_t>> image_sizes;
auto [statuses, error] = doc["statuses"].as_array();
auto [statuses, error] = doc["statuses"].get<dom::array>();
if (error) { return; }
for (dom::element tweet : statuses) {
auto [images, not_found] = tweet["entities"]["media"].as_array();
auto [images, not_found] = tweet["entities"]["media"].get<dom::array>();
if (!not_found) {
for (dom::element image : images) {
auto [sizes, error2] = image["sizes"].as_object();
auto [sizes, error2] = image["sizes"].get<dom::object>();
if (error2) { return; }
for (auto [key, size] : sizes) {
auto [width, error3] = size["w"].as_uint64_t();
auto [height, error4] = size["h"].as_uint64_t();
auto [width, error3] = size["w"].get<uint64_t>();
auto [height, error4] = size["h"].get<uint64_t>();
if (error3 || error4) { return; }
image_sizes.insert({ width, height });
}
@ -186,6 +192,8 @@ static void error_code_twitter_image_sizes(State& state) noexcept {
}
BENCHMARK(error_code_twitter_image_sizes);
SIMDJSON_PUSH_DISABLE_WARNINGS
SIMDJSON_DISABLE_DEPRECATED_WARNING
static void iterator_twitter_image_sizes(State& state) {
// Count unique image sizes
padded_string json = padded_string::load(JSON_TEST_PATH);
@ -194,7 +202,7 @@ static void iterator_twitter_image_sizes(State& state) {
set<tuple<uint64_t, uint64_t>> image_sizes;
ParsedJson::Iterator iter(pj);
// for (dom::object tweet : doc["statuses"].as_array()) {
// for (dom::object tweet : doc["statuses"].get<dom::array>()) {
if (!(iter.move_to_key("statuses") && iter.is_array())) { return; }
if (iter.down()) { // first status
do {
@ -206,11 +214,11 @@ static void iterator_twitter_image_sizes(State& state) {
if (iter.move_to_key("media")) {
if (!iter.is_array()) { return; }
// for (dom::object image : media.as_array()) {
// for (dom::object image : media.get<dom::array>()) {
if (iter.down()) { // first media
do {
// for (auto [key, size] : image["sizes"].as_object()) {
// for (auto [key, size] : image["sizes"].get<dom::object>()) {
if (!(iter.move_to_key("sizes") && iter.is_object())) { return; }
if (iter.down()) { // first size
do {
@ -256,5 +264,6 @@ static void print_json(State& state) noexcept {
}
}
BENCHMARK(print_json);
SIMDJSON_POP_DISABLE_WARNINGS
BENCHMARK_MAIN();

View File

@ -6,6 +6,8 @@ using namespace std;
const padded_string EMPTY_ARRAY("[]", 2);
SIMDJSON_PUSH_DISABLE_WARNINGS
SIMDJSON_DISABLE_DEPRECATED_WARNING
static void json_parse(State& state) {
dom::parser parser;
if (parser.set_capacity(EMPTY_ARRAY.length())) { return; }
@ -14,6 +16,7 @@ static void json_parse(State& state) {
if (error) { return; }
}
}
SIMDJSON_POP_DISABLE_WARNINGS
BENCHMARK(json_parse);
static void parser_parse_error_code(State& state) {
dom::parser parser;
@ -37,12 +40,15 @@ static void parser_parse_exception(State& state) {
}
BENCHMARK(parser_parse_exception);
SIMDJSON_PUSH_DISABLE_WARNINGS
SIMDJSON_DISABLE_DEPRECATED_WARNING
static void build_parsed_json(State& state) {
for (auto _ : state) {
dom::parser parser = simdjson::build_parsed_json(EMPTY_ARRAY);
if (!parser.valid) { return; }
}
}
SIMDJSON_POP_DISABLE_WARNINGS
BENCHMARK(build_parsed_json);
static void document_parse_error_code(State& state) {
for (auto _ : state) {

View File

@ -39,22 +39,22 @@ void print_vec(const std::vector<int64_t> &v) {
// simdjson_recurse below come be implemented like so but it is slow:
/*void simdjson_recurse(std::vector<int64_t> & v, simdjson::dom::element element) {
if (element.is_array()) {
auto [array, array_error] = element.as_array();
if (element.is<simdjson::dom::array>()) {
auto [array, array_error] = element.get<simdjson::dom::array>();
for (auto child : array) {
if (child.is_array() || child.is_object()) {
if (child.is<simdjson::dom::array>() || child.is<simdjson::dom::object>()) {
simdjson_recurse(v, child);
}
}
} else if (element.is_object()) {
auto [object, error] = element.as_object();
} else if (element.is<simdjson::dom::object>()) {
auto [object, error] = element.get<simdjson::dom::object>();
int64_t id;
object["user"]["id"].as_int64_t().tie(id,error);
object["user"]["id"].get<int64_t>().tie(id,error);
if(!error) {
v.push_back(id);
}
for (auto [key, value] : object) {
if (value.is_array() || value.is_object()) {
if (value.is<simdjson::dom::array>() || value.is<simdjson::dom::object>()) {
simdjson_recurse(v, value);
}
}
@ -64,35 +64,35 @@ void print_vec(const std::vector<int64_t> &v) {
void simdjson_recurse(std::vector<int64_t> & v, simdjson::dom::element element) {
if (element.is_array()) {
auto array = element.as_array();
if (element.is<simdjson::dom::array>()) {
auto array = element.get<simdjson::dom::array>();
for (auto child : array) {
if (child.is_array() || child.is_object()) {
if (child.is<simdjson::dom::array>() || child.is<simdjson::dom::object>()) {
simdjson_recurse(v, child);
}
}
} else if (element.is_object()) {
auto object = element.as_object();
} else if (element.is<simdjson::dom::object>()) {
auto object = element.get<simdjson::dom::object>();
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_object()) {
auto child_object = value.as_object();
if(value.is<simdjson::dom::object>()) {
auto child_object = value.get<simdjson::dom::object>();
for (auto [child_key, child_value] : child_object) {
if((child_key.size() == 2) && (memcmp(child_key.data(), "id", 2) == 0)) {
if(child_value.is_integer()) {
v.push_back(child_value.as_int64_t());
if(child_value.is<int64_t>()) {
v.push_back(child_value.get<int64_t>());
}
}
if (child_value.is_array() || child_value.is_object()) {
if (child_value.is<simdjson::dom::array>() || child_value.is<simdjson::dom::object>()) {
simdjson_recurse(v, child_value);
}
}
} else if (value.is_array()) {
} else if (value.is<simdjson::dom::array>()) {
simdjson_recurse(v, value);
}
// end of: we are in an object under the key "user"
} else if (value.is_array() || value.is_object()) {
} else if (value.is<simdjson::dom::array>() || value.is<simdjson::dom::object>()) {
simdjson_recurse(v, value);
}
}

View File

@ -51,10 +51,10 @@ void print_stat(const stat_t &s) {
really_inline void simdjson_process_atom(stat_t &s,
simdjson::dom::element element) {
if (element.is_number()) {
if (element.is<double>()) {
s.number_count++;
} else if (element.is_bool()) {
if (element.as_bool()) {
} else if (element.is<bool>()) {
if (element.get<bool>()) {
s.true_count++;
} else {
s.false_count++;
@ -65,21 +65,21 @@ really_inline void simdjson_process_atom(stat_t &s,
}
void simdjson_recurse(stat_t &s, simdjson::dom::element element) {
if (element.is_array()) {
if (element.is<simdjson::dom::array>()) {
s.array_count++;
auto [array, array_error] = element.as_array();
auto [array, array_error] = element.get<simdjson::dom::array>();
for (auto child : array) {
if (child.is_array() || child.is_object()) {
if (child.is<simdjson::dom::array>() || child.is<simdjson::dom::object>()) {
simdjson_recurse(s, child);
} else {
simdjson_process_atom(s, child);
}
}
} else if (element.is_object()) {
} else if (element.is<simdjson::dom::object>()) {
s.object_count++;
auto [object, object_error] = element.as_object();
auto [object, object_error] = element.get<simdjson::dom::object>();
for (auto [key, value] : object) {
if (value.is_array() || value.is_object()) {
if (value.is<simdjson::dom::array>() || value.is<simdjson::dom::object>()) {
simdjson_recurse(s, value);
} else {
simdjson_process_atom(s, value);

View File

@ -109,7 +109,7 @@ bool bench(const char *filename, bool verbose, bool just_data, int repeat_multip
}
if (!just_data)
BEST_TIME("simdjson (dynamic mem) ", !simdjson::dom::parser().parse(p).error(), true,
BEST_TIME("simdjson (dynamic mem) ", simdjson::dom::parser().parse(p).error(), simdjson::SUCCESS,
, repeat, volume, !just_data);
// (static alloc)
simdjson::dom::parser parser;
@ -197,14 +197,14 @@ bool bench(const char *filename, bool verbose, bool just_data, int repeat_multip
{
std::unique_ptr<jsmntok_t[]> tokens =
std::make_unique<jsmntok_t[]>(p.size());
jsmn_parser parser;
jsmn_init(&parser);
jsmn_parser jparser;
jsmn_init(&jparser);
memcpy(buffer, p.data(), p.size());
buffer[p.size()] = '\0';
BEST_TIME(
"jsmn ",
(jsmn_parse(&parser, buffer, p.size(), tokens.get(), p.size()) > 0),
true, jsmn_init(&parser), repeat, volume, !just_data);
(jsmn_parse(&jparser, buffer, p.size(), tokens.get(), p.size()) > 0),
true, jsmn_init(&jparser), repeat, volume, !just_data);
}
memcpy(buffer, p.data(), p.size());
buffer[p.size()] = '\0';
@ -244,8 +244,8 @@ bool bench(const char *filename, bool verbose, bool just_data, int repeat_multip
std::fill(stats.begin(), stats.end(), 0); // unnecessary
for (int i = 0; i < repeat; i++) {
unified.start();
auto [doc, error] = parser.parse(p);
if (error)
auto [doc, parse_error] = parser.parse(p);
if (parse_error)
printf("bug\n");
unified.end(results);
std::transform(stats.begin(), stats.end(), results.begin(), stats.begin(),

View File

@ -45,14 +45,14 @@ using stat_t = struct stat_s;
really_inline void simdjson_process_atom(stat_t &s,
simdjson::dom::element element) {
if (element.is_integer()) {
if (element.is<int64_t>()) {
s.integer_count++;
} else if(element.is_string()) {
} else if(element.is<std::string_view>()) {
s.string_count++;
} else if(element.is_float()) {
} else if(element.is<double>()) {
s.float_count++;
} else if (element.is_bool()) {
if (element.as_bool()) {
} else if (element.is<bool>()) {
if (element.get<bool>()) {
s.true_count++;
} else {
s.false_count++;
@ -63,22 +63,22 @@ really_inline void simdjson_process_atom(stat_t &s,
}
void simdjson_recurse(stat_t &s, simdjson::dom::element element) {
if (element.is_array()) {
if (element.is<simdjson::dom::array>()) {
s.array_count++;
auto [array, array_error] = element.as_array();
auto [array, array_error] = element.get<simdjson::dom::array>();
for (auto child : array) {
if (child.is_array() || child.is_object()) {
if (child.is<simdjson::dom::array>() || child.is<simdjson::dom::object>()) {
simdjson_recurse(s, child);
} else {
simdjson_process_atom(s, child);
}
}
} else if (element.is_object()) {
} else if (element.is<simdjson::dom::object>()) {
s.object_count++;
auto [object, object_error] = element.as_object();
auto [object, object_error] = element.get<simdjson::dom::object>();
for (auto [key, value] : object) {
s.string_count++; // for key
if (value.is_array() || value.is_object()) {
if (value.is<simdjson::dom::array>() || value.is<simdjson::dom::object>()) {
simdjson_recurse(s, value);
} else {
simdjson_process_atom(s, value);

View File

@ -73,7 +73,7 @@ auto cars_json = R"( [
{ "make": "Toyota", "model": "Tercel", "year": 1999, "tire_pressure": [ 29.8, 30.0, 30.2, 30.5 ] }
] )"_padded;
dom::parser parser;
dom::array cars = parser.parse(cars_json).as_array();
dom::array cars = parser.parse(cars_json).get<dom::array>();
// Iterating through an array of objects
for (dom::object car : cars) {
@ -158,7 +158,7 @@ if (error) { cerr << error << endl; exit(1); }
// Iterating through an array of objects
for (dom::element car_element : cars) {
dom::object car;
car_element.as_object().tie(car, error);
car_element.get<dom::object>().tie(car, error);
if (error) { cerr << error << endl; exit(1); }
// Accessing a field by name
@ -171,7 +171,7 @@ for (dom::element car_element : cars) {
// Casting a JSON element to an integer
uint64_t year;
car["year"].as_uint64_t().tie(year, error);
car["year"].get<uint64_t>().tie(year, error);
if (error) { cerr << error << endl; exit(1); }
cout << "- This car is " << 2020 - year << "years old." << endl;
@ -179,7 +179,7 @@ for (dom::element car_element : cars) {
double total_tire_pressure = 0;
for (dom::element tire_pressure_element : car["tire_pressure"]) {
double tire_pressure;
tire_pressure_element.as_uint64_t().tie(tire_pressure, error);
tire_pressure_element.get<uint64_t>().tie(tire_pressure, error);
if (error) { cerr << error << endl; exit(1); }
total_tire_pressure += tire_pressure;
}

View File

@ -151,97 +151,33 @@ public:
/** Whether this element is a json `null`. */
really_inline bool is_null() const noexcept;
/** Whether this is a JSON `true` or `false` */
really_inline bool is_bool() const noexcept;
/** Whether this is a JSON number (e.g. 1, 1.0 or 1e2) */
really_inline bool is_number() const noexcept;
/** Whether this is a JSON integer (e.g. 1 or -1, but *not* 1.0 or 1e2) */
really_inline bool is_integer() const noexcept;
/** Whether this is a JSON integer in [9223372036854775808, 18446744073709551616)
* that is, a value too large for a signed 64-bit integer, but that still fits
* in a 64-bit word. Note that is_integer() is true when is_unsigned_integer()
* is true.*/
really_inline bool is_unsigned_integer() const noexcept;
/** Whether this is a JSON number but not an integer */
really_inline bool is_float() const noexcept;
/** Whether this is a JSON string (e.g. "abc") */
really_inline bool is_string() const noexcept;
/** Whether this is a JSON array (e.g. []) */
really_inline bool is_array() const noexcept;
/** Whether this is a JSON array (e.g. []) */
really_inline bool is_object() const noexcept;
/**
* Read this element as a boolean (json `true` or `false`).
* Tell whether the value can be cast to the given primitive type.
*
* @return The boolean value, or:
* - UNEXPECTED_TYPE error if the JSON element is not a boolean
* Supported types:
* - Boolean: bool
* - Number: double, uint64_t, int64_t
* - String: std::string_view, const char *
* - Array: array
*/
inline simdjson_result<bool> as_bool() const noexcept;
template<typename T>
really_inline bool is() const noexcept;
/**
* Read this element as a null-terminated string.
* Get the value as the given primitive type.
*
* Does *not* convert other types to a string; requires that the JSON type of the element was
* an actual string.
* Supported types:
* - Boolean: bool
* - Number: double, uint64_t, int64_t
* - String: std::string_view, const char *
* - Array: array
*
* @return A `string_view` into the string, or:
* - UNEXPECTED_TYPE error if the JSON element is not a string
* @returns The value cast to the given type, or:
* INCORRECT_TYPE if the value cannot be cast to the given type.
*/
inline simdjson_result<const char *> as_c_str() const noexcept;
/**
* Read this element as a C++ string_view (string with length).
*
* Does *not* convert other types to a string; requires that the JSON type of the element was
* an actual string.
*
* @return A `string_view` into the string, or:
* - UNEXPECTED_TYPE error if the JSON element is not a string
*/
inline simdjson_result<std::string_view> as_string() const noexcept;
/**
* Read this element as an unsigned integer.
*
* @return The uninteger value, or:
* - UNEXPECTED_TYPE if the JSON element is not an integer
* - NUMBER_OUT_OF_RANGE if the integer doesn't fit in 64 bits or is negative
*/
inline simdjson_result<uint64_t> as_uint64_t() const noexcept;
/**
* Read this element as a signed integer.
*
* @return The integer value, or:
* - UNEXPECTED_TYPE if the JSON element is not an integer
* - NUMBER_OUT_OF_RANGE if the integer doesn't fit in 64 bits
*/
inline simdjson_result<int64_t> as_int64_t() const noexcept;
/**
* Read this element as a floating point value.
*
* @return The double value, or:
* - UNEXPECTED_TYPE if the JSON element is not a number
*/
inline simdjson_result<double> as_double() const noexcept;
/**
* Read this element as a JSON array.
*
* @return The array value, or:
* - UNEXPECTED_TYPE if the JSON element is not an array
*/
inline simdjson_result<array> as_array() const noexcept;
/**
* Read this element as a JSON object (key/value pairs).
*
* @return The object value, or:
* - UNEXPECTED_TYPE if the JSON element is not an object
*/
inline simdjson_result<object> as_object() const noexcept;
template<typename T>
really_inline simdjson_result<T> get() const noexcept;
#if SIMDJSON_EXCEPTIONS
/**
@ -379,8 +315,8 @@ public:
* The key will be matched against **unescaped** JSON:
*
* dom::parser parser;
* parser.parse(R"({ "a\n": 1 })")["a\n"].as_uint64_t().value == 1
* parser.parse(R"({ "a\n": 1 })")["a\\n"].as_uint64_t().error == NO_SUCH_FIELD
* parser.parse(R"({ "a\n": 1 })")["a\n"].get<uint64_t>().value == 1
* parser.parse(R"({ "a\n": 1 })")["a\\n"].get<uint64_t>().error == NO_SUCH_FIELD
*
* @return The value associated with this field, or:
* - NO_SUCH_FIELD if the field does not exist in the object
@ -628,8 +564,8 @@ public:
* The key will be matched against **unescaped** JSON:
*
* dom::parser parser;
* parser.parse(R"({ "a\n": 1 })")["a\n"].as_uint64_t().value == 1
* parser.parse(R"({ "a\n": 1 })")["a\\n"].as_uint64_t().error == NO_SUCH_FIELD
* parser.parse(R"({ "a\n": 1 })")["a\n"].get<uint64_t>().value == 1
* parser.parse(R"({ "a\n": 1 })")["a\\n"].get<uint64_t>().error == NO_SUCH_FIELD
*
* @return The value associated with this field, or:
* - NO_SUCH_FIELD if the field does not exist in the object
@ -1525,16 +1461,11 @@ public:
really_inline simdjson_result(dom::element &&value) noexcept;
really_inline simdjson_result(error_code error) noexcept;
/** Whether this is a JSON `null` */
inline simdjson_result<bool> is_null() const noexcept;
inline simdjson_result<bool> as_bool() const noexcept;
inline simdjson_result<std::string_view> as_string() const noexcept;
inline simdjson_result<const char *> as_c_str() const noexcept;
inline simdjson_result<uint64_t> as_uint64_t() const noexcept;
inline simdjson_result<int64_t> as_int64_t() const noexcept;
inline simdjson_result<double> as_double() const noexcept;
inline simdjson_result<dom::array> as_array() const noexcept;
inline simdjson_result<dom::object> as_object() const noexcept;
template<typename T>
inline simdjson_result<bool> is() const noexcept;
template<typename T>
inline simdjson_result<T> get() const noexcept;
inline simdjson_result<dom::element> operator[](const std::string_view &json_pointer) const noexcept;
inline simdjson_result<dom::element> operator[](const char *json_pointer) const noexcept;

View File

@ -132,18 +132,18 @@ struct simdjson_result_base : public std::pair<T, error_code> {
#if SIMDJSON_EXCEPTIONS
/**
* The value of the function.
* Get the result value.
*
* @throw simdjson_error if there was an error.
*/
really_inline T& get() noexcept(false);
really_inline T& value() noexcept(false);
/**
* The value of the function.
* Take the result value (move it).
*
* @throw simdjson_error if there was an error.
*/
really_inline T&& take() && noexcept(false);
really_inline T&& take_value() && noexcept(false);
/**
* Cast to the value (will throw on error).
@ -194,18 +194,18 @@ struct simdjson_result : public internal::simdjson_result_base<T> {
#if SIMDJSON_EXCEPTIONS
/**
* The value of the function.
* Get the result value.
*
* @throw simdjson_error if there was an error.
*/
really_inline T& get() noexcept(false);
really_inline T& value() noexcept(false);
/**
* The value of the function.
* Take the result value (move it).
*
* @throw simdjson_error if there was an error.
*/
really_inline T&& take() && noexcept(false);
really_inline T&& take_value() && noexcept(false);
/**
* Cast to the value (will throw on error).

View File

@ -27,37 +27,15 @@ inline simdjson_result<bool> simdjson_result<dom::element>::is_null() const noex
if (error()) { return error(); }
return first.is_null();
}
inline simdjson_result<bool> simdjson_result<dom::element>::as_bool() const noexcept {
template<typename T>
inline simdjson_result<bool> simdjson_result<dom::element>::is() const noexcept {
if (error()) { return error(); }
return first.as_bool();
return first.is<T>();
}
inline simdjson_result<const char*> simdjson_result<dom::element>::as_c_str() const noexcept {
template<typename T>
inline simdjson_result<T> simdjson_result<dom::element>::get() const noexcept {
if (error()) { return error(); }
return first.as_c_str();
}
inline simdjson_result<std::string_view> simdjson_result<dom::element>::as_string() const noexcept {
if (error()) { return error(); }
return first.as_string();
}
inline simdjson_result<uint64_t> simdjson_result<dom::element>::as_uint64_t() const noexcept {
if (error()) { return error(); }
return first.as_uint64_t();
}
inline simdjson_result<int64_t> simdjson_result<dom::element>::as_int64_t() const noexcept {
if (error()) { return error(); }
return first.as_int64_t();
}
inline simdjson_result<double> simdjson_result<dom::element>::as_double() const noexcept {
if (error()) { return error(); }
return first.as_double();
}
inline simdjson_result<dom::array> simdjson_result<dom::element>::as_array() const noexcept {
if (error()) { return error(); }
return first.as_array();
}
inline simdjson_result<dom::object> simdjson_result<dom::element>::as_object() const noexcept {
if (error()) { return error(); }
return first.as_object();
return first.get<T>();
}
inline simdjson_result<dom::element> simdjson_result<dom::element>::operator[](const std::string_view &json_pointer) const noexcept {
@ -88,28 +66,28 @@ inline simdjson_result<dom::element> simdjson_result<dom::element>::at_key_case_
#if SIMDJSON_EXCEPTIONS
inline simdjson_result<dom::element>::operator bool() const noexcept(false) {
return as_bool();
return get<bool>();
}
inline simdjson_result<dom::element>::operator const char *() const noexcept(false) {
return as_c_str();
return get<const char *>();
}
inline simdjson_result<dom::element>::operator std::string_view() const noexcept(false) {
return as_string();
return get<std::string_view>();
}
inline simdjson_result<dom::element>::operator uint64_t() const noexcept(false) {
return as_uint64_t();
return get<uint64_t>();
}
inline simdjson_result<dom::element>::operator int64_t() const noexcept(false) {
return as_int64_t();
return get<int64_t>();
}
inline simdjson_result<dom::element>::operator double() const noexcept(false) {
return as_double();
return get<double>();
}
inline simdjson_result<dom::element>::operator dom::array() const noexcept(false) {
return as_array();
return get<dom::array>();
}
inline simdjson_result<dom::element>::operator dom::object() const noexcept(false) {
return as_object();
return get<dom::object>();
}
#endif
@ -740,45 +718,9 @@ really_inline element::element(const document *_doc, size_t _json_index) noexcep
really_inline bool element::is_null() const noexcept {
return type() == internal::tape_type::NULL_VALUE;
}
really_inline bool element::is_bool() const noexcept {
return type() == internal::tape_type::TRUE_VALUE || type() == internal::tape_type::FALSE_VALUE;
}
really_inline bool element::is_number() const noexcept {
return type() == internal::tape_type::UINT64 || type() == internal::tape_type::INT64 || type() == internal::tape_type::DOUBLE;
}
really_inline bool element::is_float() const noexcept {
return type() == internal::tape_type::DOUBLE;
}
really_inline bool element::is_integer() const noexcept {
return type() == internal::tape_type::UINT64 || type() == internal::tape_type::INT64;
}
really_inline bool element::is_unsigned_integer() const noexcept {
return type() == internal::tape_type::UINT64;
}
really_inline bool element::is_string() const noexcept {
return type() == internal::tape_type::STRING;
}
really_inline bool element::is_array() const noexcept {
return type() == internal::tape_type::START_ARRAY;
}
really_inline bool element::is_object() const noexcept {
return type() == internal::tape_type::START_OBJECT;
}
#if SIMDJSON_EXCEPTIONS
inline element::operator bool() const noexcept(false) { return as_bool(); }
inline element::operator const char*() const noexcept(false) { return as_c_str(); }
inline element::operator std::string_view() const noexcept(false) { return as_string(); }
inline element::operator uint64_t() const noexcept(false) { return as_uint64_t(); }
inline element::operator int64_t() const noexcept(false) { return as_int64_t(); }
inline element::operator double() const noexcept(false) { return as_double(); }
inline element::operator array() const noexcept(false) { return as_array(); }
inline element::operator object() const noexcept(false) { return as_object(); }
#endif
inline simdjson_result<bool> element::as_bool() const noexcept {
template<>
inline simdjson_result<bool> element::get<bool>() const noexcept {
switch (type()) {
case internal::tape_type::TRUE_VALUE:
return true;
@ -788,7 +730,8 @@ inline simdjson_result<bool> element::as_bool() const noexcept {
return INCORRECT_TYPE;
}
}
inline simdjson_result<const char *> element::as_c_str() const noexcept {
template<>
inline simdjson_result<const char *> element::get<const char *>() const noexcept {
switch (type()) {
case internal::tape_type::STRING: {
size_t string_buf_index = tape_value();
@ -798,7 +741,8 @@ inline simdjson_result<const char *> element::as_c_str() const noexcept {
return INCORRECT_TYPE;
}
}
inline simdjson_result<std::string_view> element::as_string() const noexcept {
template<>
inline simdjson_result<std::string_view> element::get<std::string_view>() const noexcept {
switch (type()) {
case internal::tape_type::STRING:
return get_string_view();
@ -806,7 +750,8 @@ inline simdjson_result<std::string_view> element::as_string() const noexcept {
return INCORRECT_TYPE;
}
}
inline simdjson_result<uint64_t> element::as_uint64_t() const noexcept {
template<>
inline simdjson_result<uint64_t> element::get<uint64_t>() const noexcept {
switch (type()) {
case internal::tape_type::UINT64:
return next_tape_value<uint64_t>();
@ -821,7 +766,8 @@ inline simdjson_result<uint64_t> element::as_uint64_t() const noexcept {
return INCORRECT_TYPE;
}
}
inline simdjson_result<int64_t> element::as_int64_t() const noexcept {
template<>
inline simdjson_result<int64_t> element::get<int64_t>() const noexcept {
switch (type()) {
case internal::tape_type::UINT64: {
uint64_t result = next_tape_value<uint64_t>();
@ -837,7 +783,8 @@ inline simdjson_result<int64_t> element::as_int64_t() const noexcept {
return INCORRECT_TYPE;
}
}
inline simdjson_result<double> element::as_double() const noexcept {
template<>
inline simdjson_result<double> element::get<double>() const noexcept {
switch (type()) {
case internal::tape_type::UINT64:
return next_tape_value<uint64_t>();
@ -855,7 +802,8 @@ inline simdjson_result<double> element::as_double() const noexcept {
return INCORRECT_TYPE;
}
}
inline simdjson_result<array> element::as_array() const noexcept {
template<>
inline simdjson_result<array> element::get<array>() const noexcept {
switch (type()) {
case internal::tape_type::START_ARRAY:
return array(doc, json_index);
@ -863,7 +811,8 @@ inline simdjson_result<array> element::as_array() const noexcept {
return INCORRECT_TYPE;
}
}
inline simdjson_result<object> element::as_object() const noexcept {
template<>
inline simdjson_result<object> element::get<object>() const noexcept {
switch (type()) {
case internal::tape_type::START_OBJECT:
return object(doc, json_index);
@ -871,6 +820,26 @@ inline simdjson_result<object> element::as_object() const noexcept {
return INCORRECT_TYPE;
}
}
template<typename T>
really_inline bool element::is() const noexcept {
auto result = get<T>();
return !result.error();
}
#if SIMDJSON_EXCEPTIONS
inline element::operator bool() const noexcept(false) { return get<bool>(); }
inline element::operator const char*() const noexcept(false) { return get<const char *>(); }
inline element::operator std::string_view() const noexcept(false) { return get<std::string_view>(); }
inline element::operator uint64_t() const noexcept(false) { return get<uint64_t>(); }
inline element::operator int64_t() const noexcept(false) { return get<int64_t>(); }
inline element::operator double() const noexcept(false) { return get<double>(); }
inline element::operator array() const noexcept(false) { return get<array>(); }
inline element::operator object() const noexcept(false) { return get<object>(); }
#endif
inline simdjson_result<element> element::operator[](const std::string_view &json_pointer) const noexcept {
return at(json_pointer);
}
@ -888,13 +857,13 @@ inline simdjson_result<element> element::at(const std::string_view &json_pointer
}
}
inline simdjson_result<element> element::at(size_t index) const noexcept {
return as_array().at(index);
return get<array>().at(index);
}
inline simdjson_result<element> element::at_key(const std::string_view &key) const noexcept {
return as_object().at_key(key);
return get<object>().at_key(key);
}
inline simdjson_result<element> element::at_key_case_insensitive(const std::string_view &key) const noexcept {
return as_object().at_key_case_insensitive(key);
return get<object>().at_key_case_insensitive(key);
}
inline bool element::dump_raw_tape(std::ostream &out) const noexcept {

View File

@ -128,8 +128,8 @@ really_inline document_stream::iterator::iterator(document_stream& _stream, bool
}
really_inline simdjson_result<element> document_stream::iterator::operator*() noexcept {
error_code error = stream.error == SUCCESS_AND_HAS_MORE ? SUCCESS : stream.error;
if (error) { return error; }
error_code err = stream.error == SUCCESS_AND_HAS_MORE ? SUCCESS : stream.error;
if (err) { return err; }
return stream.parser.doc.root();
}

View File

@ -81,20 +81,20 @@ really_inline error_code simdjson_result_base<T>::error() const noexcept {
#if SIMDJSON_EXCEPTIONS
template<typename T>
really_inline T& simdjson_result_base<T>::get() noexcept(false) {
really_inline T& simdjson_result_base<T>::value() noexcept(false) {
if (error()) { throw simdjson_error(error()); }
return this->first;
};
template<typename T>
really_inline T&& simdjson_result_base<T>::take() && noexcept(false) {
really_inline T&& simdjson_result_base<T>::take_value() && noexcept(false) {
if (error()) { throw simdjson_error(error()); }
return std::forward<T>(this->first);
};
template<typename T>
really_inline simdjson_result_base<T>::operator T&&() && noexcept(false) {
return std::forward<simdjson_result_base<T>>(*this).take();
return std::forward<simdjson_result_base<T>>(*this).take_value();
}
#endif // SIMDJSON_EXCEPTIONS
@ -131,18 +131,18 @@ really_inline error_code simdjson_result<T>::error() const noexcept {
#if SIMDJSON_EXCEPTIONS
template<typename T>
really_inline T& simdjson_result<T>::get() noexcept(false) {
return internal::simdjson_result_base<T>::get();
really_inline T& simdjson_result<T>::value() noexcept(false) {
return internal::simdjson_result_base<T>::value();
}
template<typename T>
really_inline T&& simdjson_result<T>::take() && noexcept(false) {
return std::forward<internal::simdjson_result_base<T>>(*this).take();
really_inline T&& simdjson_result<T>::take_value() && noexcept(false) {
return std::forward<internal::simdjson_result_base<T>>(*this).take_value();
}
template<typename T>
really_inline simdjson_result<T>::operator T&&() && noexcept(false) {
return std::forward<internal::simdjson_result_base<T>>(*this).take();
return std::forward<internal::simdjson_result_base<T>>(*this).take_value();
}
#endif // SIMDJSON_EXCEPTIONS

View File

@ -49,7 +49,7 @@ namespace number_tests {
buf[n] = '\0';
fflush(NULL);
auto [actual, error] = parser.parse(buf, n).as_int64_t();
auto [actual, error] = parser.parse(buf, n).get<int64_t>();
if (error) { std::cerr << error << std::endl; return false; }
if (actual != i) {
std::cerr << "JSON '" << buf << " parsed to " << actual << " instead of " << i << std::endl;
@ -70,7 +70,7 @@ namespace number_tests {
auto n = sprintf(buf, "%.*e", std::numeric_limits<double>::max_digits10 - 1, expected);
buf[n] = '\0';
fflush(NULL);
auto [actual, error] = parser.parse(buf, n).as_double();
auto [actual, error] = parser.parse(buf, n).get<double>();
if (error) { std::cerr << error << std::endl; return false; }
int ulp = f64_ulp_dist(actual,expected);
if(ulp > maxulp) maxulp = ulp;
@ -164,7 +164,7 @@ namespace number_tests {
buf[n] = '\0';
fflush(NULL);
auto [actual, error] = parser.parse(buf, n).as_double();
auto [actual, error] = parser.parse(buf, n).get<double>();
if (error) { std::cerr << error << std::endl; return false; }
double expected = ((i >= -307) ? testing_power_of_ten[i + 307]: std::pow(10, i));
int ulp = (int) f64_ulp_dist(actual, expected);
@ -369,7 +369,7 @@ namespace document_stream_tests {
return false;
}
auto [keyid, error2] = doc["id"].as_int64_t();
auto [keyid, error2] = doc["id"].get<int64_t>();
if (error2) {
printf("Error getting id as int64 on document %zd at batch size %zu: %s\n", count, batch_size, simdjson::error_message(error2));
return false;
@ -417,7 +417,7 @@ namespace document_stream_tests {
return false;
}
auto [keyid, error2] = doc["id"].as_int64_t();
auto [keyid, error2] = doc["id"].get<int64_t>();
if (error2) {
printf("Error getting id as int64 on document %zd at batch size %zu: %s\n", count, batch_size, simdjson::error_message(error2));
return false;
@ -459,7 +459,7 @@ namespace parse_api_tests {
dom::parser parser;
auto [doc, error] = parser.parse(BASIC_JSON);
if (error) { cerr << error << endl; return false; }
if (!doc.is_array()) { cerr << "Document did not parse as an array" << endl; return false; }
if (!doc.is<dom::array>()) { cerr << "Document did not parse as an array" << endl; return false; }
return true;
}
bool parser_parse_many() {
@ -468,7 +468,7 @@ namespace parse_api_tests {
int count = 0;
for (auto [doc, error] : parser.parse_many(BASIC_NDJSON)) {
if (error) { cerr << error << endl; return false; }
if (!doc.is_array()) { cerr << "Document did not parse as an array" << endl; return false; }
if (!doc.is<dom::array>()) { cerr << "Document did not parse as an array" << endl; return false; }
count++;
}
if (count != 2) { cerr << "parse_many returned " << count << " documents, expected 2" << endl; return false; }
@ -491,7 +491,7 @@ namespace parse_api_tests {
dom::parser parser;
auto [doc, error] = parser.load(JSON_TEST_PATH);
if (error) { cerr << error << endl; return false; }
if (!doc.is_object()) { cerr << "Document did not parse as an object" << endl; return false; }
if (!doc.is<dom::object>()) { cerr << "Document did not parse as an object" << endl; return false; }
return true;
}
bool parser_load_many() {
@ -500,7 +500,7 @@ namespace parse_api_tests {
int count = 0;
for (auto [doc, error] : parser.load_many(NDJSON_TEST_PATH)) {
if (error) { cerr << error << endl; return false; }
if (!doc.is_array()) { cerr << "Document did not parse as an array" << endl; return false; }
if (!doc.is<dom::array>()) { cerr << "Document did not parse as an array" << endl; return false; }
count++;
}
if (count != 793) { cerr << "Expected 793 documents, but load_many loaded " << count << " documents." << endl; return false; }
@ -513,7 +513,7 @@ namespace parse_api_tests {
std::cout << "Running " << __func__ << std::endl;
dom::parser parser;
element doc = parser.parse(BASIC_JSON);
if (!doc.is_array()) { cerr << "Document did not parse as an array" << endl; return false; }
if (!doc.is<dom::array>()) { cerr << "Document did not parse as an array" << endl; return false; }
return true;
}
bool parser_parse_many_exception() {
@ -521,7 +521,7 @@ namespace parse_api_tests {
dom::parser parser;
int count = 0;
for (const element doc : parser.parse_many(BASIC_NDJSON)) {
if (!doc.is_array()) { cerr << "Document did not parse as an array" << endl; return false; }
if (!doc.is<dom::array>()) { cerr << "Document did not parse as an array" << endl; return false; }
count++;
}
if (count != 2) { cerr << "parse_many returned " << count << " documents, expected 2" << endl; return false; }
@ -532,7 +532,7 @@ namespace parse_api_tests {
std::cout << "Running " << __func__ << std::endl;
dom::parser parser;
const element doc = parser.load(JSON_TEST_PATH);
if (!doc.is_object()) { cerr << "Document did not parse as an object" << endl; return false; }
if (!doc.is<dom::object>()) { cerr << "Document did not parse as an object" << endl; return false; }
return true;
}
bool parser_load_many_exception() {
@ -540,7 +540,7 @@ namespace parse_api_tests {
dom::parser parser;
int count = 0;
for (const element doc : parser.load_many(NDJSON_TEST_PATH)) {
if (!doc.is_array()) { cerr << "Document did not parse as an array" << endl; return false; }
if (!doc.is<dom::array>()) { cerr << "Document did not parse as an array" << endl; return false; }
count++;
}
if (count != 793) { cerr << "Expected 1 document, but load_many loaded " << count << " documents." << endl; return false; }
@ -682,10 +682,10 @@ namespace dom_api_tests {
int i = 0;
dom::parser parser;
auto [object, error] = parser.parse(json).as_object();
auto [object, error] = parser.parse(json).get<dom::object>();
if (error) { cerr << "Error: " << error << endl; return false; }
for (auto [key, value] : object) {
if (key != expected_key[i] || value.as_uint64_t().first != expected_value[i]) { cerr << "Expected " << expected_key[i] << " = " << expected_value[i] << ", got " << key << "=" << value << endl; return false; }
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; }
i++;
}
if (i*sizeof(uint64_t) != sizeof(expected_value)) { cout << "Expected " << sizeof(expected_value) << " values, got " << i << endl; return false; }
@ -699,10 +699,10 @@ namespace dom_api_tests {
int i=0;
dom::parser parser;
auto [array, error] = parser.parse(json).as_array();
auto [array, error] = parser.parse(json).get<dom::array>();
if (error) { cerr << "Error: " << error << endl; return false; }
for (auto value : array) {
if (value.as_uint64_t().first != expected_value[i]) { cerr << "Expected " << expected_value[i] << ", got " << value << endl; return false; }
if (value.get<uint64_t>().first != expected_value[i]) { cerr << "Expected " << expected_value[i] << ", got " << value << endl; return false; }
i++;
}
if (i*sizeof(uint64_t) != sizeof(expected_value)) { cout << "Expected " << sizeof(expected_value) << " values, got " << i << endl; return false; }
@ -715,7 +715,7 @@ namespace dom_api_tests {
int i = 0;
dom::parser parser;
auto [object, error] = parser.parse(json).as_object();
auto [object, error] = parser.parse(json).get<dom::object>();
if (error) { cerr << "Error: " << error << endl; return false; }
for (auto [key, value] : object) {
cout << "Unexpected " << key << " = " << value << endl;
@ -731,7 +731,7 @@ namespace dom_api_tests {
int i=0;
dom::parser parser;
auto [array, error] = parser.parse(json).as_array();
auto [array, error] = parser.parse(json).get<dom::array>();
if (error) { cerr << "Error: " << error << endl; return false; }
for (auto value : array) {
cout << "Unexpected value " << value << endl;
@ -745,13 +745,13 @@ namespace dom_api_tests {
std::cout << "Running " << __func__ << std::endl;
string json(R"([ "hi", "has backslash\\" ])");
dom::parser parser;
auto [array, error] = parser.parse(json).as_array();
auto [array, error] = parser.parse(json).get<dom::array>();
if (error) { cerr << "Error: " << error << endl; return false; }
auto val = array.begin();
if ((*val).as_string().first != "hi") { cerr << "Expected value to be \"hi\", was " << (*val).as_string().first << endl; return false; }
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).as_string().first != "has backslash\\") { cerr << "Expected string_view(\"has backslash\\\\\") to be \"has backslash\\\", was " << (*val).as_string().first << endl; return false; }
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;
}
@ -759,22 +759,22 @@ namespace dom_api_tests {
std::cout << "Running " << __func__ << std::endl;
string json(R"([ 0, 1, -1, 1.1 ])");
dom::parser parser;
auto [array, error] = parser.parse(json).as_array();
auto [array, error] = parser.parse(json).get<dom::array>();
if (error) { cerr << "Error: " << error << endl; return false; }
auto val = array.begin();
if ((*val).as_uint64_t().first != 0) { cerr << "Expected uint64_t(0) to be 0, was " << (*val) << endl; return false; }
if ((*val).as_int64_t().first != 0) { cerr << "Expected int64_t(0) to be 0, was " << (*val).as_int64_t().first << endl; return false; }
if ((*val).as_double().first != 0) { cerr << "Expected double(0) to be 0, was " << (*val).as_double().first << endl; return false; }
if ((*val).get<uint64_t>().first != 0) { cerr << "Expected uint64_t(0) to be 0, was " << (*val) << endl; return false; }
if ((*val).get<int64_t>().first != 0) { cerr << "Expected int64_t(0) to be 0, was " << (*val).get<int64_t>().first << endl; return false; }
if ((*val).get<double>().first != 0) { cerr << "Expected double(0) to be 0, was " << (*val).get<double>().first << endl; return false; }
++val;
if ((*val).as_uint64_t().first != 1) { cerr << "Expected uint64_t(1) to be 1, was " << (*val) << endl; return false; }
if ((*val).as_int64_t().first != 1) { cerr << "Expected int64_t(1) to be 1, was " << (*val).as_int64_t().first << endl; return false; }
if ((*val).as_double().first != 1) { cerr << "Expected double(1) to be 1, was " << (*val).as_double().first << endl; return false; }
if ((*val).get<uint64_t>().first != 1) { cerr << "Expected uint64_t(1) to be 1, was " << (*val) << endl; return false; }
if ((*val).get<int64_t>().first != 1) { cerr << "Expected int64_t(1) to be 1, was " << (*val).get<int64_t>().first << endl; return false; }
if ((*val).get<double>().first != 1) { cerr << "Expected double(1) to be 1, was " << (*val).get<double>().first << endl; return false; }
++val;
if ((*val).as_int64_t().first != -1) { cerr << "Expected int64_t(-1) to be -1, was " << (*val).as_int64_t().first << endl; return false; }
if ((*val).as_double().first != -1) { cerr << "Expected double(-1) to be -1, was " << (*val).as_double().first << endl; return false; }
if ((*val).get<int64_t>().first != -1) { cerr << "Expected int64_t(-1) to be -1, was " << (*val).get<int64_t>().first << endl; return false; }
if ((*val).get<double>().first != -1) { cerr << "Expected double(-1) to be -1, was " << (*val).get<double>().first << endl; return false; }
++val;
if ((*val).as_double().first != 1.1) { cerr << "Expected double(1.1) to be 1.1, was " << (*val).as_double().first << endl; return false; }
if ((*val).get<double>().first != 1.1) { cerr << "Expected double(1.1) to be 1.1, was " << (*val).get<double>().first << endl; return false; }
return true;
}
@ -782,13 +782,13 @@ namespace dom_api_tests {
std::cout << "Running " << __func__ << std::endl;
string json(R"([ true, false ])");
dom::parser parser;
auto [array, error] = parser.parse(json).as_array();
auto [array, error] = parser.parse(json).get<dom::array>();
if (error) { cerr << "Error: " << error << endl; return false; }
auto val = array.begin();
if ((*val).as_bool().first != true) { cerr << "Expected bool(true) to be true, was " << (*val) << endl; return false; }
if ((*val).get<bool>().first != true) { cerr << "Expected bool(true) to be true, was " << (*val) << endl; return false; }
++val;
if ((*val).as_bool().first != false) { cerr << "Expected bool(false) to be false, was " << (*val) << endl; return false; }
if ((*val).get<bool>().first != false) { cerr << "Expected bool(false) to be false, was " << (*val) << endl; return false; }
return true;
}
@ -796,7 +796,7 @@ namespace dom_api_tests {
std::cout << "Running " << __func__ << std::endl;
string json(R"([ null ])");
dom::parser parser;
auto [array, error] = parser.parse(json).as_array();
auto [array, error] = parser.parse(json).get<dom::array>();
if (error) { cerr << "Error: " << error << endl; return false; }
auto val = array.begin();
if (!(*val).is_null()) { cerr << "Expected null to be null!" << endl; return false; }
@ -808,13 +808,13 @@ namespace dom_api_tests {
string json(R"({ "a": 1, "b": 2, "c": 3})");
dom::parser parser;
auto [doc, error] = parser.parse(json);
if (doc["a"].as_uint64_t().first != 1) { cerr << "Expected uint64_t(doc[\"a\"]) to be 1, was " << doc["a"].first << endl; return false; }
if (doc["b"].as_uint64_t().first != 2) { cerr << "Expected uint64_t(doc[\"b\"]) to be 2, was " << doc["b"].first << endl; return false; }
if (doc["c"].as_uint64_t().first != 3) { cerr << "Expected uint64_t(doc[\"c\"]) to be 3, was " << doc["c"].first << endl; return false; }
if (doc["a"].get<uint64_t>().first != 1) { cerr << "Expected uint64_t(doc[\"a\"]) to be 1, was " << doc["a"].first << endl; return false; }
if (doc["b"].get<uint64_t>().first != 2) { cerr << "Expected uint64_t(doc[\"b\"]) to be 2, was " << doc["b"].first << endl; return false; }
if (doc["c"].get<uint64_t>().first != 3) { cerr << "Expected uint64_t(doc[\"c\"]) to be 3, was " << doc["c"].first << endl; return false; }
// Check all three again in backwards order, to ensure we can go backwards
if (doc["c"].as_uint64_t().first != 3) { cerr << "Expected uint64_t(doc[\"c\"]) to be 3, was " << doc["c"].first << endl; return false; }
if (doc["b"].as_uint64_t().first != 2) { cerr << "Expected uint64_t(doc[\"b\"]) to be 2, was " << doc["b"].first << endl; return false; }
if (doc["a"].as_uint64_t().first != 1) { cerr << "Expected uint64_t(doc[\"a\"]) to be 1, was " << doc["a"].first << endl; return false; }
if (doc["c"].get<uint64_t>().first != 3) { cerr << "Expected uint64_t(doc[\"c\"]) to be 3, was " << doc["c"].first << endl; return false; }
if (doc["b"].get<uint64_t>().first != 2) { cerr << "Expected uint64_t(doc[\"b\"]) to be 2, was " << doc["b"].first << endl; return false; }
if (doc["a"].get<uint64_t>().first != 1) { cerr << "Expected uint64_t(doc[\"a\"]) to be 1, was " << doc["a"].first << endl; return false; }
UNUSED element val;
// tie(val, error) = doc["d"]; fails with "no viable overloaded '='" on Apple clang version 11.0.0 tie(val, error) = doc["d"];
@ -829,21 +829,21 @@ namespace dom_api_tests {
dom::parser parser;
auto [doc, error] = parser.parse(json);
if (error) { cerr << "Error: " << error << endl; return false; }
if (doc["obj"]["a"].as_uint64_t().first != 1) { cerr << "Expected uint64_t(doc[\"obj\"][\"a\"]) to be 1, was " << doc["obj"]["a"].first << endl; return false; }
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; }
object obj;
doc.as_object().tie(obj, error); // tie(...) = fails with "no viable overloaded '='" on Apple clang version 11.0.0
doc.get<dom::object>().tie(obj, error); // tie(...) = fails with "no viable overloaded '='" on Apple clang version 11.0.0
if (error) { cerr << "Error: " << error << endl; return false; }
if (obj["obj"]["a"].as_uint64_t().first != 1) { cerr << "Expected uint64_t(doc[\"obj\"][\"a\"]) to be 1, was " << doc["obj"]["a"].first << endl; return false; }
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; }
obj["obj"].as_object().tie(obj, error); // tie(...) = fails with "no viable overloaded '='" on Apple clang version 11.0.0
if (obj["a"].as_uint64_t().first != 1) { cerr << "Expected uint64_t(obj[\"a\"]) to be 1, was " << obj["a"].first << endl; return false; }
if (obj["b"].as_uint64_t().first != 2) { cerr << "Expected uint64_t(obj[\"b\"]) to be 2, was " << obj["b"].first << endl; return false; }
if (obj["c"].as_uint64_t().first != 3) { cerr << "Expected uint64_t(obj[\"c\"]) to be 3, was " << obj["c"].first << endl; return false; }
obj["obj"].get<dom::object>().tie(obj, error); // tie(...) = fails with "no viable overloaded '='" on Apple clang version 11.0.0
if (obj["a"].get<uint64_t>().first != 1) { cerr << "Expected uint64_t(obj[\"a\"]) to be 1, was " << obj["a"].first << endl; return false; }
if (obj["b"].get<uint64_t>().first != 2) { cerr << "Expected uint64_t(obj[\"b\"]) to be 2, was " << obj["b"].first << endl; return false; }
if (obj["c"].get<uint64_t>().first != 3) { cerr << "Expected uint64_t(obj[\"c\"]) to be 3, was " << obj["c"].first << endl; return false; }
// Check all three again in backwards order, to ensure we can go backwards
if (obj["c"].as_uint64_t().first != 3) { cerr << "Expected uint64_t(obj[\"c\"]) to be 3, was " << obj["c"].first << endl; return false; }
if (obj["b"].as_uint64_t().first != 2) { cerr << "Expected uint64_t(obj[\"b\"]) to be 2, was " << obj["b"].first << endl; return false; }
if (obj["a"].as_uint64_t().first != 1) { cerr << "Expected uint64_t(obj[\"a\"]) to be 1, was " << obj["a"].first << endl; return false; }
if (obj["c"].get<uint64_t>().first != 3) { cerr << "Expected uint64_t(obj[\"c\"]) to be 3, was " << obj["c"].first << endl; return false; }
if (obj["b"].get<uint64_t>().first != 2) { cerr << "Expected uint64_t(obj[\"b\"]) to be 2, was " << obj["b"].first << endl; return false; }
if (obj["a"].get<uint64_t>().first != 1) { cerr << "Expected uint64_t(obj[\"a\"]) to be 1, was " << obj["a"].first << endl; return false; }
UNUSED element val;
doc["d"].tie(val, error); // tie(...) = fails with "no viable overloaded '='" on Apple clang version 11.0.0;
@ -855,7 +855,7 @@ namespace dom_api_tests {
std::cout << "Running " << __func__ << std::endl;
// Prints the number of results in twitter.json
dom::parser parser;
auto [result_count, error] = parser.load(JSON_TEST_PATH)["search_metadata"]["count"].as_uint64_t();
auto [result_count, error] = parser.load(JSON_TEST_PATH)["search_metadata"]["count"].get<uint64_t>();
if (error) { cerr << "Error: " << error << endl; return false; }
if (result_count != 100) { cerr << "Expected twitter.json[metadata_count][count] = 100, got " << result_count << endl; return false; }
return true;
@ -866,18 +866,18 @@ namespace dom_api_tests {
// Print users with a default profile.
set<string_view> default_users;
dom::parser parser;
auto [tweets, error] = parser.load(JSON_TEST_PATH)["statuses"].as_array();
auto [tweets, error] = parser.load(JSON_TEST_PATH)["statuses"].get<dom::array>();
if (error) { cerr << "Error: " << error << endl; return false; }
for (auto tweet : tweets) {
object user;
tweet["user"].as_object().tie(user, error); // tie(...) = fails with "no viable overloaded '='" on Apple clang version 11.0.0;
tweet["user"].get<dom::object>().tie(user, error); // tie(...) = fails with "no viable overloaded '='" on Apple clang version 11.0.0;
if (error) { cerr << "Error: " << error << endl; return false; }
bool default_profile;
user["default_profile"].as_bool().tie(default_profile, error); // tie(...) = fails with "no viable overloaded '='" on Apple clang version 11.0.0;
user["default_profile"].get<bool>().tie(default_profile, error); // tie(...) = fails with "no viable overloaded '='" on Apple clang version 11.0.0;
if (error) { cerr << "Error: " << error << endl; return false; }
if (default_profile) {
std::string_view screen_name;
user["screen_name"].as_string().tie(screen_name, error); // tie(...) = fails with "no viable overloaded '='" on Apple clang version 11.0.0;
user["screen_name"].get<std::string_view>().tie(screen_name, error); // tie(...) = fails with "no viable overloaded '='" on Apple clang version 11.0.0;
if (error) { cerr << "Error: " << error << endl; return false; }
default_users.insert(screen_name);
}
@ -891,20 +891,20 @@ namespace dom_api_tests {
// Print image names and sizes
set<pair<uint64_t, uint64_t>> image_sizes;
dom::parser parser;
auto [tweets, error] = parser.load(JSON_TEST_PATH)["statuses"].as_array();
auto [tweets, error] = parser.load(JSON_TEST_PATH)["statuses"].get<dom::array>();
if (error) { cerr << "Error: " << error << endl; return false; }
for (auto tweet : tweets) {
auto [media, not_found] = tweet["entities"]["media"].as_array();
auto [media, not_found] = tweet["entities"]["media"].get<dom::array>();
if (!not_found) {
for (auto image : media) {
object sizes;
image["sizes"].as_object().tie(sizes, error); // tie(...) = fails with "no viable overloaded '='" on Apple clang version 11.0.0;
image["sizes"].get<dom::object>().tie(sizes, error); // tie(...) = fails with "no viable overloaded '='" on Apple clang version 11.0.0;
if (error) { cerr << "Error: " << error << endl; return false; }
for (auto [key, size] : sizes) {
uint64_t width, height;
size["w"].as_uint64_t().tie(width, error); // tie(...) = fails with "no viable overloaded '='" on Apple clang version 11.0.0;
size["w"].get<uint64_t>().tie(width, error); // tie(...) = fails with "no viable overloaded '='" on Apple clang version 11.0.0;
if (error) { cerr << "Error: " << error << endl; return false; }
size["h"].as_uint64_t().tie(height, error); // tie(...) = fails with "no viable overloaded '='" on Apple clang version 11.0.0;
size["h"].get<uint64_t>().tie(height, error); // tie(...) = fails with "no viable overloaded '='" on Apple clang version 11.0.0;
if (error) { cerr << "Error: " << error << endl; return false; }
image_sizes.insert(make_pair(width, height));
}
@ -926,7 +926,7 @@ namespace dom_api_tests {
dom::parser parser;
element doc = parser.parse(json);
for (auto [key, value] : doc.as_object()) {
for (auto [key, value] : doc.get<dom::object>()) {
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; }
i++;
}
@ -942,7 +942,7 @@ namespace dom_api_tests {
dom::parser parser;
element doc = parser.parse(json);
for (uint64_t value : doc.as_array()) {
for (uint64_t value : doc.get<dom::array>()) {
if (value != expected_value[i]) { cerr << "Expected " << expected_value[i] << ", got " << value << endl; return false; }
i++;
}
@ -954,7 +954,7 @@ namespace dom_api_tests {
std::cout << "Running " << __func__ << std::endl;
string json(R"([ "hi", "has backslash\\" ])");
dom::parser parser;
auto val = parser.parse(json).as_array().begin();
auto val = parser.parse(json).get<dom::array>().begin();
if (strcmp((const char*)*val, "hi")) { cerr << "Expected const char*(\"hi\") to be \"hi\", was " << (const char*)*val << endl; return false; }
if (string_view(*val) != "hi") { cerr << "Expected string_view(\"hi\") to be \"hi\", was " << string_view(*val) << endl; return false; }
@ -968,7 +968,7 @@ namespace dom_api_tests {
std::cout << "Running " << __func__ << std::endl;
string json(R"([ 0, 1, -1, 1.1 ])");
dom::parser parser;
auto val = parser.parse(json).as_array().begin();
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; }
if (int64_t(*val) != 0) { cerr << "Expected int64_t(0) to be 0, was " << int64_t(*val) << endl; return false; }
@ -989,7 +989,7 @@ namespace dom_api_tests {
std::cout << "Running " << __func__ << std::endl;
string json(R"([ true, false ])");
dom::parser parser;
auto val = parser.parse(json).as_array().begin();
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; }
++val;
@ -1001,7 +1001,7 @@ namespace dom_api_tests {
std::cout << "Running " << __func__ << std::endl;
string json(R"([ null ])");
dom::parser parser;
auto val = parser.parse(json).as_array().begin();
auto val = parser.parse(json).get<dom::array>().begin();
if (!(*val).is_null()) { cerr << "Expected null to be null!" << endl; return false; }
return true;
@ -1041,7 +1041,7 @@ namespace dom_api_tests {
set<string_view> default_users;
dom::parser parser;
element doc = parser.load(JSON_TEST_PATH);
for (object tweet : doc["statuses"].as_array()) {
for (object tweet : doc["statuses"].get<dom::array>()) {
object user = tweet["user"];
if (user["default_profile"]) {
default_users.insert(user["screen_name"]);
@ -1057,11 +1057,11 @@ namespace dom_api_tests {
set<pair<uint64_t, uint64_t>> image_sizes;
dom::parser parser;
element doc = parser.load(JSON_TEST_PATH);
for (object tweet : doc["statuses"].as_array()) {
for (object tweet : doc["statuses"].get<dom::array>()) {
auto [media, not_found] = tweet["entities"]["media"];
if (!not_found) {
for (object image : media.as_array()) {
for (auto [key, size] : image["sizes"].as_object()) {
for (object image : media.get<dom::array>()) {
for (auto [key, size] : image["sizes"].get<dom::object>()) {
image_sizes.insert(make_pair(size["w"], size["h"]));
}
}
@ -1159,7 +1159,7 @@ namespace format_tests {
bool print_array() {
std::cout << "Running " << __func__ << std::endl;
dom::parser parser;
auto [value, error] = parser.parse(DOCUMENT)["bar"].as_array();
auto [value, error] = parser.parse(DOCUMENT)["bar"].get<dom::array>();
ostringstream s;
s << value;
return assert_minified(s, "[1,2,3]");
@ -1167,7 +1167,7 @@ namespace format_tests {
bool print_minify_array() {
std::cout << "Running " << __func__ << std::endl;
dom::parser parser;
auto [value, error] = parser.parse(DOCUMENT)["bar"].as_array();
auto [value, error] = parser.parse(DOCUMENT)["bar"].get<dom::array>();
ostringstream s;
s << minify(value);
return assert_minified(s, "[1,2,3]");
@ -1176,7 +1176,7 @@ namespace format_tests {
bool print_object() {
std::cout << "Running " << __func__ << std::endl;
dom::parser parser;
auto [value, error] = parser.parse(DOCUMENT)["baz"].as_object();
auto [value, error] = parser.parse(DOCUMENT)["baz"].get<dom::object>();
ostringstream s;
s << value;
return assert_minified(s, R"({"a":1,"b":2,"c":3})");
@ -1184,7 +1184,7 @@ namespace format_tests {
bool print_minify_object() {
std::cout << "Running " << __func__ << std::endl;
dom::parser parser;
auto [value, error] = parser.parse(DOCUMENT)["baz"].as_object();
auto [value, error] = parser.parse(DOCUMENT)["baz"].get<dom::object>();
ostringstream s;
s << minify(value);
return assert_minified(s, R"({"a":1,"b":2,"c":3})");
@ -1250,7 +1250,7 @@ namespace format_tests {
dom::parser parser;
element doc = parser.parse(DOCUMENT);
ostringstream s;
s << doc["bar"].as_array();
s << doc["bar"].get<dom::array>();
return assert_minified(s, "[1,2,3]");
}
bool print_minify_array_result_exception() {
@ -1258,7 +1258,7 @@ namespace format_tests {
dom::parser parser;
element doc = parser.parse(DOCUMENT);
ostringstream s;
s << minify(doc["bar"].as_array());
s << minify(doc["bar"].get<dom::array>());
return assert_minified(s, "[1,2,3]");
}
@ -1267,7 +1267,7 @@ namespace format_tests {
dom::parser parser;
element doc = parser.parse(DOCUMENT);
ostringstream s;
s << doc["baz"].as_object();
s << doc["baz"].get<dom::object>();
return assert_minified(s, R"({"a":1,"b":2,"c":3})");
}
bool print_minify_object_result_exception() {
@ -1275,7 +1275,7 @@ namespace format_tests {
dom::parser parser;
element doc = parser.parse(DOCUMENT);
ostringstream s;
s << minify(doc["baz"].as_object());
s << minify(doc["baz"].get<dom::object>());
return assert_minified(s, R"({"a":1,"b":2,"c":3})");
}

View File

@ -67,7 +67,7 @@ namespace parser_load {
bool parser_load_chain() {
TEST_START();
dom::parser parser;
auto [val, error] = parser.load(NONEXISTENT_FILE)["foo"].as_uint64_t();
auto [val, error] = parser.load(NONEXISTENT_FILE)["foo"].get<uint64_t>();
ASSERT_ERROR(error, IO_ERROR);
TEST_SUCCEED();
}
@ -75,7 +75,7 @@ namespace parser_load {
TEST_START();
dom::parser parser;
for (auto doc : parser.load_many(NONEXISTENT_FILE)) {
auto [val, error] = doc["foo"].as_uint64_t();
auto [val, error] = doc["foo"].get<uint64_t>();
ASSERT_ERROR(error, IO_ERROR);
TEST_SUCCEED();
}

View File

@ -36,11 +36,11 @@ static void parse_and_validate(const std::string src, T expected) {
bool result;
if constexpr (std::is_same<int64_t, T>::value) {
auto [actual, error] = parser.parse(pstr).as_object()["key"].as_int64_t();
auto [actual, error] = parser.parse(pstr).get<dom::object>()["key"].get<int64_t>();
if (error) { std::cerr << error << std::endl; abort(); }
result = (expected == actual);
} else {
auto [actual, error] = parser.parse(pstr).as_object()["key"].as_uint64_t();
auto [actual, error] = parser.parse(pstr).get<dom::object>()["key"].get<uint64_t>();
if (error) { std::cerr << error << std::endl; abort(); }
result = (expected == actual);
}
@ -55,18 +55,18 @@ static bool parse_and_check_signed(const std::string src) {
std::cout << "src: " << src << ", expecting signed" << std::endl;
const padded_string pstr{src};
simdjson::dom::parser parser;
auto [value, error] = parser.parse(pstr).as_object()["key"];
auto [value, error] = parser.parse(pstr).get<dom::object>()["key"];
if (error) { std::cerr << error << std::endl; abort(); }
return value.is_integer() && value.is_number();
return value.is<int64_t>();
}
static bool parse_and_check_unsigned(const std::string src) {
std::cout << "src: " << src << ", expecting signed" << std::endl;
const padded_string pstr{src};
simdjson::dom::parser parser;
auto [value, error] = parser.parse(pstr).as_object()["key"];
auto [value, error] = parser.parse(pstr).get<dom::object>()["key"];
if (error) { std::cerr << error << std::endl; abort(); }
return value.is_unsigned_integer() && value.is_number();
return value.is<uint64_t>();
}
int main() {

View File

@ -35,7 +35,7 @@ const padded_string TEST_JSON = R"(
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;
dom::parser parser;
auto [value, error] = parser.parse(TEST_JSON)[json_pointer].as_string();
auto [value, error] = parser.parse(TEST_JSON)[json_pointer].get<std::string_view>();
if (error) { std::cerr << "Unexpected Error: " << error << std::endl; return false; }
ASSERT(value == expected_value);
return true;

View File

@ -57,9 +57,9 @@ void recurse(simdjson::dom::element element, stat_t &s, size_t depth) {
if (depth > s.maximum_depth) {
s.maximum_depth = depth;
}
if (element.is_array()) {
if (element.is<simdjson::dom::array>()) {
s.array_count++;
auto [array, array_error] = element.as_array();
auto [array, array_error] = element.get<simdjson::dom::array>();
if (!array_error) {
size_t counter = 0;
for (auto child : array) {
@ -70,9 +70,9 @@ void recurse(simdjson::dom::element element, stat_t &s, size_t depth) {
s.maximum_array_size = counter;
}
}
} else if (element.is_object()) {
} else if (element.is<simdjson::dom::object>()) {
s.object_count++;
auto [object, object_error] = element.as_object();
auto [object, object_error] = element.get<simdjson::dom::object>();
if (!object_error) {
size_t counter = 0;
for (auto [key, value] : object) {
@ -96,24 +96,24 @@ void recurse(simdjson::dom::element element, stat_t &s, size_t depth) {
}
}
} else {
if (element.is_float()) {
if (element.is<double>()) {
s.float_count++;
} else if (element.is_integer()) {
} else if (element.is<int64_t>()) {
s.integer_count++;
} else if (element.is_bool()) {
if (element.as_bool()) {
} else if (element.is<bool>()) {
if (element.get<bool>()) {
s.true_count++;
} else {
s.false_count++;
}
} else if (element.is_null()) {
s.null_count++;
} else if (element.is_string()) {
} else if (element.is<std::string_view>()) {
s.string_count++;
if (is_ascii(element.as_string())) {
if (is_ascii(element.get<std::string_view>())) {
s.ascii_string_count++;
}
const std::string_view strval = element.as_string();
const std::string_view strval = element.get<std::string_view>();
if (strval.size() > s.string_maximum_length) {
s.string_maximum_length = strval.size();
}