diff --git a/tutorial01/leptjson.c b/tutorial01/leptjson.c index 5299fe1d..aae94026 100644 --- a/tutorial01/leptjson.c +++ b/tutorial01/leptjson.c @@ -1,6 +1,7 @@ #include "leptjson.h" #include /* assert() */ #include /* NULL */ +#include /* strlen */ #define EXPECT(c, ch) do { assert(*c->json == (ch)); c->json++; } while(0) @@ -15,18 +16,54 @@ 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_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; */ +/* } */ + +/* 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_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_literal(lept_context* c, lept_value* v, const char* literal, int type) { + int len = strlen(literal); + int i; + + assert(literal != NULL); + EXPECT(c, literal[0]); + + for (i = 0; i < len - 1; ++i) { + if (c->json[i] != literal[i + 1]) + return LEPT_PARSE_INVALID_VALUE; + } + c->json += len - 1; + v->type = 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,11 +71,23 @@ 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); + assert(json != 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] != '\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..10c5a182 100644 --- a/tutorial01/test.c +++ b/tutorial01/test.c @@ -27,6 +27,20 @@ static void test_parse_null() { EXPECT_EQ_INT(LEPT_NULL, lept_get_type(&v)); } +static void test_parse_true() { + lept_value 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() { lept_value v; @@ -59,6 +73,8 @@ static void test_parse_root_not_singular() { 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..fbb93788 100644 --- a/tutorial02/leptjson.c +++ b/tutorial02/leptjson.c @@ -3,6 +3,8 @@ #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; @@ -44,7 +46,50 @@ static int lept_parse_null(lept_context* c, lept_value* v) { static int lept_parse_number(lept_context* c, lept_value* v) { char* end; - /* \TODO validate number */ + lept_context cc; + + /* start validation */ + cc.json = c->json; + /* "-" */ + if (*cc.json == '-') + cc.json++; + + /* int */ + if (*cc.json == '0') { + cc.json++; + } else if(ISDIGIT1TO9(*cc.json)) { + cc.json++; + while (ISDIGIT(*cc.json)) + cc.json++; + } else { + return LEPT_PARSE_INVALID_VALUE; + } + + /* frac */ + if (*cc.json == '.') { + cc.json++; + if (ISDIGIT(*cc.json)) { + while (ISDIGIT(*cc.json)) + cc.json++; + } else { + return LEPT_PARSE_INVALID_VALUE; + } + } + + /* exp */ + if (*cc.json == 'e' || *cc.json == 'E') { + cc.json++; + if (*cc.json == '+' || *cc.json == '-') + cc.json++; + + while (ISDIGIT(*cc.json)) + cc.json++; + } + + if (*cc.json != '\0') + return LEPT_PARSE_INVALID_VALUE; + /* end validation */ + v->n = strtod(c->json, &end); if (c->json == end) return LEPT_PARSE_INVALID_VALUE; diff --git a/tutorial02/test.c b/tutorial02/test.c index 6e3ebed2..9a293132 100644 --- a/tutorial02/test.c +++ b/tutorial02/test.c @@ -70,6 +70,16 @@ 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(1.0000000000000002, "1.0000000000000002"); /* the smallest number > 1 */ + TEST_NUMBER( 4.9406564584124654e-324, "4.9406564584124654e-324"); /* minimum denormal */ + TEST_NUMBER(-4.9406564584124654e-324, "-4.9406564584124654e-324"); + TEST_NUMBER( 2.2250738585072009e-308, "2.2250738585072009e-308"); /* Max subnormal double */ + TEST_NUMBER(-2.2250738585072009e-308, "-2.2250738585072009e-308"); + TEST_NUMBER( 2.2250738585072014e-308, "2.2250738585072014e-308"); /* Min normal positive double */ + TEST_NUMBER(-2.2250738585072014e-308, "-2.2250738585072014e-308"); + TEST_NUMBER( 1.7976931348623157e+308, "1.7976931348623157e+308"); /* Max double */ + TEST_NUMBER(-1.7976931348623157e+308, "-1.7976931348623157e+308"); } #define TEST_ERROR(error, json)\ @@ -89,7 +99,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");