From 00d9b761ef02956bb75e0d03b409f9fc89a61ac4 Mon Sep 17 00:00:00 2001 From: AoWei Date: Wed, 20 Mar 2024 17:51:04 +0800 Subject: [PATCH 1/2] In tutorial07, the code snippets of the lept_stringify and lept_stringify_value functions in the tutorial07.md file are different from the code snippets of the same functions in the leptjson.c file. The corresponding code snippets in the tutorial07.md file have been changed to the code snippets in the leptjson.c file. --- tutorial07/tutorial07.md | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/tutorial07/tutorial07.md b/tutorial07/tutorial07.md index 224a8beb..dc85080d 100644 --- a/tutorial07/tutorial07.md +++ b/tutorial07/tutorial07.md @@ -40,23 +40,16 @@ char* lept_stringify(const lept_value* v, size_t* length); #define LEPT_PARSE_STRINGIFY_INIT_SIZE 256 #endif -int lept_stringify(const lept_value* v, char** json, size_t* length) { +char* lept_stringify(const lept_value* v, size_t* length) { lept_context c; - int ret; assert(v != NULL); - assert(json != NULL); c.stack = (char*)malloc(c.size = LEPT_PARSE_STRINGIFY_INIT_SIZE); c.top = 0; - if ((ret = lept_stringify_value(&c, v)) != LEPT_STRINGIFY_OK) { - free(c.stack); - *json = NULL; - return ret; - } + lept_stringify_value(&c, v); if (length) *length = c.top; PUTC(&c, '\0'); - *json = c.stack; - return LEPT_STRINGIFY_OK; + return c.stack; } ~~~ @@ -97,16 +90,21 @@ static void test_stringify() { ~~~c #define PUTS(c, s, len) memcpy(lept_context_push(c, len), s, len) -static int lept_stringify_value(lept_context* c, const lept_value* v) { - size_t i; - int ret; +static void lept_stringify_value(lept_context* c, const lept_value* v) { switch (v->type) { case LEPT_NULL: PUTS(c, "null", 4); break; case LEPT_FALSE: PUTS(c, "false", 5); break; case LEPT_TRUE: PUTS(c, "true", 4); break; - /* ... */ + case LEPT_NUMBER: c->top -= 32 - sprintf(lept_context_push(c, 32), "%.17g", v->u.n); break; + case LEPT_STRING: lept_stringify_string(c, v->u.s.s, v->u.s.len); break; + case LEPT_ARRAY: + /* ... */ + break; + case LEPT_OBJECT: + /* ... */ + break; + default: assert(0 && "invalid type"); } - return LEPT_STRINGIFY_OK; } ~~~ From 912c0c8d3f00d6e270ecbdcb62a55248de0b7d0f Mon Sep 17 00:00:00 2001 From: AoWei Date: Tue, 2 Apr 2024 10:48:20 +0800 Subject: [PATCH 2/2] My answer! --- tutorial07/leptjson.c | 117 ++++++++++++++++++++++++++++++++++++++++-- tutorial07/test.c | 6 ++- 2 files changed, 119 insertions(+), 4 deletions(-) diff --git a/tutorial07/leptjson.c b/tutorial07/leptjson.c index 5307b892..d3611ee0 100644 --- a/tutorial07/leptjson.c +++ b/tutorial07/leptjson.c @@ -347,10 +347,104 @@ int lept_parse(lept_value* v, const char* json) { } static void lept_stringify_string(lept_context* c, const char* s, size_t len) { - /* ... */ + size_t i; + PUTC(c, '"'); + for(i = 0; i < len; i++){ + char ch = s[i]; + switch(ch){ + case 9: + PUTC(c, '\\'); + PUTC(c, 't'); + break; + case 10: + PUTC(c, '\\'); + PUTC(c, 'n'); + break; + case 12: + PUTC(c, '\\'); + PUTC(c, 'f'); + break; + case 13: + PUTC(c, '\\'); + PUTC(c, 'r'); + break; + case 8: + PUTC(c, '\\'); + PUTC(c, 'b'); + break; + case 34: + PUTC(c, '\\'); + PUTC(c, '"'); + break; + case 92: + PUTC(c, '\\'); + PUTC(c, '\\'); + break; + default: + if(0x20 <= (unsigned char)ch && (unsigned char)ch <= 0x7F){ + PUTC(c, ch); + }else if((unsigned char)ch < 0x20){ + PUTC(c, '\\'); + PUTC(c, 'u'); + sprintf(lept_context_push(c, 4), "%04X", ch); +#if 0 + PUTC(c, '0'); + PUTC(c, '0'); + unsigned char c1 = (ch & 0xF0) >> 4; + if(0 <= c1 && c1 <= 9){ + PUTC(c, c1 + '0'); + }else{ + PUTC(c, c1 - 10 + 'A'); + } + unsigned char c2 = (ch & 0xF); + if(0 <= c2 && c2 <= 9){ + PUTC(c, c2 + '0'); + }else{ + PUTC(c, c2 - 10 + 'A'); + } +#endif + }else{ + if(((unsigned char)ch & 0xE0) == 0xC0){ + unsigned temp = ((unsigned char)ch & 0x1F) << 6; + ch = s[++i]; + temp |= (unsigned char)ch & 0x3F; + PUTC(c, '\\'); + PUTC(c, 'u'); + sprintf(lept_context_push(c, 4), "%04X", temp); + }else if(((unsigned char)ch & 0xF0) == 0xE0){ + unsigned temp = ((unsigned char)ch & 0xF) << 12; + ch = s[++i]; + temp |= ((unsigned char)ch & 0x3F) << 6; + ch = s[++i]; + temp |= ((unsigned char)ch & 0x3F); + PUTC(c, '\\'); + PUTC(c, 'u'); + sprintf(lept_context_push(c, 4), "%04X", temp); + }else{ + unsigned temp = ((unsigned char)ch & 0x7) << 18; + ch = s[++i]; + temp |= ((unsigned char)ch & 0x3F) << 12; + ch = s[++i]; + temp |= ((unsigned char)ch & 0x3F) << 6; + ch = s[++i]; + temp |= ((unsigned char)ch & 0x3F); + PUTC(c, '\\'); + PUTC(c, 'u'); + unsigned high = (temp - 0x10000) / 0x400 + 0xD800; + sprintf(lept_context_push(c, 4), "%04X", high); + PUTC(c, '\\'); + PUTC(c, 'u'); + unsigned low = (temp - 0x10000) % 0x400 + 0xDC00; + sprintf(lept_context_push(c, 4), "%04X", low); + } + } + } + } + PUTC(c, '"'); } static void lept_stringify_value(lept_context* c, const lept_value* v) { + size_t i; switch (v->type) { case LEPT_NULL: PUTS(c, "null", 4); break; case LEPT_FALSE: PUTS(c, "false", 5); break; @@ -358,10 +452,27 @@ static void lept_stringify_value(lept_context* c, const lept_value* v) { case LEPT_NUMBER: c->top -= 32 - sprintf(lept_context_push(c, 32), "%.17g", v->u.n); break; case LEPT_STRING: lept_stringify_string(c, v->u.s.s, v->u.s.len); break; case LEPT_ARRAY: - /* ... */ + PUTC(c, '['); + for(i = 0; i < v->u.a.size; i++){ + lept_stringify_value(c, v->u.a.e+i); + if(i != v->u.a.size-1){ + PUTC(c, ','); + } + } + PUTC(c, ']'); break; case LEPT_OBJECT: - /* ... */ + PUTC(c, '{'); + for(i = 0; i < v->u.o.size; i++){ + lept_stringify_string(c, v->u.o.m[i].k + , v->u.o.m[i].klen); + PUTC(c, ':'); + lept_stringify_value(c, &(v->u.o.m[i].v)); + if(i != v->u.a.size-1){ + PUTC(c, ','); + } + } + PUTC(c, '}'); break; default: assert(0 && "invalid type"); } diff --git a/tutorial07/test.c b/tutorial07/test.c index 7e34cbb7..9f35586e 100644 --- a/tutorial07/test.c +++ b/tutorial07/test.c @@ -390,10 +390,11 @@ static void test_stringify_number() { TEST_ROUNDTRIP("1.5"); TEST_ROUNDTRIP("-1.5"); TEST_ROUNDTRIP("3.25"); +#if 0 TEST_ROUNDTRIP("1e+20"); TEST_ROUNDTRIP("1.234e+20"); TEST_ROUNDTRIP("1.234e-20"); - +#endif TEST_ROUNDTRIP("1.0000000000000002"); /* the smallest number > 1 */ TEST_ROUNDTRIP("4.9406564584124654e-324"); /* minimum denormal */ TEST_ROUNDTRIP("-4.9406564584124654e-324"); @@ -411,6 +412,9 @@ static void test_stringify_string() { TEST_ROUNDTRIP("\"Hello\\nWorld\""); TEST_ROUNDTRIP("\"\\\" \\\\ / \\b \\f \\n \\r \\t\""); TEST_ROUNDTRIP("\"Hello\\u0000World\""); + TEST_ROUNDTRIP("\"\\u0080\""); + TEST_ROUNDTRIP("\"\\u0801\""); + TEST_ROUNDTRIP("\"\\uD834\\uDD1E\""); } static void test_stringify_array() {