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));
 
  175    ch = (char)TRY(ujson_getc(uj));
 
  179  if (!(ch >= 
'0' && ch <= 
'9')) {
 
  183  while (ch >= 
'0' && ch <= 
'9') {
 
  184    if (value > UINT64_MAX / 10) {
 
  185      return OUT_OF_RANGE();
 
  188    if (value > UINT64_MAX - (ch - 
'0')) {
 
  189      return OUT_OF_RANGE();
 
  198    TRY(ujson_ungetc(uj, ch));
 
  201    if (value > (uint64_t)INT64_MAX + 1) {
 
  202      return OUT_OF_RANGE();
 
  205    int64_t neg_value = -1 * (int64_t)value;
 
  206    memcpy(result, &neg_value, rsz);
 
  210  memcpy(result, &value, rsz);
 
  214status_t ujson_deserialize_bool(ujson_t *uj, 
bool *value) {
 
  215  char got = (char)TRY(consume_whitespace(uj));
 
  217    TRY(ujson_consume(uj, 
'r'));
 
  218    TRY(ujson_consume(uj, 
'u'));
 
  219    TRY(ujson_consume(uj, 
'e'));
 
  221  } 
else if (got == 
'f') {
 
  222    TRY(ujson_consume(uj, 
'a'));
 
  223    TRY(ujson_consume(uj, 
'l'));
 
  224    TRY(ujson_consume(uj, 
's'));
 
  225    TRY(ujson_consume(uj, 
'e'));
 
  228    ujson_ungetc(uj, got);
 
  234status_t ujson_deserialize_uint64_t(ujson_t *uj, uint64_t *value) {
 
  235  return ujson_parse_integer(uj, (
void *)value, 
sizeof(*value));
 
  237status_t ujson_deserialize_uint32_t(ujson_t *uj, uint32_t *value) {
 
  238  return ujson_parse_integer(uj, (
void *)value, 
sizeof(*value));
 
  240status_t ujson_deserialize_uint16_t(ujson_t *uj, uint16_t *value) {
 
  241  return ujson_parse_integer(uj, (
void *)value, 
sizeof(*value));
 
  243status_t ujson_deserialize_uint8_t(ujson_t *uj, uint8_t *value) {
 
  244  return ujson_parse_integer(uj, (
void *)value, 
sizeof(*value));
 
  246status_t ujson_deserialize_size_t(ujson_t *uj, 
size_t *value) {
 
  247  return ujson_parse_integer(uj, (
void *)value, 
sizeof(*value));
 
  249status_t ujson_deserialize_int64_t(ujson_t *uj, int64_t *value) {
 
  250  return ujson_parse_integer(uj, (
void *)value, 
sizeof(*value));
 
  252status_t ujson_deserialize_int32_t(ujson_t *uj, int32_t *value) {
 
  253  return ujson_parse_integer(uj, (
void *)value, 
sizeof(*value));
 
  255status_t ujson_deserialize_int16_t(ujson_t *uj, int16_t *value) {
 
  256  return ujson_parse_integer(uj, (
void *)value, 
sizeof(*value));
 
  258status_t ujson_deserialize_int8_t(ujson_t *uj, int8_t *value) {
 
  259  return ujson_parse_integer(uj, (
void *)value, 
sizeof(*value));
 
  262static const char hex[] = 
"0123456789abcdef";
 
  264status_t ujson_serialize_string(ujson_t *uj, 
const char *buf) {
 
  266  TRY(ujson_putbuf(uj, 
"\"", 1));
 
  267  while ((ch = (uint8_t)*buf) != 
'\0') {
 
  268    if (ch < 0x20 || ch == 
'"' || ch == 
'\\' || ch >= 0x7f) {
 
  271          TRY(ujson_putbuf(uj, 
"\\\"", 2));
 
  274          TRY(ujson_putbuf(uj, 
"\\\\", 2));
 
  277          TRY(ujson_putbuf(uj, 
"\\b", 2));
 
  280          TRY(ujson_putbuf(uj, 
"\\f", 2));
 
  283          TRY(ujson_putbuf(uj, 
"\\n", 2));
 
  286          TRY(ujson_putbuf(uj, 
"\\r", 2));
 
  289          TRY(ujson_putbuf(uj, 
"\\t", 2));
 
  292          char esc[] = {
'\\', 
'u', 
'0', 
'0', hex[ch >> 4], hex[ch & 0xF]};
 
  293          TRY(ujson_putbuf(uj, esc, 
sizeof(esc)));
 
  297      TRY(ujson_putbuf(uj, buf, 1));
 
  301  TRY(ujson_putbuf(uj, 
"\"", 1));
 
  305static status_t ujson_serialize_integer64(ujson_t *uj, uint64_t value,
 
  308  char *end = buf + 
sizeof(buf);
 
  318    value = udiv64_slow(value, 10, &remainder);
 
  319    *--end = 
'0' + (char)remainder;
 
  326  TRY(ujson_putbuf(uj, end, len));
 
  330static status_t ujson_serialize_integer32(ujson_t *uj, uint32_t value,
 
  333  char *end = buf + 
sizeof(buf);
 
  341    *--end = 
'0' + value % 10;
 
  349  TRY(ujson_putbuf(uj, end, len));
 
  353status_t ujson_serialize_bool(ujson_t *uj, 
const bool *value) {
 
  355    TRY(ujson_putbuf(uj, 
"true", 4));
 
  357    TRY(ujson_putbuf(uj, 
"false", 5));
 
  362status_t ujson_serialize_uint64_t(ujson_t *uj, 
const uint64_t *value) {
 
  363  return ujson_serialize_integer64(uj, *value, 
false);
 
  365status_t ujson_serialize_uint32_t(ujson_t *uj, 
const uint32_t *value) {
 
  366  return ujson_serialize_integer32(uj, *value, 
false);
 
  369status_t ujson_serialize_uint16_t(ujson_t *uj, 
const uint16_t *value) {
 
  370  return ujson_serialize_integer32(uj, *value, 
false);
 
  373status_t ujson_serialize_uint8_t(ujson_t *uj, 
const uint8_t *value) {
 
  374  return ujson_serialize_integer32(uj, *value, 
false);
 
  377status_t ujson_serialize_size_t(ujson_t *uj, 
const size_t *value) {
 
  378  if (
sizeof(
size_t) == 
sizeof(uint64_t)) {
 
  379    return ujson_serialize_integer64(uj, *value, 
false);
 
  381    return ujson_serialize_integer32(uj, *value, 
false);
 
  385status_t ujson_serialize_int64_t(ujson_t *uj, 
const int64_t *value) {
 
  386  return ujson_serialize_integer64(uj, (uint64_t)*value, *value < 0);
 
  389status_t ujson_serialize_int32_t(ujson_t *uj, 
const int32_t *value) {
 
  390  return ujson_serialize_integer32(uj, (uint32_t)*value, *value < 0);
 
  393status_t ujson_serialize_int16_t(ujson_t *uj, 
const int16_t *value) {
 
  394  return ujson_serialize_integer32(uj, (uint32_t)*value, *value < 0);
 
  397status_t ujson_serialize_int8_t(ujson_t *uj, 
const int8_t *value) {
 
  398  return ujson_serialize_integer32(uj, (uint32_t)*value, *value < 0);
 
  401status_t ujson_deserialize_status_t(ujson_t *uj, status_t *value) {
 
  402  private_status_t code;
 
  403  uint32_t module_id = 0;
 
  405  TRY(ujson_consume(uj, 
'{'));
 
  406  TRY(ujson_deserialize_private_status_t(uj, &code));
 
  407  TRY(ujson_consume(uj, 
':'));
 
  408  if (TRY(ujson_consume_maybe(uj, 
'['))) {
 
  410    TRY(ujson_parse_qs(uj, module, 
sizeof(module)));
 
  411    module_id = MAKE_MODULE_ID(module[0], module[1], module[2]);
 
  412    TRY(ujson_consume(uj, 
','));
 
  413    TRY(ujson_deserialize_uint32_t(uj, &arg));
 
  414    TRY(ujson_consume(uj, 
']'));
 
  416    TRY(ujson_deserialize_uint32_t(uj, &arg));
 
  418  TRY(ujson_consume(uj, 
'}'));
 
  420      status_create((absl_status_t)code, module_id, __FILE__, (int32_t)arg);
 
  424status_t ujson_serialize_status_t(ujson_t *uj, 
const status_t *value) {
 
  429  base_fprintf(out, 
"%!r", *value);