github.com/bytedance/sonic@v1.11.7-0.20240517092252-d2edb31b167b/native/get_by_path.c (about)

     1  #include "scanning.h"
     2  
     3  long get_by_path(const GoString *src, long *p, const GoSlice *path, StateMachine* sm) {
     4      GoIface *ps = (GoIface*)(path->buf);
     5      GoIface *pe = (GoIface*)(path->buf) + path->len;
     6      char c = 0;
     7      int64_t index;
     8      long found;
     9  
    10  query:
    11      /* to be safer for invalid json, use slower skip for the demanded fields */
    12      if (ps == pe) {
    13          if (sm == NULL) {
    14              return skip_one_fast_1(src, p);
    15          }
    16          return skip_one_1(src, p, sm, 0);
    17      }
    18  
    19      /* match type: should query key in object, query index in array */
    20      c = advance_ns(src, p);
    21      if (is_str(ps)) {
    22          if (c != '{') {
    23              goto err_inval;
    24          }
    25          goto skip_in_obj;
    26      } else if (is_int(ps)) {
    27          if (c != '[') {
    28              goto err_inval;
    29          }
    30  
    31          index = get_int(ps);
    32          if (index < 0) {
    33              goto err_path;
    34          }
    35  
    36          goto skip_in_arr;
    37      } else {
    38          goto err_path;
    39      }
    40  
    41  skip_in_obj:
    42      c = advance_ns(src, p);
    43      if (c == '}') {
    44          goto not_found;
    45      }
    46      if (c != '"') {
    47          goto err_inval;
    48      }
    49  
    50      /* parse the object key */
    51      found = match_key(src, p, get_str(ps));
    52      if (found < 0) {
    53          return found; // parse string errors
    54      }
    55  
    56      /* value should after : */
    57      c = advance_ns(src, p);
    58      if (c != ':') {
    59          goto err_inval;
    60      }
    61      if (found) {
    62          ps++;
    63          goto query;
    64      }
    65  
    66      /* skip the unknown fields */
    67      skip_one_fast_1(src, p);
    68      c = advance_ns(src, p);
    69      if (c == '}') {
    70          goto not_found;
    71      }
    72      if (c != ',') {
    73          goto err_inval;
    74      }
    75      goto skip_in_obj;
    76  
    77  skip_in_arr:
    78      /* check empty array */
    79      c = advance_ns(src, p);
    80      if (c == ']') {
    81          goto not_found;
    82      }
    83      *p -= 1;
    84  
    85      /* skip array elem one by one */
    86      while (index-- > 0) {
    87          skip_one_fast_1(src, p);
    88          c = advance_ns(src, p);
    89          if (c == ']') {
    90              goto not_found;
    91          }
    92          if (c != ',') {
    93              goto err_inval;
    94          }
    95      }
    96      ps++;
    97      goto query;
    98  
    99  not_found:
   100      *p -= 1; // backward error position
   101      return -ERR_NOT_FOUND;
   102  err_inval:
   103      *p -= 1;
   104      return -ERR_INVAL;
   105  err_path:
   106      *p -= 1;
   107      return -ERR_UNSUPPORT_TYPE;
   108  }