From 3941dccda8f2d900ef0faab9081f3cf576920ac9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=AE=B4=E7=90=86?= Date: Tue, 11 Sep 2018 19:00:44 +0800 Subject: [PATCH 1/2] my answer --- tutorial01/leptjson.c | 27 ++++++++++++++++++++++++++- tutorial01/test.c | 16 ++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/tutorial01/leptjson.c b/tutorial01/leptjson.c index 5299fe1d..892b5968 100644 --- a/tutorial01/leptjson.c +++ b/tutorial01/leptjson.c @@ -23,10 +23,28 @@ static int lept_parse_null(lept_context* c, lept_value* v) { v->type = LEPT_NULL; return LEPT_PARSE_OK; } +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_NULL; + 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_NULL; + 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 't': return lept_parse_true(c, v); + case 'f': return lept_parse_false(c, v); case '\0': return LEPT_PARSE_EXPECT_VALUE; default: return LEPT_PARSE_INVALID_VALUE; } @@ -38,7 +56,14 @@ int lept_parse(lept_value* v, const char* json) { c.json = json; v->type = LEPT_NULL; lept_parse_whitespace(&c); - return lept_parse_value(&c, v); + int ret; + if ((ret=lept_parse_value(&c, v)) == LEPT_PARSE_OK) + { + lept_parse_whitespace(&c); + if (*c.json != '\0') + ret = LEPT_PARSE_ROOT_NOT_SINGULAR; + } + return ret; } lept_type lept_get_type(const lept_value* v) { diff --git a/tutorial01/test.c b/tutorial01/test.c index e7672181..e5ad2021 100644 --- a/tutorial01/test.c +++ b/tutorial01/test.c @@ -57,15 +57,31 @@ static void test_parse_root_not_singular() { EXPECT_EQ_INT(LEPT_NULL, lept_get_type(&v)); } +static void test_parse_true() { + lept_value v; + v.type = LEPT_FALSE; + EXPECT_EQ_INT(LEPT_PARSE_OK, lept_parse(&v, "true")); + EXPECT_EQ_INT(LEPT_NULL, lept_get_type(&v)); +} +static void test_parse_false() { + lept_value v; + v.type = LEPT_FALSE; + EXPECT_EQ_INT(LEPT_PARSE_OK, lept_parse(&v, "false")); + EXPECT_EQ_INT(LEPT_NULL, lept_get_type(&v)); +} + static void test_parse() { test_parse_null(); test_parse_expect_value(); test_parse_invalid_value(); test_parse_root_not_singular(); + test_parse_true(); + test_parse_false(); } int main() { test_parse(); printf("%d/%d (%3.2f%%) passed\n", test_pass, test_count, test_pass * 100.0 / test_count); + system("PAUSE"); return main_ret; } From 0bb8c4bb94b03a6553ab9853dccc7704c320b1cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=AE=B4=E7=90=86?= Date: Tue, 11 Sep 2018 21:02:48 +0800 Subject: [PATCH 2/2] My answer --- tutorial02/leptjson.c | 82 +++++++++++++++++++++++++------------------ tutorial02/test.c | 7 ++-- 2 files changed, 51 insertions(+), 38 deletions(-) diff --git a/tutorial02/leptjson.c b/tutorial02/leptjson.c index 7693e43b..99222493 100644 --- a/tutorial02/leptjson.c +++ b/tutorial02/leptjson.c @@ -1,8 +1,12 @@ #include "leptjson.h" #include /* assert() */ +#include /* errno, ERANGE */ +#include /* HUGE_VAL */ #include /* NULL, strtod() */ #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,57 @@ 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; - return LEPT_PARSE_OK; +static int lept_parse_literal(lept_context* c, lept_value* v, const char* literal, lept_type type) +{ + size_t i; + EXPECT(c, literal[0]); + for (i = 0; literal[i + 1] != '\0'; i++) + if (c->json[i] != literal[i + 1]) + return LEPT_PARSE_INVALID_VALUE; + c->json += i; + v->type = 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) { + + const char* p=c->json; + if (*p == '-') p++; + if (*p == '0') p++; + else + { + if (!ISDIGIT1TO9(*p)) return LEPT_PARSE_INVALID_VALUE; + for (p++; ISDIGIT(*p); p++); + } + if (*p == '.') + { + p++; + if (!ISDIGIT(*p)) return LEPT_PARSE_INVALID_VALUE; + for (p++; ISDIGIT(*p);p++); + } + if (*p == 'E' || *p == 'e') + { + p++; + if (*p == '-' || *p == '+') p++; + if (!ISDIGIT(*p)) return LEPT_PARSE_INVALID_VALUE; + for (p++; ISDIGIT(*p); 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; - return LEPT_PARSE_OK; -} + errno = 0; + v->n = strtod(c->json, NULL); + if (errno == ERANGE && (v->n == HUGE_VAL || v->n == -HUGE_VAL)) + return LEPT_PARSE_NUMBER_TOO_BIG; + v->type = LEPT_NUMBER; + c->json = p; + return LEPT_PARSE_OK; -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) - return LEPT_PARSE_INVALID_VALUE; - c->json = end; - 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..d27d52bd 100644 --- a/tutorial02/test.c +++ b/tutorial02/test.c @@ -89,7 +89,7 @@ static void test_parse_invalid_value() { TEST_ERROR(LEPT_PARSE_INVALID_VALUE, "nul"); TEST_ERROR(LEPT_PARSE_INVALID_VALUE, "?"); -#if 0 +#if 1 /* invalid number */ TEST_ERROR(LEPT_PARSE_INVALID_VALUE, "+0"); TEST_ERROR(LEPT_PARSE_INVALID_VALUE, "+1"); @@ -105,7 +105,7 @@ static void test_parse_invalid_value() { static void test_parse_root_not_singular() { TEST_ERROR(LEPT_PARSE_ROOT_NOT_SINGULAR, "null x"); -#if 0 +#if 1 /* invalid number */ TEST_ERROR(LEPT_PARSE_ROOT_NOT_SINGULAR, "0123"); /* after zero should be '.' or nothing */ TEST_ERROR(LEPT_PARSE_ROOT_NOT_SINGULAR, "0x0"); @@ -114,7 +114,7 @@ static void test_parse_root_not_singular() { } static void test_parse_number_too_big() { -#if 0 +#if 1 TEST_ERROR(LEPT_PARSE_NUMBER_TOO_BIG, "1e309"); TEST_ERROR(LEPT_PARSE_NUMBER_TOO_BIG, "-1e309"); #endif @@ -134,5 +134,6 @@ static void test_parse() { int main() { test_parse(); printf("%d/%d (%3.2f%%) passed\n", test_pass, test_count, test_pass * 100.0 / test_count); + system("PAUSE"); return main_ret; }