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 }