json: support parsing and serializing 'uint64_t'
Introduce support for 'uint64_t' type, so that unsigned numbers can be serialized into JSON payloads. Signed-off-by: Mykhailo Lohvynenko <Mykhailo_Lohvynenko@epam.com>
This commit is contained in:
parent
ae63c62f0e
commit
03029e7bd7
3 changed files with 92 additions and 5 deletions
|
@ -43,6 +43,7 @@ enum json_tokens {
|
||||||
JSON_TOK_OBJ_ARRAY = '3',
|
JSON_TOK_OBJ_ARRAY = '3',
|
||||||
JSON_TOK_ENCODED_OBJ = '4',
|
JSON_TOK_ENCODED_OBJ = '4',
|
||||||
JSON_TOK_INT64 = '5',
|
JSON_TOK_INT64 = '5',
|
||||||
|
JSON_TOK_UINT64 = '6',
|
||||||
JSON_TOK_TRUE = 't',
|
JSON_TOK_TRUE = 't',
|
||||||
JSON_TOK_FALSE = 'f',
|
JSON_TOK_FALSE = 'f',
|
||||||
JSON_TOK_NULL = 'n',
|
JSON_TOK_NULL = 'n',
|
||||||
|
|
|
@ -309,6 +309,7 @@ static int element_token(enum json_tokens token)
|
||||||
case JSON_TOK_STRING:
|
case JSON_TOK_STRING:
|
||||||
case JSON_TOK_NUMBER:
|
case JSON_TOK_NUMBER:
|
||||||
case JSON_TOK_INT64:
|
case JSON_TOK_INT64:
|
||||||
|
case JSON_TOK_UINT64:
|
||||||
case JSON_TOK_FLOAT:
|
case JSON_TOK_FLOAT:
|
||||||
case JSON_TOK_OPAQUE:
|
case JSON_TOK_OPAQUE:
|
||||||
case JSON_TOK_OBJ_ARRAY:
|
case JSON_TOK_OBJ_ARRAY:
|
||||||
|
@ -469,6 +470,30 @@ static int decode_int64(const struct json_token *token, int64_t *num)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int decode_uint64(const struct json_token *token, uint64_t *num)
|
||||||
|
{
|
||||||
|
char *endptr;
|
||||||
|
char prev_end;
|
||||||
|
|
||||||
|
prev_end = *token->end;
|
||||||
|
*token->end = '\0';
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
*num = strtoull(token->start, &endptr, 10);
|
||||||
|
|
||||||
|
*token->end = prev_end;
|
||||||
|
|
||||||
|
if (errno != 0) {
|
||||||
|
return -errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (endptr != token->end) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static bool equivalent_types(enum json_tokens type1, enum json_tokens type2)
|
static bool equivalent_types(enum json_tokens type1, enum json_tokens type2)
|
||||||
{
|
{
|
||||||
if (type1 == JSON_TOK_TRUE || type1 == JSON_TOK_FALSE) {
|
if (type1 == JSON_TOK_TRUE || type1 == JSON_TOK_FALSE) {
|
||||||
|
@ -483,6 +508,10 @@ static bool equivalent_types(enum json_tokens type1, enum json_tokens type2)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (type1 == JSON_TOK_NUMBER && type2 == JSON_TOK_UINT64) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (type1 == JSON_TOK_STRING && type2 == JSON_TOK_OPAQUE) {
|
if (type1 == JSON_TOK_STRING && type2 == JSON_TOK_OPAQUE) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -545,6 +574,11 @@ static int64_t decode_value(struct json_obj *obj,
|
||||||
|
|
||||||
return decode_int64(value, num);
|
return decode_int64(value, num);
|
||||||
}
|
}
|
||||||
|
case JSON_TOK_UINT64: {
|
||||||
|
uint64_t *num = field;
|
||||||
|
|
||||||
|
return decode_uint64(value, num);
|
||||||
|
}
|
||||||
case JSON_TOK_OPAQUE:
|
case JSON_TOK_OPAQUE:
|
||||||
case JSON_TOK_FLOAT: {
|
case JSON_TOK_FLOAT: {
|
||||||
struct json_obj_token *obj_token = field;
|
struct json_obj_token *obj_token = field;
|
||||||
|
@ -573,6 +607,8 @@ static ptrdiff_t get_elem_size(const struct json_obj_descr *descr)
|
||||||
return sizeof(int32_t);
|
return sizeof(int32_t);
|
||||||
case JSON_TOK_INT64:
|
case JSON_TOK_INT64:
|
||||||
return sizeof(int64_t);
|
return sizeof(int64_t);
|
||||||
|
case JSON_TOK_UINT64:
|
||||||
|
return sizeof(uint64_t);
|
||||||
case JSON_TOK_OPAQUE:
|
case JSON_TOK_OPAQUE:
|
||||||
case JSON_TOK_FLOAT:
|
case JSON_TOK_FLOAT:
|
||||||
case JSON_TOK_OBJ_ARRAY:
|
case JSON_TOK_OBJ_ARRAY:
|
||||||
|
@ -1035,6 +1071,23 @@ static int int64_encode(const int64_t *num, json_append_bytes_t append_bytes,
|
||||||
return append_bytes(buf, (size_t)ret, data);
|
return append_bytes(buf, (size_t)ret, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int uint64_encode(const uint64_t *num, json_append_bytes_t append_bytes,
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
char buf[sizeof("18446744073709551610")];
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = snprintk(buf, sizeof(buf), "%" PRIu64, *num);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
if (ret >= (int)sizeof(buf)) {
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
return append_bytes(buf, (size_t)ret, data);
|
||||||
|
}
|
||||||
|
|
||||||
static int float_ascii_encode(struct json_obj_token *num, json_append_bytes_t append_bytes,
|
static int float_ascii_encode(struct json_obj_token *num, json_append_bytes_t append_bytes,
|
||||||
void *data)
|
void *data)
|
||||||
{
|
{
|
||||||
|
@ -1099,6 +1152,8 @@ static int encode(const struct json_obj_descr *descr, const void *val,
|
||||||
return num_encode(ptr, append_bytes, data);
|
return num_encode(ptr, append_bytes, data);
|
||||||
case JSON_TOK_INT64:
|
case JSON_TOK_INT64:
|
||||||
return int64_encode(ptr, append_bytes, data);
|
return int64_encode(ptr, append_bytes, data);
|
||||||
|
case JSON_TOK_UINT64:
|
||||||
|
return uint64_encode(ptr, append_bytes, data);
|
||||||
case JSON_TOK_FLOAT:
|
case JSON_TOK_FLOAT:
|
||||||
return float_ascii_encode(ptr, append_bytes, data);
|
return float_ascii_encode(ptr, append_bytes, data);
|
||||||
case JSON_TOK_OPAQUE:
|
case JSON_TOK_OPAQUE:
|
||||||
|
|
|
@ -14,6 +14,7 @@ struct test_nested {
|
||||||
bool nested_bool;
|
bool nested_bool;
|
||||||
const char *nested_string;
|
const char *nested_string;
|
||||||
int64_t nested_int64;
|
int64_t nested_int64;
|
||||||
|
uint64_t nested_uint64;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct test_struct {
|
struct test_struct {
|
||||||
|
@ -22,6 +23,8 @@ struct test_struct {
|
||||||
bool some_bool;
|
bool some_bool;
|
||||||
int64_t some_int64;
|
int64_t some_int64;
|
||||||
int64_t another_int64;
|
int64_t another_int64;
|
||||||
|
int64_t some_uint64;
|
||||||
|
int64_t another_uint64;
|
||||||
struct test_nested some_nested_struct;
|
struct test_nested some_nested_struct;
|
||||||
int some_array[16];
|
int some_array[16];
|
||||||
size_t some_array_len;
|
size_t some_array_len;
|
||||||
|
@ -51,6 +54,9 @@ struct test_int_limits {
|
||||||
int64_t int64_max;
|
int64_t int64_max;
|
||||||
int64_t int64_cero;
|
int64_t int64_cero;
|
||||||
int64_t int64_min;
|
int64_t int64_min;
|
||||||
|
uint64_t uint64_max;
|
||||||
|
uint64_t uint64_cero;
|
||||||
|
uint64_t uint64_min;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct json_obj_descr nested_descr[] = {
|
static const struct json_obj_descr nested_descr[] = {
|
||||||
|
@ -60,6 +66,8 @@ static const struct json_obj_descr nested_descr[] = {
|
||||||
JSON_TOK_STRING),
|
JSON_TOK_STRING),
|
||||||
JSON_OBJ_DESCR_PRIM(struct test_nested, nested_int64,
|
JSON_OBJ_DESCR_PRIM(struct test_nested, nested_int64,
|
||||||
JSON_TOK_INT64),
|
JSON_TOK_INT64),
|
||||||
|
JSON_OBJ_DESCR_PRIM(struct test_nested, nested_uint64,
|
||||||
|
JSON_TOK_UINT64),
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct json_obj_descr test_descr[] = {
|
static const struct json_obj_descr test_descr[] = {
|
||||||
|
@ -70,6 +78,10 @@ static const struct json_obj_descr test_descr[] = {
|
||||||
JSON_TOK_INT64),
|
JSON_TOK_INT64),
|
||||||
JSON_OBJ_DESCR_PRIM(struct test_struct, another_int64,
|
JSON_OBJ_DESCR_PRIM(struct test_struct, another_int64,
|
||||||
JSON_TOK_INT64),
|
JSON_TOK_INT64),
|
||||||
|
JSON_OBJ_DESCR_PRIM(struct test_struct, some_uint64,
|
||||||
|
JSON_TOK_UINT64),
|
||||||
|
JSON_OBJ_DESCR_PRIM(struct test_struct, another_uint64,
|
||||||
|
JSON_TOK_UINT64),
|
||||||
JSON_OBJ_DESCR_OBJECT(struct test_struct, some_nested_struct,
|
JSON_OBJ_DESCR_OBJECT(struct test_struct, some_nested_struct,
|
||||||
nested_descr),
|
nested_descr),
|
||||||
JSON_OBJ_DESCR_ARRAY(struct test_struct, some_array,
|
JSON_OBJ_DESCR_ARRAY(struct test_struct, some_array,
|
||||||
|
@ -104,6 +116,9 @@ static const struct json_obj_descr obj_limits_descr[] = {
|
||||||
JSON_OBJ_DESCR_PRIM(struct test_int_limits, int64_max, JSON_TOK_INT64),
|
JSON_OBJ_DESCR_PRIM(struct test_int_limits, int64_max, JSON_TOK_INT64),
|
||||||
JSON_OBJ_DESCR_PRIM(struct test_int_limits, int64_cero, JSON_TOK_INT64),
|
JSON_OBJ_DESCR_PRIM(struct test_int_limits, int64_cero, JSON_TOK_INT64),
|
||||||
JSON_OBJ_DESCR_PRIM(struct test_int_limits, int64_min, JSON_TOK_INT64),
|
JSON_OBJ_DESCR_PRIM(struct test_int_limits, int64_min, JSON_TOK_INT64),
|
||||||
|
JSON_OBJ_DESCR_PRIM(struct test_int_limits, uint64_max, JSON_TOK_UINT64),
|
||||||
|
JSON_OBJ_DESCR_PRIM(struct test_int_limits, uint64_cero, JSON_TOK_UINT64),
|
||||||
|
JSON_OBJ_DESCR_PRIM(struct test_int_limits, uint64_min, JSON_TOK_UINT64),
|
||||||
};
|
};
|
||||||
|
|
||||||
struct array {
|
struct array {
|
||||||
|
@ -197,12 +212,15 @@ ZTEST(lib_json_test, test_json_encoding)
|
||||||
.some_int = 42,
|
.some_int = 42,
|
||||||
.some_int64 = 1152921504606846977,
|
.some_int64 = 1152921504606846977,
|
||||||
.another_int64 = -2305843009213693937,
|
.another_int64 = -2305843009213693937,
|
||||||
|
.some_uint64 = 18446744073709551615U,
|
||||||
|
.another_uint64 = 0,
|
||||||
.some_bool = true,
|
.some_bool = true,
|
||||||
.some_nested_struct = {
|
.some_nested_struct = {
|
||||||
.nested_int = -1234,
|
.nested_int = -1234,
|
||||||
.nested_bool = false,
|
.nested_bool = false,
|
||||||
.nested_string = "this should be escaped: \t",
|
.nested_string = "this should be escaped: \t",
|
||||||
.nested_int64 = 4503599627370496,
|
.nested_int64 = 4503599627370496,
|
||||||
|
.nested_uint64 = 18446744073709551610U,
|
||||||
},
|
},
|
||||||
.some_array[0] = 1,
|
.some_array[0] = 1,
|
||||||
.some_array[1] = 4,
|
.some_array[1] = 4,
|
||||||
|
@ -222,6 +240,7 @@ ZTEST(lib_json_test, test_json_encoding)
|
||||||
.nested_bool = true,
|
.nested_bool = true,
|
||||||
.nested_string = "no escape necessary",
|
.nested_string = "no escape necessary",
|
||||||
.nested_int64 = 4503599627370496,
|
.nested_int64 = 4503599627370496,
|
||||||
|
.nested_uint64 = 18446744073709551610U,
|
||||||
},
|
},
|
||||||
.nested_obj_array = {
|
.nested_obj_array = {
|
||||||
{1, true, "true"},
|
{1, true, "true"},
|
||||||
|
@ -233,10 +252,13 @@ ZTEST(lib_json_test, test_json_encoding)
|
||||||
"\"some_int\":42,\"some_bool\":true,"
|
"\"some_int\":42,\"some_bool\":true,"
|
||||||
"\"some_int64\":1152921504606846977,"
|
"\"some_int64\":1152921504606846977,"
|
||||||
"\"another_int64\":-2305843009213693937,"
|
"\"another_int64\":-2305843009213693937,"
|
||||||
|
"\"some_uint64\":18446744073709551615,"
|
||||||
|
"\"another_uint64\":0,"
|
||||||
"\"some_nested_struct\":{\"nested_int\":-1234,"
|
"\"some_nested_struct\":{\"nested_int\":-1234,"
|
||||||
"\"nested_bool\":false,\"nested_string\":"
|
"\"nested_bool\":false,\"nested_string\":"
|
||||||
"\"this should be escaped: \\t\","
|
"\"this should be escaped: \\t\","
|
||||||
"\"nested_int64\":4503599627370496},"
|
"\"nested_int64\":4503599627370496,"
|
||||||
|
"\"nested_uint64\":18446744073709551610},"
|
||||||
"\"some_array\":[1,4,8,16,32],"
|
"\"some_array\":[1,4,8,16,32],"
|
||||||
"\"another_b!@l\":true,"
|
"\"another_b!@l\":true,"
|
||||||
"\"if\":false,"
|
"\"if\":false,"
|
||||||
|
@ -244,10 +266,11 @@ ZTEST(lib_json_test, test_json_encoding)
|
||||||
"\"4nother_ne$+\":{\"nested_int\":1234,"
|
"\"4nother_ne$+\":{\"nested_int\":1234,"
|
||||||
"\"nested_bool\":true,"
|
"\"nested_bool\":true,"
|
||||||
"\"nested_string\":\"no escape necessary\","
|
"\"nested_string\":\"no escape necessary\","
|
||||||
"\"nested_int64\":4503599627370496},"
|
"\"nested_int64\":4503599627370496,"
|
||||||
|
"\"nested_uint64\":18446744073709551610},"
|
||||||
"\"nested_obj_array\":["
|
"\"nested_obj_array\":["
|
||||||
"{\"nested_int\":1,\"nested_bool\":true,\"nested_string\":\"true\",\"nested_int64\":0},"
|
"{\"nested_int\":1,\"nested_bool\":true,\"nested_string\":\"true\",\"nested_int64\":0,\"nested_uint64\":0},"
|
||||||
"{\"nested_int\":0,\"nested_bool\":false,\"nested_string\":\"false\",\"nested_int64\":0}]"
|
"{\"nested_int\":0,\"nested_bool\":false,\"nested_string\":\"false\",\"nested_int64\":0,\"nested_uint64\":0}]"
|
||||||
"}";
|
"}";
|
||||||
char buffer[sizeof(encoded)];
|
char buffer[sizeof(encoded)];
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -274,6 +297,8 @@ ZTEST(lib_json_test, test_json_decoding)
|
||||||
"\r ,"
|
"\r ,"
|
||||||
"\"some_int64\":-4611686018427387904,"
|
"\"some_int64\":-4611686018427387904,"
|
||||||
"\"another_int64\":-2147483648,"
|
"\"another_int64\":-2147483648,"
|
||||||
|
"\"some_uint64\":18446744073709551615,"
|
||||||
|
"\"another_uint64\":0,"
|
||||||
"\"some_nested_struct\":{ "
|
"\"some_nested_struct\":{ "
|
||||||
"\"nested_int\":-1234,\n\n"
|
"\"nested_int\":-1234,\n\n"
|
||||||
"\"nested_bool\":false,\t"
|
"\"nested_bool\":false,\t"
|
||||||
|
@ -368,7 +393,10 @@ ZTEST(lib_json_test, test_json_limits)
|
||||||
"\"int_min\":-2147483648,"
|
"\"int_min\":-2147483648,"
|
||||||
"\"int64_max\":9223372036854775807,"
|
"\"int64_max\":9223372036854775807,"
|
||||||
"\"int64_cero\":0,"
|
"\"int64_cero\":0,"
|
||||||
"\"int64_min\":-9223372036854775808"
|
"\"int64_min\":-9223372036854775808,"
|
||||||
|
"\"uint64_max\":18446744073709551615,"
|
||||||
|
"\"uint64_cero\":0,"
|
||||||
|
"\"uint64_min\":0"
|
||||||
"}";
|
"}";
|
||||||
|
|
||||||
struct test_int_limits limits = {
|
struct test_int_limits limits = {
|
||||||
|
@ -378,6 +406,9 @@ ZTEST(lib_json_test, test_json_limits)
|
||||||
.int64_max = INT64_MAX,
|
.int64_max = INT64_MAX,
|
||||||
.int64_cero = 0,
|
.int64_cero = 0,
|
||||||
.int64_min = INT64_MIN,
|
.int64_min = INT64_MIN,
|
||||||
|
.uint64_max = UINT64_MAX,
|
||||||
|
.uint64_cero = 0,
|
||||||
|
.uint64_min = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
char buffer[sizeof(encoded)];
|
char buffer[sizeof(encoded)];
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue