Allowing casts instead of get_double, get_uint64 and get_int64 (#1705)

This commit is contained in:
Daniel Lemire 2021-08-27 10:25:17 -04:00 committed by GitHub
parent 4afe7565b4
commit b935ce2e06
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 37 additions and 12 deletions

View File

@ -1238,10 +1238,9 @@ instance. Upon success, it returns an `ondemand::number` instance.
An `ondemand::number` instance may contain an integer value or a floating-point value.
Thus it is a dynamically typed number. Before accessing the value, you must determine the detected type:
* `number.get_number_type()` has value `number_type::signed_integer` if we have a integer in [-9223372036854775808,9223372036854775808). You can recover the value by the `get_int64()` method applied on the `ondemand::number` instance. When `number.get_number_type()` has value `number_type::signed_integer`, you also have that `number.is_int64()` is true. Calling `get_int64()` on the `ondemand::number` instance when `number.get_number_type()` is not `number_type::signed_integer` is unsafe.
* `number.get_number_type()` has value `number_type::unsigned_integer` if we have a integer in [9223372036854775808,18446744073709551616). You can recover the value by the `get_uint64()` method applied on the `ondemand::number` instance. When `number.get_number_type()` has value `number_type::unsigned_integer`, you also have that `number.is_uint64()` is true. Calling `get_uint64()` on the `ondemand::number` instance when `number.get_number_type()` is not `number_type::unsigned_integer` is unsafe.
* `number.get_number_type()` has value `number_type::unsigned_integer` if we have a integer in [9223372036854775808,18446744073709551616). You can recover the value by the `get_uint64()` method applied on the `ondemand::number` instance. When `number.get_number_type()` has value `number_type::unsigned_integer`, you also have that `number.is_uint64()` is true. Calling `get_uint64()` on the `ondemand::number` instance when `number.get_number_type()` is not `number_type::unsigned_integer` is unsafe.
* `number.get_number_type()` has value `number_type::floating_point_number` if we have and we have a floating-point (binary64) number. You can recover the value by the `get_double()` method applied on the `ondemand::number` instance. When `number.get_number_type()` has value `number_type::floating_point_number`, you also have that `number.is_double()` is true. Calling `get_double()` on the `ondemand::number` instance when `number.get_number_type()` is not `number_type::floating_point_number` is unsafe.
* `number.get_number_type()` has value `number_type::signed_integer` if we have a integer in [-9223372036854775808,9223372036854775808). You can recover the value by the `get_int64()` method applied on the `ondemand::number` instance. When `number.get_number_type()` has value `number_type::signed_integer`, you also have that `number.is_int64()` is true. Calling `get_int64()` on the `ondemand::number` instance when `number.get_number_type()` is not `number_type::signed_integer` is unsafe. You may replace `get_int64()` by a cast to a `int64_t` value.
* `number.get_number_type()` has value `number_type::unsigned_integer` if we have a integer in [9223372036854775808,18446744073709551616). You can recover the value by the `get_uint64()` method applied on the `ondemand::number` instance. When `number.get_number_type()` has value `number_type::unsigned_integer`, you also have that `number.is_uint64()` is true. Calling `get_uint64()` on the `ondemand::number` instance when `number.get_number_type()` is not `number_type::unsigned_integer` is unsafe. You may replace `get_uint64()` by a cast to a `uint64_t` value.
* `number.get_number_type()` has value `number_type::floating_point_number` if we have and we have a floating-point (binary64) number. You can recover the value by the `get_double()` method applied on the `ondemand::number` instance. When `number.get_number_type()` has value `number_type::floating_point_number`, you also have that `number.is_double()` is true. Calling `get_double()` on the `ondemand::number` instance when `number.get_number_type()` is not `number_type::floating_point_number` is unsafe. You may replace `get_double()` by a cast to a `double` value.
You must check the type before accessing the value: it is an error to call `get_int64()` when `number.get_number_type()` is not `number_type::signed_integer` and when `number.is_int64()` is false. You are responsible for this check as the user of the library.
@ -1262,12 +1261,15 @@ Consider the following example:
ondemand::number_type t = num.get_number_type();
switch(t) {
case ondemand::number_type::signed_integer:
std::cout << "integer: " << int64_t(num) << " ";
std::cout << "integer: " << num.get_int64() << std::endl;
break;
case ondemand::number_type::unsigned_integer:
std::cout << "large 64-bit integer: " << uint64_t(num) << " ";
std::cout << "large 64-bit integer: " << num.get_uint64() << std::endl;
break;
case ondemand::number_type::floating_point_number:
std::cout << "float: " << double(num) << " ";
std::cout << "float: " << num.get_double() << std::endl;
break;
}
@ -1277,12 +1279,12 @@ Consider the following example:
It will output:
```
1.0 negative: 0 is_integer: 0 float: 1
3 negative: 0 is_integer: 1 integer: 3
1 negative: 0 is_integer: 1 integer: 1
3.1415 negative: 0 is_integer: 0 float: 3.1415
-13231232 negative: 1 is_integer: 1 integer: -13231232
9999999999999999999 negative: 0 is_integer: 1 large 64-bit integer: 9999999999999999999
1.0 negative: 0 is_integer: 0 float: 1 float: 1
3 negative: 0 is_integer: 1 integer: 3 integer: 3
1 negative: 0 is_integer: 1 integer: 1 integer: 1
3.1415 negative: 0 is_integer: 0 float: 3.1415 float: 3.1415
-13231232 negative: 1 is_integer: 1 integer: -13231232 integer: -13231232
9999999999999999999 negative: 0 is_integer: 1 large 64-bit integer: 9999999999999999999 large 64-bit integer: 9999999999999999999
```
Thread Safety

View File

@ -44,6 +44,10 @@ simdjson_really_inline uint64_t number::get_uint64() const noexcept {
return payload.unsigned_integer;
}
simdjson_really_inline number::operator uint64_t() const noexcept {
return get_uint64();
}
simdjson_really_inline bool number::is_int64() const noexcept {
return get_number_type() == number_type::signed_integer;
@ -53,6 +57,10 @@ simdjson_really_inline int64_t number::get_int64() const noexcept {
return payload.signed_integer;
}
simdjson_really_inline number::operator int64_t() const noexcept {
return get_int64();
}
simdjson_really_inline bool number::is_double() const noexcept {
return get_number_type() == number_type::floating_point_number;
}
@ -61,6 +69,10 @@ simdjson_really_inline double number::get_double() const noexcept {
return payload.floating_point_number;
}
simdjson_really_inline number::operator double() const noexcept {
return get_double();
}
simdjson_really_inline double number::as_double() const noexcept {
if(is_double()) {
return payload.floating_point_number;

View File

@ -47,6 +47,7 @@ struct number {
* return the value as a uint64_t, only valid if is_uint64() is true.
*/
simdjson_really_inline uint64_t get_uint64() const noexcept;
simdjson_really_inline operator uint64_t() const noexcept;
/**
* return true if the automatically determined type of
@ -57,6 +58,7 @@ struct number {
* return the value as a int64_t, only valid if is_int64() is true.
*/
simdjson_really_inline int64_t get_int64() const noexcept;
simdjson_really_inline operator int64_t() const noexcept;
/**
@ -68,6 +70,8 @@ struct number {
* return the value as a double, only valid if is_double() is true.
*/
simdjson_really_inline double get_double() const noexcept;
simdjson_really_inline operator double() const noexcept;
/**
* Convert the number to a double. Though it always succeed, the conversion
* may be lossy if the number cannot be represented exactly.
@ -75,8 +79,6 @@ struct number {
simdjson_really_inline double as_double() const noexcept;
protected:
/**
* The next block of declaration is designed so that we can call the number parsing

View File

@ -237,16 +237,22 @@ namespace number_tests {
}
if(counter == 0) {
ASSERT_EQUAL(num.get_double(), 1.0);
ASSERT_EQUAL((double)num, 1.0);
} else if(counter == 1) {
ASSERT_EQUAL(num.get_int64(), 3);
ASSERT_EQUAL((int64_t)num, 3);
} else if(counter == 2) {
ASSERT_EQUAL(num.get_int64(), 1);
ASSERT_EQUAL((int64_t)num, 1);
} else if(counter == 3) {
ASSERT_EQUAL(num.get_double(), 3.1415);
ASSERT_EQUAL((double)num, 3.1415);
} else if(counter == 4) {
ASSERT_EQUAL(num.get_int64(), -13231232);
ASSERT_EQUAL((int64_t)num, -13231232);
} else if(counter == 5) {
ASSERT_EQUAL(num.get_uint64(), UINT64_C(9999999999999999999));
ASSERT_EQUAL((uint64_t)num, UINT64_C(9999999999999999999));
}
counter++;
}

View File

@ -22,12 +22,15 @@ using error_code=simdjson::error_code;
ondemand::number_type t = num.get_number_type();
switch(t) {
case ondemand::number_type::signed_integer:
std::cout << "integer: " << int64_t(num) << " ";
std::cout << "integer: " << num.get_int64() << std::endl;
break;
case ondemand::number_type::unsigned_integer:
std::cout << "large 64-bit integer: " << uint64_t(num) << " ";
std::cout << "large 64-bit integer: " << num.get_uint64() << std::endl;
break;
case ondemand::number_type::floating_point_number:
std::cout << "float: " << double(num) << " ";
std::cout << "float: " << num.get_double() << std::endl;
break;
}