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"
17 static bool is_space(
int c) {
return c ==
' ' || (c >=
'\t' && c <
'\t' + 5); }
20 status_t (*putbuf)(
void *,
const char *,
size_t)) {
21 ujson_t u = UJSON_INIT(context, getc, putbuf);
25 void ujson_crc32_reset(
ujson_t *uj) { crc32_init(&uj->
crc32); }
27 uint32_t ujson_crc32_finish(
ujson_t *uj) {
return crc32_finish(&uj->
crc32); }
30 crc32_add(&uj->
crc32, buf, len);
35 int16_t buffer = uj->
buffer;
38 return OK_STATUS(buffer);
42 crc32_add8(&uj->
crc32, (uint8_t)s.value);
50 return FAILED_PRECONDITION();
56 bool ujson_streq(
const char *a,
const char *b) {
57 while (*a && *b && *a == *b) {
68 ch = TRY(ujson_getc(uj));
69 }
while (is_space(ch));
74 int ch = TRY(ujson_getc(uj));
75 if (ch >=
'0' && ch <=
'9') {
76 return OK_STATUS(ch -
'0');
77 }
else if (ch >=
'A' && ch <=
'F') {
78 return OK_STATUS(ch -
'A' + 10);
79 }
else if (ch >=
'a' && ch <=
'f') {
80 return OK_STATUS(ch -
'a' + 10);
82 return OUT_OF_RANGE();
87 int a = TRY(consume_hexdigit(uj));
88 int b = TRY(consume_hexdigit(uj));
89 int c = TRY(consume_hexdigit(uj));
90 int d = TRY(consume_hexdigit(uj));
91 return OK_STATUS((a << 12) | (b << 8) | (c << 4) | d);
95 if (ch != TRY(consume_whitespace(uj))) {
102 char got = (char)TRY(consume_whitespace(uj));
104 ujson_ungetc(uj, got);
114 TRY(ujson_consume(uj,
'"'));
116 ch = (char)TRY(ujson_getc(uj));
120 ch = (char)TRY(ujson_getc(uj));
142 ch = (char)TRY(consume_hex(uj));
145 return OUT_OF_RANGE();
159 char ch = (char)TRY(consume_whitespace(uj));
164 ch = (char)TRY(ujson_getc(uj));
168 if (!(ch >=
'0' && ch <=
'9')) {
172 while (ch >=
'0' && ch <=
'9') {
173 if (value > UINT64_MAX / 10) {
174 return OUT_OF_RANGE();
177 if (value > UINT64_MAX - (ch -
'0')) {
178 return OUT_OF_RANGE();
187 TRY(ujson_ungetc(uj, ch));
190 if (value > (uint64_t)INT64_MAX + 1) {
191 return OUT_OF_RANGE();
194 int64_t neg_value = -1 * (int64_t)value;
195 memcpy(result, &neg_value, rsz);
199 memcpy(result, &value, rsz);
204 char got = (char)TRY(consume_whitespace(uj));
206 TRY(ujson_consume(uj,
'r'));
207 TRY(ujson_consume(uj,
'u'));
208 TRY(ujson_consume(uj,
'e'));
210 }
else if (got ==
'f') {
211 TRY(ujson_consume(uj,
'a'));
212 TRY(ujson_consume(uj,
'l'));
213 TRY(ujson_consume(uj,
's'));
214 TRY(ujson_consume(uj,
'e'));
217 ujson_ungetc(uj, got);
224 return ujson_parse_integer(uj, (
void *)value,
sizeof(*value));
227 return ujson_parse_integer(uj, (
void *)value,
sizeof(*value));
230 return ujson_parse_integer(uj, (
void *)value,
sizeof(*value));
233 return ujson_parse_integer(uj, (
void *)value,
sizeof(*value));
236 return ujson_parse_integer(uj, (
void *)value,
sizeof(*value));
239 return ujson_parse_integer(uj, (
void *)value,
sizeof(*value));
242 return ujson_parse_integer(uj, (
void *)value,
sizeof(*value));
245 return ujson_parse_integer(uj, (
void *)value,
sizeof(*value));
248 return ujson_parse_integer(uj, (
void *)value,
sizeof(*value));
251 static const char hex[] =
"0123456789abcdef";
255 TRY(ujson_putbuf(uj,
"\"", 1));
256 while ((ch = (uint8_t)*buf) !=
'\0') {
257 if (ch < 0x20 || ch == '"' || ch == '\\' || ch >= 0x7f) {
260 TRY(ujson_putbuf(uj,
"\\\"", 2));
263 TRY(ujson_putbuf(uj,
"\\\\", 2));
266 TRY(ujson_putbuf(uj,
"\\b", 2));
269 TRY(ujson_putbuf(uj,
"\\f", 2));
272 TRY(ujson_putbuf(uj,
"\\n", 2));
275 TRY(ujson_putbuf(uj,
"\\r", 2));
278 TRY(ujson_putbuf(uj,
"\\t", 2));
281 char esc[] = {
'\\',
'u',
'0',
'0', hex[ch >> 4], hex[ch & 0xF]};
282 TRY(ujson_putbuf(uj, esc,
sizeof(esc)));
286 TRY(ujson_putbuf(uj, buf, 1));
290 TRY(ujson_putbuf(uj,
"\"", 1));
297 char *end = buf +
sizeof(buf);
308 *--end =
'0' + (char)remainder;
315 TRY(ujson_putbuf(uj, end, len));
322 char *end = buf +
sizeof(buf);
330 *--end =
'0' + value % 10;
338 TRY(ujson_putbuf(uj, end, len));
344 TRY(ujson_putbuf(uj,
"true", 4));
346 TRY(ujson_putbuf(uj,
"false", 5));
351 status_t ujson_serialize_uint64_t(
ujson_t *uj,
const uint64_t *value) {
352 return ujson_serialize_integer64(uj, *value,
false);
354 status_t ujson_serialize_uint32_t(
ujson_t *uj,
const uint32_t *value) {
355 return ujson_serialize_integer32(uj, *value,
false);
358 status_t ujson_serialize_uint16_t(
ujson_t *uj,
const uint16_t *value) {
359 return ujson_serialize_integer32(uj, *value,
false);
363 return ujson_serialize_integer32(uj, *value,
false);
367 if (
sizeof(
size_t) ==
sizeof(uint64_t)) {
368 return ujson_serialize_integer64(uj, *value,
false);
370 return ujson_serialize_integer32(uj, *value,
false);
375 return ujson_serialize_integer64(uj, (uint64_t)*value, *value < 0);
379 return ujson_serialize_integer32(uj, (uint32_t)*value, *value < 0);
383 return ujson_serialize_integer32(uj, (uint32_t)*value, *value < 0);
387 return ujson_serialize_integer32(uj, (uint32_t)*value, *value < 0);
391 private_status_t code;
392 uint32_t module_id = 0;
394 TRY(ujson_consume(uj,
'{'));
395 TRY(ujson_deserialize_private_status_t(uj, &code));
396 TRY(ujson_consume(uj,
':'));
397 if (TRY(ujson_consume_maybe(uj,
'['))) {
399 TRY(ujson_parse_qs(uj, module,
sizeof(module)));
400 module_id = MAKE_MODULE_ID(module[0], module[1], module[2]);
401 TRY(ujson_consume(uj,
','));
402 TRY(ujson_deserialize_uint32_t(uj, &arg));
403 TRY(ujson_consume(uj,
']'));
405 TRY(ujson_deserialize_uint32_t(uj, &arg));
407 TRY(ujson_consume(uj,
'}'));
409 status_create((absl_status_t)code, module_id, __FILE__, (int32_t)arg);
416 .sink = (size_t(*)(
void *,
const char *, size_t))ujson_putbuf,