mirror of
https://github.com/simdjson/simdjson
synced 2026-06-08 17:27:07 +00:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8c1bfe782b | |||
| 730939f01c | |||
| b169dc2ea7 |
+1
-7
@@ -1401,10 +1401,6 @@ You must check the type before accessing the value: it is an error to call `get_
|
||||
|
||||
The `get_number()` function is designed with performance in mind. When calling `get_number()`, you scan the number string only once, determining efficiently the type and storing it in an efficient manner.
|
||||
|
||||
If you only need to compute `v.get_number().get_number_type()` on
|
||||
a `document` or `value` instance, you should call directly the faster method
|
||||
`v.get_number_type()` which does not generate an
|
||||
intermediate `number` instance.
|
||||
|
||||
Consider the following example:
|
||||
```C++
|
||||
@@ -1417,9 +1413,7 @@ Consider the following example:
|
||||
std::cout << "negative: " << val.is_negative() << " ";
|
||||
std::cout << "is_integer: " << val.is_integer() << " ";
|
||||
ondemand::number num = val.get_number();
|
||||
// direct computation without materializing the number:
|
||||
ondemand::number_type dt = val.get_number_type();
|
||||
if(t != dt) { throw std::runtime_error("bug"); }
|
||||
ondemand::number_type t = num.get_number_type();
|
||||
switch(t) {
|
||||
case ondemand::number_type::signed_integer:
|
||||
std::cout << "integer: " << int64_t(num) << " ";
|
||||
|
||||
@@ -1067,6 +1067,11 @@ simdjson_unused simdjson_really_inline simdjson_result<ondemand::number_type> ge
|
||||
while(static_cast<uint8_t>(*p - '0') <= 9) { p++; }
|
||||
if ( p == src ) { return NUMBER_ERROR; }
|
||||
if (jsoncharutils::is_structural_or_whitespace(*p)) {
|
||||
// We have an integer.
|
||||
// If the number is negative and valid, it must be a signed integer.
|
||||
if(negative) { return ondemand::number_type::signed_integer; }
|
||||
// We want values larger or equal to 9223372036854775808 to be unsigned
|
||||
// integers, and the other values to be signed integers.
|
||||
int digit_count = int(p - src);
|
||||
if(digit_count >= 19) {
|
||||
const uint8_t * smaller_big_integer = reinterpret_cast<const uint8_t *>("9223372036854775808");
|
||||
@@ -1076,6 +1081,7 @@ simdjson_unused simdjson_really_inline simdjson_result<ondemand::number_type> ge
|
||||
}
|
||||
return ondemand::number_type::signed_integer;
|
||||
}
|
||||
// Hopefully, we have 'e' or 'E' or '.'.
|
||||
return ondemand::number_type::floating_point_number;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,10 @@ inline simdjson_result<const char *> document::current_location() noexcept {
|
||||
return iter.current_location();
|
||||
}
|
||||
|
||||
inline int32_t document::current_depth() const noexcept {
|
||||
return iter.depth();
|
||||
}
|
||||
|
||||
inline bool document::is_alive() noexcept {
|
||||
return iter.is_alive();
|
||||
}
|
||||
@@ -471,6 +475,11 @@ simdjson_really_inline simdjson_result<const char *> simdjson_result<SIMDJSON_IM
|
||||
return first.current_location();
|
||||
}
|
||||
|
||||
simdjson_really_inline int32_t simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::current_depth() const noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first.current_depth();
|
||||
}
|
||||
|
||||
simdjson_really_inline simdjson_result<std::string_view> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::raw_json_token() noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first.raw_json_token();
|
||||
@@ -528,6 +537,7 @@ simdjson_really_inline simdjson_result<value> document_reference::find_field_uno
|
||||
simdjson_really_inline simdjson_result<json_type> document_reference::type() noexcept { return doc->type(); }
|
||||
simdjson_really_inline simdjson_result<bool> document_reference::is_scalar() noexcept { return doc->is_scalar(); }
|
||||
simdjson_really_inline simdjson_result<const char *> document_reference::current_location() noexcept { return doc->current_location(); }
|
||||
simdjson_really_inline int32_t document_reference::current_depth() const noexcept { return doc->current_depth(); }
|
||||
simdjson_really_inline bool document_reference::is_negative() noexcept { return doc->is_negative(); }
|
||||
simdjson_really_inline simdjson_result<bool> document_reference::is_integer() noexcept { return doc->is_integer(); }
|
||||
simdjson_really_inline simdjson_result<number_type> document_reference::get_number_type() noexcept { return doc->get_number_type(); }
|
||||
|
||||
@@ -399,7 +399,14 @@ public:
|
||||
*/
|
||||
simdjson_really_inline simdjson_result<bool> is_integer() noexcept;
|
||||
/**
|
||||
* Determine the number type (integer or floating-point number).
|
||||
* Determine the number type (integer or floating-point number) as quickly
|
||||
* as possible. This function does not fully validate the input. It is
|
||||
* useful when you only need to classify the numbers, without parsing them.
|
||||
*
|
||||
* If you are planning to retrieve the value or you need full validation,
|
||||
* consider using the get_number() method instead: it will fully parse
|
||||
* and validate the input, and give you access to the type:
|
||||
* get_number().get_number_type().
|
||||
*
|
||||
* get_number_type() is number_type::unsigned_integer if we have
|
||||
* an integer greater or equal to 9223372036854775808
|
||||
@@ -407,8 +414,7 @@ public:
|
||||
* integer that is less than 9223372036854775808
|
||||
* Otherwise, get_number_type() has value number_type::floating_point_number
|
||||
*
|
||||
* This function req
|
||||
* uires processing the number string, but it is expected
|
||||
* This function requires processing the number string, but it is expected
|
||||
* to be faster than get_number().get_number_type() because it is does not
|
||||
* parse the number value.
|
||||
*
|
||||
@@ -489,6 +495,17 @@ public:
|
||||
*/
|
||||
inline simdjson_result<const char *> current_location() noexcept;
|
||||
|
||||
/**
|
||||
* Returns the current depth in the document if in bounds.
|
||||
*
|
||||
* E.g.,
|
||||
* 0 = finished with document
|
||||
* 1 = document root value (could be [ or {, not yet known)
|
||||
* 2 = , or } inside root array/object
|
||||
* 3 = key or value inside root array/object.
|
||||
*/
|
||||
simdjson_really_inline int32_t current_depth() const noexcept;
|
||||
|
||||
/**
|
||||
* Get the value associated with the given JSON pointer. We use the RFC 6901
|
||||
* https://tools.ietf.org/html/rfc6901 standard.
|
||||
@@ -609,6 +626,7 @@ public:
|
||||
simdjson_really_inline simdjson_result<bool> is_scalar() noexcept;
|
||||
|
||||
simdjson_really_inline simdjson_result<const char *> current_location() noexcept;
|
||||
simdjson_really_inline int32_t current_depth() const noexcept;
|
||||
simdjson_really_inline bool is_negative() noexcept;
|
||||
simdjson_really_inline simdjson_result<bool> is_integer() noexcept;
|
||||
simdjson_really_inline simdjson_result<number_type> get_number_type() noexcept;
|
||||
@@ -675,6 +693,7 @@ public:
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::json_type> type() noexcept;
|
||||
simdjson_really_inline simdjson_result<bool> is_scalar() noexcept;
|
||||
simdjson_really_inline simdjson_result<const char *> current_location() noexcept;
|
||||
simdjson_really_inline int32_t current_depth() const noexcept;
|
||||
simdjson_really_inline bool is_negative() noexcept;
|
||||
simdjson_really_inline simdjson_result<bool> is_integer() noexcept;
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::number_type> get_number_type() noexcept;
|
||||
@@ -735,6 +754,7 @@ public:
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::json_type> type() noexcept;
|
||||
simdjson_really_inline simdjson_result<bool> is_scalar() noexcept;
|
||||
simdjson_really_inline simdjson_result<const char *> current_location() noexcept;
|
||||
simdjson_really_inline int32_t current_depth() const noexcept;
|
||||
simdjson_really_inline bool is_negative() noexcept;
|
||||
simdjson_really_inline simdjson_result<bool> is_integer() noexcept;
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::number_type> get_number_type() noexcept;
|
||||
|
||||
@@ -181,6 +181,10 @@ simdjson_really_inline simdjson_result<const char *> value::current_location() n
|
||||
return iter.json_iter().current_location();
|
||||
}
|
||||
|
||||
simdjson_really_inline int32_t value::current_depth() const noexcept{
|
||||
return iter.json_iter().depth();
|
||||
}
|
||||
|
||||
simdjson_really_inline simdjson_result<value> value::at_pointer(std::string_view json_pointer) noexcept {
|
||||
json_type t;
|
||||
SIMDJSON_TRY(type().get(t));
|
||||
@@ -400,6 +404,11 @@ simdjson_really_inline simdjson_result<const char *> simdjson_result<SIMDJSON_IM
|
||||
return first.current_location();
|
||||
}
|
||||
|
||||
simdjson_really_inline int32_t simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::current_depth() const noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first.current_depth();
|
||||
}
|
||||
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::at_pointer(std::string_view json_pointer) noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first.at_pointer(json_pointer);
|
||||
|
||||
@@ -369,7 +369,14 @@ public:
|
||||
*/
|
||||
simdjson_really_inline simdjson_result<bool> is_integer() noexcept;
|
||||
/**
|
||||
* Determine the number type (integer or floating-point number).
|
||||
* Determine the number type (integer or floating-point number) as quickly
|
||||
* as possible. This function does not fully validate the input. It is
|
||||
* useful when you only need to classify the numbers, without parsing them.
|
||||
*
|
||||
* If you are planning to retrieve the value or you need full validation,
|
||||
* consider using the get_number() method instead: it will fully parse
|
||||
* and validate the input, and give you access to the type:
|
||||
* get_number().get_number_type().
|
||||
*
|
||||
* get_number_type() is number_type::unsigned_integer if we have
|
||||
* an integer greater or equal to 9223372036854775808
|
||||
@@ -448,6 +455,17 @@ public:
|
||||
*/
|
||||
simdjson_really_inline simdjson_result<const char *> current_location() noexcept;
|
||||
|
||||
/**
|
||||
* Returns the current depth in the document if in bounds.
|
||||
*
|
||||
* E.g.,
|
||||
* 0 = finished with document
|
||||
* 1 = document root value (could be [ or {, not yet known)
|
||||
* 2 = , or } inside root array/object
|
||||
* 3 = key or value inside root array/object.
|
||||
*/
|
||||
simdjson_really_inline int32_t current_depth() const noexcept;
|
||||
|
||||
/**
|
||||
* Get the value associated with the given JSON pointer. We use the RFC 6901
|
||||
* https://tools.ietf.org/html/rfc6901 standard.
|
||||
@@ -650,7 +668,8 @@ public:
|
||||
|
||||
/** @copydoc simdjson_really_inline simdjson_result<const char *> current_location() noexcept */
|
||||
simdjson_really_inline simdjson_result<const char *> current_location() noexcept;
|
||||
|
||||
/** @copydoc simdjson_really_inline int32_t current_depth() const noexcept */
|
||||
simdjson_really_inline int32_t current_depth() const noexcept;
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> at_pointer(std::string_view json_pointer) noexcept;
|
||||
};
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@ public:
|
||||
/**
|
||||
* Get the depth of this value.
|
||||
*/
|
||||
simdjson_really_inline depth_t depth() const noexcept;
|
||||
simdjson_really_inline int32_t depth() const noexcept;
|
||||
|
||||
/**
|
||||
* Get the JSON type of this value.
|
||||
|
||||
@@ -197,16 +197,18 @@ namespace number_tests {
|
||||
bool get_number_tests() {
|
||||
TEST_START();
|
||||
ondemand::parser parser;
|
||||
padded_string docdata = R"([1.0, 3, 1, 3.1415,-13231232,9999999999999999999])"_padded;
|
||||
padded_string docdata = R"([1.0, 3, 1, 3.1415,-13231232,9999999999999999999,-9223372036854775807,-9223372036854775808])"_padded;
|
||||
ondemand::number_type expectedtypes[] = {ondemand::number_type::floating_point_number,
|
||||
ondemand::number_type::signed_integer,
|
||||
ondemand::number_type::signed_integer,
|
||||
ondemand::number_type::floating_point_number,
|
||||
ondemand::number_type::signed_integer,
|
||||
ondemand::number_type::unsigned_integer
|
||||
ondemand::number_type::unsigned_integer,
|
||||
ondemand::number_type::signed_integer,
|
||||
ondemand::number_type::signed_integer
|
||||
};
|
||||
bool is_negative[] = {false, false, false, false, true, false};
|
||||
bool is_integer[] = {false, true, true, false, true, true};
|
||||
bool is_negative[] = {false, false, false, false, true, false, true, true};
|
||||
bool is_integer[] = {false, true, true, false, true, true, true, true};
|
||||
|
||||
ondemand::document doc;
|
||||
ASSERT_SUCCESS(parser.iterate(docdata).get(doc));
|
||||
|
||||
@@ -109,6 +109,85 @@ bool basics_treewalk() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void print_depth_space(ondemand::value element) {
|
||||
for(auto i = 0; i < element.current_depth(); i++) {
|
||||
cout << " ";
|
||||
}
|
||||
}
|
||||
|
||||
void recursive_print_json_breakline(ondemand::value element) {
|
||||
bool add_comma;
|
||||
switch (element.type()) {
|
||||
case ondemand::json_type::array:
|
||||
cout << endl;
|
||||
print_depth_space(element);
|
||||
cout << "[";
|
||||
add_comma = false;
|
||||
for (auto child : element.get_array()) {
|
||||
if (add_comma) {
|
||||
print_depth_space(element);
|
||||
cout << ",";
|
||||
}
|
||||
// We need the call to value() to get
|
||||
// an ondemand::value type.
|
||||
recursive_print_json_breakline(child.value());
|
||||
add_comma = true;
|
||||
}
|
||||
cout << "]";
|
||||
break;
|
||||
case ondemand::json_type::object:
|
||||
cout << endl;
|
||||
print_depth_space(element);
|
||||
cout << "{";
|
||||
add_comma = false;
|
||||
for (auto field : element.get_object()) {
|
||||
if (add_comma) {
|
||||
print_depth_space(element);
|
||||
cout << ",";
|
||||
}
|
||||
// key() returns the key as it appears in the raw
|
||||
// JSON document, if we want the unescaped key,
|
||||
// we should do field.unescaped_key().
|
||||
cout << "\"" << field.key() << "\": ";
|
||||
recursive_print_json_breakline(field.value());
|
||||
add_comma = true;
|
||||
}
|
||||
cout << "}\n";
|
||||
break;
|
||||
case ondemand::json_type::number:
|
||||
// assume it fits in a double
|
||||
cout << element.get_double();
|
||||
break;
|
||||
case ondemand::json_type::string:
|
||||
// get_string() would return escaped string, but
|
||||
// we are happy with unescaped string.
|
||||
cout << "\"" << element.get_raw_json_string() << "\"";
|
||||
break;
|
||||
case ondemand::json_type::boolean:
|
||||
cout << element.get_bool();
|
||||
break;
|
||||
case ondemand::json_type::null:
|
||||
cout << "null";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool basics_treewalk_breakline() {
|
||||
padded_string json[3] = {R"( [
|
||||
{ "make": "Toyota", "model": "Camry", "year": 2018, "tire_pressure": [ 40.1, 39.9, 37.7, 40.4 ] },
|
||||
{ "make": "Kia", "model": "Soul", "year": 2012, "tire_pressure": [ 30.1, 31.0, 28.6, 28.7 ] },
|
||||
{ "make": "Toyota", "model": "Tercel", "year": 1999, "tire_pressure": [ 29.8, 30.0, 30.2, 30.5 ] }
|
||||
] )"_padded, R"( {"key":"value"} )"_padded, "[12,3]"_padded};
|
||||
ondemand::parser parser;
|
||||
for(size_t i = 0 ; i < 3; i++) {
|
||||
ondemand::document doc = parser.iterate(json[i]);
|
||||
ondemand::value val = doc;
|
||||
recursive_print_json_breakline(val);
|
||||
std::cout << std::endl;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool basics_1() {
|
||||
TEST_START();
|
||||
|
||||
@@ -882,6 +961,7 @@ bool current_location_no_error() {
|
||||
int main() {
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
basics_treewalk();
|
||||
basics_treewalk_breakline();
|
||||
#endif
|
||||
if (
|
||||
true
|
||||
|
||||
Reference in New Issue
Block a user