11cb0ef41Sopenharmony_ci/*
21cb0ef41Sopenharmony_ci * sfparse
31cb0ef41Sopenharmony_ci *
41cb0ef41Sopenharmony_ci * Copyright (c) 2023 sfparse contributors
51cb0ef41Sopenharmony_ci * Copyright (c) 2019 nghttp3 contributors
61cb0ef41Sopenharmony_ci * Copyright (c) 2015 nghttp2 contributors
71cb0ef41Sopenharmony_ci *
81cb0ef41Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining
91cb0ef41Sopenharmony_ci * a copy of this software and associated documentation files (the
101cb0ef41Sopenharmony_ci * "Software"), to deal in the Software without restriction, including
111cb0ef41Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish,
121cb0ef41Sopenharmony_ci * distribute, sublicense, and/or sell copies of the Software, and to
131cb0ef41Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to
141cb0ef41Sopenharmony_ci * the following conditions:
151cb0ef41Sopenharmony_ci *
161cb0ef41Sopenharmony_ci * The above copyright notice and this permission notice shall be
171cb0ef41Sopenharmony_ci * included in all copies or substantial portions of the Software.
181cb0ef41Sopenharmony_ci *
191cb0ef41Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
201cb0ef41Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
211cb0ef41Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
221cb0ef41Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
231cb0ef41Sopenharmony_ci * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
241cb0ef41Sopenharmony_ci * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
251cb0ef41Sopenharmony_ci * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
261cb0ef41Sopenharmony_ci */
271cb0ef41Sopenharmony_ci#include "sfparse.h"
281cb0ef41Sopenharmony_ci
291cb0ef41Sopenharmony_ci#include <string.h>
301cb0ef41Sopenharmony_ci#include <assert.h>
311cb0ef41Sopenharmony_ci#include <stdlib.h>
321cb0ef41Sopenharmony_ci
331cb0ef41Sopenharmony_ci#define SF_STATE_DICT 0x08u
341cb0ef41Sopenharmony_ci#define SF_STATE_LIST 0x10u
351cb0ef41Sopenharmony_ci#define SF_STATE_ITEM 0x18u
361cb0ef41Sopenharmony_ci
371cb0ef41Sopenharmony_ci#define SF_STATE_INNER_LIST 0x04u
381cb0ef41Sopenharmony_ci
391cb0ef41Sopenharmony_ci#define SF_STATE_BEFORE 0x00u
401cb0ef41Sopenharmony_ci#define SF_STATE_BEFORE_PARAMS 0x01u
411cb0ef41Sopenharmony_ci#define SF_STATE_PARAMS 0x02u
421cb0ef41Sopenharmony_ci#define SF_STATE_AFTER 0x03u
431cb0ef41Sopenharmony_ci
441cb0ef41Sopenharmony_ci#define SF_STATE_OP_MASK 0x03u
451cb0ef41Sopenharmony_ci
461cb0ef41Sopenharmony_ci#define SF_SET_STATE_AFTER(NAME) (SF_STATE_##NAME | SF_STATE_AFTER)
471cb0ef41Sopenharmony_ci#define SF_SET_STATE_BEFORE_PARAMS(NAME)                                       \
481cb0ef41Sopenharmony_ci  (SF_STATE_##NAME | SF_STATE_BEFORE_PARAMS)
491cb0ef41Sopenharmony_ci#define SF_SET_STATE_INNER_LIST_BEFORE(NAME)                                   \
501cb0ef41Sopenharmony_ci  (SF_STATE_##NAME | SF_STATE_INNER_LIST | SF_STATE_BEFORE)
511cb0ef41Sopenharmony_ci
521cb0ef41Sopenharmony_ci#define SF_STATE_DICT_AFTER SF_SET_STATE_AFTER(DICT)
531cb0ef41Sopenharmony_ci#define SF_STATE_DICT_BEFORE_PARAMS SF_SET_STATE_BEFORE_PARAMS(DICT)
541cb0ef41Sopenharmony_ci#define SF_STATE_DICT_INNER_LIST_BEFORE SF_SET_STATE_INNER_LIST_BEFORE(DICT)
551cb0ef41Sopenharmony_ci
561cb0ef41Sopenharmony_ci#define SF_STATE_LIST_AFTER SF_SET_STATE_AFTER(LIST)
571cb0ef41Sopenharmony_ci#define SF_STATE_LIST_BEFORE_PARAMS SF_SET_STATE_BEFORE_PARAMS(LIST)
581cb0ef41Sopenharmony_ci#define SF_STATE_LIST_INNER_LIST_BEFORE SF_SET_STATE_INNER_LIST_BEFORE(LIST)
591cb0ef41Sopenharmony_ci
601cb0ef41Sopenharmony_ci#define SF_STATE_ITEM_AFTER SF_SET_STATE_AFTER(ITEM)
611cb0ef41Sopenharmony_ci#define SF_STATE_ITEM_BEFORE_PARAMS SF_SET_STATE_BEFORE_PARAMS(ITEM)
621cb0ef41Sopenharmony_ci#define SF_STATE_ITEM_INNER_LIST_BEFORE SF_SET_STATE_INNER_LIST_BEFORE(ITEM)
631cb0ef41Sopenharmony_ci
641cb0ef41Sopenharmony_ci#define SF_STATE_INITIAL 0x00u
651cb0ef41Sopenharmony_ci
661cb0ef41Sopenharmony_ci#define DIGIT_CASES                                                            \
671cb0ef41Sopenharmony_ci  case '0':                                                                    \
681cb0ef41Sopenharmony_ci  case '1':                                                                    \
691cb0ef41Sopenharmony_ci  case '2':                                                                    \
701cb0ef41Sopenharmony_ci  case '3':                                                                    \
711cb0ef41Sopenharmony_ci  case '4':                                                                    \
721cb0ef41Sopenharmony_ci  case '5':                                                                    \
731cb0ef41Sopenharmony_ci  case '6':                                                                    \
741cb0ef41Sopenharmony_ci  case '7':                                                                    \
751cb0ef41Sopenharmony_ci  case '8':                                                                    \
761cb0ef41Sopenharmony_ci  case '9'
771cb0ef41Sopenharmony_ci
781cb0ef41Sopenharmony_ci#define LCALPHA_CASES                                                          \
791cb0ef41Sopenharmony_ci  case 'a':                                                                    \
801cb0ef41Sopenharmony_ci  case 'b':                                                                    \
811cb0ef41Sopenharmony_ci  case 'c':                                                                    \
821cb0ef41Sopenharmony_ci  case 'd':                                                                    \
831cb0ef41Sopenharmony_ci  case 'e':                                                                    \
841cb0ef41Sopenharmony_ci  case 'f':                                                                    \
851cb0ef41Sopenharmony_ci  case 'g':                                                                    \
861cb0ef41Sopenharmony_ci  case 'h':                                                                    \
871cb0ef41Sopenharmony_ci  case 'i':                                                                    \
881cb0ef41Sopenharmony_ci  case 'j':                                                                    \
891cb0ef41Sopenharmony_ci  case 'k':                                                                    \
901cb0ef41Sopenharmony_ci  case 'l':                                                                    \
911cb0ef41Sopenharmony_ci  case 'm':                                                                    \
921cb0ef41Sopenharmony_ci  case 'n':                                                                    \
931cb0ef41Sopenharmony_ci  case 'o':                                                                    \
941cb0ef41Sopenharmony_ci  case 'p':                                                                    \
951cb0ef41Sopenharmony_ci  case 'q':                                                                    \
961cb0ef41Sopenharmony_ci  case 'r':                                                                    \
971cb0ef41Sopenharmony_ci  case 's':                                                                    \
981cb0ef41Sopenharmony_ci  case 't':                                                                    \
991cb0ef41Sopenharmony_ci  case 'u':                                                                    \
1001cb0ef41Sopenharmony_ci  case 'v':                                                                    \
1011cb0ef41Sopenharmony_ci  case 'w':                                                                    \
1021cb0ef41Sopenharmony_ci  case 'x':                                                                    \
1031cb0ef41Sopenharmony_ci  case 'y':                                                                    \
1041cb0ef41Sopenharmony_ci  case 'z'
1051cb0ef41Sopenharmony_ci
1061cb0ef41Sopenharmony_ci#define UCALPHA_CASES                                                          \
1071cb0ef41Sopenharmony_ci  case 'A':                                                                    \
1081cb0ef41Sopenharmony_ci  case 'B':                                                                    \
1091cb0ef41Sopenharmony_ci  case 'C':                                                                    \
1101cb0ef41Sopenharmony_ci  case 'D':                                                                    \
1111cb0ef41Sopenharmony_ci  case 'E':                                                                    \
1121cb0ef41Sopenharmony_ci  case 'F':                                                                    \
1131cb0ef41Sopenharmony_ci  case 'G':                                                                    \
1141cb0ef41Sopenharmony_ci  case 'H':                                                                    \
1151cb0ef41Sopenharmony_ci  case 'I':                                                                    \
1161cb0ef41Sopenharmony_ci  case 'J':                                                                    \
1171cb0ef41Sopenharmony_ci  case 'K':                                                                    \
1181cb0ef41Sopenharmony_ci  case 'L':                                                                    \
1191cb0ef41Sopenharmony_ci  case 'M':                                                                    \
1201cb0ef41Sopenharmony_ci  case 'N':                                                                    \
1211cb0ef41Sopenharmony_ci  case 'O':                                                                    \
1221cb0ef41Sopenharmony_ci  case 'P':                                                                    \
1231cb0ef41Sopenharmony_ci  case 'Q':                                                                    \
1241cb0ef41Sopenharmony_ci  case 'R':                                                                    \
1251cb0ef41Sopenharmony_ci  case 'S':                                                                    \
1261cb0ef41Sopenharmony_ci  case 'T':                                                                    \
1271cb0ef41Sopenharmony_ci  case 'U':                                                                    \
1281cb0ef41Sopenharmony_ci  case 'V':                                                                    \
1291cb0ef41Sopenharmony_ci  case 'W':                                                                    \
1301cb0ef41Sopenharmony_ci  case 'X':                                                                    \
1311cb0ef41Sopenharmony_ci  case 'Y':                                                                    \
1321cb0ef41Sopenharmony_ci  case 'Z'
1331cb0ef41Sopenharmony_ci
1341cb0ef41Sopenharmony_ci#define ALPHA_CASES                                                            \
1351cb0ef41Sopenharmony_ci  UCALPHA_CASES:                                                               \
1361cb0ef41Sopenharmony_ci  LCALPHA_CASES
1371cb0ef41Sopenharmony_ci
1381cb0ef41Sopenharmony_ci#define X20_21_CASES                                                           \
1391cb0ef41Sopenharmony_ci  case ' ':                                                                    \
1401cb0ef41Sopenharmony_ci  case '!'
1411cb0ef41Sopenharmony_ci
1421cb0ef41Sopenharmony_ci#define X23_5B_CASES                                                           \
1431cb0ef41Sopenharmony_ci  case '#':                                                                    \
1441cb0ef41Sopenharmony_ci  case '$':                                                                    \
1451cb0ef41Sopenharmony_ci  case '%':                                                                    \
1461cb0ef41Sopenharmony_ci  case '&':                                                                    \
1471cb0ef41Sopenharmony_ci  case '\'':                                                                   \
1481cb0ef41Sopenharmony_ci  case '(':                                                                    \
1491cb0ef41Sopenharmony_ci  case ')':                                                                    \
1501cb0ef41Sopenharmony_ci  case '*':                                                                    \
1511cb0ef41Sopenharmony_ci  case '+':                                                                    \
1521cb0ef41Sopenharmony_ci  case ',':                                                                    \
1531cb0ef41Sopenharmony_ci  case '-':                                                                    \
1541cb0ef41Sopenharmony_ci  case '.':                                                                    \
1551cb0ef41Sopenharmony_ci  case '/':                                                                    \
1561cb0ef41Sopenharmony_ci  DIGIT_CASES:                                                                 \
1571cb0ef41Sopenharmony_ci  case ':':                                                                    \
1581cb0ef41Sopenharmony_ci  case ';':                                                                    \
1591cb0ef41Sopenharmony_ci  case '<':                                                                    \
1601cb0ef41Sopenharmony_ci  case '=':                                                                    \
1611cb0ef41Sopenharmony_ci  case '>':                                                                    \
1621cb0ef41Sopenharmony_ci  case '?':                                                                    \
1631cb0ef41Sopenharmony_ci  case '@':                                                                    \
1641cb0ef41Sopenharmony_ci  UCALPHA_CASES:                                                               \
1651cb0ef41Sopenharmony_ci  case '['
1661cb0ef41Sopenharmony_ci
1671cb0ef41Sopenharmony_ci#define X5D_7E_CASES                                                           \
1681cb0ef41Sopenharmony_ci  case ']':                                                                    \
1691cb0ef41Sopenharmony_ci  case '^':                                                                    \
1701cb0ef41Sopenharmony_ci  case '_':                                                                    \
1711cb0ef41Sopenharmony_ci  case '`':                                                                    \
1721cb0ef41Sopenharmony_ci  LCALPHA_CASES:                                                               \
1731cb0ef41Sopenharmony_ci  case '{':                                                                    \
1741cb0ef41Sopenharmony_ci  case '|':                                                                    \
1751cb0ef41Sopenharmony_ci  case '}':                                                                    \
1761cb0ef41Sopenharmony_ci  case '~'
1771cb0ef41Sopenharmony_ci
1781cb0ef41Sopenharmony_cistatic int is_ws(uint8_t c) {
1791cb0ef41Sopenharmony_ci  switch (c) {
1801cb0ef41Sopenharmony_ci  case ' ':
1811cb0ef41Sopenharmony_ci  case '\t':
1821cb0ef41Sopenharmony_ci    return 1;
1831cb0ef41Sopenharmony_ci  default:
1841cb0ef41Sopenharmony_ci    return 0;
1851cb0ef41Sopenharmony_ci  }
1861cb0ef41Sopenharmony_ci}
1871cb0ef41Sopenharmony_ci
1881cb0ef41Sopenharmony_cistatic int parser_eof(sf_parser *sfp) { return sfp->pos == sfp->end; }
1891cb0ef41Sopenharmony_ci
1901cb0ef41Sopenharmony_cistatic void parser_discard_ows(sf_parser *sfp) {
1911cb0ef41Sopenharmony_ci  for (; !parser_eof(sfp) && is_ws(*sfp->pos); ++sfp->pos)
1921cb0ef41Sopenharmony_ci    ;
1931cb0ef41Sopenharmony_ci}
1941cb0ef41Sopenharmony_ci
1951cb0ef41Sopenharmony_cistatic void parser_discard_sp(sf_parser *sfp) {
1961cb0ef41Sopenharmony_ci  for (; !parser_eof(sfp) && *sfp->pos == ' '; ++sfp->pos)
1971cb0ef41Sopenharmony_ci    ;
1981cb0ef41Sopenharmony_ci}
1991cb0ef41Sopenharmony_ci
2001cb0ef41Sopenharmony_cistatic void parser_set_op_state(sf_parser *sfp, uint32_t op) {
2011cb0ef41Sopenharmony_ci  sfp->state &= ~SF_STATE_OP_MASK;
2021cb0ef41Sopenharmony_ci  sfp->state |= op;
2031cb0ef41Sopenharmony_ci}
2041cb0ef41Sopenharmony_ci
2051cb0ef41Sopenharmony_cistatic void parser_unset_inner_list_state(sf_parser *sfp) {
2061cb0ef41Sopenharmony_ci  sfp->state &= ~SF_STATE_INNER_LIST;
2071cb0ef41Sopenharmony_ci}
2081cb0ef41Sopenharmony_ci
2091cb0ef41Sopenharmony_cistatic int parser_key(sf_parser *sfp, sf_vec *dest) {
2101cb0ef41Sopenharmony_ci  const uint8_t *base;
2111cb0ef41Sopenharmony_ci
2121cb0ef41Sopenharmony_ci  switch (*sfp->pos) {
2131cb0ef41Sopenharmony_ci  case '*':
2141cb0ef41Sopenharmony_ci  LCALPHA_CASES:
2151cb0ef41Sopenharmony_ci    break;
2161cb0ef41Sopenharmony_ci  default:
2171cb0ef41Sopenharmony_ci    return SF_ERR_PARSE_ERROR;
2181cb0ef41Sopenharmony_ci  }
2191cb0ef41Sopenharmony_ci
2201cb0ef41Sopenharmony_ci  base = sfp->pos++;
2211cb0ef41Sopenharmony_ci
2221cb0ef41Sopenharmony_ci  for (; !parser_eof(sfp); ++sfp->pos) {
2231cb0ef41Sopenharmony_ci    switch (*sfp->pos) {
2241cb0ef41Sopenharmony_ci    case '_':
2251cb0ef41Sopenharmony_ci    case '-':
2261cb0ef41Sopenharmony_ci    case '.':
2271cb0ef41Sopenharmony_ci    case '*':
2281cb0ef41Sopenharmony_ci    DIGIT_CASES:
2291cb0ef41Sopenharmony_ci    LCALPHA_CASES:
2301cb0ef41Sopenharmony_ci      continue;
2311cb0ef41Sopenharmony_ci    }
2321cb0ef41Sopenharmony_ci
2331cb0ef41Sopenharmony_ci    break;
2341cb0ef41Sopenharmony_ci  }
2351cb0ef41Sopenharmony_ci
2361cb0ef41Sopenharmony_ci  if (dest) {
2371cb0ef41Sopenharmony_ci    dest->base = (uint8_t *)base;
2381cb0ef41Sopenharmony_ci    dest->len = (size_t)(sfp->pos - dest->base);
2391cb0ef41Sopenharmony_ci  }
2401cb0ef41Sopenharmony_ci
2411cb0ef41Sopenharmony_ci  return 0;
2421cb0ef41Sopenharmony_ci}
2431cb0ef41Sopenharmony_ci
2441cb0ef41Sopenharmony_cistatic int parser_number(sf_parser *sfp, sf_value *dest) {
2451cb0ef41Sopenharmony_ci  int sign = 1;
2461cb0ef41Sopenharmony_ci  int64_t value = 0;
2471cb0ef41Sopenharmony_ci  size_t len = 0;
2481cb0ef41Sopenharmony_ci  size_t fpos = 0;
2491cb0ef41Sopenharmony_ci
2501cb0ef41Sopenharmony_ci  if (*sfp->pos == '-') {
2511cb0ef41Sopenharmony_ci    ++sfp->pos;
2521cb0ef41Sopenharmony_ci    if (parser_eof(sfp)) {
2531cb0ef41Sopenharmony_ci      return SF_ERR_PARSE_ERROR;
2541cb0ef41Sopenharmony_ci    }
2551cb0ef41Sopenharmony_ci
2561cb0ef41Sopenharmony_ci    sign = -1;
2571cb0ef41Sopenharmony_ci  }
2581cb0ef41Sopenharmony_ci
2591cb0ef41Sopenharmony_ci  assert(!parser_eof(sfp));
2601cb0ef41Sopenharmony_ci
2611cb0ef41Sopenharmony_ci  for (; !parser_eof(sfp); ++sfp->pos) {
2621cb0ef41Sopenharmony_ci    switch (*sfp->pos) {
2631cb0ef41Sopenharmony_ci    DIGIT_CASES:
2641cb0ef41Sopenharmony_ci      if (++len > 15) {
2651cb0ef41Sopenharmony_ci        return SF_ERR_PARSE_ERROR;
2661cb0ef41Sopenharmony_ci      }
2671cb0ef41Sopenharmony_ci
2681cb0ef41Sopenharmony_ci      value *= 10;
2691cb0ef41Sopenharmony_ci      value += *sfp->pos - '0';
2701cb0ef41Sopenharmony_ci
2711cb0ef41Sopenharmony_ci      continue;
2721cb0ef41Sopenharmony_ci    }
2731cb0ef41Sopenharmony_ci
2741cb0ef41Sopenharmony_ci    break;
2751cb0ef41Sopenharmony_ci  }
2761cb0ef41Sopenharmony_ci
2771cb0ef41Sopenharmony_ci  if (len == 0) {
2781cb0ef41Sopenharmony_ci    return SF_ERR_PARSE_ERROR;
2791cb0ef41Sopenharmony_ci  }
2801cb0ef41Sopenharmony_ci
2811cb0ef41Sopenharmony_ci  if (parser_eof(sfp) || *sfp->pos != '.') {
2821cb0ef41Sopenharmony_ci    if (dest) {
2831cb0ef41Sopenharmony_ci      dest->type = SF_TYPE_INTEGER;
2841cb0ef41Sopenharmony_ci      dest->flags = SF_VALUE_FLAG_NONE;
2851cb0ef41Sopenharmony_ci      dest->integer = value * sign;
2861cb0ef41Sopenharmony_ci    }
2871cb0ef41Sopenharmony_ci
2881cb0ef41Sopenharmony_ci    return 0;
2891cb0ef41Sopenharmony_ci  }
2901cb0ef41Sopenharmony_ci
2911cb0ef41Sopenharmony_ci  /* decimal */
2921cb0ef41Sopenharmony_ci
2931cb0ef41Sopenharmony_ci  if (len > 12) {
2941cb0ef41Sopenharmony_ci    return SF_ERR_PARSE_ERROR;
2951cb0ef41Sopenharmony_ci  }
2961cb0ef41Sopenharmony_ci
2971cb0ef41Sopenharmony_ci  fpos = len;
2981cb0ef41Sopenharmony_ci
2991cb0ef41Sopenharmony_ci  ++sfp->pos;
3001cb0ef41Sopenharmony_ci
3011cb0ef41Sopenharmony_ci  for (; !parser_eof(sfp); ++sfp->pos) {
3021cb0ef41Sopenharmony_ci    switch (*sfp->pos) {
3031cb0ef41Sopenharmony_ci    DIGIT_CASES:
3041cb0ef41Sopenharmony_ci      if (++len > 15) {
3051cb0ef41Sopenharmony_ci        return SF_ERR_PARSE_ERROR;
3061cb0ef41Sopenharmony_ci      }
3071cb0ef41Sopenharmony_ci
3081cb0ef41Sopenharmony_ci      value *= 10;
3091cb0ef41Sopenharmony_ci      value += *sfp->pos - '0';
3101cb0ef41Sopenharmony_ci
3111cb0ef41Sopenharmony_ci      continue;
3121cb0ef41Sopenharmony_ci    }
3131cb0ef41Sopenharmony_ci
3141cb0ef41Sopenharmony_ci    break;
3151cb0ef41Sopenharmony_ci  }
3161cb0ef41Sopenharmony_ci
3171cb0ef41Sopenharmony_ci  if (fpos == len || len - fpos > 3) {
3181cb0ef41Sopenharmony_ci    return SF_ERR_PARSE_ERROR;
3191cb0ef41Sopenharmony_ci  }
3201cb0ef41Sopenharmony_ci
3211cb0ef41Sopenharmony_ci  if (dest) {
3221cb0ef41Sopenharmony_ci    dest->type = SF_TYPE_DECIMAL;
3231cb0ef41Sopenharmony_ci    dest->flags = SF_VALUE_FLAG_NONE;
3241cb0ef41Sopenharmony_ci    dest->decimal.numer = value * sign;
3251cb0ef41Sopenharmony_ci
3261cb0ef41Sopenharmony_ci    switch (len - fpos) {
3271cb0ef41Sopenharmony_ci    case 1:
3281cb0ef41Sopenharmony_ci      dest->decimal.denom = 10;
3291cb0ef41Sopenharmony_ci
3301cb0ef41Sopenharmony_ci      break;
3311cb0ef41Sopenharmony_ci    case 2:
3321cb0ef41Sopenharmony_ci      dest->decimal.denom = 100;
3331cb0ef41Sopenharmony_ci
3341cb0ef41Sopenharmony_ci      break;
3351cb0ef41Sopenharmony_ci    case 3:
3361cb0ef41Sopenharmony_ci      dest->decimal.denom = 1000;
3371cb0ef41Sopenharmony_ci
3381cb0ef41Sopenharmony_ci      break;
3391cb0ef41Sopenharmony_ci    }
3401cb0ef41Sopenharmony_ci  }
3411cb0ef41Sopenharmony_ci
3421cb0ef41Sopenharmony_ci  return 0;
3431cb0ef41Sopenharmony_ci}
3441cb0ef41Sopenharmony_ci
3451cb0ef41Sopenharmony_cistatic int parser_date(sf_parser *sfp, sf_value *dest) {
3461cb0ef41Sopenharmony_ci  int rv;
3471cb0ef41Sopenharmony_ci  sf_value val;
3481cb0ef41Sopenharmony_ci
3491cb0ef41Sopenharmony_ci  /* The first byte has already been validated by the caller. */
3501cb0ef41Sopenharmony_ci  assert('@' == *sfp->pos);
3511cb0ef41Sopenharmony_ci
3521cb0ef41Sopenharmony_ci  ++sfp->pos;
3531cb0ef41Sopenharmony_ci
3541cb0ef41Sopenharmony_ci  if (parser_eof(sfp)) {
3551cb0ef41Sopenharmony_ci    return SF_ERR_PARSE_ERROR;
3561cb0ef41Sopenharmony_ci  }
3571cb0ef41Sopenharmony_ci
3581cb0ef41Sopenharmony_ci  rv = parser_number(sfp, &val);
3591cb0ef41Sopenharmony_ci  if (rv != 0) {
3601cb0ef41Sopenharmony_ci    return rv;
3611cb0ef41Sopenharmony_ci  }
3621cb0ef41Sopenharmony_ci
3631cb0ef41Sopenharmony_ci  if (val.type != SF_TYPE_INTEGER) {
3641cb0ef41Sopenharmony_ci    return SF_ERR_PARSE_ERROR;
3651cb0ef41Sopenharmony_ci  }
3661cb0ef41Sopenharmony_ci
3671cb0ef41Sopenharmony_ci  if (dest) {
3681cb0ef41Sopenharmony_ci    *dest = val;
3691cb0ef41Sopenharmony_ci    dest->type = SF_TYPE_DATE;
3701cb0ef41Sopenharmony_ci  }
3711cb0ef41Sopenharmony_ci
3721cb0ef41Sopenharmony_ci  return 0;
3731cb0ef41Sopenharmony_ci}
3741cb0ef41Sopenharmony_ci
3751cb0ef41Sopenharmony_cistatic int parser_string(sf_parser *sfp, sf_value *dest) {
3761cb0ef41Sopenharmony_ci  const uint8_t *base;
3771cb0ef41Sopenharmony_ci  uint32_t flags = SF_VALUE_FLAG_NONE;
3781cb0ef41Sopenharmony_ci
3791cb0ef41Sopenharmony_ci  /* The first byte has already been validated by the caller. */
3801cb0ef41Sopenharmony_ci  assert('"' == *sfp->pos);
3811cb0ef41Sopenharmony_ci
3821cb0ef41Sopenharmony_ci  base = ++sfp->pos;
3831cb0ef41Sopenharmony_ci
3841cb0ef41Sopenharmony_ci  for (; !parser_eof(sfp); ++sfp->pos) {
3851cb0ef41Sopenharmony_ci    switch (*sfp->pos) {
3861cb0ef41Sopenharmony_ci    X20_21_CASES:
3871cb0ef41Sopenharmony_ci    X23_5B_CASES:
3881cb0ef41Sopenharmony_ci    X5D_7E_CASES:
3891cb0ef41Sopenharmony_ci      break;
3901cb0ef41Sopenharmony_ci    case '\\':
3911cb0ef41Sopenharmony_ci      ++sfp->pos;
3921cb0ef41Sopenharmony_ci      if (parser_eof(sfp)) {
3931cb0ef41Sopenharmony_ci        return SF_ERR_PARSE_ERROR;
3941cb0ef41Sopenharmony_ci      }
3951cb0ef41Sopenharmony_ci
3961cb0ef41Sopenharmony_ci      switch (*sfp->pos) {
3971cb0ef41Sopenharmony_ci      case '"':
3981cb0ef41Sopenharmony_ci      case '\\':
3991cb0ef41Sopenharmony_ci        flags = SF_VALUE_FLAG_ESCAPED_STRING;
4001cb0ef41Sopenharmony_ci
4011cb0ef41Sopenharmony_ci        break;
4021cb0ef41Sopenharmony_ci      default:
4031cb0ef41Sopenharmony_ci        return SF_ERR_PARSE_ERROR;
4041cb0ef41Sopenharmony_ci      }
4051cb0ef41Sopenharmony_ci
4061cb0ef41Sopenharmony_ci      break;
4071cb0ef41Sopenharmony_ci    case '"':
4081cb0ef41Sopenharmony_ci      if (dest) {
4091cb0ef41Sopenharmony_ci        dest->type = SF_TYPE_STRING;
4101cb0ef41Sopenharmony_ci        dest->flags = flags;
4111cb0ef41Sopenharmony_ci        dest->vec.len = (size_t)(sfp->pos - base);
4121cb0ef41Sopenharmony_ci        dest->vec.base = dest->vec.len == 0 ? NULL : (uint8_t *)base;
4131cb0ef41Sopenharmony_ci      }
4141cb0ef41Sopenharmony_ci
4151cb0ef41Sopenharmony_ci      ++sfp->pos;
4161cb0ef41Sopenharmony_ci
4171cb0ef41Sopenharmony_ci      return 0;
4181cb0ef41Sopenharmony_ci    default:
4191cb0ef41Sopenharmony_ci      return SF_ERR_PARSE_ERROR;
4201cb0ef41Sopenharmony_ci    }
4211cb0ef41Sopenharmony_ci  }
4221cb0ef41Sopenharmony_ci
4231cb0ef41Sopenharmony_ci  return SF_ERR_PARSE_ERROR;
4241cb0ef41Sopenharmony_ci}
4251cb0ef41Sopenharmony_ci
4261cb0ef41Sopenharmony_cistatic int parser_token(sf_parser *sfp, sf_value *dest) {
4271cb0ef41Sopenharmony_ci  const uint8_t *base;
4281cb0ef41Sopenharmony_ci
4291cb0ef41Sopenharmony_ci  /* The first byte has already been validated by the caller. */
4301cb0ef41Sopenharmony_ci  base = sfp->pos++;
4311cb0ef41Sopenharmony_ci
4321cb0ef41Sopenharmony_ci  for (; !parser_eof(sfp); ++sfp->pos) {
4331cb0ef41Sopenharmony_ci    switch (*sfp->pos) {
4341cb0ef41Sopenharmony_ci    case '!':
4351cb0ef41Sopenharmony_ci    case '#':
4361cb0ef41Sopenharmony_ci    case '$':
4371cb0ef41Sopenharmony_ci    case '%':
4381cb0ef41Sopenharmony_ci    case '&':
4391cb0ef41Sopenharmony_ci    case '\'':
4401cb0ef41Sopenharmony_ci    case '*':
4411cb0ef41Sopenharmony_ci    case '+':
4421cb0ef41Sopenharmony_ci    case '-':
4431cb0ef41Sopenharmony_ci    case '.':
4441cb0ef41Sopenharmony_ci    case '^':
4451cb0ef41Sopenharmony_ci    case '_':
4461cb0ef41Sopenharmony_ci    case '`':
4471cb0ef41Sopenharmony_ci    case '|':
4481cb0ef41Sopenharmony_ci    case '~':
4491cb0ef41Sopenharmony_ci    case ':':
4501cb0ef41Sopenharmony_ci    case '/':
4511cb0ef41Sopenharmony_ci    DIGIT_CASES:
4521cb0ef41Sopenharmony_ci    ALPHA_CASES:
4531cb0ef41Sopenharmony_ci      continue;
4541cb0ef41Sopenharmony_ci    }
4551cb0ef41Sopenharmony_ci
4561cb0ef41Sopenharmony_ci    break;
4571cb0ef41Sopenharmony_ci  }
4581cb0ef41Sopenharmony_ci
4591cb0ef41Sopenharmony_ci  if (dest) {
4601cb0ef41Sopenharmony_ci    dest->type = SF_TYPE_TOKEN;
4611cb0ef41Sopenharmony_ci    dest->flags = SF_VALUE_FLAG_NONE;
4621cb0ef41Sopenharmony_ci    dest->vec.base = (uint8_t *)base;
4631cb0ef41Sopenharmony_ci    dest->vec.len = (size_t)(sfp->pos - base);
4641cb0ef41Sopenharmony_ci  }
4651cb0ef41Sopenharmony_ci
4661cb0ef41Sopenharmony_ci  return 0;
4671cb0ef41Sopenharmony_ci}
4681cb0ef41Sopenharmony_ci
4691cb0ef41Sopenharmony_cistatic int parser_byteseq(sf_parser *sfp, sf_value *dest) {
4701cb0ef41Sopenharmony_ci  const uint8_t *base;
4711cb0ef41Sopenharmony_ci
4721cb0ef41Sopenharmony_ci  /* The first byte has already been validated by the caller. */
4731cb0ef41Sopenharmony_ci  assert(':' == *sfp->pos);
4741cb0ef41Sopenharmony_ci
4751cb0ef41Sopenharmony_ci  base = ++sfp->pos;
4761cb0ef41Sopenharmony_ci
4771cb0ef41Sopenharmony_ci  for (; !parser_eof(sfp); ++sfp->pos) {
4781cb0ef41Sopenharmony_ci    switch (*sfp->pos) {
4791cb0ef41Sopenharmony_ci    case '+':
4801cb0ef41Sopenharmony_ci    case '/':
4811cb0ef41Sopenharmony_ci    DIGIT_CASES:
4821cb0ef41Sopenharmony_ci    ALPHA_CASES:
4831cb0ef41Sopenharmony_ci      continue;
4841cb0ef41Sopenharmony_ci    case '=':
4851cb0ef41Sopenharmony_ci      switch ((sfp->pos - base) & 0x3) {
4861cb0ef41Sopenharmony_ci      case 0:
4871cb0ef41Sopenharmony_ci      case 1:
4881cb0ef41Sopenharmony_ci        return SF_ERR_PARSE_ERROR;
4891cb0ef41Sopenharmony_ci      case 2:
4901cb0ef41Sopenharmony_ci        switch (*(sfp->pos - 1)) {
4911cb0ef41Sopenharmony_ci        case 'A':
4921cb0ef41Sopenharmony_ci        case 'Q':
4931cb0ef41Sopenharmony_ci        case 'g':
4941cb0ef41Sopenharmony_ci        case 'w':
4951cb0ef41Sopenharmony_ci          break;
4961cb0ef41Sopenharmony_ci        default:
4971cb0ef41Sopenharmony_ci          return SF_ERR_PARSE_ERROR;
4981cb0ef41Sopenharmony_ci        }
4991cb0ef41Sopenharmony_ci
5001cb0ef41Sopenharmony_ci        ++sfp->pos;
5011cb0ef41Sopenharmony_ci
5021cb0ef41Sopenharmony_ci        if (parser_eof(sfp) || *sfp->pos != '=') {
5031cb0ef41Sopenharmony_ci          return SF_ERR_PARSE_ERROR;
5041cb0ef41Sopenharmony_ci        }
5051cb0ef41Sopenharmony_ci
5061cb0ef41Sopenharmony_ci        break;
5071cb0ef41Sopenharmony_ci      case 3:
5081cb0ef41Sopenharmony_ci        switch (*(sfp->pos - 1)) {
5091cb0ef41Sopenharmony_ci        case 'A':
5101cb0ef41Sopenharmony_ci        case 'E':
5111cb0ef41Sopenharmony_ci        case 'I':
5121cb0ef41Sopenharmony_ci        case 'M':
5131cb0ef41Sopenharmony_ci        case 'Q':
5141cb0ef41Sopenharmony_ci        case 'U':
5151cb0ef41Sopenharmony_ci        case 'Y':
5161cb0ef41Sopenharmony_ci        case 'c':
5171cb0ef41Sopenharmony_ci        case 'g':
5181cb0ef41Sopenharmony_ci        case 'k':
5191cb0ef41Sopenharmony_ci        case 'o':
5201cb0ef41Sopenharmony_ci        case 's':
5211cb0ef41Sopenharmony_ci        case 'w':
5221cb0ef41Sopenharmony_ci        case '0':
5231cb0ef41Sopenharmony_ci        case '4':
5241cb0ef41Sopenharmony_ci        case '8':
5251cb0ef41Sopenharmony_ci          break;
5261cb0ef41Sopenharmony_ci        default:
5271cb0ef41Sopenharmony_ci          return SF_ERR_PARSE_ERROR;
5281cb0ef41Sopenharmony_ci        }
5291cb0ef41Sopenharmony_ci
5301cb0ef41Sopenharmony_ci        break;
5311cb0ef41Sopenharmony_ci      }
5321cb0ef41Sopenharmony_ci
5331cb0ef41Sopenharmony_ci      ++sfp->pos;
5341cb0ef41Sopenharmony_ci
5351cb0ef41Sopenharmony_ci      if (parser_eof(sfp) || *sfp->pos != ':') {
5361cb0ef41Sopenharmony_ci        return SF_ERR_PARSE_ERROR;
5371cb0ef41Sopenharmony_ci      }
5381cb0ef41Sopenharmony_ci
5391cb0ef41Sopenharmony_ci      goto fin;
5401cb0ef41Sopenharmony_ci    case ':':
5411cb0ef41Sopenharmony_ci      if ((sfp->pos - base) & 0x3) {
5421cb0ef41Sopenharmony_ci        return SF_ERR_PARSE_ERROR;
5431cb0ef41Sopenharmony_ci      }
5441cb0ef41Sopenharmony_ci
5451cb0ef41Sopenharmony_ci      goto fin;
5461cb0ef41Sopenharmony_ci    default:
5471cb0ef41Sopenharmony_ci      return SF_ERR_PARSE_ERROR;
5481cb0ef41Sopenharmony_ci    }
5491cb0ef41Sopenharmony_ci  }
5501cb0ef41Sopenharmony_ci
5511cb0ef41Sopenharmony_ci  return SF_ERR_PARSE_ERROR;
5521cb0ef41Sopenharmony_ci
5531cb0ef41Sopenharmony_cifin:
5541cb0ef41Sopenharmony_ci  if (dest) {
5551cb0ef41Sopenharmony_ci    dest->type = SF_TYPE_BYTESEQ;
5561cb0ef41Sopenharmony_ci    dest->flags = SF_VALUE_FLAG_NONE;
5571cb0ef41Sopenharmony_ci    dest->vec.len = (size_t)(sfp->pos - base);
5581cb0ef41Sopenharmony_ci    dest->vec.base = dest->vec.len == 0 ? NULL : (uint8_t *)base;
5591cb0ef41Sopenharmony_ci  }
5601cb0ef41Sopenharmony_ci
5611cb0ef41Sopenharmony_ci  ++sfp->pos;
5621cb0ef41Sopenharmony_ci
5631cb0ef41Sopenharmony_ci  return 0;
5641cb0ef41Sopenharmony_ci}
5651cb0ef41Sopenharmony_ci
5661cb0ef41Sopenharmony_cistatic int parser_boolean(sf_parser *sfp, sf_value *dest) {
5671cb0ef41Sopenharmony_ci  int b;
5681cb0ef41Sopenharmony_ci
5691cb0ef41Sopenharmony_ci  /* The first byte has already been validated by the caller. */
5701cb0ef41Sopenharmony_ci  assert('?' == *sfp->pos);
5711cb0ef41Sopenharmony_ci
5721cb0ef41Sopenharmony_ci  ++sfp->pos;
5731cb0ef41Sopenharmony_ci
5741cb0ef41Sopenharmony_ci  if (parser_eof(sfp)) {
5751cb0ef41Sopenharmony_ci    return SF_ERR_PARSE_ERROR;
5761cb0ef41Sopenharmony_ci  }
5771cb0ef41Sopenharmony_ci
5781cb0ef41Sopenharmony_ci  switch (*sfp->pos) {
5791cb0ef41Sopenharmony_ci  case '0':
5801cb0ef41Sopenharmony_ci    b = 0;
5811cb0ef41Sopenharmony_ci
5821cb0ef41Sopenharmony_ci    break;
5831cb0ef41Sopenharmony_ci  case '1':
5841cb0ef41Sopenharmony_ci    b = 1;
5851cb0ef41Sopenharmony_ci
5861cb0ef41Sopenharmony_ci    break;
5871cb0ef41Sopenharmony_ci  default:
5881cb0ef41Sopenharmony_ci    return SF_ERR_PARSE_ERROR;
5891cb0ef41Sopenharmony_ci  }
5901cb0ef41Sopenharmony_ci
5911cb0ef41Sopenharmony_ci  ++sfp->pos;
5921cb0ef41Sopenharmony_ci
5931cb0ef41Sopenharmony_ci  if (dest) {
5941cb0ef41Sopenharmony_ci    dest->type = SF_TYPE_BOOLEAN;
5951cb0ef41Sopenharmony_ci    dest->flags = SF_VALUE_FLAG_NONE;
5961cb0ef41Sopenharmony_ci    dest->boolean = b;
5971cb0ef41Sopenharmony_ci  }
5981cb0ef41Sopenharmony_ci
5991cb0ef41Sopenharmony_ci  return 0;
6001cb0ef41Sopenharmony_ci}
6011cb0ef41Sopenharmony_ci
6021cb0ef41Sopenharmony_cistatic int parser_bare_item(sf_parser *sfp, sf_value *dest) {
6031cb0ef41Sopenharmony_ci  switch (*sfp->pos) {
6041cb0ef41Sopenharmony_ci  case '"':
6051cb0ef41Sopenharmony_ci    return parser_string(sfp, dest);
6061cb0ef41Sopenharmony_ci  case '-':
6071cb0ef41Sopenharmony_ci  DIGIT_CASES:
6081cb0ef41Sopenharmony_ci    return parser_number(sfp, dest);
6091cb0ef41Sopenharmony_ci  case '@':
6101cb0ef41Sopenharmony_ci    return parser_date(sfp, dest);
6111cb0ef41Sopenharmony_ci  case ':':
6121cb0ef41Sopenharmony_ci    return parser_byteseq(sfp, dest);
6131cb0ef41Sopenharmony_ci  case '?':
6141cb0ef41Sopenharmony_ci    return parser_boolean(sfp, dest);
6151cb0ef41Sopenharmony_ci  case '*':
6161cb0ef41Sopenharmony_ci  ALPHA_CASES:
6171cb0ef41Sopenharmony_ci    return parser_token(sfp, dest);
6181cb0ef41Sopenharmony_ci  default:
6191cb0ef41Sopenharmony_ci    return SF_ERR_PARSE_ERROR;
6201cb0ef41Sopenharmony_ci  }
6211cb0ef41Sopenharmony_ci}
6221cb0ef41Sopenharmony_ci
6231cb0ef41Sopenharmony_cistatic int parser_skip_inner_list(sf_parser *sfp);
6241cb0ef41Sopenharmony_ci
6251cb0ef41Sopenharmony_ciint sf_parser_param(sf_parser *sfp, sf_vec *dest_key, sf_value *dest_value) {
6261cb0ef41Sopenharmony_ci  int rv;
6271cb0ef41Sopenharmony_ci
6281cb0ef41Sopenharmony_ci  switch (sfp->state & SF_STATE_OP_MASK) {
6291cb0ef41Sopenharmony_ci  case SF_STATE_BEFORE:
6301cb0ef41Sopenharmony_ci    rv = parser_skip_inner_list(sfp);
6311cb0ef41Sopenharmony_ci    if (rv != 0) {
6321cb0ef41Sopenharmony_ci      return rv;
6331cb0ef41Sopenharmony_ci    }
6341cb0ef41Sopenharmony_ci
6351cb0ef41Sopenharmony_ci    /* fall through */
6361cb0ef41Sopenharmony_ci  case SF_STATE_BEFORE_PARAMS:
6371cb0ef41Sopenharmony_ci    parser_set_op_state(sfp, SF_STATE_PARAMS);
6381cb0ef41Sopenharmony_ci
6391cb0ef41Sopenharmony_ci    break;
6401cb0ef41Sopenharmony_ci  case SF_STATE_PARAMS:
6411cb0ef41Sopenharmony_ci    break;
6421cb0ef41Sopenharmony_ci  default:
6431cb0ef41Sopenharmony_ci    assert(0);
6441cb0ef41Sopenharmony_ci    abort();
6451cb0ef41Sopenharmony_ci  }
6461cb0ef41Sopenharmony_ci
6471cb0ef41Sopenharmony_ci  if (parser_eof(sfp) || *sfp->pos != ';') {
6481cb0ef41Sopenharmony_ci    parser_set_op_state(sfp, SF_STATE_AFTER);
6491cb0ef41Sopenharmony_ci
6501cb0ef41Sopenharmony_ci    return SF_ERR_EOF;
6511cb0ef41Sopenharmony_ci  }
6521cb0ef41Sopenharmony_ci
6531cb0ef41Sopenharmony_ci  ++sfp->pos;
6541cb0ef41Sopenharmony_ci
6551cb0ef41Sopenharmony_ci  parser_discard_sp(sfp);
6561cb0ef41Sopenharmony_ci  if (parser_eof(sfp)) {
6571cb0ef41Sopenharmony_ci    return SF_ERR_PARSE_ERROR;
6581cb0ef41Sopenharmony_ci  }
6591cb0ef41Sopenharmony_ci
6601cb0ef41Sopenharmony_ci  rv = parser_key(sfp, dest_key);
6611cb0ef41Sopenharmony_ci  if (rv != 0) {
6621cb0ef41Sopenharmony_ci    return rv;
6631cb0ef41Sopenharmony_ci  }
6641cb0ef41Sopenharmony_ci
6651cb0ef41Sopenharmony_ci  if (parser_eof(sfp) || *sfp->pos != '=') {
6661cb0ef41Sopenharmony_ci    if (dest_value) {
6671cb0ef41Sopenharmony_ci      dest_value->type = SF_TYPE_BOOLEAN;
6681cb0ef41Sopenharmony_ci      dest_value->flags = SF_VALUE_FLAG_NONE;
6691cb0ef41Sopenharmony_ci      dest_value->boolean = 1;
6701cb0ef41Sopenharmony_ci    }
6711cb0ef41Sopenharmony_ci
6721cb0ef41Sopenharmony_ci    return 0;
6731cb0ef41Sopenharmony_ci  }
6741cb0ef41Sopenharmony_ci
6751cb0ef41Sopenharmony_ci  ++sfp->pos;
6761cb0ef41Sopenharmony_ci
6771cb0ef41Sopenharmony_ci  if (parser_eof(sfp)) {
6781cb0ef41Sopenharmony_ci    return SF_ERR_PARSE_ERROR;
6791cb0ef41Sopenharmony_ci  }
6801cb0ef41Sopenharmony_ci
6811cb0ef41Sopenharmony_ci  return parser_bare_item(sfp, dest_value);
6821cb0ef41Sopenharmony_ci}
6831cb0ef41Sopenharmony_ci
6841cb0ef41Sopenharmony_cistatic int parser_skip_params(sf_parser *sfp) {
6851cb0ef41Sopenharmony_ci  int rv;
6861cb0ef41Sopenharmony_ci
6871cb0ef41Sopenharmony_ci  for (;;) {
6881cb0ef41Sopenharmony_ci    rv = sf_parser_param(sfp, NULL, NULL);
6891cb0ef41Sopenharmony_ci    switch (rv) {
6901cb0ef41Sopenharmony_ci    case 0:
6911cb0ef41Sopenharmony_ci      break;
6921cb0ef41Sopenharmony_ci    case SF_ERR_EOF:
6931cb0ef41Sopenharmony_ci      return 0;
6941cb0ef41Sopenharmony_ci    case SF_ERR_PARSE_ERROR:
6951cb0ef41Sopenharmony_ci      return rv;
6961cb0ef41Sopenharmony_ci    default:
6971cb0ef41Sopenharmony_ci      assert(0);
6981cb0ef41Sopenharmony_ci      abort();
6991cb0ef41Sopenharmony_ci    }
7001cb0ef41Sopenharmony_ci  }
7011cb0ef41Sopenharmony_ci}
7021cb0ef41Sopenharmony_ci
7031cb0ef41Sopenharmony_ciint sf_parser_inner_list(sf_parser *sfp, sf_value *dest) {
7041cb0ef41Sopenharmony_ci  int rv;
7051cb0ef41Sopenharmony_ci
7061cb0ef41Sopenharmony_ci  switch (sfp->state & SF_STATE_OP_MASK) {
7071cb0ef41Sopenharmony_ci  case SF_STATE_BEFORE:
7081cb0ef41Sopenharmony_ci    parser_discard_sp(sfp);
7091cb0ef41Sopenharmony_ci    if (parser_eof(sfp)) {
7101cb0ef41Sopenharmony_ci      return SF_ERR_PARSE_ERROR;
7111cb0ef41Sopenharmony_ci    }
7121cb0ef41Sopenharmony_ci
7131cb0ef41Sopenharmony_ci    break;
7141cb0ef41Sopenharmony_ci  case SF_STATE_BEFORE_PARAMS:
7151cb0ef41Sopenharmony_ci    rv = parser_skip_params(sfp);
7161cb0ef41Sopenharmony_ci    if (rv != 0) {
7171cb0ef41Sopenharmony_ci      return rv;
7181cb0ef41Sopenharmony_ci    }
7191cb0ef41Sopenharmony_ci
7201cb0ef41Sopenharmony_ci    /* Technically, we are entering SF_STATE_AFTER, but we will set
7211cb0ef41Sopenharmony_ci       another state without reading the state. */
7221cb0ef41Sopenharmony_ci    /* parser_set_op_state(sfp, SF_STATE_AFTER); */
7231cb0ef41Sopenharmony_ci
7241cb0ef41Sopenharmony_ci    /* fall through */
7251cb0ef41Sopenharmony_ci  case SF_STATE_AFTER:
7261cb0ef41Sopenharmony_ci    if (parser_eof(sfp)) {
7271cb0ef41Sopenharmony_ci      return SF_ERR_PARSE_ERROR;
7281cb0ef41Sopenharmony_ci    }
7291cb0ef41Sopenharmony_ci
7301cb0ef41Sopenharmony_ci    switch (*sfp->pos) {
7311cb0ef41Sopenharmony_ci    case ' ':
7321cb0ef41Sopenharmony_ci      parser_discard_sp(sfp);
7331cb0ef41Sopenharmony_ci      if (parser_eof(sfp)) {
7341cb0ef41Sopenharmony_ci        return SF_ERR_PARSE_ERROR;
7351cb0ef41Sopenharmony_ci      }
7361cb0ef41Sopenharmony_ci
7371cb0ef41Sopenharmony_ci      break;
7381cb0ef41Sopenharmony_ci    case ')':
7391cb0ef41Sopenharmony_ci      break;
7401cb0ef41Sopenharmony_ci    default:
7411cb0ef41Sopenharmony_ci      return SF_ERR_PARSE_ERROR;
7421cb0ef41Sopenharmony_ci    }
7431cb0ef41Sopenharmony_ci
7441cb0ef41Sopenharmony_ci    break;
7451cb0ef41Sopenharmony_ci  default:
7461cb0ef41Sopenharmony_ci    assert(0);
7471cb0ef41Sopenharmony_ci    abort();
7481cb0ef41Sopenharmony_ci  }
7491cb0ef41Sopenharmony_ci
7501cb0ef41Sopenharmony_ci  if (*sfp->pos == ')') {
7511cb0ef41Sopenharmony_ci    ++sfp->pos;
7521cb0ef41Sopenharmony_ci
7531cb0ef41Sopenharmony_ci    parser_unset_inner_list_state(sfp);
7541cb0ef41Sopenharmony_ci    parser_set_op_state(sfp, SF_STATE_BEFORE_PARAMS);
7551cb0ef41Sopenharmony_ci
7561cb0ef41Sopenharmony_ci    return SF_ERR_EOF;
7571cb0ef41Sopenharmony_ci  }
7581cb0ef41Sopenharmony_ci
7591cb0ef41Sopenharmony_ci  rv = parser_bare_item(sfp, dest);
7601cb0ef41Sopenharmony_ci  if (rv != 0) {
7611cb0ef41Sopenharmony_ci    return rv;
7621cb0ef41Sopenharmony_ci  }
7631cb0ef41Sopenharmony_ci
7641cb0ef41Sopenharmony_ci  parser_set_op_state(sfp, SF_STATE_BEFORE_PARAMS);
7651cb0ef41Sopenharmony_ci
7661cb0ef41Sopenharmony_ci  return 0;
7671cb0ef41Sopenharmony_ci}
7681cb0ef41Sopenharmony_ci
7691cb0ef41Sopenharmony_cistatic int parser_skip_inner_list(sf_parser *sfp) {
7701cb0ef41Sopenharmony_ci  int rv;
7711cb0ef41Sopenharmony_ci
7721cb0ef41Sopenharmony_ci  for (;;) {
7731cb0ef41Sopenharmony_ci    rv = sf_parser_inner_list(sfp, NULL);
7741cb0ef41Sopenharmony_ci    switch (rv) {
7751cb0ef41Sopenharmony_ci    case 0:
7761cb0ef41Sopenharmony_ci      break;
7771cb0ef41Sopenharmony_ci    case SF_ERR_EOF:
7781cb0ef41Sopenharmony_ci      return 0;
7791cb0ef41Sopenharmony_ci    case SF_ERR_PARSE_ERROR:
7801cb0ef41Sopenharmony_ci      return rv;
7811cb0ef41Sopenharmony_ci    default:
7821cb0ef41Sopenharmony_ci      assert(0);
7831cb0ef41Sopenharmony_ci      abort();
7841cb0ef41Sopenharmony_ci    }
7851cb0ef41Sopenharmony_ci  }
7861cb0ef41Sopenharmony_ci}
7871cb0ef41Sopenharmony_ci
7881cb0ef41Sopenharmony_cistatic int parser_next_key_or_item(sf_parser *sfp) {
7891cb0ef41Sopenharmony_ci  parser_discard_ows(sfp);
7901cb0ef41Sopenharmony_ci
7911cb0ef41Sopenharmony_ci  if (parser_eof(sfp)) {
7921cb0ef41Sopenharmony_ci    return SF_ERR_EOF;
7931cb0ef41Sopenharmony_ci  }
7941cb0ef41Sopenharmony_ci
7951cb0ef41Sopenharmony_ci  if (*sfp->pos != ',') {
7961cb0ef41Sopenharmony_ci    return SF_ERR_PARSE_ERROR;
7971cb0ef41Sopenharmony_ci  }
7981cb0ef41Sopenharmony_ci
7991cb0ef41Sopenharmony_ci  ++sfp->pos;
8001cb0ef41Sopenharmony_ci
8011cb0ef41Sopenharmony_ci  parser_discard_ows(sfp);
8021cb0ef41Sopenharmony_ci  if (parser_eof(sfp)) {
8031cb0ef41Sopenharmony_ci    return SF_ERR_PARSE_ERROR;
8041cb0ef41Sopenharmony_ci  }
8051cb0ef41Sopenharmony_ci
8061cb0ef41Sopenharmony_ci  return 0;
8071cb0ef41Sopenharmony_ci}
8081cb0ef41Sopenharmony_ci
8091cb0ef41Sopenharmony_cistatic int parser_dict_value(sf_parser *sfp, sf_value *dest) {
8101cb0ef41Sopenharmony_ci  int rv;
8111cb0ef41Sopenharmony_ci
8121cb0ef41Sopenharmony_ci  if (parser_eof(sfp) || *(sfp->pos) != '=') {
8131cb0ef41Sopenharmony_ci    /* Boolean true */
8141cb0ef41Sopenharmony_ci    if (dest) {
8151cb0ef41Sopenharmony_ci      dest->type = SF_TYPE_BOOLEAN;
8161cb0ef41Sopenharmony_ci      dest->flags = SF_VALUE_FLAG_NONE;
8171cb0ef41Sopenharmony_ci      dest->boolean = 1;
8181cb0ef41Sopenharmony_ci    }
8191cb0ef41Sopenharmony_ci
8201cb0ef41Sopenharmony_ci    sfp->state = SF_STATE_DICT_BEFORE_PARAMS;
8211cb0ef41Sopenharmony_ci
8221cb0ef41Sopenharmony_ci    return 0;
8231cb0ef41Sopenharmony_ci  }
8241cb0ef41Sopenharmony_ci
8251cb0ef41Sopenharmony_ci  ++sfp->pos;
8261cb0ef41Sopenharmony_ci
8271cb0ef41Sopenharmony_ci  if (parser_eof(sfp)) {
8281cb0ef41Sopenharmony_ci    return SF_ERR_PARSE_ERROR;
8291cb0ef41Sopenharmony_ci  }
8301cb0ef41Sopenharmony_ci
8311cb0ef41Sopenharmony_ci  if (*sfp->pos == '(') {
8321cb0ef41Sopenharmony_ci    if (dest) {
8331cb0ef41Sopenharmony_ci      dest->type = SF_TYPE_INNER_LIST;
8341cb0ef41Sopenharmony_ci      dest->flags = SF_VALUE_FLAG_NONE;
8351cb0ef41Sopenharmony_ci    }
8361cb0ef41Sopenharmony_ci
8371cb0ef41Sopenharmony_ci    ++sfp->pos;
8381cb0ef41Sopenharmony_ci
8391cb0ef41Sopenharmony_ci    sfp->state = SF_STATE_DICT_INNER_LIST_BEFORE;
8401cb0ef41Sopenharmony_ci
8411cb0ef41Sopenharmony_ci    return 0;
8421cb0ef41Sopenharmony_ci  }
8431cb0ef41Sopenharmony_ci
8441cb0ef41Sopenharmony_ci  rv = parser_bare_item(sfp, dest);
8451cb0ef41Sopenharmony_ci  if (rv != 0) {
8461cb0ef41Sopenharmony_ci    return rv;
8471cb0ef41Sopenharmony_ci  }
8481cb0ef41Sopenharmony_ci
8491cb0ef41Sopenharmony_ci  sfp->state = SF_STATE_DICT_BEFORE_PARAMS;
8501cb0ef41Sopenharmony_ci
8511cb0ef41Sopenharmony_ci  return 0;
8521cb0ef41Sopenharmony_ci}
8531cb0ef41Sopenharmony_ci
8541cb0ef41Sopenharmony_ciint sf_parser_dict(sf_parser *sfp, sf_vec *dest_key, sf_value *dest_value) {
8551cb0ef41Sopenharmony_ci  int rv;
8561cb0ef41Sopenharmony_ci
8571cb0ef41Sopenharmony_ci  switch (sfp->state) {
8581cb0ef41Sopenharmony_ci  case SF_STATE_DICT_INNER_LIST_BEFORE:
8591cb0ef41Sopenharmony_ci    rv = parser_skip_inner_list(sfp);
8601cb0ef41Sopenharmony_ci    if (rv != 0) {
8611cb0ef41Sopenharmony_ci      return rv;
8621cb0ef41Sopenharmony_ci    }
8631cb0ef41Sopenharmony_ci
8641cb0ef41Sopenharmony_ci    /* fall through */
8651cb0ef41Sopenharmony_ci  case SF_STATE_DICT_BEFORE_PARAMS:
8661cb0ef41Sopenharmony_ci    rv = parser_skip_params(sfp);
8671cb0ef41Sopenharmony_ci    if (rv != 0) {
8681cb0ef41Sopenharmony_ci      return rv;
8691cb0ef41Sopenharmony_ci    }
8701cb0ef41Sopenharmony_ci
8711cb0ef41Sopenharmony_ci    /* fall through */
8721cb0ef41Sopenharmony_ci  case SF_STATE_DICT_AFTER:
8731cb0ef41Sopenharmony_ci    rv = parser_next_key_or_item(sfp);
8741cb0ef41Sopenharmony_ci    if (rv != 0) {
8751cb0ef41Sopenharmony_ci      return rv;
8761cb0ef41Sopenharmony_ci    }
8771cb0ef41Sopenharmony_ci
8781cb0ef41Sopenharmony_ci    break;
8791cb0ef41Sopenharmony_ci  case SF_STATE_INITIAL:
8801cb0ef41Sopenharmony_ci    parser_discard_sp(sfp);
8811cb0ef41Sopenharmony_ci
8821cb0ef41Sopenharmony_ci    if (parser_eof(sfp)) {
8831cb0ef41Sopenharmony_ci      return SF_ERR_EOF;
8841cb0ef41Sopenharmony_ci    }
8851cb0ef41Sopenharmony_ci
8861cb0ef41Sopenharmony_ci    break;
8871cb0ef41Sopenharmony_ci  default:
8881cb0ef41Sopenharmony_ci    assert(0);
8891cb0ef41Sopenharmony_ci    abort();
8901cb0ef41Sopenharmony_ci  }
8911cb0ef41Sopenharmony_ci
8921cb0ef41Sopenharmony_ci  rv = parser_key(sfp, dest_key);
8931cb0ef41Sopenharmony_ci  if (rv != 0) {
8941cb0ef41Sopenharmony_ci    return rv;
8951cb0ef41Sopenharmony_ci  }
8961cb0ef41Sopenharmony_ci
8971cb0ef41Sopenharmony_ci  return parser_dict_value(sfp, dest_value);
8981cb0ef41Sopenharmony_ci}
8991cb0ef41Sopenharmony_ci
9001cb0ef41Sopenharmony_ciint sf_parser_list(sf_parser *sfp, sf_value *dest) {
9011cb0ef41Sopenharmony_ci  int rv;
9021cb0ef41Sopenharmony_ci
9031cb0ef41Sopenharmony_ci  switch (sfp->state) {
9041cb0ef41Sopenharmony_ci  case SF_STATE_LIST_INNER_LIST_BEFORE:
9051cb0ef41Sopenharmony_ci    rv = parser_skip_inner_list(sfp);
9061cb0ef41Sopenharmony_ci    if (rv != 0) {
9071cb0ef41Sopenharmony_ci      return rv;
9081cb0ef41Sopenharmony_ci    }
9091cb0ef41Sopenharmony_ci
9101cb0ef41Sopenharmony_ci    /* fall through */
9111cb0ef41Sopenharmony_ci  case SF_STATE_LIST_BEFORE_PARAMS:
9121cb0ef41Sopenharmony_ci    rv = parser_skip_params(sfp);
9131cb0ef41Sopenharmony_ci    if (rv != 0) {
9141cb0ef41Sopenharmony_ci      return rv;
9151cb0ef41Sopenharmony_ci    }
9161cb0ef41Sopenharmony_ci
9171cb0ef41Sopenharmony_ci    /* fall through */
9181cb0ef41Sopenharmony_ci  case SF_STATE_LIST_AFTER:
9191cb0ef41Sopenharmony_ci    rv = parser_next_key_or_item(sfp);
9201cb0ef41Sopenharmony_ci    if (rv != 0) {
9211cb0ef41Sopenharmony_ci      return rv;
9221cb0ef41Sopenharmony_ci    }
9231cb0ef41Sopenharmony_ci
9241cb0ef41Sopenharmony_ci    break;
9251cb0ef41Sopenharmony_ci  case SF_STATE_INITIAL:
9261cb0ef41Sopenharmony_ci    parser_discard_sp(sfp);
9271cb0ef41Sopenharmony_ci
9281cb0ef41Sopenharmony_ci    if (parser_eof(sfp)) {
9291cb0ef41Sopenharmony_ci      return SF_ERR_EOF;
9301cb0ef41Sopenharmony_ci    }
9311cb0ef41Sopenharmony_ci
9321cb0ef41Sopenharmony_ci    break;
9331cb0ef41Sopenharmony_ci  default:
9341cb0ef41Sopenharmony_ci    assert(0);
9351cb0ef41Sopenharmony_ci    abort();
9361cb0ef41Sopenharmony_ci  }
9371cb0ef41Sopenharmony_ci
9381cb0ef41Sopenharmony_ci  if (*sfp->pos == '(') {
9391cb0ef41Sopenharmony_ci    if (dest) {
9401cb0ef41Sopenharmony_ci      dest->type = SF_TYPE_INNER_LIST;
9411cb0ef41Sopenharmony_ci      dest->flags = SF_VALUE_FLAG_NONE;
9421cb0ef41Sopenharmony_ci    }
9431cb0ef41Sopenharmony_ci
9441cb0ef41Sopenharmony_ci    ++sfp->pos;
9451cb0ef41Sopenharmony_ci
9461cb0ef41Sopenharmony_ci    sfp->state = SF_STATE_LIST_INNER_LIST_BEFORE;
9471cb0ef41Sopenharmony_ci
9481cb0ef41Sopenharmony_ci    return 0;
9491cb0ef41Sopenharmony_ci  }
9501cb0ef41Sopenharmony_ci
9511cb0ef41Sopenharmony_ci  rv = parser_bare_item(sfp, dest);
9521cb0ef41Sopenharmony_ci  if (rv != 0) {
9531cb0ef41Sopenharmony_ci    return rv;
9541cb0ef41Sopenharmony_ci  }
9551cb0ef41Sopenharmony_ci
9561cb0ef41Sopenharmony_ci  sfp->state = SF_STATE_LIST_BEFORE_PARAMS;
9571cb0ef41Sopenharmony_ci
9581cb0ef41Sopenharmony_ci  return 0;
9591cb0ef41Sopenharmony_ci}
9601cb0ef41Sopenharmony_ci
9611cb0ef41Sopenharmony_ciint sf_parser_item(sf_parser *sfp, sf_value *dest) {
9621cb0ef41Sopenharmony_ci  int rv;
9631cb0ef41Sopenharmony_ci
9641cb0ef41Sopenharmony_ci  switch (sfp->state) {
9651cb0ef41Sopenharmony_ci  case SF_STATE_INITIAL:
9661cb0ef41Sopenharmony_ci    parser_discard_sp(sfp);
9671cb0ef41Sopenharmony_ci
9681cb0ef41Sopenharmony_ci    if (parser_eof(sfp)) {
9691cb0ef41Sopenharmony_ci      return SF_ERR_PARSE_ERROR;
9701cb0ef41Sopenharmony_ci    }
9711cb0ef41Sopenharmony_ci
9721cb0ef41Sopenharmony_ci    break;
9731cb0ef41Sopenharmony_ci  case SF_STATE_ITEM_INNER_LIST_BEFORE:
9741cb0ef41Sopenharmony_ci    rv = parser_skip_inner_list(sfp);
9751cb0ef41Sopenharmony_ci    if (rv != 0) {
9761cb0ef41Sopenharmony_ci      return rv;
9771cb0ef41Sopenharmony_ci    }
9781cb0ef41Sopenharmony_ci
9791cb0ef41Sopenharmony_ci    /* fall through */
9801cb0ef41Sopenharmony_ci  case SF_STATE_ITEM_BEFORE_PARAMS:
9811cb0ef41Sopenharmony_ci    rv = parser_skip_params(sfp);
9821cb0ef41Sopenharmony_ci    if (rv != 0) {
9831cb0ef41Sopenharmony_ci      return rv;
9841cb0ef41Sopenharmony_ci    }
9851cb0ef41Sopenharmony_ci
9861cb0ef41Sopenharmony_ci    /* fall through */
9871cb0ef41Sopenharmony_ci  case SF_STATE_ITEM_AFTER:
9881cb0ef41Sopenharmony_ci    parser_discard_sp(sfp);
9891cb0ef41Sopenharmony_ci
9901cb0ef41Sopenharmony_ci    if (!parser_eof(sfp)) {
9911cb0ef41Sopenharmony_ci      return SF_ERR_PARSE_ERROR;
9921cb0ef41Sopenharmony_ci    }
9931cb0ef41Sopenharmony_ci
9941cb0ef41Sopenharmony_ci    return SF_ERR_EOF;
9951cb0ef41Sopenharmony_ci  default:
9961cb0ef41Sopenharmony_ci    assert(0);
9971cb0ef41Sopenharmony_ci    abort();
9981cb0ef41Sopenharmony_ci  }
9991cb0ef41Sopenharmony_ci
10001cb0ef41Sopenharmony_ci  if (*sfp->pos == '(') {
10011cb0ef41Sopenharmony_ci    if (dest) {
10021cb0ef41Sopenharmony_ci      dest->type = SF_TYPE_INNER_LIST;
10031cb0ef41Sopenharmony_ci      dest->flags = SF_VALUE_FLAG_NONE;
10041cb0ef41Sopenharmony_ci    }
10051cb0ef41Sopenharmony_ci
10061cb0ef41Sopenharmony_ci    ++sfp->pos;
10071cb0ef41Sopenharmony_ci
10081cb0ef41Sopenharmony_ci    sfp->state = SF_STATE_ITEM_INNER_LIST_BEFORE;
10091cb0ef41Sopenharmony_ci
10101cb0ef41Sopenharmony_ci    return 0;
10111cb0ef41Sopenharmony_ci  }
10121cb0ef41Sopenharmony_ci
10131cb0ef41Sopenharmony_ci  rv = parser_bare_item(sfp, dest);
10141cb0ef41Sopenharmony_ci  if (rv != 0) {
10151cb0ef41Sopenharmony_ci    return rv;
10161cb0ef41Sopenharmony_ci  }
10171cb0ef41Sopenharmony_ci
10181cb0ef41Sopenharmony_ci  sfp->state = SF_STATE_ITEM_BEFORE_PARAMS;
10191cb0ef41Sopenharmony_ci
10201cb0ef41Sopenharmony_ci  return 0;
10211cb0ef41Sopenharmony_ci}
10221cb0ef41Sopenharmony_ci
10231cb0ef41Sopenharmony_civoid sf_parser_init(sf_parser *sfp, const uint8_t *data, size_t datalen) {
10241cb0ef41Sopenharmony_ci  if (datalen == 0) {
10251cb0ef41Sopenharmony_ci    sfp->pos = sfp->end = NULL;
10261cb0ef41Sopenharmony_ci  } else {
10271cb0ef41Sopenharmony_ci    sfp->pos = data;
10281cb0ef41Sopenharmony_ci    sfp->end = data + datalen;
10291cb0ef41Sopenharmony_ci  }
10301cb0ef41Sopenharmony_ci
10311cb0ef41Sopenharmony_ci  sfp->state = SF_STATE_INITIAL;
10321cb0ef41Sopenharmony_ci}
10331cb0ef41Sopenharmony_ci
10341cb0ef41Sopenharmony_civoid sf_unescape(sf_vec *dest, const sf_vec *src) {
10351cb0ef41Sopenharmony_ci  const uint8_t *p, *q;
10361cb0ef41Sopenharmony_ci  uint8_t *o;
10371cb0ef41Sopenharmony_ci  size_t len, slen;
10381cb0ef41Sopenharmony_ci
10391cb0ef41Sopenharmony_ci  if (src->len == 0) {
10401cb0ef41Sopenharmony_ci    *dest = *src;
10411cb0ef41Sopenharmony_ci
10421cb0ef41Sopenharmony_ci    return;
10431cb0ef41Sopenharmony_ci  }
10441cb0ef41Sopenharmony_ci
10451cb0ef41Sopenharmony_ci  o = dest->base;
10461cb0ef41Sopenharmony_ci  p = src->base;
10471cb0ef41Sopenharmony_ci  len = src->len;
10481cb0ef41Sopenharmony_ci
10491cb0ef41Sopenharmony_ci  for (;;) {
10501cb0ef41Sopenharmony_ci    q = memchr(p, '\\', len);
10511cb0ef41Sopenharmony_ci    if (q == NULL) {
10521cb0ef41Sopenharmony_ci      if (len == src->len) {
10531cb0ef41Sopenharmony_ci        *dest = *src;
10541cb0ef41Sopenharmony_ci
10551cb0ef41Sopenharmony_ci        return;
10561cb0ef41Sopenharmony_ci      }
10571cb0ef41Sopenharmony_ci
10581cb0ef41Sopenharmony_ci      memcpy(o, p, len);
10591cb0ef41Sopenharmony_ci      o += len;
10601cb0ef41Sopenharmony_ci
10611cb0ef41Sopenharmony_ci      break;
10621cb0ef41Sopenharmony_ci    }
10631cb0ef41Sopenharmony_ci
10641cb0ef41Sopenharmony_ci    slen = (size_t)(q - p);
10651cb0ef41Sopenharmony_ci    memcpy(o, p, slen);
10661cb0ef41Sopenharmony_ci    o += slen;
10671cb0ef41Sopenharmony_ci
10681cb0ef41Sopenharmony_ci    p = q + 1;
10691cb0ef41Sopenharmony_ci    *o++ = *p++;
10701cb0ef41Sopenharmony_ci    len -= slen + 2;
10711cb0ef41Sopenharmony_ci  }
10721cb0ef41Sopenharmony_ci
10731cb0ef41Sopenharmony_ci  dest->len = (size_t)(o - dest->base);
10741cb0ef41Sopenharmony_ci}
10751cb0ef41Sopenharmony_ci
10761cb0ef41Sopenharmony_civoid sf_base64decode(sf_vec *dest, const sf_vec *src) {
10771cb0ef41Sopenharmony_ci  static const int index_tbl[] = {
10781cb0ef41Sopenharmony_ci      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
10791cb0ef41Sopenharmony_ci      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
10801cb0ef41Sopenharmony_ci      -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57,
10811cb0ef41Sopenharmony_ci      58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0,  1,  2,  3,  4,  5,  6,
10821cb0ef41Sopenharmony_ci      7,  8,  9,  10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
10831cb0ef41Sopenharmony_ci      25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
10841cb0ef41Sopenharmony_ci      37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1,
10851cb0ef41Sopenharmony_ci      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
10861cb0ef41Sopenharmony_ci      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
10871cb0ef41Sopenharmony_ci      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
10881cb0ef41Sopenharmony_ci      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
10891cb0ef41Sopenharmony_ci      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
10901cb0ef41Sopenharmony_ci      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
10911cb0ef41Sopenharmony_ci      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
10921cb0ef41Sopenharmony_ci      -1, -1, -1, -1};
10931cb0ef41Sopenharmony_ci  uint8_t *o;
10941cb0ef41Sopenharmony_ci  const uint8_t *p, *end;
10951cb0ef41Sopenharmony_ci  uint32_t n;
10961cb0ef41Sopenharmony_ci  size_t i;
10971cb0ef41Sopenharmony_ci  int idx;
10981cb0ef41Sopenharmony_ci
10991cb0ef41Sopenharmony_ci  assert((src->len & 0x3) == 0);
11001cb0ef41Sopenharmony_ci
11011cb0ef41Sopenharmony_ci  if (src->len == 0) {
11021cb0ef41Sopenharmony_ci    *dest = *src;
11031cb0ef41Sopenharmony_ci
11041cb0ef41Sopenharmony_ci    return;
11051cb0ef41Sopenharmony_ci  }
11061cb0ef41Sopenharmony_ci
11071cb0ef41Sopenharmony_ci  o = dest->base;
11081cb0ef41Sopenharmony_ci  p = src->base;
11091cb0ef41Sopenharmony_ci  end = src->base + src->len;
11101cb0ef41Sopenharmony_ci
11111cb0ef41Sopenharmony_ci  for (; p != end;) {
11121cb0ef41Sopenharmony_ci    n = 0;
11131cb0ef41Sopenharmony_ci
11141cb0ef41Sopenharmony_ci    for (i = 1; i <= 4; ++i, ++p) {
11151cb0ef41Sopenharmony_ci      idx = index_tbl[*p];
11161cb0ef41Sopenharmony_ci
11171cb0ef41Sopenharmony_ci      if (idx == -1) {
11181cb0ef41Sopenharmony_ci        assert(i > 2);
11191cb0ef41Sopenharmony_ci
11201cb0ef41Sopenharmony_ci        if (i == 3) {
11211cb0ef41Sopenharmony_ci          assert(*p == '=' && *(p + 1) == '=' && p + 2 == end);
11221cb0ef41Sopenharmony_ci
11231cb0ef41Sopenharmony_ci          *o++ = (uint8_t)(n >> 16);
11241cb0ef41Sopenharmony_ci
11251cb0ef41Sopenharmony_ci          goto fin;
11261cb0ef41Sopenharmony_ci        }
11271cb0ef41Sopenharmony_ci
11281cb0ef41Sopenharmony_ci        assert(*p == '=' && p + 1 == end);
11291cb0ef41Sopenharmony_ci
11301cb0ef41Sopenharmony_ci        *o++ = (uint8_t)(n >> 16);
11311cb0ef41Sopenharmony_ci        *o++ = (n >> 8) & 0xffu;
11321cb0ef41Sopenharmony_ci
11331cb0ef41Sopenharmony_ci        goto fin;
11341cb0ef41Sopenharmony_ci      }
11351cb0ef41Sopenharmony_ci
11361cb0ef41Sopenharmony_ci      n += (uint32_t)(idx << (24 - i * 6));
11371cb0ef41Sopenharmony_ci    }
11381cb0ef41Sopenharmony_ci
11391cb0ef41Sopenharmony_ci    *o++ = (uint8_t)(n >> 16);
11401cb0ef41Sopenharmony_ci    *o++ = (n >> 8) & 0xffu;
11411cb0ef41Sopenharmony_ci    *o++ = n & 0xffu;
11421cb0ef41Sopenharmony_ci  }
11431cb0ef41Sopenharmony_ci
11441cb0ef41Sopenharmony_cifin:
11451cb0ef41Sopenharmony_ci  dest->len = (size_t)(o - dest->base);
11461cb0ef41Sopenharmony_ci}
1147