5#include "sw/device/lib/ujson/ujson.h"
11#include "sw/device/lib/base/crc32.h"
13#include "sw/device/lib/base/status.h"
15#include "sw/device/lib/ujson/private_status.h"
17static bool is_space(
int c) {
return c ==
' ' || (c >=
'\t' && c <
'\t' + 5); }
19ujson_t ujson_init(
void *context, status_t (*getc)(
void *),
20 status_t (*putbuf)(
void *,
const char *,
size_t),
21 status_t (*flushbuf)(
void *)) {
22 ujson_t u = UJSON_INIT(context, getc, putbuf, flushbuf);
26void ujson_crc32_reset(ujson_t *uj) { crc32_init(&uj->
crc32); }
28uint32_t ujson_crc32_finish(ujson_t *uj) {
return crc32_finish(&uj->
crc32); }
30status_t ujson_putbuf(ujson_t *uj,
const char *buf,
size_t len) {
31 crc32_add(&uj->
crc32, buf, len);
35static size_t ujson_putbuf_sink(ujson_t *uj,
const char *buf,
size_t len) {
36 status_t result = ujson_putbuf(uj, buf, len);
37 if (!status_ok(result)) {
40 return (
size_t)result.value;
45status_t ujson_getc(ujson_t *uj) {
46 int16_t buffer = uj->
buffer;
49 return OK_STATUS(buffer);
53 crc32_add8(&uj->
crc32, (uint8_t)s.value);
59status_t ujson_ungetc(ujson_t *uj,
char ch) {
61 return FAILED_PRECONDITION();
67bool ujson_streq(
const char *a,
const char *b) {
68 while (*a && *b && *a == *b) {
76static status_t consume_whitespace(ujson_t *uj) {
79 ch = TRY(ujson_getc(uj));
80 }
while (is_space(ch));
84static status_t consume_hexdigit(ujson_t *uj) {
85 int ch = TRY(ujson_getc(uj));
86 if (ch >=
'0' && ch <=
'9') {
87 return OK_STATUS(ch -
'0');
88 }
else if (ch >=
'A' && ch <=
'F') {
89 return OK_STATUS(ch -
'A' + 10);
90 }
else if (ch >=
'a' && ch <=
'f') {
91 return OK_STATUS(ch -
'a' + 10);
93 return OUT_OF_RANGE();
97static status_t consume_hex(ujson_t *uj) {
98 int a = TRY(consume_hexdigit(uj));
99 int b = TRY(consume_hexdigit(uj));
100 int c = TRY(consume_hexdigit(uj));
101 int d = TRY(consume_hexdigit(uj));
102 return OK_STATUS((a << 12) | (b << 8) | (c << 4) | d);
105status_t ujson_consume(ujson_t *uj,
char ch) {
106 if (ch != TRY(consume_whitespace(uj))) {
112status_t ujson_consume_maybe(ujson_t *uj,
char ch) {
113 char got = (char)TRY(consume_whitespace(uj));
115 ujson_ungetc(uj, got);
121status_t ujson_parse_qs(ujson_t *uj,
char *str,
size_t len) {
125 TRY(ujson_consume(uj,
'"'));
127 ch = (char)TRY(ujson_getc(uj));
131 ch = (char)TRY(ujson_getc(uj));
153 ch = (char)TRY(consume_hex(uj));
156 return OUT_OF_RANGE();
169status_t ujson_parse_integer(ujson_t *uj,
void *result,
size_t rsz) {
170 char ch = (char)TRY(consume_whitespace(uj));
179 ch = (char)TRY(ujson_getc(uj));
184 ch = (char)TRY(ujson_getc(uj));
188 if (!(ch >=
'0' && ch <=
'9')) {
192 while (ch >=
'0' && ch <=
'9') {
193 if (value > UINT64_MAX / 10) {
194 return OUT_OF_RANGE();
197 if (value > UINT64_MAX - (ch -
'0')) {
198 return OUT_OF_RANGE();
210 return INVALID_ARGUMENT();
216 TRY(ujson_ungetc(uj, ch));
221 if (value > (uint64_t)INT64_MAX + 1) {
222 return OUT_OF_RANGE();
225 int64_t neg_value = -1 * (int64_t)value;
226 memcpy(result, &neg_value, rsz);
230 memcpy(result, &value, rsz);
234status_t ujson_deserialize_bool(ujson_t *uj,
bool *value) {
235 char got = (char)TRY(consume_whitespace(uj));
237 TRY(ujson_consume(uj,
'r'));
238 TRY(ujson_consume(uj,
'u'));
239 TRY(ujson_consume(uj,
'e'));
241 }
else if (got ==
'f') {
242 TRY(ujson_consume(uj,
'a'));
243 TRY(ujson_consume(uj,
'l'));
244 TRY(ujson_consume(uj,
's'));
245 TRY(ujson_consume(uj,
'e'));
248 ujson_ungetc(uj, got);
254status_t ujson_deserialize_uint64_t(ujson_t *uj, uint64_t *value) {
255 return ujson_parse_integer(uj, (
void *)value,
sizeof(*value));
257status_t ujson_deserialize_uint32_t(ujson_t *uj, uint32_t *value) {
258 return ujson_parse_integer(uj, (
void *)value,
sizeof(*value));
260status_t ujson_deserialize_uint16_t(ujson_t *uj, uint16_t *value) {
261 return ujson_parse_integer(uj, (
void *)value,
sizeof(*value));
263status_t ujson_deserialize_uint8_t(ujson_t *uj, uint8_t *value) {
264 return ujson_parse_integer(uj, (
void *)value,
sizeof(*value));
266status_t ujson_deserialize_size_t(ujson_t *uj,
size_t *value) {
267 return ujson_parse_integer(uj, (
void *)value,
sizeof(*value));
269status_t ujson_deserialize_int64_t(ujson_t *uj, int64_t *value) {
270 return ujson_parse_integer(uj, (
void *)value,
sizeof(*value));
272status_t ujson_deserialize_int32_t(ujson_t *uj, int32_t *value) {
273 return ujson_parse_integer(uj, (
void *)value,
sizeof(*value));
275status_t ujson_deserialize_int16_t(ujson_t *uj, int16_t *value) {
276 return ujson_parse_integer(uj, (
void *)value,
sizeof(*value));
278status_t ujson_deserialize_int8_t(ujson_t *uj, int8_t *value) {
279 return ujson_parse_integer(uj, (
void *)value,
sizeof(*value));
282static const char hex[] =
"0123456789abcdef";
284status_t ujson_serialize_string(ujson_t *uj,
const char *buf) {
286 TRY(ujson_putbuf(uj,
"\"", 1));
287 while ((ch = (uint8_t)*buf) !=
'\0') {
288 if (ch < 0x20 || ch ==
'"' || ch ==
'\\' || ch >= 0x7f) {
291 TRY(ujson_putbuf(uj,
"\\\"", 2));
294 TRY(ujson_putbuf(uj,
"\\\\", 2));
297 TRY(ujson_putbuf(uj,
"\\b", 2));
300 TRY(ujson_putbuf(uj,
"\\f", 2));
303 TRY(ujson_putbuf(uj,
"\\n", 2));
306 TRY(ujson_putbuf(uj,
"\\r", 2));
309 TRY(ujson_putbuf(uj,
"\\t", 2));
312 char esc[] = {
'\\',
'u',
'0',
'0', hex[ch >> 4], hex[ch & 0xF]};
313 TRY(ujson_putbuf(uj, esc,
sizeof(esc)));
317 TRY(ujson_putbuf(uj, buf, 1));
321 TRY(ujson_putbuf(uj,
"\"", 1));
325static status_t ujson_serialize_integer64(ujson_t *uj, uint64_t value,
328 char *end = buf +
sizeof(buf);
338 value = udiv64_slow(value, 10, &remainder);
339 *--end =
'0' + (char)remainder;
346 TRY(ujson_putbuf(uj, end, len));
350static status_t ujson_serialize_integer32(ujson_t *uj, uint32_t value,
353 char *end = buf +
sizeof(buf);
361 *--end =
'0' + value % 10;
369 TRY(ujson_putbuf(uj, end, len));
373status_t ujson_serialize_bool(ujson_t *uj,
const bool *value) {
375 TRY(ujson_putbuf(uj,
"true", 4));
377 TRY(ujson_putbuf(uj,
"false", 5));
382status_t ujson_serialize_uint64_t(ujson_t *uj,
const uint64_t *value) {
383 return ujson_serialize_integer64(uj, *value,
false);
385status_t ujson_serialize_uint32_t(ujson_t *uj,
const uint32_t *value) {
386 return ujson_serialize_integer32(uj, *value,
false);
389status_t ujson_serialize_uint16_t(ujson_t *uj,
const uint16_t *value) {
390 return ujson_serialize_integer32(uj, *value,
false);
393status_t ujson_serialize_uint8_t(ujson_t *uj,
const uint8_t *value) {
394 return ujson_serialize_integer32(uj, *value,
false);
397status_t ujson_serialize_size_t(ujson_t *uj,
const size_t *value) {
398 if (
sizeof(
size_t) ==
sizeof(uint64_t)) {
399 return ujson_serialize_integer64(uj, *value,
false);
401 return ujson_serialize_integer32(uj, *value,
false);
405status_t ujson_serialize_int64_t(ujson_t *uj,
const int64_t *value) {
406 return ujson_serialize_integer64(uj, (uint64_t)*value, *value < 0);
409status_t ujson_serialize_int32_t(ujson_t *uj,
const int32_t *value) {
410 return ujson_serialize_integer32(uj, (uint32_t)*value, *value < 0);
413status_t ujson_serialize_int16_t(ujson_t *uj,
const int16_t *value) {
414 return ujson_serialize_integer32(uj, (uint32_t)*value, *value < 0);
417status_t ujson_serialize_int8_t(ujson_t *uj,
const int8_t *value) {
418 return ujson_serialize_integer32(uj, (uint32_t)*value, *value < 0);
421status_t ujson_deserialize_status_t(ujson_t *uj, status_t *value) {
422 private_status_t code;
423 uint32_t module_id = 0;
425 TRY(ujson_consume(uj,
'{'));
426 TRY(ujson_deserialize_private_status_t(uj, &code));
427 TRY(ujson_consume(uj,
':'));
428 if (TRY(ujson_consume_maybe(uj,
'['))) {
430 TRY(ujson_parse_qs(uj, module,
sizeof(module)));
431 module_id = MAKE_MODULE_ID(module[0], module[1], module[2]);
432 TRY(ujson_consume(uj,
','));
433 TRY(ujson_deserialize_uint32_t(uj, &arg));
434 TRY(ujson_consume(uj,
']'));
436 TRY(ujson_deserialize_uint32_t(uj, &arg));
438 TRY(ujson_consume(uj,
'}'));
440 status_create((absl_status_t)code, module_id, __FILE__, (int32_t)arg);
444status_t ujson_serialize_status_t(ujson_t *uj,
const status_t *value) {
449 base_fprintf(out,
"%!r", *value);