leptjson note2
Table of Contents
leptjson note2 #
从零开始的 JSON 库教程 笔记.
重构 #
使用宏的方式简化重复部分高的函数.
JSON 数字语法 #
JSON number 类型的语法如下:
number = [ "-" ] int [ frac ] [ exp ]
int = "0" / digit1-9 *digit
frac = "." 1*digit
exp = ("e" / "E") ["-" / "+"] 1*digit
number 以十进制表示, 由四部分组成:
- 负号, 注意这部分里正号是不合法的
- 整数, 这部分是必需的
- 小数
- 指数, 指数部分由大写 E 或小写 e 开始, 之后可有正负号, 之后是一或多个数字 (0-9)
数字表示方式 #
用双精度浮点数存储 JSON 中的数字.
为 lept_value
添加成员:
typedef struct {
double n;
lept_type type;
}lept_value;
只有当 type == LEPT_NUMBER
时, n
才表示 JSON 数字的数值. 因此, 获取该值的 API 如下:
double lept_get_number(const lept_value* v) {
assert(v != NULL && v->type == LEPT_NUMBER);
return v->n;
}
用断言来保证调用 API 时类型正确.
单元测试 #
十进制转换至二进制 #
把十进制表示的字符串转换为二进制的 double
. 为了简单起见, 使用标准库的 strtod
来进行转换.
- C 库函数
double strtod(const char *str, char **endptr)
把参数str
所指向的字符串转换为一个浮点数 (类型为double
型) . 如果endptr
不为空, 则指向转换中最后一个字符后的字符的指针会存储在endptr
引用的位置. - 该函数返回转换后的双精度浮点数. 如果没有执行有效的转换, 则返回零 (0.0) .
strtod
可转换 JSON 所要求的格式, 但一些 JSON 不容许的格式, strtod
也可转换, 因此需要自行进行格式校验.
# include <stdlib.h> /* NULL, strtod() */
static int lept_parse_number(lept_context* c, lept_value* v) {
char* end;
/* \TODO validate number */
v->n = strtod(c->json, &end);
if (c->json == end) // end 指向位置与原指针相同, 转换失败
return LEPT_PARSE_INVALID_VALUE;
c->json = end; // 指向数字后的字符串
v->type = LEPT_NUMBER;
return LEPT_PARSE_OK;
}
由于 lept_parse_number()
内部将会校验输入是否正确的值, 因此 lept_parse_value()
可以这样编写:
static int lept_parse_value(lept_context* c, lept_value* v) {
switch (*c->json) {
case 't': return lept_parse_true(c, v);
case 'f': return lept_parse_false(c, v);
case 'n': return lept_parse_null(c, v);
default: return lept_parse_number(c, v);
case '\0': return LEPT_PARSE_EXPECT_VALUE;
}
}