1
2
3
4
5
6
7
typedef enum { LEPT_NULL,
LEPT_FALSE,
LEPT_TRUE,
LEPT_NUMBER,
LEPT_STRING,
LEPT_ARRAY,
LEPT_OBJECT } lept_type;

json数据分为 null,true,false,number,string,array,object这几个类型,用枚举存放

lept_value 存放解析好的json串 lept_type表示解析好的json类型

lept_member 代表json成员

1
2
3
4
5
6
7
8
9
10
11
12
13
struct lept_value {
union {
struct { lept_member* m; size_t size; }o; /* object: members, member count */
struct { lept_value* e; size_t size; }a; /* array: elements, element count */
struct { char* s; size_t len; }s; /* string: null-terminated string, string length */
double n; /* number */
}u;
lept_type type;
};
struct lept_member {
char* k; size_t klen; /* member key string, key string length */
lept_value v; /* member value */
};

lept_context

json代表解析的串

stack代表栈

size 表示栈的大小

top 表示栈顶指针

1
2
3
4
5
typedef struct {
const char *json;
char *stack;
size_t size, top;
} lept_context;

json语法

1
2
JSON-text = ws value ws
ws = *(%x20 / %x09 / %x0A / %x0D)

在value前后有一些空白字符,需要处理掉

1
2
3
4
5
6
static void lept_parse_whitespace(lept_context *c) {
const char *p = c->json;
while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r')
p++;
c->json = p;
}

lept_parse()

传入json串,将解析好的json数据存在v中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
int lept_parse(lept_value *v, const char *json) {
lept_context c;
int ret;
assert(v != NULL);
c.json = json;
c.stack = NULL;
c.size = c.top = 0;
lept_init(v);
lept_parse_whitespace(&c);
if ((ret = lept_parse_value(&c, v)) == LEPT_PARSE_OK) { //进行解析,ret为返回值
lept_parse_whitespace(&c);
if (*c.json != '\0') { //如果解析后json串还有东西,代表语法错误
v->type = LEPT_NULL;
ret = LEPT_PARSE_ROOT_NOT_SINGULAR;
}
}
assert(c.top == 0);
free(c.stack);
return ret;
}

lept_parse_value()

查看当前json解析位置,是否为以下字符,分别进入相应的解析函数

1
2
3
4
5
6
7
8
9
10
11
12
static int lept_parse_value(lept_context *c, lept_value *v) {
switch (*c->json) {
case 't': return lept_parse_literal(c, v, "true", LEPT_TRUE);
case 'f': return lept_parse_literal(c, v, "false", LEPT_FALSE);
case 'n': return lept_parse_literal(c, v, "null", LEPT_NULL);
default: return lept_parse_number(c, v);
case '"': return lept_parse_string(c, v);
case '[': return lept_parse_array(c, v);
case '{': return lept_parse_object(c, v);
case '\0': return LEPT_PARSE_EXPECT_VALUE;
}
}

lept_parse_literal() : 查看此时c->json位置是否与literal一样(检查null,true,false)

1
2
3
4
5
6
7
8
9
10
static int lept_parse_literal(lept_context *c, lept_value *v, const char *literal, lept_type type) {
size_t i;
EXPECT(c, literal[0]);
for (i = 0; literal[i + 1]; i++)
if (c->json[i] != literal[i + 1])
return LEPT_PARSE_INVALID_VALUE;
c->json += i;
v->type = type;
return LEPT_PARSE_OK;
}

lept_parse_number() : 查看此时是否符合number标准

1
2
3
4
number = [ "-" ] int [ frac ] [ exp ]
int = "0" / digit1-9 *digit
frac = "." 1*digit
exp = ("e" / "E") ["-" / "+"] 1*digit

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
static int lept_parse_number(lept_context *c, lept_value *v) {
const char *p = c->json;
if (*p == '-') p++;
if (*p == '0')
p++;
else {
if (!ISDIGIT1TO9(*p)) return LEPT_PARSE_INVALID_VALUE;
for (p++; ISDIGIT(*p); p++);
}
if (*p == '.') {
p++;
if (!ISDIGIT(*p)) return LEPT_PARSE_INVALID_VALUE;
for (p++; ISDIGIT(*p); p++);
}
if (*p == 'e' || *p == 'E') {
p++;
if (*p == '+' || *p == '-') p++;
if (!ISDIGIT(*p)) return LEPT_PARSE_INVALID_VALUE;
for (p++; ISDIGIT(*p); p++);
}
errno = 0;
v->u.n = strtod(c->json, NULL);
if (errno == ERANGE && (v->u.n == HUGE_VAL || v->u.n == -HUGE_VAL))
return LEPT_PARSE_NUMBER_TOO_BIG;
v->type = LEPT_NUMBER;
c->json = p;
return LEPT_PARSE_OK;
}

lept_parse_string_raw() : 将c->json的字符串复制到*str指向的位置上,长度为len

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
static int lept_parse_string_raw(lept_context *c, char **str, size_t *len) {
size_t head = c->top;
unsigned u, u2;
const char *p;
EXPECT(c, '\"');
p = c->json;
for (;;) {
char ch = *p++;
switch (ch) {
case '\"':
*len = c->top - head;
*str = lept_context_pop(c, *len);
c->json = p;
return LEPT_PARSE_OK;
case '\\':
switch (*p++) {
case '\"': PUTC(c, '\"'); break;
case '\\': PUTC(c, '\\'); break;
case '/': PUTC(c, '/'); break;
case 'b': PUTC(c, '\b'); break;
case 'f': PUTC(c, '\f'); break;
case 'n': PUTC(c, '\n'); break;
case 'r': PUTC(c, '\r'); break;
case 't': PUTC(c, '\t'); break;
case 'u':
if (!(p = lept_parse_hex4(p, &u)))
STRING_ERROR(LEPT_PARSE_INVALID_UNICODE_HEX);
if (u >= 0xD800 && u <= 0xDBFF) { /* surrogate pair */
if (*p++ != '\\')
STRING_ERROR(LEPT_PARSE_INVALID_UNICODE_SURROGATE);
if (*p++ != 'u')
STRING_ERROR(LEPT_PARSE_INVALID_UNICODE_SURROGATE);
if (!(p = lept_parse_hex4(p, &u2)))
STRING_ERROR(LEPT_PARSE_INVALID_UNICODE_HEX);
if (u2 < 0xDC00 || u2 > 0xDFFF)
STRING_ERROR(LEPT_PARSE_INVALID_UNICODE_SURROGATE);
u = (((u - 0xD800) << 10) | (u2 - 0xDC00)) + 0x10000;
}
lept_encode_utf8(c, u);
break;
default:
STRING_ERROR(LEPT_PARSE_INVALID_STRING_ESCAPE);
}
break;
case '\0':
STRING_ERROR(LEPT_PARSE_MISS_QUOTATION_MARK);
default:
if ((unsigned char)ch < 0x20)
STRING_ERROR(LEPT_PARSE_INVALID_STRING_CHAR);
PUTC(c, ch);
}
}
}