Commit bda05d93 authored by Marko Mikulicic's avatar Marko Mikulicic

Import frozen

    PUBLISHED_FROM=9f6f38e92b5952b9571d73569c2752b6805f15c5
parent 59bc2af4
...@@ -543,7 +543,7 @@ double cs_time() { ...@@ -543,7 +543,7 @@ double cs_time() {
* See the GNU General Public License for more details. * See the GNU General Public License for more details.
* *
* Alternatively, you can license this library under a commercial * Alternatively, you can license this library under a commercial
* license, as set out in <https://www.cesanta.com/license>. * license, as set out in <http://cesanta.com/products.html>.
*/ */
#define _CRT_SECURE_NO_WARNINGS /* Disable deprecation warning in VS2005+ */ #define _CRT_SECURE_NO_WARNINGS /* Disable deprecation warning in VS2005+ */
...@@ -578,8 +578,15 @@ struct frozen { ...@@ -578,8 +578,15 @@ struct frozen {
static int parse_object(struct frozen *f); static int parse_object(struct frozen *f);
static int parse_value(struct frozen *f); static int parse_value(struct frozen *f);
#define EXPECT(cond, err_code) do { if (!(cond)) return (err_code); } while (0) #define EXPECT(cond, err_code) \
#define TRY(expr) do { int _n = expr; if (_n < 0) return _n; } while (0) do { \
if (!(cond)) return (err_code); \
} while (0)
#define TRY(expr) \
do { \
int _n = expr; \
if (_n < 0) return _n; \
} while (0)
#define END_OF_STRING (-1) #define END_OF_STRING (-1)
static int left(const struct frozen *f) { static int left(const struct frozen *f) {
...@@ -596,12 +603,23 @@ static void skip_whitespaces(struct frozen *f) { ...@@ -596,12 +603,23 @@ static void skip_whitespaces(struct frozen *f) {
static int cur(struct frozen *f) { static int cur(struct frozen *f) {
skip_whitespaces(f); skip_whitespaces(f);
return f->cur >= f->end ? END_OF_STRING : * (unsigned char *) f->cur; return f->cur >= f->end ? END_OF_STRING : *(unsigned char *) f->cur;
} }
static int test_and_skip(struct frozen *f, int expected) { static int test_and_skip(struct frozen *f, int expected) {
int ch = cur(f); int ch = cur(f);
if (ch == expected) { f->cur++; return 0; } if (ch == expected) {
f->cur++;
return 0;
}
return ch == END_OF_STRING ? JSON_STRING_INCOMPLETE : JSON_STRING_INVALID;
}
static int test_no_skip(struct frozen *f, int expected) {
int ch = cur(f);
if (ch == expected) {
return 0;
}
return ch == END_OF_STRING ? JSON_STRING_INCOMPLETE : JSON_STRING_INVALID; return ch == END_OF_STRING ? JSON_STRING_INCOMPLETE : JSON_STRING_INVALID;
} }
...@@ -620,11 +638,19 @@ static int is_hex_digit(int ch) { ...@@ -620,11 +638,19 @@ static int is_hex_digit(int ch) {
static int get_escape_len(const char *s, int len) { static int get_escape_len(const char *s, int len) {
switch (*s) { switch (*s) {
case 'u': case 'u':
return len < 6 ? JSON_STRING_INCOMPLETE : return len < 6 ? JSON_STRING_INCOMPLETE
is_hex_digit(s[1]) && is_hex_digit(s[2]) && : is_hex_digit(s[1]) && is_hex_digit(s[2]) &&
is_hex_digit(s[3]) && is_hex_digit(s[4]) ? 5 : JSON_STRING_INVALID; is_hex_digit(s[3]) && is_hex_digit(s[4])
case '"': case '\\': case '/': case 'b': ? 5
case 'f': case 'n': case 'r': case 't': : JSON_STRING_INVALID;
case '"':
case '\\':
case '/':
case 'b':
case 'f':
case 'n':
case 'r':
case 't':
return len < 2 ? JSON_STRING_INCOMPLETE : 1; return len < 2 ? JSON_STRING_INCOMPLETE : 1;
default: default:
return JSON_STRING_INVALID; return JSON_STRING_INVALID;
...@@ -670,9 +696,12 @@ static int parse_identifier(struct frozen *f) { ...@@ -670,9 +696,12 @@ static int parse_identifier(struct frozen *f) {
static int get_utf8_char_len(unsigned char ch) { static int get_utf8_char_len(unsigned char ch) {
if ((ch & 0x80) == 0) return 1; if ((ch & 0x80) == 0) return 1;
switch (ch & 0xf0) { switch (ch & 0xf0) {
case 0xf0: return 4; case 0xf0:
case 0xe0: return 3; return 4;
default: return 2; case 0xe0:
return 3;
default:
return 2;
} }
} }
...@@ -682,7 +711,7 @@ static int parse_string(struct frozen *f) { ...@@ -682,7 +711,7 @@ static int parse_string(struct frozen *f) {
TRY(test_and_skip(f, '"')); TRY(test_and_skip(f, '"'));
TRY(capture_ptr(f, f->cur, JSON_TYPE_STRING)); TRY(capture_ptr(f, f->cur, JSON_TYPE_STRING));
for (; f->cur < f->end; f->cur += len) { for (; f->cur < f->end; f->cur += len) {
ch = * (unsigned char *) f->cur; ch = *(unsigned char *) f->cur;
len = get_utf8_char_len((unsigned char) ch); len = get_utf8_char_len((unsigned char) ch);
EXPECT(ch >= 32 && len > 0, JSON_STRING_INVALID); /* No control chars */ EXPECT(ch >= 32 && len > 0, JSON_STRING_INVALID); /* No control chars */
EXPECT(len < left(f), JSON_STRING_INCOMPLETE); EXPECT(len < left(f), JSON_STRING_INCOMPLETE);
...@@ -764,14 +793,35 @@ static int parse_value(struct frozen *f) { ...@@ -764,14 +793,35 @@ static int parse_value(struct frozen *f) {
int ch = cur(f); int ch = cur(f);
switch (ch) { switch (ch) {
case '"': TRY(parse_string(f)); break; case '"':
case '{': TRY(parse_object(f)); break; TRY(parse_string(f));
case '[': TRY(parse_array(f)); break; break;
case 'n': TRY(expect(f, "null", 4, JSON_TYPE_NULL)); break; case '{':
case 't': TRY(expect(f, "true", 4, JSON_TYPE_TRUE)); break; TRY(parse_object(f));
case 'f': TRY(expect(f, "false", 5, JSON_TYPE_FALSE)); break; break;
case '-': case '0': case '1': case '2': case '3': case '4': case '[':
case '5': case '6': case '7': case '8': case '9': TRY(parse_array(f));
break;
case 'n':
TRY(expect(f, "null", 4, JSON_TYPE_NULL));
break;
case 't':
TRY(expect(f, "true", 4, JSON_TYPE_TRUE));
break;
case 'f':
TRY(expect(f, "false", 5, JSON_TYPE_FALSE));
break;
case '-':
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
TRY(parse_number(f)); TRY(parse_number(f));
break; break;
default: default:
...@@ -821,9 +871,19 @@ static int parse_object(struct frozen *f) { ...@@ -821,9 +871,19 @@ static int parse_object(struct frozen *f) {
} }
static int doit(struct frozen *f) { static int doit(struct frozen *f) {
int ret = 0;
if (f->cur == 0 || f->end < f->cur) return JSON_STRING_INVALID; if (f->cur == 0 || f->end < f->cur) return JSON_STRING_INVALID;
if (f->end == f->cur) return JSON_STRING_INCOMPLETE; if (f->end == f->cur) return JSON_STRING_INCOMPLETE;
if (0 == (ret = test_no_skip(f, '{'))) {
TRY(parse_object(f)); TRY(parse_object(f));
} else if (0 == (ret = test_no_skip(f, '['))) {
TRY(parse_array(f));
} else {
return ret;
}
TRY(capture_ptr(f, f->cur, JSON_TYPE_EOF)); TRY(capture_ptr(f, f->cur, JSON_TYPE_EOF));
capture_len(f, f->num_tokens, f->cur); capture_len(f, f->num_tokens, f->cur);
return 0; return 0;
...@@ -877,7 +937,8 @@ struct json_token *find_json_token(struct json_token *toks, const char *path) { ...@@ -877,7 +937,8 @@ struct json_token *find_json_token(struct json_token *toks, const char *path) {
} }
if (path[n++] != ']') return 0; if (path[n++] != ']') return 0;
skip = 1; /* In objects, we skip 2 elems while iterating, in arrays 1. */ skip = 1; /* In objects, we skip 2 elems while iterating, in arrays 1. */
} else if (toks->type != JSON_TYPE_OBJECT) return 0; } else if (toks->type != JSON_TYPE_OBJECT)
return 0;
toks++; toks++;
for (i = 0; i < toks[-1].num_desc; i += skip, ind2++) { for (i = 0; i < toks[-1].num_desc; i += skip, ind2++) {
/* ind == -1 indicated that we're iterating an array, not object */ /* ind == -1 indicated that we're iterating an array, not object */
...@@ -919,20 +980,46 @@ int json_emit_quoted_str(char *s, int s_len, const char *str, int len) { ...@@ -919,20 +980,46 @@ int json_emit_quoted_str(char *s, int s_len, const char *str, int len) {
const char *begin = s, *end = s + s_len, *str_end = str + len; const char *begin = s, *end = s + s_len, *str_end = str + len;
char ch; char ch;
#define EMIT(x) do { if (s < end) *s = x; s++; } while (0) #define EMIT(x) \
do { \
if (s < end) *s = x; \
s++; \
} while (0)
EMIT('"'); EMIT('"');
while (str < str_end) { while (str < str_end) {
ch = *str++; ch = *str++;
switch (ch) { switch (ch) {
case '"': EMIT('\\'); EMIT('"'); break; case '"':
case '\\': EMIT('\\'); EMIT('\\'); break; EMIT('\\');
case '\b': EMIT('\\'); EMIT('b'); break; EMIT('"');
case '\f': EMIT('\\'); EMIT('f'); break; break;
case '\n': EMIT('\\'); EMIT('n'); break; case '\\':
case '\r': EMIT('\\'); EMIT('r'); break; EMIT('\\');
case '\t': EMIT('\\'); EMIT('t'); break; EMIT('\\');
default: EMIT(ch); break;
case '\b':
EMIT('\\');
EMIT('b');
break;
case '\f':
EMIT('\\');
EMIT('f');
break;
case '\n':
EMIT('\\');
EMIT('n');
break;
case '\r':
EMIT('\\');
EMIT('r');
break;
case '\t':
EMIT('\\');
EMIT('t');
break;
default:
EMIT(ch);
} }
} }
EMIT('"'); EMIT('"');
...@@ -960,18 +1047,26 @@ int json_emit_va(char *s, int s_len, const char *fmt, va_list ap) { ...@@ -960,18 +1047,26 @@ int json_emit_va(char *s, int s_len, const char *fmt, va_list ap) {
while (*fmt != '\0') { while (*fmt != '\0') {
switch (*fmt) { switch (*fmt) {
case '[': case ']': case '{': case '}': case ',': case ':': case '[':
case ' ': case '\r': case '\n': case '\t': case ']':
case '{':
case '}':
case ',':
case ':':
case ' ':
case '\r':
case '\n':
case '\t':
if (s < end) { if (s < end) {
*s = *fmt; *s = *fmt;
} }
s++; s++;
break; break;
case 'i': case 'i':
s += json_emit_long(s, end - s, va_arg(ap, long)); s += json_emit_long(s, end - s, va_arg(ap, long) );
break; break;
case 'f': case 'f':
s += json_emit_double(s, end - s, va_arg(ap, double)); s += json_emit_double(s, end - s, va_arg(ap, double) );
break; break;
case 'v': case 'v':
str = va_arg(ap, char *); str = va_arg(ap, char *);
......
...@@ -840,7 +840,7 @@ size_t strnlen(const char *s, size_t maxlen); ...@@ -840,7 +840,7 @@ size_t strnlen(const char *s, size_t maxlen);
* See the GNU General Public License for more details. * See the GNU General Public License for more details.
* *
* Alternatively, you can license this library under a commercial * Alternatively, you can license this library under a commercial
* license, as set out in <https://www.cesanta.com/license>. * license, as set out in <http://cesanta.com/products.html>.
*/ */
#ifndef FROZEN_HEADER_INCLUDED #ifndef FROZEN_HEADER_INCLUDED
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment