diff --git a/tutorial01/.cache/clangd/index/leptjson.c.793D9597D461A4AF.idx b/tutorial01/.cache/clangd/index/leptjson.c.793D9597D461A4AF.idx new file mode 100644 index 00000000..1dfd5ad6 Binary files /dev/null and b/tutorial01/.cache/clangd/index/leptjson.c.793D9597D461A4AF.idx differ diff --git a/tutorial01/.cache/clangd/index/leptjson.h.CDC4968BBDE8B0BC.idx b/tutorial01/.cache/clangd/index/leptjson.h.CDC4968BBDE8B0BC.idx new file mode 100644 index 00000000..3819f565 Binary files /dev/null and b/tutorial01/.cache/clangd/index/leptjson.h.CDC4968BBDE8B0BC.idx differ diff --git a/tutorial01/.cache/clangd/index/test.c.664A6CD92B020790.idx b/tutorial01/.cache/clangd/index/test.c.664A6CD92B020790.idx new file mode 100644 index 00000000..8b6481e0 Binary files /dev/null and b/tutorial01/.cache/clangd/index/test.c.664A6CD92B020790.idx differ diff --git a/tutorial01/leptjson.c b/tutorial01/leptjson.c index 5299fe1d..87e7f934 100644 --- a/tutorial01/leptjson.c +++ b/tutorial01/leptjson.c @@ -1,47 +1,87 @@ #include "leptjson.h" -#include /* assert() */ -#include /* NULL */ +#include /* assert() */ +#include /* NULL */ -#define EXPECT(c, ch) do { assert(*c->json == (ch)); c->json++; } while(0) +#define EXPECT(c, ch) \ + do { \ + assert(*c->json == (ch)); \ + c->json++; \ + } while (0) typedef struct { - const char* json; -}lept_context; - -static void lept_parse_whitespace(lept_context* c) { - const char *p = c->json; - while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r') - p++; - c->json = p; + const char *json; +} lept_context; + +static void lept_parse_whitespace(lept_context *c) { + const char *p = c->json; + while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r') + p++; + 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; - return LEPT_PARSE_OK; +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_value(lept_context* c, lept_value* v) { - switch (*c->json) { - case 'n': return lept_parse_null(c, v); - case '\0': return LEPT_PARSE_EXPECT_VALUE; - default: return LEPT_PARSE_INVALID_VALUE; - } +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; } -int lept_parse(lept_value* v, const char* json) { - lept_context c; - assert(v != NULL); - c.json = json; - v->type = LEPT_NULL; +static int lept_parse_value(lept_context *c, lept_value *v) { + switch (*c->json) { + case 'n': + return lept_parse_null(c, v); + case '\0': + return LEPT_PARSE_EXPECT_VALUE; + case 't': + return lept_parse_true(c, v); + case 'f': + return lept_parse_false(c, v); + default: + return LEPT_PARSE_INVALID_VALUE; + } +} + +int lept_parse(lept_value *v, const char *json) { + lept_context c; + int res; + assert(v != NULL); + c.json = json; + v->type = LEPT_NULL; + lept_parse_whitespace(&c); + res = lept_parse_value(&c, v); + if (res == LEPT_PARSE_OK) { lept_parse_whitespace(&c); - return lept_parse_value(&c, v); + if (c.json[0] != '\0') { + res = LEPT_PARSE_ROOT_NOT_SINGULAR; + } + } + return res; } -lept_type lept_get_type(const lept_value* v) { - assert(v != NULL); - return v->type; +lept_type lept_get_type(const lept_value *v) { + assert(v != NULL); + return v->type; } diff --git a/tutorial01/test.c b/tutorial01/test.c index e7672181..2098ec3b 100644 --- a/tutorial01/test.c +++ b/tutorial01/test.c @@ -27,6 +27,21 @@ 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 +74,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/.cache/clangd/index/leptjson.c.1E269D31D4DDC82F.idx b/tutorial02/.cache/clangd/index/leptjson.c.1E269D31D4DDC82F.idx new file mode 100644 index 00000000..1de6bde9 Binary files /dev/null and b/tutorial02/.cache/clangd/index/leptjson.c.1E269D31D4DDC82F.idx differ diff --git a/tutorial02/.cache/clangd/index/leptjson.h.3484794EA4220B95.idx b/tutorial02/.cache/clangd/index/leptjson.h.3484794EA4220B95.idx new file mode 100644 index 00000000..e9f5cdb5 Binary files /dev/null and b/tutorial02/.cache/clangd/index/leptjson.h.3484794EA4220B95.idx differ diff --git a/tutorial02/.cache/clangd/index/test.c.E013ADDE26D3B5C9.idx b/tutorial02/.cache/clangd/index/test.c.E013ADDE26D3B5C9.idx new file mode 100644 index 00000000..8fb122ea Binary files /dev/null and b/tutorial02/.cache/clangd/index/test.c.E013ADDE26D3B5C9.idx differ diff --git a/tutorial02/leptjson.c b/tutorial02/leptjson.c index 7693e43b..6da42e1e 100644 --- a/tutorial02/leptjson.c +++ b/tutorial02/leptjson.c @@ -1,8 +1,15 @@ #include "leptjson.h" #include /* assert() */ +#include #include /* NULL, strtod() */ +#include +/* #include */ +#include +#include #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,7 +22,7 @@ static void lept_parse_whitespace(lept_context* c) { c->json = p; } -static int lept_parse_true(lept_context* c, lept_value* v) { +/*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; @@ -40,12 +47,55 @@ static int lept_parse_null(lept_context* c, lept_value* v) { c->json += 3; v->type = LEPT_NULL; return LEPT_PARSE_OK; +}*/ + +static int lept_parse_literal(lept_context* c, lept_value* v, const char* target, int type) { + int len = strlen(target); + int i; + /* assert(strlen(c->json) == len); */ + for (i = 0; i < len; ++i) { + if (c->json[i] != target[i]) { + return LEPT_PARSE_INVALID_VALUE; + } + } + c->json += len; + v->type = type; + return LEPT_PARSE_OK; } static int lept_parse_number(lept_context* c, lept_value* v) { char* end; /* \TODO validate number */ + /* 1. start with 0-9 or - */ + int len = strlen(c->json); + if (c->json[0] != '-' && !ISDIGIT(c->json[0])) { + return LEPT_PARSE_INVALID_VALUE; + } + /* 2. 0 must be single 0, can't be like 0.0 */ + if (c->json[0] == '0' && len > 1) { + if (c->json[1] != '.') { + return LEPT_PARSE_ROOT_NOT_SINGULAR; + } + } + /* 3. there must be some numbers after . */ + if (len > 1) { + int i = 0; + for (i = 0; i < len; ++i) { + if (c->json[i] == '.') { + if (i == len - 1) { + return LEPT_PARSE_INVALID_VALUE; + } else { + break; + } + } + } + } + errno = 0; v->n = strtod(c->json, &end); + if (errno == ERANGE && (v->n == HUGE_VAL || v->n == -HUGE_VAL)) { + v->type = LEPT_NULL; + return LEPT_PARSE_NUMBER_TOO_BIG; + } if (c->json == end) return LEPT_PARSE_INVALID_VALUE; c->json = end; @@ -55,9 +105,14 @@ static int lept_parse_number(lept_context* c, lept_value* v) { 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 eaa5db69..78a26d25 100644 --- a/tutorial02/test.c +++ b/tutorial02/test.c @@ -70,6 +70,12 @@ 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"); + TEST_NUMBER(4.9406564584124654e-324, "4.9406564584124654e-324"); + TEST_NUMBER(2.2250738585072009e-308, "2.2250738585072009e-308"); + TEST_NUMBER(2.2250738585072014e-308, "2.2250738585072014e-308"); + TEST_NUMBER(1.7976931348623157e+308, "1.7976931348623157e+308"); } #define TEST_ERROR(error, json)\ @@ -89,7 +95,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 +104,19 @@ 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 '.' , 'E' , 'e' 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() {