// value = 'null' | 'true' | 'false' | number | string | array | object static int parse_value(struct frozen *f) { int ch = cur(f); if (ch == '"') { TRY(parse_string(f)); } else if (ch == '{') { TRY(parse_object(f)); } else if (ch == '[') { TRY(parse_array(f)); } else if (ch == 'n' && left(f) > 4 && compare(f->cur, "null", 4)) { TRY(capture_ptr(f, f->cur, JSON_TYPE_NULL)); f->cur += 4; capture_len(f, f->num_tokens - 1, f->cur); } else if (ch == 't' && left(f) > 4 && compare(f->cur, "true", 4)) { TRY(capture_ptr(f, f->cur, JSON_TYPE_TRUE)); f->cur += 4; capture_len(f, f->num_tokens - 1, f->cur); } else if (ch == 'f' && left(f) > 5 && compare(f->cur, "false", 5)) { TRY(capture_ptr(f, f->cur, JSON_TYPE_FALSE)); f->cur += 5; capture_len(f, f->num_tokens - 1, f->cur); } else if (is_digit(ch) || (ch == '-' && f->cur + 1 < f->end && is_digit(f->cur[1]))) { TRY(parse_number(f)); } else { return ch == END_OF_STRING ? JSON_STRING_INCOMPLETE : JSON_STRING_INVALID; } return 0; }
static int doit(struct frozen *f) { if (f->cur == 0 || f->end < f->cur) return JSON_STRING_INVALID; if (f->end == f->cur) return JSON_STRING_INCOMPLETE; TRY(parse_object(f)); TRY(capture_ptr(f, f->cur, JSON_TYPE_EOF)); capture_len(f, f->num_tokens, f->cur); return 0; }
// identifier = letter { letter | digit | '_' } static int parse_identifier(struct frozen *f) { EXPECT(is_alpha(cur(f)), JSON_STRING_INVALID); TRY(capture_ptr(f, f->cur, JSON_TYPE_STRING)); while (f->cur < f->end && (*f->cur == '_' || is_alpha(*f->cur) || is_digit(*f->cur))) { f->cur++; } capture_len(f, f->num_tokens - 1, f->cur); return 0; }
// json = object int parse_json(const char *s, int s_len, struct json_token *arr, int arr_len) { struct frozen frozen = { s + s_len, s, arr, arr_len, 0 }; if (s == 0 || s_len < 0) return JSON_STRING_INVALID; if (s_len == 0) return JSON_STRING_INCOMPLETE; TRY(parse_object(&frozen)); TRY(capture_ptr(&frozen, frozen.cur, JSON_TYPE_EOF)); capture_len(&frozen, frozen.num_tokens, frozen.cur); return frozen.cur - s; }
// object = '{' pair { ',' pair } '}' static int parse_object(struct frozen *f) { int ind; TRY(test_and_skip(f, '{')); TRY(capture_ptr(f, f->cur - 1, JSON_TYPE_OBJECT)); ind = f->num_tokens - 1; while (cur(f) != '}') { TRY(parse_pair(f)); if (cur(f) == ',') f->cur++; } TRY(test_and_skip(f, '}')); capture_len(f, ind, f->cur); return 0; }
// array = '[' [ value { ',' value } ] ']' static int parse_array(struct frozen *f) { int ind; TRY(test_and_skip(f, '[')); TRY(capture_ptr(f, f->cur - 1, JSON_TYPE_ARRAY)); ind = f->num_tokens - 1; while (cur(f) != ']') { TRY(parse_value(f)); if (cur(f) == ',') f->cur++; } TRY(test_and_skip(f, ']')); capture_len(f, ind, f->cur); return 0; }
// string = '"' { quoted_printable_chars } '"' static int parse_string(struct frozen *f) { int n, ch = 0, len = 0; TRY(test_and_skip(f, '"')); TRY(capture_ptr(f, f->cur, JSON_TYPE_STRING)); for (; f->cur < f->end; f->cur += len) { ch = * (unsigned char *) f->cur; len = get_utf8_char_len((unsigned char) ch); //printf("[%c] [%d]\n", ch, len); EXPECT(ch >= 32 && len > 0, JSON_STRING_INVALID); // No control chars EXPECT(len < left(f), JSON_STRING_INCOMPLETE); if (ch == '\\') { EXPECT((n = get_escape_len(f->cur + 1, left(f))) > 0, n); len += n; } else if (ch == '"') { capture_len(f, f->num_tokens - 1, f->cur); f->cur++; break; }; } return ch == '"' ? 0 : JSON_STRING_INCOMPLETE; }
// number = [ '-' ] digit+ [ '.' digit+ ] [ ['e'|'E'] ['+'|'-'] digit+ ] static int parse_number(struct frozen *f) { int ch = cur(f); TRY(capture_ptr(f, f->cur, JSON_TYPE_NUMBER)); if (ch == '-') f->cur++; EXPECT(f->cur < f->end, JSON_STRING_INCOMPLETE); EXPECT(is_digit(f->cur[0]), JSON_STRING_INVALID); while (f->cur < f->end && is_digit(f->cur[0])) f->cur++; if (f->cur < f->end && f->cur[0] == '.') { f->cur++; EXPECT(f->cur < f->end, JSON_STRING_INCOMPLETE); EXPECT(is_digit(f->cur[0]), JSON_STRING_INVALID); while (f->cur < f->end && is_digit(f->cur[0])) f->cur++; } if (f->cur < f->end && (f->cur[0] == 'e' || f->cur[0] == 'E')) { f->cur++; EXPECT(f->cur < f->end, JSON_STRING_INCOMPLETE); if ((f->cur[0] == '+' || f->cur[0] == '-')) f->cur++; EXPECT(f->cur < f->end, JSON_STRING_INCOMPLETE); EXPECT(is_digit(f->cur[0]), JSON_STRING_INVALID); while (f->cur < f->end && is_digit(f->cur[0])) f->cur++; } capture_len(f, f->num_tokens - 1, f->cur); return 0; }
void test_mm_align16(int p) { _MM_ALIGN16 int i; capture_ptr(&i); }