From df849065a6c303d52ba168494866ff33608ae0a9 Mon Sep 17 00:00:00 2001 From: Alex Chao Date: Tue, 4 Oct 2016 01:32:16 +0800 Subject: [PATCH 1/5] Finish tutorial01 and tutorial02 --- tutorial01/leptjson.c | 32 ++++++++++++---- tutorial01/leptjson.h | 3 ++ tutorial01/test.c | 54 +++++++++++++++++++-------- tutorial02/leptjson.c | 86 +++++++++++++++++++++++++++---------------- tutorial02/test.c | 10 ++--- 5 files changed, 125 insertions(+), 60 deletions(-) diff --git a/tutorial01/leptjson.c b/tutorial01/leptjson.c index 5299fe1d..b345ca5c 100644 --- a/tutorial01/leptjson.c +++ b/tutorial01/leptjson.c @@ -15,18 +15,21 @@ static void lept_parse_whitespace(lept_context* c) { c->json = p; } -static int lept_parse_null(lept_context* c, lept_value* v) { - EXPECT(c, 'n'); - if (c->json[0] != 'u' || c->json[1] != 'l' || c->json[2] != 'l') - return LEPT_PARSE_INVALID_VALUE; - c->json += 3; - v->type = LEPT_NULL; +static int lept_parse_literal(lept_context* c, lept_value* v, const char* literal, int lept_type) { + EXPECT(c, *literal); + while (*++literal != '\0') { + if (*(c->json++) != *literal) + return LEPT_PARSE_INVALID_VALUE; + } + v->type = lept_type; return LEPT_PARSE_OK; } static int lept_parse_value(lept_context* c, lept_value* v) { switch (*c->json) { - case 'n': return lept_parse_null(c, v); + case 'n': return lept_parse_literal(c, v, "null", LEPT_NULL); + case 't': return lept_parse_literal(c, v, "true", LEPT_TRUE); + case 'f': return lept_parse_literal(c, v, "false", LEPT_FALSE); case '\0': return LEPT_PARSE_EXPECT_VALUE; default: return LEPT_PARSE_INVALID_VALUE; } @@ -34,14 +37,27 @@ static int lept_parse_value(lept_context* c, lept_value* v) { int lept_parse(lept_value* v, const char* json) { lept_context c; + int ret; assert(v != NULL); c.json = json; v->type = LEPT_NULL; lept_parse_whitespace(&c); - return lept_parse_value(&c, v); + ret = lept_parse_value(&c, v); + + if (ret == LEPT_PARSE_OK) { + lept_parse_whitespace(&c); + if (*c.json != '\0') + return LEPT_PARSE_ROOT_NOT_SINGULAR; + } + return ret; } lept_type lept_get_type(const lept_value* v) { assert(v != NULL); return v->type; } + +double lept_get_number(const lept_value* v) { + assert(v != NULL && v->type == LEPT_NUMBER); + return v->n; +} diff --git a/tutorial01/leptjson.h b/tutorial01/leptjson.h index 9b65d22a..84dc8236 100644 --- a/tutorial01/leptjson.h +++ b/tutorial01/leptjson.h @@ -4,6 +4,7 @@ typedef enum { LEPT_NULL, LEPT_FALSE, LEPT_TRUE, LEPT_NUMBER, LEPT_STRING, LEPT_ARRAY, LEPT_OBJECT } lept_type; typedef struct { + double n; lept_type type; }lept_value; @@ -18,4 +19,6 @@ int lept_parse(lept_value* v, const char* json); lept_type lept_get_type(const lept_value* v); +double lept_get_number(const lept_value* v); + #endif /* LEPTJSON_H__ */ diff --git a/tutorial01/test.c b/tutorial01/test.c index e7672181..cc4491e1 100644 --- a/tutorial01/test.c +++ b/tutorial01/test.c @@ -18,13 +18,44 @@ static int test_pass = 0; }\ } while(0) + #define EXPECT_EQ_INT(expect, actual) EXPECT_EQ_BASE((expect) == (actual), expect, actual, "%d") +#define TEST_ERROR(error, json)\ + do {\ + lept_value v;\ + v.type = LEPT_FALSE;\ + EXPECT_EQ_INT(error, lept_parse(&v, json));\ + EXPECT_EQ_INT(LEPT_NULL, lept_get_type(&v));\ + } while(0) + +#define EXPECT_EQ_DOUBLE(expect, actual) EXPECT_EQ_DOUBLE(expect) == (actual), expect, actual, "%f") + +#define TEST_NUMBER(expect, json)\ + do {\ + lept_value v;\ + EXPECT_EQ_INT(LEPT_PARSE_OK, lept_parse(&v, json));\ + EXPECT_EQ_INT(LEPT_NUMBER, lept_get_type(&v));\ + EXPECT_EQ_DOUBLE(expect, lept_get_number(&v));\ + } while(0) + + static void test_parse_null() { + TEST_ERROR(LEPT_PARSE_OK, "null"); +} + +static void test_parse_true() { lept_value v; - v.type = LEPT_FALSE; - EXPECT_EQ_INT(LEPT_PARSE_OK, lept_parse(&v, "null")); - EXPECT_EQ_INT(LEPT_NULL, lept_get_type(&v)); + v.type = LEPT_NULL; + EXPECT_EQ_INT(LEPT_PARSE_OK, lept_parse(&v, "true")); + EXPECT_EQ_INT(LEPT_TRUE, lept_get_type(&v)); +} + +static void test_parse_false() { + lept_value v; + v.type = LEPT_NULL; + EXPECT_EQ_INT(LEPT_PARSE_OK, lept_parse(&v, "false")); + EXPECT_EQ_INT(LEPT_FALSE, lept_get_type(&v)); } static void test_parse_expect_value() { @@ -40,25 +71,18 @@ static void test_parse_expect_value() { } static void test_parse_invalid_value() { - lept_value v; - v.type = LEPT_FALSE; - EXPECT_EQ_INT(LEPT_PARSE_INVALID_VALUE, lept_parse(&v, "nul")); - EXPECT_EQ_INT(LEPT_NULL, lept_get_type(&v)); - - v.type = LEPT_FALSE; - EXPECT_EQ_INT(LEPT_PARSE_INVALID_VALUE, lept_parse(&v, "?")); - EXPECT_EQ_INT(LEPT_NULL, lept_get_type(&v)); + TEST_ERROR(LEPT_PARSE_INVALID_VALUE, "nul"); + TEST_ERROR(LEPT_PARSE_INVALID_VALUE, "?"); } static void test_parse_root_not_singular() { - lept_value v; - v.type = LEPT_FALSE; - EXPECT_EQ_INT(LEPT_PARSE_ROOT_NOT_SINGULAR, lept_parse(&v, "null x")); - EXPECT_EQ_INT(LEPT_NULL, lept_get_type(&v)); + TEST_ERROR(LEPT_PARSE_ROOT_NOT_SINGULAR, "null x"); } static void test_parse() { test_parse_null(); + test_parse_true(); + test_parse_false(); test_parse_expect_value(); test_parse_invalid_value(); test_parse_root_not_singular(); diff --git a/tutorial02/leptjson.c b/tutorial02/leptjson.c index 7693e43b..7c409e05 100644 --- a/tutorial02/leptjson.c +++ b/tutorial02/leptjson.c @@ -1,8 +1,12 @@ #include "leptjson.h" #include /* assert() */ #include /* NULL, strtod() */ +#include /* HUGE_VAL */ +#include /* errno */ #define EXPECT(c, ch) do { assert(*c->json == (ch)); c->json++; } while(0) +#define ISDIGIT(ch) ((ch) >= '0' && (ch) <= '9') +#define ISDIGIT1TO9(ch) ((ch) >= '1' && (ch) <= '9') typedef struct { const char* json; @@ -15,49 +19,69 @@ static void lept_parse_whitespace(lept_context* c) { c->json = p; } -static int lept_parse_true(lept_context* c, lept_value* v) { - EXPECT(c, 't'); - if (c->json[0] != 'r' || c->json[1] != 'u' || c->json[2] != 'e') - return LEPT_PARSE_INVALID_VALUE; - c->json += 3; - v->type = LEPT_TRUE; +static int lept_parse_literal(lept_context* c, lept_value* v, const char* literal, int lept_type) { + EXPECT(c, *literal); + while (*++literal != '\0') { + if (*(c->json++) != *literal) + return LEPT_PARSE_INVALID_VALUE; + } + v->type = lept_type; return LEPT_PARSE_OK; } -static int lept_parse_false(lept_context* c, lept_value* v) { - EXPECT(c, 'f'); - if (c->json[0] != 'a' || c->json[1] != 'l' || c->json[2] != 's' || c->json[3] != 'e') - return LEPT_PARSE_INVALID_VALUE; - c->json += 4; - v->type = LEPT_FALSE; - return LEPT_PARSE_OK; -} +static int lept_parse_number(lept_context* c, lept_value* v) { + double n; + const char* ch = c->json; + /* validate number */ -static int lept_parse_null(lept_context* c, lept_value* v) { - EXPECT(c, 'n'); - if (c->json[0] != 'u' || c->json[1] != 'l' || c->json[2] != 'l') - return LEPT_PARSE_INVALID_VALUE; - c->json += 3; - v->type = LEPT_NULL; - return LEPT_PARSE_OK; -} + if (*ch == '-') ch++; -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) + if (*ch == '0') + ch++; + else if (ISDIGIT1TO9(*ch)) { + ch++; + while (ISDIGIT(*ch)) + ch++; + } else return LEPT_PARSE_INVALID_VALUE; - c->json = end; + + if (*ch == '.') { + ch++; + if (ISDIGIT(*ch)) { + ch++; + while (ISDIGIT(*ch)) + ch++; + } else + return LEPT_PARSE_INVALID_VALUE; + } + + if (*ch == 'e' || *ch == 'E') { + ch++; + if (*ch == '+' || *ch == '-') ch++; + if (ISDIGIT(*ch)) { + ch++; + while (ISDIGIT(*ch)) + ch++; + } else { + return LEPT_PARSE_INVALID_VALUE; + } + } + + errno = 0; + n = strtod(c->json, NULL); + if (errno == ERANGE && (n == HUGE_VAL || n == -HUGE_VAL)) + return LEPT_PARSE_NUMBER_TOO_BIG; + c->json = ch; + v->n = n; v->type = LEPT_NUMBER; return LEPT_PARSE_OK; } 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); + 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 '\0': return LEPT_PARSE_EXPECT_VALUE; } diff --git a/tutorial02/test.c b/tutorial02/test.c index 6e3ebed2..accf8144 100644 --- a/tutorial02/test.c +++ b/tutorial02/test.c @@ -70,6 +70,10 @@ static void test_parse_number() { TEST_NUMBER(1.234E+10, "1.234E+10"); TEST_NUMBER(1.234E-10, "1.234E-10"); TEST_NUMBER(0.0, "1e-10000"); /* must underflow */ + TEST_NUMBER(5E-324, "5E-324"); /* Min subnormal positive double */ + TEST_NUMBER(2.2250738585072009E-308, "2.2250738585072009E-308"); /* Max subnormal double */ + TEST_NUMBER(2.2250738585072014E-308, "2.2250738585072014E-308"); /* Min normal positive double */ + TEST_NUMBER(1.7976931348623157E308, "1.7976931348623157E308"); /* Max Double */ } #define TEST_ERROR(error, json)\ @@ -89,7 +93,6 @@ static void test_parse_invalid_value() { TEST_ERROR(LEPT_PARSE_INVALID_VALUE, "nul"); TEST_ERROR(LEPT_PARSE_INVALID_VALUE, "?"); -#if 0 /* invalid number */ TEST_ERROR(LEPT_PARSE_INVALID_VALUE, "+0"); TEST_ERROR(LEPT_PARSE_INVALID_VALUE, "+1"); @@ -99,25 +102,20 @@ static void test_parse_invalid_value() { TEST_ERROR(LEPT_PARSE_INVALID_VALUE, "inf"); TEST_ERROR(LEPT_PARSE_INVALID_VALUE, "NAN"); TEST_ERROR(LEPT_PARSE_INVALID_VALUE, "nan"); -#endif } static void test_parse_root_not_singular() { TEST_ERROR(LEPT_PARSE_ROOT_NOT_SINGULAR, "null x"); -#if 0 /* invalid number */ TEST_ERROR(LEPT_PARSE_ROOT_NOT_SINGULAR, "0123"); /* after zero should be '.' or nothing */ TEST_ERROR(LEPT_PARSE_ROOT_NOT_SINGULAR, "0x0"); TEST_ERROR(LEPT_PARSE_ROOT_NOT_SINGULAR, "0x123"); -#endif } static void test_parse_number_too_big() { -#if 0 TEST_ERROR(LEPT_PARSE_NUMBER_TOO_BIG, "1e309"); TEST_ERROR(LEPT_PARSE_NUMBER_TOO_BIG, "-1e309"); -#endif } static void test_parse() { From e88a85776369b318d9fedd8761c7ce39eb66e098 Mon Sep 17 00:00:00 2001 From: Alex Chao Date: Tue, 4 Oct 2016 18:07:26 +0800 Subject: [PATCH 2/5] Tutorial03 --- tutorial03/leptjson.c | 26 +++++++++++++++++++++++++- tutorial03/test.c | 26 ++++++++++++++++++++------ 2 files changed, 45 insertions(+), 7 deletions(-) diff --git a/tutorial03/leptjson.c b/tutorial03/leptjson.c index 07f7e2c7..39778ac8 100644 --- a/tutorial03/leptjson.c +++ b/tutorial03/leptjson.c @@ -102,7 +102,22 @@ static int lept_parse_string(lept_context* c, lept_value* v) { case '\0': c->top = head; return LEPT_PARSE_MISS_QUOTATION_MARK; + 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; + default: + return LEPT_PARSE_INVALID_STRING_ESCAPE; + } + break; default: + if (ch < '\x20') return LEPT_PARSE_INVALID_STRING_CHAR; PUTC(c, ch); } } @@ -154,11 +169,17 @@ lept_type lept_get_type(const lept_value* v) { int lept_get_boolean(const lept_value* v) { /* \TODO */ - return 0; + assert(v != NULL && (v->type == LEPT_TRUE || v->type == LEPT_FALSE)); + return v->type == LEPT_TRUE; } void lept_set_boolean(lept_value* v, int b) { /* \TODO */ + assert(v != NULL); + if (b == 0) + v->type = LEPT_FALSE; + else + v->type = LEPT_TRUE; } double lept_get_number(const lept_value* v) { @@ -168,6 +189,9 @@ double lept_get_number(const lept_value* v) { void lept_set_number(lept_value* v, double n) { /* \TODO */ + assert(v != NULL); + v->u.n = n; + v->type = LEPT_NUMBER; } const char* lept_get_string(const lept_value* v) { diff --git a/tutorial03/test.c b/tutorial03/test.c index ac788aca..45d162c5 100644 --- a/tutorial03/test.c +++ b/tutorial03/test.c @@ -107,10 +107,8 @@ static void test_parse_number() { static void test_parse_string() { TEST_STRING("", "\"\""); TEST_STRING("Hello", "\"Hello\""); -#if 0 TEST_STRING("Hello\nWorld", "\"Hello\\nWorld\""); TEST_STRING("\" \\ / \b \f \n \r \t", "\"\\\" \\\\ \\/ \\b \\f \\n \\r \\t\""); -#endif } #define TEST_ERROR(error, json)\ @@ -163,19 +161,15 @@ static void test_parse_missing_quotation_mark() { } static void test_parse_invalid_string_escape() { -#if 0 TEST_ERROR(LEPT_PARSE_INVALID_STRING_ESCAPE, "\"\\v\""); TEST_ERROR(LEPT_PARSE_INVALID_STRING_ESCAPE, "\"\\'\""); TEST_ERROR(LEPT_PARSE_INVALID_STRING_ESCAPE, "\"\\0\""); TEST_ERROR(LEPT_PARSE_INVALID_STRING_ESCAPE, "\"\\x12\""); -#endif } static void test_parse_invalid_string_char() { -#if 0 TEST_ERROR(LEPT_PARSE_INVALID_STRING_CHAR, "\"\x01\""); TEST_ERROR(LEPT_PARSE_INVALID_STRING_CHAR, "\"\x1F\""); -#endif } static void test_access_null() { @@ -190,10 +184,30 @@ static void test_access_null() { static void test_access_boolean() { /* \TODO */ /* Use EXPECT_TRUE() and EXPECT_FALSE() */ + lept_value v; + lept_init(&v); + lept_set_boolean(&v, 1); + EXPECT_TRUE(lept_get_boolean(&v)); + lept_set_boolean(&v, 0); + EXPECT_FALSE(lept_get_boolean(&v)); + lept_free(&v); } static void test_access_number() { /* \TODO */ + lept_value v; + lept_init(&v); + lept_set_number(&v, 0.0); + EXPECT_EQ_DOUBLE(0.0, lept_get_number(&v)); + lept_set_number(&v, -0.1); + EXPECT_EQ_DOUBLE(-0.1, lept_get_number(&v)); + lept_set_number(&v, 1.23); + EXPECT_EQ_DOUBLE(1.23, lept_get_number(&v)); + lept_set_number(&v, -12.34e-56); + EXPECT_EQ_DOUBLE(-12.34e-56, lept_get_number(&v)); + lept_set_number(&v, 4.9406564584124654E-324); + EXPECT_EQ_DOUBLE(4.9406564584124654E-324, lept_get_number(&v)); + lept_free(&v); } static void test_access_string() { From 59163ffdebeabb60939d65dd76e7ec36c1a777a4 Mon Sep 17 00:00:00 2001 From: Alex Chao Date: Sat, 15 Oct 2016 01:37:39 +0800 Subject: [PATCH 3/5] Improve code statement --- tutorial03/leptjson.c | 13 ++++++++----- tutorial03/test.c | 2 ++ 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/tutorial03/leptjson.c b/tutorial03/leptjson.c index 39778ac8..38ef3520 100644 --- a/tutorial03/leptjson.c +++ b/tutorial03/leptjson.c @@ -113,11 +113,15 @@ static int lept_parse_string(lept_context* c, lept_value* v) { case 'r': PUTC(c, '\r'); break; case 't': PUTC(c, '\t'); break; default: + c->top = head; return LEPT_PARSE_INVALID_STRING_ESCAPE; } break; default: - if (ch < '\x20') return LEPT_PARSE_INVALID_STRING_CHAR; + if (ch < '\x20') { + c->top = head; + return LEPT_PARSE_INVALID_STRING_CHAR; + } PUTC(c, ch); } } @@ -176,10 +180,8 @@ int lept_get_boolean(const lept_value* v) { void lept_set_boolean(lept_value* v, int b) { /* \TODO */ assert(v != NULL); - if (b == 0) - v->type = LEPT_FALSE; - else - v->type = LEPT_TRUE; + lept_free(v); + v->type = b ? LEPT_TRUE : LEPT_FALSE; } double lept_get_number(const lept_value* v) { @@ -190,6 +192,7 @@ double lept_get_number(const lept_value* v) { void lept_set_number(lept_value* v, double n) { /* \TODO */ assert(v != NULL); + lept_free(v); v->u.n = n; v->type = LEPT_NUMBER; } diff --git a/tutorial03/test.c b/tutorial03/test.c index 45d162c5..65911a7e 100644 --- a/tutorial03/test.c +++ b/tutorial03/test.c @@ -186,6 +186,7 @@ static void test_access_boolean() { /* Use EXPECT_TRUE() and EXPECT_FALSE() */ lept_value v; lept_init(&v); + lept_set_string(&v, "a", 1); lept_set_boolean(&v, 1); EXPECT_TRUE(lept_get_boolean(&v)); lept_set_boolean(&v, 0); @@ -197,6 +198,7 @@ static void test_access_number() { /* \TODO */ lept_value v; lept_init(&v); + lept_set_string(&v, "a", 1); lept_set_number(&v, 0.0); EXPECT_EQ_DOUBLE(0.0, lept_get_number(&v)); lept_set_number(&v, -0.1); From 0933432d91c750e2168f1d18253f004a9cd0154d Mon Sep 17 00:00:00 2001 From: Alex Chao Date: Sat, 15 Oct 2016 04:36:18 +0800 Subject: [PATCH 4/5] Complete tutorial04 --- tutorial04/leptjson.c | 48 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/tutorial04/leptjson.c b/tutorial04/leptjson.c index 0a123bf2..d2938440 100644 --- a/tutorial04/leptjson.c +++ b/tutorial04/leptjson.c @@ -5,8 +5,9 @@ #include "leptjson.h" #include /* assert() */ #include /* errno, ERANGE */ +#include /* isxdigit() */ #include /* HUGE_VAL */ -#include /* NULL, malloc(), realloc(), free(), strtod() */ +#include /* NULL, malloc(), realloc(), free(), strtod(), strtoul */ #include /* memcpy() */ #ifndef LEPT_PARSE_STACK_INIT_SIZE @@ -92,11 +93,39 @@ static int lept_parse_number(lept_context* c, lept_value* v) { static const char* lept_parse_hex4(const char* p, unsigned* u) { /* \TODO */ + int i; + char unicode[6] = { '0', 'x' }; + for (i = 0; i < 4; i++) { + if (isxdigit(*p)) + unicode[i+2] = *p++; + else { + p = NULL; + break; + } + } + + if (p != NULL) *u = (unsigned) strtoul(unicode, NULL, 16); return p; } static void lept_encode_utf8(lept_context* c, unsigned u) { /* \TODO */ + assert(u >= 0 && u <= 0x10ffff); + if (u <= 0x7f) { + PUTC(c, u); + } else if (u <= 0x7ff) { + PUTC(c, 0xC0 | ((u >> 6) & 0x2f)); + PUTC(c, 0x80 | ( u & 0x3f)); + } else if (u <= 0xffff) { + PUTC(c, 0xE0 | ((u >> 12) & 0xf)); + PUTC(c, 0x80 | ((u >> 6) & 0x3f)); + PUTC(c, 0x80 | ( u & 0x3f)); + } else { + PUTC(c, 0xF0 | ((u >> 18) & 0x7)); + PUTC(c, 0x80 | ((u >> 12) & 0x3f)); + PUTC(c, 0x80 | ((u >> 6) & 0x3f)); + PUTC(c, 0x80 | (u & 0x3f)); + } } #define STRING_ERROR(ret) do { c->top = head; return ret; } while(0) @@ -104,11 +133,14 @@ static void lept_encode_utf8(lept_context* c, unsigned u) { static int lept_parse_string(lept_context* c, lept_value* v) { size_t head = c->top, len; unsigned u; + unsigned h = 0; const char* p; EXPECT(c, '\"'); p = c->json; for (;;) { char ch = *p++; + if (h > 0 && ch != '\\') + STRING_ERROR(LEPT_PARSE_INVALID_UNICODE_SURROGATE); switch (ch) { case '\"': len = c->top - head; @@ -116,6 +148,8 @@ static int lept_parse_string(lept_context* c, lept_value* v) { c->json = p; return LEPT_PARSE_OK; case '\\': + if (h > 0 && *p != 'u') + STRING_ERROR(LEPT_PARSE_INVALID_UNICODE_SURROGATE); switch (*p++) { case '\"': PUTC(c, '\"'); break; case '\\': PUTC(c, '\\'); break; @@ -129,6 +163,18 @@ static int lept_parse_string(lept_context* c, lept_value* v) { if (!(p = lept_parse_hex4(p, &u))) STRING_ERROR(LEPT_PARSE_INVALID_UNICODE_HEX); /* \TODO surrogate handling */ + if (u >= 0xd800 && u<= 0xdbff) { + h = u; + break; + } else if (u >= 0xdc00 && u<= 0xdfff) { + if (h > 0) { + u = 0x10000 + (h - 0xd800) * 0x400 + (u - 0xdc00); + h = 0; + } else + STRING_ERROR(LEPT_PARSE_INVALID_UNICODE_SURROGATE); + } else if (h > 0) + STRING_ERROR(LEPT_PARSE_INVALID_UNICODE_SURROGATE); + lept_encode_utf8(c, u); break; default: From 99922f092925721fe989bd1328591b6c6beb75df Mon Sep 17 00:00:00 2001 From: Alex Chao Date: Sat, 15 Oct 2016 14:01:46 +0800 Subject: [PATCH 5/5] Fix a hex error --- tutorial04/leptjson.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tutorial04/leptjson.c b/tutorial04/leptjson.c index d2938440..49e7f5dd 100644 --- a/tutorial04/leptjson.c +++ b/tutorial04/leptjson.c @@ -114,7 +114,7 @@ static void lept_encode_utf8(lept_context* c, unsigned u) { if (u <= 0x7f) { PUTC(c, u); } else if (u <= 0x7ff) { - PUTC(c, 0xC0 | ((u >> 6) & 0x2f)); + PUTC(c, 0xC0 | ((u >> 6) & 0x1f)); PUTC(c, 0x80 | ( u & 0x3f)); } else if (u <= 0xffff) { PUTC(c, 0xE0 | ((u >> 12) & 0xf));