Skip to content

Commit 03029e7

Browse files
mlohvynenkonashif
authored andcommitted
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 <[email protected]>
1 parent ae63c62 commit 03029e7

File tree

3 files changed

+92
-5
lines changed

3 files changed

+92
-5
lines changed

include/zephyr/data/json.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ enum json_tokens {
4343
JSON_TOK_OBJ_ARRAY = '3',
4444
JSON_TOK_ENCODED_OBJ = '4',
4545
JSON_TOK_INT64 = '5',
46+
JSON_TOK_UINT64 = '6',
4647
JSON_TOK_TRUE = 't',
4748
JSON_TOK_FALSE = 'f',
4849
JSON_TOK_NULL = 'n',

lib/utils/json.c

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,7 @@ static int element_token(enum json_tokens token)
309309
case JSON_TOK_STRING:
310310
case JSON_TOK_NUMBER:
311311
case JSON_TOK_INT64:
312+
case JSON_TOK_UINT64:
312313
case JSON_TOK_FLOAT:
313314
case JSON_TOK_OPAQUE:
314315
case JSON_TOK_OBJ_ARRAY:
@@ -469,6 +470,30 @@ static int decode_int64(const struct json_token *token, int64_t *num)
469470
return 0;
470471
}
471472

473+
static int decode_uint64(const struct json_token *token, uint64_t *num)
474+
{
475+
char *endptr;
476+
char prev_end;
477+
478+
prev_end = *token->end;
479+
*token->end = '\0';
480+
481+
errno = 0;
482+
*num = strtoull(token->start, &endptr, 10);
483+
484+
*token->end = prev_end;
485+
486+
if (errno != 0) {
487+
return -errno;
488+
}
489+
490+
if (endptr != token->end) {
491+
return -EINVAL;
492+
}
493+
494+
return 0;
495+
}
496+
472497
static bool equivalent_types(enum json_tokens type1, enum json_tokens type2)
473498
{
474499
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)
483508
return true;
484509
}
485510

511+
if (type1 == JSON_TOK_NUMBER && type2 == JSON_TOK_UINT64) {
512+
return true;
513+
}
514+
486515
if (type1 == JSON_TOK_STRING && type2 == JSON_TOK_OPAQUE) {
487516
return true;
488517
}
@@ -545,6 +574,11 @@ static int64_t decode_value(struct json_obj *obj,
545574

546575
return decode_int64(value, num);
547576
}
577+
case JSON_TOK_UINT64: {
578+
uint64_t *num = field;
579+
580+
return decode_uint64(value, num);
581+
}
548582
case JSON_TOK_OPAQUE:
549583
case JSON_TOK_FLOAT: {
550584
struct json_obj_token *obj_token = field;
@@ -573,6 +607,8 @@ static ptrdiff_t get_elem_size(const struct json_obj_descr *descr)
573607
return sizeof(int32_t);
574608
case JSON_TOK_INT64:
575609
return sizeof(int64_t);
610+
case JSON_TOK_UINT64:
611+
return sizeof(uint64_t);
576612
case JSON_TOK_OPAQUE:
577613
case JSON_TOK_FLOAT:
578614
case JSON_TOK_OBJ_ARRAY:
@@ -1035,6 +1071,23 @@ static int int64_encode(const int64_t *num, json_append_bytes_t append_bytes,
10351071
return append_bytes(buf, (size_t)ret, data);
10361072
}
10371073

1074+
static int uint64_encode(const uint64_t *num, json_append_bytes_t append_bytes,
1075+
void *data)
1076+
{
1077+
char buf[sizeof("18446744073709551610")];
1078+
int ret;
1079+
1080+
ret = snprintk(buf, sizeof(buf), "%" PRIu64, *num);
1081+
if (ret < 0) {
1082+
return ret;
1083+
}
1084+
if (ret >= (int)sizeof(buf)) {
1085+
return -ENOMEM;
1086+
}
1087+
1088+
return append_bytes(buf, (size_t)ret, data);
1089+
}
1090+
10381091
static int float_ascii_encode(struct json_obj_token *num, json_append_bytes_t append_bytes,
10391092
void *data)
10401093
{
@@ -1099,6 +1152,8 @@ static int encode(const struct json_obj_descr *descr, const void *val,
10991152
return num_encode(ptr, append_bytes, data);
11001153
case JSON_TOK_INT64:
11011154
return int64_encode(ptr, append_bytes, data);
1155+
case JSON_TOK_UINT64:
1156+
return uint64_encode(ptr, append_bytes, data);
11021157
case JSON_TOK_FLOAT:
11031158
return float_ascii_encode(ptr, append_bytes, data);
11041159
case JSON_TOK_OPAQUE:

tests/lib/json/src/main.c

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ struct test_nested {
1414
bool nested_bool;
1515
const char *nested_string;
1616
int64_t nested_int64;
17+
uint64_t nested_uint64;
1718
};
1819

1920
struct test_struct {
@@ -22,6 +23,8 @@ struct test_struct {
2223
bool some_bool;
2324
int64_t some_int64;
2425
int64_t another_int64;
26+
int64_t some_uint64;
27+
int64_t another_uint64;
2528
struct test_nested some_nested_struct;
2629
int some_array[16];
2730
size_t some_array_len;
@@ -51,6 +54,9 @@ struct test_int_limits {
5154
int64_t int64_max;
5255
int64_t int64_cero;
5356
int64_t int64_min;
57+
uint64_t uint64_max;
58+
uint64_t uint64_cero;
59+
uint64_t uint64_min;
5460
};
5561

5662
static const struct json_obj_descr nested_descr[] = {
@@ -60,6 +66,8 @@ static const struct json_obj_descr nested_descr[] = {
6066
JSON_TOK_STRING),
6167
JSON_OBJ_DESCR_PRIM(struct test_nested, nested_int64,
6268
JSON_TOK_INT64),
69+
JSON_OBJ_DESCR_PRIM(struct test_nested, nested_uint64,
70+
JSON_TOK_UINT64),
6371
};
6472

6573
static const struct json_obj_descr test_descr[] = {
@@ -70,6 +78,10 @@ static const struct json_obj_descr test_descr[] = {
7078
JSON_TOK_INT64),
7179
JSON_OBJ_DESCR_PRIM(struct test_struct, another_int64,
7280
JSON_TOK_INT64),
81+
JSON_OBJ_DESCR_PRIM(struct test_struct, some_uint64,
82+
JSON_TOK_UINT64),
83+
JSON_OBJ_DESCR_PRIM(struct test_struct, another_uint64,
84+
JSON_TOK_UINT64),
7385
JSON_OBJ_DESCR_OBJECT(struct test_struct, some_nested_struct,
7486
nested_descr),
7587
JSON_OBJ_DESCR_ARRAY(struct test_struct, some_array,
@@ -104,6 +116,9 @@ static const struct json_obj_descr obj_limits_descr[] = {
104116
JSON_OBJ_DESCR_PRIM(struct test_int_limits, int64_max, JSON_TOK_INT64),
105117
JSON_OBJ_DESCR_PRIM(struct test_int_limits, int64_cero, JSON_TOK_INT64),
106118
JSON_OBJ_DESCR_PRIM(struct test_int_limits, int64_min, JSON_TOK_INT64),
119+
JSON_OBJ_DESCR_PRIM(struct test_int_limits, uint64_max, JSON_TOK_UINT64),
120+
JSON_OBJ_DESCR_PRIM(struct test_int_limits, uint64_cero, JSON_TOK_UINT64),
121+
JSON_OBJ_DESCR_PRIM(struct test_int_limits, uint64_min, JSON_TOK_UINT64),
107122
};
108123

109124
struct array {
@@ -197,12 +212,15 @@ ZTEST(lib_json_test, test_json_encoding)
197212
.some_int = 42,
198213
.some_int64 = 1152921504606846977,
199214
.another_int64 = -2305843009213693937,
215+
.some_uint64 = 18446744073709551615U,
216+
.another_uint64 = 0,
200217
.some_bool = true,
201218
.some_nested_struct = {
202219
.nested_int = -1234,
203220
.nested_bool = false,
204221
.nested_string = "this should be escaped: \t",
205222
.nested_int64 = 4503599627370496,
223+
.nested_uint64 = 18446744073709551610U,
206224
},
207225
.some_array[0] = 1,
208226
.some_array[1] = 4,
@@ -222,6 +240,7 @@ ZTEST(lib_json_test, test_json_encoding)
222240
.nested_bool = true,
223241
.nested_string = "no escape necessary",
224242
.nested_int64 = 4503599627370496,
243+
.nested_uint64 = 18446744073709551610U,
225244
},
226245
.nested_obj_array = {
227246
{1, true, "true"},
@@ -233,21 +252,25 @@ ZTEST(lib_json_test, test_json_encoding)
233252
"\"some_int\":42,\"some_bool\":true,"
234253
"\"some_int64\":1152921504606846977,"
235254
"\"another_int64\":-2305843009213693937,"
255+
"\"some_uint64\":18446744073709551615,"
256+
"\"another_uint64\":0,"
236257
"\"some_nested_struct\":{\"nested_int\":-1234,"
237258
"\"nested_bool\":false,\"nested_string\":"
238259
"\"this should be escaped: \\t\","
239-
"\"nested_int64\":4503599627370496},"
260+
"\"nested_int64\":4503599627370496,"
261+
"\"nested_uint64\":18446744073709551610},"
240262
"\"some_array\":[1,4,8,16,32],"
241263
"\"another_b!@l\":true,"
242264
"\"if\":false,"
243265
"\"another-array\":[2,3,5,7],"
244266
"\"4nother_ne$+\":{\"nested_int\":1234,"
245267
"\"nested_bool\":true,"
246268
"\"nested_string\":\"no escape necessary\","
247-
"\"nested_int64\":4503599627370496},"
269+
"\"nested_int64\":4503599627370496,"
270+
"\"nested_uint64\":18446744073709551610},"
248271
"\"nested_obj_array\":["
249-
"{\"nested_int\":1,\"nested_bool\":true,\"nested_string\":\"true\",\"nested_int64\":0},"
250-
"{\"nested_int\":0,\"nested_bool\":false,\"nested_string\":\"false\",\"nested_int64\":0}]"
272+
"{\"nested_int\":1,\"nested_bool\":true,\"nested_string\":\"true\",\"nested_int64\":0,\"nested_uint64\":0},"
273+
"{\"nested_int\":0,\"nested_bool\":false,\"nested_string\":\"false\",\"nested_int64\":0,\"nested_uint64\":0}]"
251274
"}";
252275
char buffer[sizeof(encoded)];
253276
int ret;
@@ -274,6 +297,8 @@ ZTEST(lib_json_test, test_json_decoding)
274297
"\r ,"
275298
"\"some_int64\":-4611686018427387904,"
276299
"\"another_int64\":-2147483648,"
300+
"\"some_uint64\":18446744073709551615,"
301+
"\"another_uint64\":0,"
277302
"\"some_nested_struct\":{ "
278303
"\"nested_int\":-1234,\n\n"
279304
"\"nested_bool\":false,\t"
@@ -368,7 +393,10 @@ ZTEST(lib_json_test, test_json_limits)
368393
"\"int_min\":-2147483648,"
369394
"\"int64_max\":9223372036854775807,"
370395
"\"int64_cero\":0,"
371-
"\"int64_min\":-9223372036854775808"
396+
"\"int64_min\":-9223372036854775808,"
397+
"\"uint64_max\":18446744073709551615,"
398+
"\"uint64_cero\":0,"
399+
"\"uint64_min\":0"
372400
"}";
373401

374402
struct test_int_limits limits = {
@@ -378,6 +406,9 @@ ZTEST(lib_json_test, test_json_limits)
378406
.int64_max = INT64_MAX,
379407
.int64_cero = 0,
380408
.int64_min = INT64_MIN,
409+
.uint64_max = UINT64_MAX,
410+
.uint64_cero = 0,
411+
.uint64_min = 0,
381412
};
382413

383414
char buffer[sizeof(encoded)];

0 commit comments

Comments
 (0)