lept_json的学习之stringify
lept_json的學(xué)習(xí)之stringify
這一節(jié)我們講解所有類型的生成Stringify。
其實(shí)stringify的意思本不是生成,而是字符串化,但為了方便理解,我直接稱之為生成(generate)也是可以的。
Stringify
生成器它生成得好,可以生成出很整潔的字符串,方便我們閱讀,不過在這里我們只進(jìn)行字符生成,不進(jìn)行排版操作,所以最后生成出來的就是一長串的擠在一行里的字符串。
在這里我們也能想到,生成器的操作就是解析器反過來,所以它大致的架構(gòu)也是一個循環(huán)里套一個switch語句。
這里為了代碼的美觀我們也是像parse和parse_value那樣將stringify和stringify_value區(qū)分開來。
這里的stringify函數(shù)的主要操作是創(chuàng)建一個context并為其分配一定初識內(nèi)存(初始化)以及最后的在字符串尾放一個空字符
Null/Bool Stringify
case LEPT_NULL: PUTS(c, "null", 4); break; case LEPT_FALSE: PUTS(c, "false", 5); break; case LEPT_TRUE: PUTS(c, "true", 4);break;簡單類型,不多贅述,
Number Stringify
case LEPT_NUMBER: c.top -= 32 - (sprintf((char*)lept_context_push(c, 32), "%.17g", v.u.m_num)); break;這里的操作其實(shí)不是很美觀,在對性能的極致追求上,將一些理解性的臨時變量給省略了。如果換成以下的代碼也許會更好理解:
case LEPT_NUMBER:{//向context中壓入32的內(nèi)存(32為數(shù)字最大占用字符串大小)char* buffer = lept_context_push(c, 32);//在其中寫入數(shù)據(jù)(number->string),并記錄占用的字符數(shù)int length = sprintf(buffer, "%.17g", v->u.n);//棧頂移動c->top -= 32 - length;}break;String Stringify
String的生成因?yàn)樯婕暗睫D(zhuǎn)義序列,而轉(zhuǎn)義序列會用到switch,為了代碼的美觀,我們將string_stringify封裝以下。
在stringify_value中代碼如下
string_stringify函數(shù):
static void lept_stringify_string(lept_context& c, const char* s, size_t len) {//十六進(jìn)制編碼轉(zhuǎn)換的常量static const char hex_digits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };size_t i, size;char* head, * p;assert(s != NULL);p = head = (char*)lept_context_push(c, size = len * 6 + 2); /* "\u00xx..." */*p++ = '"';for (i = 0; i < len; i++) {unsigned char ch = (unsigned char)s[i];switch (ch) {case '\"': *p++ = '\\'; *p++ = '\"'; break;case '\\': *p++ = '\\'; *p++ = '\\'; break;case '\b': *p++ = '\\'; *p++ = 'b'; break;case '\f': *p++ = '\\'; *p++ = 'f'; break;case '\n': *p++ = '\\'; *p++ = 'n'; break;case '\r': *p++ = '\\'; *p++ = 'r'; break;case '\t': *p++ = '\\'; *p++ = 't'; break;default://十六進(jìn)制編碼轉(zhuǎn)換if (ch < 0x20) {*p++ = '\\'; *p++ = 'u'; *p++ = '0'; *p++ = '0';*p++ = hex_digits[ch >> 4];*p++ = hex_digits[ch & 15];}else*p++ = s[i];}}*p++ = '"';c.top -= size - (p - head); }Array Stringify&Object Stringify
因?yàn)槎呤窒嗨?#xff0c;都遞歸了stringify_value,我就放一起了,object只是多一個key值的stringify
case LEPT_ARRAY:PUTC(c, '[');for (i = 0; i < v.u.m_arr.size; i++) {if (i > 0)PUTC(c, ',');lept_stringify_value(c, v.u.m_arr.e[i]);}PUTC(c, ']');break;case LEPT_OBJECT:PUTC(c, '{');for (i = 0; i < v.u.m_obj.size; i++) {if (i > 0)PUTC(c, ',');lept_stringify_string(c, v.u.m_obj.m[i].k, v.u.m_obj.m[i].klen);PUTC(c, ':');lept_stringify_value(c, v.u.m_obj.m[i].v);}PUTC(c, '}');break;如果要進(jìn)行美化的話,可以使用局部靜態(tài)變量。
以下是我的美化操作:
這里主要對object進(jìn)行了美化,也就是說其它的變量比如array依然是會輸出在同一行。
最后可以自行進(jìn)行一些測試,因?yàn)楝F(xiàn)在能夠生成字符串了,自行感受以下整潔的數(shù)據(jù)結(jié)構(gòu)還是很享受的一件事。
單元測試
不過該有的單元測試還是要有的
為貫徹 TDD,先寫測試:
專門定義一個生成測試宏
#define TEST_ROUNDTRIP(json)\do {\lept_value v;\char* json2;\size_t length;\lept_init(&v);\EXPECT_EQ_INT(LEPT_PARSE_OK, lept_parse(&v, json));\EXPECT_EQ_INT(LEPT_STRINGIFY_OK, lept_stringify(&v, &json2, &length));\EXPECT_EQ_STRING(json, json2, length);\lept_free(&v);\free(json2);\} while(0)static void test_stringify_number() {TEST_ROUNDTRIP("0");TEST_ROUNDTRIP("-0");TEST_ROUNDTRIP("1");TEST_ROUNDTRIP("-1");TEST_ROUNDTRIP("1.5");TEST_ROUNDTRIP("-1.5");TEST_ROUNDTRIP("3.25");TEST_ROUNDTRIP("1e+20");TEST_ROUNDTRIP("1.234e+20");TEST_ROUNDTRIP("1.234e-20");TEST_ROUNDTRIP("1.0000000000000002"); /* the smallest number > 1 */TEST_ROUNDTRIP("4.9406564584124654e-324"); /* minimum denormal */TEST_ROUNDTRIP("-4.9406564584124654e-324");TEST_ROUNDTRIP("2.2250738585072009e-308"); /* Max subnormal double */TEST_ROUNDTRIP("-2.2250738585072009e-308");TEST_ROUNDTRIP("2.2250738585072014e-308"); /* Min normal positive double */TEST_ROUNDTRIP("-2.2250738585072014e-308");TEST_ROUNDTRIP("1.7976931348623157e+308"); /* Max double */TEST_ROUNDTRIP("-1.7976931348623157e+308");}static void test_stringify_string() {TEST_ROUNDTRIP("\"\"");TEST_ROUNDTRIP("\"Hello\"");TEST_ROUNDTRIP("\"Hello\\nWorld\"");TEST_ROUNDTRIP("\"\\\" \\\\ / \\b \\f \\n \\r \\t\"");TEST_ROUNDTRIP("\"Hello\\u0000World\"");}static void test_stringify_array() {TEST_ROUNDTRIP("[]");TEST_ROUNDTRIP("[null,false,true,123,\"abc\",[1,2,3]]");}static void test_stringify_object(){TEST_ROUNDTRIP("{}");TEST_ROUNDTRIP("{\"n\":null,\"f\":false,\"t\":true,\"i\":123,\"s\":\"abc\",\"a\":[1,2,3],\"o\":{\"1\":1,\"2\":2,\"3\":3}}");}static void test_stringify() {TEST_ROUNDTRIP("null");TEST_ROUNDTRIP("false");TEST_ROUNDTRIP("true");test_stringify_number();test_stringify_string();test_stringify_array();test_stringify_object();}以上就是生成器的編寫。之后講以下所有的api,那么整個json的復(fù)習(xí)(對于我自己)就結(jié)束了。之后就要進(jìn)入下一個項(xiàng)目的學(xué)習(xí)了
我走在一條未知的道路上,我所能做的就是走下去,直到路口或者盡頭
lept_json Github:https://github.com/miloyip/json-tutorial
本人流星畫魂第七次在csdn上做筆記,有什么錯誤或者是需要改進(jìn)的地方請即時提出
我只是一個對編程感興趣的人,但懶得要死,學(xué)得又不認(rèn)真,希望讀者能罵就罵兩句,真的太懶了
總結(jié)
以上是生活随笔為你收集整理的lept_json的学习之stringify的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android 实现切换主题皮肤功能(类
- 下一篇: This version of MySQ