File tree Expand file tree Collapse file tree 5 files changed +12
-12
lines changed Expand file tree Collapse file tree 5 files changed +12
-12
lines changed Original file line number Diff line number Diff line change 3838
3939本教程预计分为 9 个单元,第 1-8 个单元附带练习和解答。
4040
41- 1 . [ 启程] ( tutorial01/tutorial01.md ) (2016/9/15 完成):编译环境、JSON 简介、测试驱动、解析器主要函数及各数据结构。练习 JSON 布尔类型的解析。[ 启程解答编 ] ( tutorial01_answer/tutorial01_answer.md ) (2016/9/17 完成)。
42- 2 . [ 解析数字] ( tutorial02/tutorial02.md ) (2016/9/18 完成):JSON number 的语法。练习 JSON number 类型的校验。[ 解析数字解答编 ] ( tutorial02_answer/tutorial02_answer.md ) (2016/9/20 完成)。
43- 3 . [ 解析字符串] ( tutorial03/tutorial03.md ) (2016/9/22 完成):使用 union 存储 variant、自动扩展的堆栈、JSON string 的语法、valgrind。练习最基本的 JSON string 类型的解析、内存释放。
41+ 1 . [ 启程] ( tutorial01/tutorial01.md ) (2016/9/15 完成):编译环境、JSON 简介、测试驱动、解析器主要函数及各数据结构。练习 JSON 布尔类型的解析。[ 启程解答篇 ] ( tutorial01_answer/tutorial01_answer.md ) (2016/9/17 完成)。
42+ 2 . [ 解析数字] ( tutorial02/tutorial02.md ) (2016/9/18 完成):JSON number 的语法。练习 JSON number 类型的校验。[ 解析数字解答篇 ] ( tutorial02_answer/tutorial02_answer.md ) (2016/9/20 完成)。
43+ 3 . [ 解析字符串] ( tutorial03/tutorial03.md ) (2016/9/22 完成):使用 union 存储 variant、自动扩展的堆栈、JSON string 的语法、valgrind。练习最基本的 JSON string 类型的解析、内存释放。[ 解析字符串解答篇 ] ( tutorial03_answer/tutorial03_answer.md ) (2016/9/27 完成)。
44444 . Unicode:Unicode 和 UTF-8 的基本知识、JSON string 的 unicode 处理。练习完成 JSON string 类型的解析。
45455 . 解析数组:JSON array 的语法。练习完成 JSON array 类型的解析、相关内存释放。
46466 . 解析对象:JSON object 的语法、重构 string 解析函数。练习完成 JSON object 的解析、相关内存释放。
Original file line number Diff line number Diff line change @@ -96,7 +96,7 @@ static int lept_parse_string(lept_context* c, lept_value* v) {
9696 switch (ch ) {
9797 case '\"' :
9898 len = c -> top - head ;
99- lept_set_string (v , lept_context_pop (c , len ), len );
99+ lept_set_string (v , ( const char * ) lept_context_pop (c , len ), len );
100100 c -> json = p ;
101101 return LEPT_PARSE_OK ;
102102 case '\0' :
Original file line number Diff line number Diff line change @@ -197,7 +197,7 @@ int lept_parse(lept_value* v, const char* json) {
197197
198198然后,我们实现堆栈的压入及弹出操作。和普通的堆栈不一样,我们这个堆栈是以字节储存的。每次可要求压入任意大小的数据,它会返回数据起始的指针(会 C++ 的同学可再参考[1]):
199199
200- ~~~
200+ ~~~c
201201#ifndef LEPT_PARSE_STACK_INIT_SIZE
202202#define LEPT_PARSE_STACK_INIT_SIZE 256
203203#endif
@@ -246,7 +246,7 @@ static int lept_parse_string(lept_context* c, lept_value* v) {
246246 switch (ch) {
247247 case '\" ':
248248 len = c->top - head;
249- lept_set_string(v, lept_context_pop(c, len), len);
249+ lept_set_string(v, (const char * ) lept_context_pop(c, len), len);
250250 c->json = p;
251251 return LEPT_PARSE_OK;
252252 case '\0':
Original file line number Diff line number Diff line change @@ -100,7 +100,7 @@ static int lept_parse_string(lept_context* c, lept_value* v) {
100100 switch (ch ) {
101101 case '\"' :
102102 len = c -> top - head ;
103- lept_set_string (v , lept_context_pop (c , len ), len );
103+ lept_set_string (v , ( const char * ) lept_context_pop (c , len ), len );
104104 c -> json = p ;
105105 return LEPT_PARSE_OK ;
106106 case '\\' :
Original file line number Diff line number Diff line change 1- # 从零开始的 JSON 库教程(三):解析字符串解答编
1+ # 从零开始的 JSON 库教程(三):解析字符串解答篇
22
33* Milo Yip
4- * 2016/9/24
4+ * 2016/9/27
55
66本文是[ 《从零开始的 JSON 库教程》] ( https://zhuanlan.zhihu.com/json-tutorial ) 的第三个单元解答编。解答代码位于 [ json-tutorial/tutorial03_answer] ( https://github.com/miloyip/json-tutorial/blob/master/tutorial03_answer ) 。
77
@@ -101,7 +101,7 @@ C:\GitHub\json-tutorial\tutorial03_answer\leptjson.c(212) : {79} normal block at
101101Object dump complete.
102102~~~
103103
104- 这正是我们在单元测试中,先设置字符串,然后设布尔值时设释放字符串所分配的内存 。比较麻烦的是,它没有显示调用堆栈。从输出信息中 ` ... {79} ... ` 我们知道是第 79 次分配的内存做成问题,我们可以加上 ` _CrtSetBreakAlloc(79); ` 来调试,那么它便会在第 79 次时中断于分配调用的位置,那时候就能从调用堆栈去找出来龙去脉。
104+ 这正是我们在单元测试中,先设置字符串,然后设布尔值时没释放字符串所分配的内存 。比较麻烦的是,它没有显示调用堆栈。从输出信息中 ` ... {79} ... ` 我们知道是第 79 次分配的内存做成问题,我们可以加上 ` _CrtSetBreakAlloc(79); ` 来调试,那么它便会在第 79 次时中断于分配调用的位置,那时候就能从调用堆栈去找出来龙去脉。
105105
106106## 1B. Linux/OSX 下的内存泄漏检测方法
107107
@@ -221,8 +221,8 @@ unescaped = %x20-21 / %x23-5B / %x5D-10FFFF
221221
222222这是本教程第一次的开放式问题,没有标准答案。以下列出一些我想到的。
223223
224- 1 . 如果整个字符串都没有转义符,我们不就是把字符复制了两次?第一次是从 ` json ` 到 ` stack ` ,第二次是从 ` stack ` 到 ` v->u.s.s ` 。我们可以在 ` json ` 扫瞄 ` '\0' ` 、` '\"' ` 和 ` '\\' ` 3 个字符( ` ch < 0x20 ` 还是要检查),直至它们其中一个出现,才开始用现在的解析方法。这样做的话,前半没转义的部分可以只复制一次。缺点是,代码变得复杂一些,我们也不能使用 ` lept_set_string() ` 。
225- 2 . 对于扫瞄没转义部分 ,我们可考虑用 SIMD 加速,如 [ RapidJSON 代码剖析(二):使用 SSE4.2 优化字符串扫描] ( https://zhuanlan.zhihu.com/p/20037058 ) 的做法。这类底层优化的缺点是不跨平台,需要设置编译选项等。
224+ 1 . 如果整个字符串都没有转义符,我们不就是把字符复制了两次?第一次是从 ` json ` 到 ` stack ` ,第二次是从 ` stack ` 到 ` v->u.s.s ` 。我们可以在 ` json ` 扫描 ` '\0' ` 、` '\"' ` 和 ` '\\' ` 3 个字符( ` ch < 0x20 ` 还是要检查),直至它们其中一个出现,才开始用现在的解析方法。这样做的话,前半没转义的部分可以只复制一次。缺点是,代码变得复杂一些,我们也不能使用 ` lept_set_string() ` 。
225+ 2 . 对于扫描没转义部分 ,我们可考虑用 SIMD 加速,如 [ RapidJSON 代码剖析(二):使用 SSE4.2 优化字符串扫描] ( https://zhuanlan.zhihu.com/p/20037058 ) 的做法。这类底层优化的缺点是不跨平台,需要设置编译选项等。
2262263 . 在 gcc/clang 上使用 ` __builtin_expect() ` 指令来处理低概率事件,例如需要对每个字符做 ` LEPT_PARSE_INVALID_STRING_CHAR ` 检测,我们可以假设出现不合法字符是低概率事件,然后用这个指令告之编译器,那么编译器可能可生成较快的代码。然而,这类做法明显是不跨编译器,甚至是某个版本后的 gcc 才支持。
227227
228228## 5. 总结
You can’t perform that action at this time.
0 commit comments