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) {
32 crc32_add(&uj->
crc32, buf, len);
36static size_t ujson_putbuf_sink(ujson_t *uj,
const char *buf,
size_t len) {
37 status_t result = ujson_putbuf(uj, buf, len);
38 if (!status_ok(result)) {
41 return (
size_t)result.value;
46status_t ujson_getc(ujson_t *uj) {
47 int16_t buffer = uj->
buffer;
50 return OK_STATUS(buffer);
55 crc32_add8(&uj->
crc32, (uint8_t)s.value);
61status_t ujson_ungetc(ujson_t *uj,
char ch) {
63 return FAILED_PRECONDITION();
69bool ujson_streq(
const char *a,
const char *b) {
70 while (*a && *b && *a == *b) {
78static status_t consume_whitespace(ujson_t *uj) {
81 ch = TRY(ujson_getc(uj));
82 }
while (is_space(ch));
86static status_t consume_hexdigit(ujson_t *uj) {
87 int ch = TRY(ujson_getc(uj));
88 if (ch >=
'0' && ch <=
'9') {
89 return OK_STATUS(ch -
'0');
90 }
else if (ch >=
'A' && ch <=
'F') {
91 return OK_STATUS(ch -
'A' + 10);
92 }
else if (ch >=
'a' && ch <=
'f') {
93 return OK_STATUS(ch -
'a' + 10);
95 return OUT_OF_RANGE();
99static status_t consume_hex(ujson_t *uj) {
100 int a = TRY(consume_hexdigit(uj));
101 int b = TRY(consume_hexdigit(uj));
102 int c = TRY(consume_hexdigit(uj));
103 int d = TRY(consume_hexdigit(uj));
104 return OK_STATUS((a << 12) | (b << 8) | (c << 4) | d);
107status_t ujson_consume(ujson_t *uj,
char ch) {
108 if (ch != TRY(consume_whitespace(uj))) {
114status_t ujson_consume_maybe(ujson_t *uj,
char ch) {
115 char got = (char)TRY(consume_whitespace(uj));
117 ujson_ungetc(uj, got);
123status_t ujson_parse_qs(ujson_t *uj,
char *str,
size_t len) {
127 TRY(ujson_consume(uj,
'"'));
129 ch = (char)TRY(ujson_getc(uj));
133 ch = (char)TRY(ujson_getc(uj));
155 ch = (char)TRY(consume_hex(uj));
158 return OUT_OF_RANGE();
171status_t ujson_parse_integer(ujson_t *uj,
void *result,
size_t rsz) {
172 char ch = (char)TRY(consume_whitespace(uj));
181 ch = (char)TRY(ujson_getc(uj));
186 ch = (char)TRY(ujson_getc(uj));
190 if (!(ch >=
'0' && ch <=
'9')) {
194 while (ch >=
'0' && ch <=
'9') {
195 if (value > UINT64_MAX / 10) {
196 return OUT_OF_RANGE();
199 if (value > UINT64_MAX - (ch -
'0')) {
200 return OUT_OF_RANGE();
212 return INVALID_ARGUMENT();
218 TRY(ujson_ungetc(uj, ch));
223 if (value > (uint64_t)INT64_MAX + 1) {
224 return OUT_OF_RANGE();
227 int64_t neg_value = -1 * (int64_t)value;
228 memcpy(result, &neg_value, rsz);
232 memcpy(result, &value, rsz);
236status_t ujson_deserialize_bool(ujson_t *uj,
bool *value) {
237 char got = (char)TRY(consume_whitespace(uj));
239 TRY(ujson_consume(uj,
'r'));
240 TRY(ujson_consume(uj,
'u'));
241 TRY(ujson_consume(uj,
'e'));
243 }
else if (got ==
'f') {
244 TRY(ujson_consume(uj,
'a'));
245 TRY(ujson_consume(uj,
'l'));
246 TRY(ujson_consume(uj,
's'));
247 TRY(ujson_consume(uj,
'e'));
250 ujson_ungetc(uj, got);
256status_t ujson_deserialize_uint64_t(ujson_t *uj, uint64_t *value) {
257 return ujson_parse_integer(uj, (
void *)value,
sizeof(*value));
259status_t ujson_deserialize_uint32_t(ujson_t *uj, uint32_t *value) {
260 return ujson_parse_integer(uj, (
void *)value,
sizeof(*value));
262status_t ujson_deserialize_uint16_t(ujson_t *uj, uint16_t *value) {
263 return ujson_parse_integer(uj, (
void *)value,
sizeof(*value));
265status_t ujson_deserialize_uint8_t(ujson_t *uj, uint8_t *value) {
266 return ujson_parse_integer(uj, (
void *)value,
sizeof(*value));
268status_t ujson_deserialize_size_t(ujson_t *uj,
size_t *value) {
269 return ujson_parse_integer(uj, (
void *)value,
sizeof(*value));
271status_t ujson_deserialize_int64_t(ujson_t *uj, int64_t *value) {
272 return ujson_parse_integer(uj, (
void *)value,
sizeof(*value));
274status_t ujson_deserialize_int32_t(ujson_t *uj, int32_t *value) {
275 return ujson_parse_integer(uj, (
void *)value,
sizeof(*value));
277status_t ujson_deserialize_int16_t(ujson_t *uj, int16_t *value) {
278 return ujson_parse_integer(uj, (
void *)value,
sizeof(*value));
280status_t ujson_deserialize_int8_t(ujson_t *uj, int8_t *value) {
281 return ujson_parse_integer(uj, (
void *)value,
sizeof(*value));
284static const char hex[] =
"0123456789abcdef";
286status_t ujson_serialize_string(ujson_t *uj,
const char *buf) {
288 TRY(ujson_putbuf(uj,
"\"", 1));
289 while ((ch = (uint8_t)*buf) !=
'\0') {
290 if (ch < 0x20 || ch ==
'"' || ch ==
'\\' || ch >= 0x7f) {
293 TRY(ujson_putbuf(uj,
"\\\"", 2));
296 TRY(ujson_putbuf(uj,
"\\\\", 2));
299 TRY(ujson_putbuf(uj,
"\\b", 2));
302 TRY(ujson_putbuf(uj,
"\\f", 2));
305 TRY(ujson_putbuf(uj,
"\\n", 2));
308 TRY(ujson_putbuf(uj,
"\\r", 2));
311 TRY(ujson_putbuf(uj,
"\\t", 2));
314 char esc[] = {
'\\',
'u',
'0',
'0', hex[ch >> 4], hex[ch & 0xF]};
315 TRY(ujson_putbuf(uj, esc,
sizeof(esc)));
319 TRY(ujson_putbuf(uj, buf, 1));
323 TRY(ujson_putbuf(uj,
"\"", 1));
327static status_t ujson_serialize_integer64(ujson_t *uj, uint64_t value,
330 char *end = buf +
sizeof(buf);
340 value = udiv64_slow(value, 10, &remainder);
341 *--end =
'0' + (char)remainder;
348 TRY(ujson_putbuf(uj, end, len));
352static status_t ujson_serialize_integer32(ujson_t *uj, uint32_t value,
355 char *end = buf +
sizeof(buf);
363 *--end =
'0' + value % 10;
371 TRY(ujson_putbuf(uj, end, len));
375status_t ujson_serialize_bool(ujson_t *uj,
const bool *value) {
377 TRY(ujson_putbuf(uj,
"true", 4));
379 TRY(ujson_putbuf(uj,
"false", 5));
384status_t ujson_serialize_uint64_t(ujson_t *uj,
const uint64_t *value) {
385 return ujson_serialize_integer64(uj, *value,
false);
387status_t ujson_serialize_uint32_t(ujson_t *uj,
const uint32_t *value) {
388 return ujson_serialize_integer32(uj, *value,
false);
391status_t ujson_serialize_uint16_t(ujson_t *uj,
const uint16_t *value) {
392 return ujson_serialize_integer32(uj, *value,
false);
395status_t ujson_serialize_uint8_t(ujson_t *uj,
const uint8_t *value) {
396 return ujson_serialize_integer32(uj, *value,
false);
399status_t ujson_serialize_size_t(ujson_t *uj,
const size_t *value) {
400 if (
sizeof(
size_t) ==
sizeof(uint64_t)) {
401 return ujson_serialize_integer64(uj, *value,
false);
403 return ujson_serialize_integer32(uj, *value,
false);
407status_t ujson_serialize_int64_t(ujson_t *uj,
const int64_t *value) {
408 return ujson_serialize_integer64(uj, (uint64_t)*value, *value < 0);
411status_t ujson_serialize_int32_t(ujson_t *uj,
const int32_t *value) {
412 return ujson_serialize_integer32(uj, (uint32_t)*value, *value < 0);
415status_t ujson_serialize_int16_t(ujson_t *uj,
const int16_t *value) {
416 return ujson_serialize_integer32(uj, (uint32_t)*value, *value < 0);
419status_t ujson_serialize_int8_t(ujson_t *uj,
const int8_t *value) {
420 return ujson_serialize_integer32(uj, (uint32_t)*value, *value < 0);
423status_t ujson_deserialize_status_t(ujson_t *uj, status_t *value) {
424 private_status_t code;
425 uint32_t module_id = 0;
427 TRY(ujson_consume(uj,
'{'));
428 TRY(ujson_deserialize_private_status_t(uj, &code));
429 TRY(ujson_consume(uj,
':'));
430 if (TRY(ujson_consume_maybe(uj,
'['))) {
432 TRY(ujson_parse_qs(uj, module,
sizeof(module)));
433 module_id = MAKE_MODULE_ID(module[0], module[1], module[2]);
434 TRY(ujson_consume(uj,
','));
435 TRY(ujson_deserialize_uint32_t(uj, &arg));
436 TRY(ujson_consume(uj,
']'));
438 TRY(ujson_deserialize_uint32_t(uj, &arg));
440 TRY(ujson_consume(uj,
'}'));
442 status_create((absl_status_t)code, module_id, __FILE__, (int32_t)arg);
446status_t ujson_serialize_status_t(ujson_t *uj,
const status_t *value) {
451 base_fprintf(out,
"%!r", *value);