Skip to content

Commit

Permalink
Add auto-type conversion (uint<->sint) to yyjson_ptr_get_uint/sint fu…
Browse files Browse the repository at this point in the history
…nctions.
  • Loading branch information
ibireme committed Jan 22, 2024
1 parent f1867b0 commit b63b3e1
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 16 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ All notable changes to this project will be documented in this file.
#### Added
- Add `YYJSON_WRITE_NEWLINE_AT_END` flag for JSON writer: #147

#### Changed
- Add auto-type conversion (uint<->sint) to `yyjson_ptr_get_uint/sint()`: #152


## 0.8.0 (2023-09-13)
#### Added
Expand Down
34 changes: 20 additions & 14 deletions src/yyjson.h
Original file line number Diff line number Diff line change
Expand Up @@ -7734,33 +7734,39 @@ yyjson_api_inline bool yyjson_ptr_get_bool(
}

/**
Set provided `value` if the JSON Pointer (RFC 6901) exists and is type uint.
Returns true if value at `ptr` exists and is the correct type, otherwise false.
Set provided `value` if the JSON Pointer (RFC 6901) exists and is an integer
that fits in `uint64_t`. Returns true if successful, otherwise false.
*/
yyjson_api_inline bool yyjson_ptr_get_uint(
yyjson_val *root, const char *ptr, uint64_t *value) {
yyjson_val *val = yyjson_ptr_get(root, ptr);
if (value && yyjson_is_uint(val)) {
*value = unsafe_yyjson_get_uint(val);
return true;
} else {
return false;
if (value) {
uint64_t ret = val->uni.u64;
if (unsafe_yyjson_is_uint(val) ||
(unsafe_yyjson_is_sint(val) && !(ret >> 63))) {
*value = ret;
return true;
}
}
return false;
}

/**
Set provided `value` if the JSON Pointer (RFC 6901) exists and is type sint.
Returns true if value at `ptr` exists and is the correct type, otherwise false.
Set provided `value` if the JSON Pointer (RFC 6901) exists and is an integer
that fits in `int64_t`. Returns true if successful, otherwise false.
*/
yyjson_api_inline bool yyjson_ptr_get_sint(
yyjson_val *root, const char *ptr, int64_t *value) {
yyjson_val *val = yyjson_ptr_get(root, ptr);
if (value && yyjson_is_sint(val)) {
*value = unsafe_yyjson_get_sint(val);
return true;
} else {
return false;
if (value) {
int64_t ret = val->uni.i64;
if (unsafe_yyjson_is_sint(val) ||
(unsafe_yyjson_is_uint(val) && ret >= 0)) {
*value = ret;
return true;
}
}
return false;
}

/**
Expand Down
16 changes: 14 additions & 2 deletions test/test_json_pointer.c
Original file line number Diff line number Diff line change
Expand Up @@ -3259,6 +3259,10 @@ static void test_ptr_get_type(void) {
\"answer\": {\"to\": {\"life\": 42}}, \
\"true\": true, \
\"-1\": -1, \
\"1\": 1, \
\"0\": 0, \
\"i64_max\": 9223372036854775807, \
\"i64_max+\": 9223372036854775808, \
\"zero\": 0, \
\"pi\": 3.14159, \
\"pistr\": \"3.14159\" \
Expand All @@ -3277,6 +3281,13 @@ static void test_ptr_get_type(void) {
yy_assert(yyjson_ptr_get_bool(root, "/true", &bool_value) == true && bool_value == true);
yy_assert(yyjson_ptr_get_uint(root, "/answer/to/life", &uint_value) == true && uint_value == 42);
yy_assert(yyjson_ptr_get_sint(root, "/-1", &sint_value) == true && sint_value == -1);
yy_assert(yyjson_ptr_get_sint(root, "/1", &sint_value) == true && sint_value == 1);
yy_assert(yyjson_ptr_get_uint(root, "/1", &uint_value) == true && uint_value == 1);
yy_assert(yyjson_ptr_get_sint(root, "/0", &sint_value) == true && sint_value == 0);
yy_assert(yyjson_ptr_get_uint(root, "/0", &uint_value) == true && uint_value == 0);
yy_assert(yyjson_ptr_get_sint(root, "/i64_max", &sint_value) == true);
yy_assert(yyjson_ptr_get_uint(root, "/i64_max", &uint_value) == true);
yy_assert(yyjson_ptr_get_uint(root, "/i64_max+", &uint_value) == true);
yy_assert(yyjson_ptr_get_real(root, "/pi", &real_value) == true && real_value == (double)3.14159);
yy_assert(yyjson_ptr_get_num(root, "/-1", &real_value) == true && real_value == (double)-1.0);
yy_assert(yyjson_ptr_get_num(root, "/zero", &real_value) == true && real_value == (double)0.0);
Expand All @@ -3285,10 +3296,11 @@ static void test_ptr_get_type(void) {
yy_assert(yyjson_ptr_get_str(root, "/pistr", &string_value) == true && strcmp(string_value, "3.14159") == 0);

// unsuccessful gets
yy_assert(yyjson_ptr_get_uint(root, "/-1", &uint_value) == false); // wrong type
yy_assert(yyjson_ptr_get_uint(root, "/-1", &uint_value) == false); // type cast error
yy_assert(yyjson_ptr_get_sint(root, "/i64_max+", &sint_value) == false); // type cast error
yy_assert(yyjson_ptr_get_num(root, "/pistr", &real_value) == false); // wrong type
yy_assert(yyjson_ptr_get_str(root, "/answer/to", &string_value) == false); // wrong type
yy_assert(yyjson_ptr_get_real(root, "/nosuch", &real_value) == false); // Does not exist
yy_assert(yyjson_ptr_get_real(root, "/nosuch", &real_value) == false); // not exist

// type mismatch
yy_assert(yyjson_ptr_get_bool(root, "/pi", &bool_value) == false);
Expand Down

0 comments on commit b63b3e1

Please sign in to comment.