mirror of
https://github.com/cesanta/mongoose.git
synced 2025-01-19 08:03:14 +08:00
Import frozen
PUBLISHED_FROM=9f6f38e92b5952b9571d73569c2752b6805f15c5
This commit is contained in:
parent
59bc2af4d6
commit
bda05d9372
159
mongoose.c
159
mongoose.c
@ -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 {
|
|||||||
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) {
|
||||||
@ -601,7 +608,18 @@ static int cur(struct frozen *f) {
|
|||||||
|
|
||||||
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) {
|
|||||||
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) {
|
|||||||
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
|||||||
}
|
}
|
||||||
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) {
|
|||||||
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,8 +1047,16 @@ 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;
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user