From 55949808f813d93d6273d76223d04a186f2b02b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B6=85=20=E5=BC=A0?= Date: Sun, 25 Sep 2016 23:49:51 +0800 Subject: [PATCH 01/20] add self --- self01/CMakeLists.txt | 10 +++++ self01/leptjson.c | 86 ++++++++++++++++++++++++++++++++++++++ self01/leptjson.h | 21 ++++++++++ self01/test.c | 96 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 213 insertions(+) create mode 100644 self01/CMakeLists.txt create mode 100644 self01/leptjson.c create mode 100644 self01/leptjson.h create mode 100644 self01/test.c diff --git a/self01/CMakeLists.txt b/self01/CMakeLists.txt new file mode 100644 index 00000000..49ba19de --- /dev/null +++ b/self01/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required (VERSION 2.6) +project (leptjson_test C) + +if (CMAKE_C_COMPILER_ID MATCHES "GNU|Clang") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ansi -pedantic -Wall") +endif() + +add_library(leptjson leptjson.c) +add_executable(leptjson_test test.c) +target_link_libraries(leptjson_test leptjson) diff --git a/self01/leptjson.c b/self01/leptjson.c new file mode 100644 index 00000000..0fb57b70 --- /dev/null +++ b/self01/leptjson.c @@ -0,0 +1,86 @@ +#include "leptjson.h" +#include +#include + +#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; +} + +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_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; + } +} + +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); + if ((ret = lept_parse_value(&c, v)) == 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; +} diff --git a/self01/leptjson.h b/self01/leptjson.h new file mode 100644 index 00000000..83f9de70 --- /dev/null +++ b/self01/leptjson.h @@ -0,0 +1,21 @@ +#ifndef LEPTJSON_H__ +#define LEPTJSON_H__ + +typedef enum {LEPT_NULL, LEPT_FALSE, LEPT_TRUE, LEPT_NUMBER, LEPT_STRING, LEPT_ARRAY, LEPT_OBJECT } lept_type; + +typedef struct{ + lept_type type; +}lept_value; + +enum{ + LEPT_PARSE_OK = 0, + LEPT_PARSE_EXPECT_VALUE, + LEPT_PARSE_INVALID_VALUE, + LEPT_PARSE_ROOT_NOT_SINGULAR +}; + +int lept_parse(lept_value * v, const char * json); + +lept_type lept_get_type(const lept_value *v); + +#endif diff --git a/self01/test.c b/self01/test.c new file mode 100644 index 00000000..2eaea043 --- /dev/null +++ b/self01/test.c @@ -0,0 +1,96 @@ +#include +#include +#include +#include "leptjson.h" + +static int main_ret = 0; +static int test_count = 0; +static int test_pass = 0; + +#define EXPECT_EQ_BASE(equality, expect, actual, format) \ +do {\ +test_count++;\ +if (equality)\ +test_pass++;\ +else {\ +fprintf(stderr, "%s:%d: expect: " format " actual: " format "\n", __FILE__, __LINE__, expect, actual);\ +main_ret = 1;\ +}\ +} while(0) + +#define EXPECT_EQ_INT(expect, actual) EXPECT_EQ_BASE((expect) == (actual), expect, actual, "%d") + +static void test_parse_null() +{ + 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)); +} + +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_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; + + v.type = LEPT_FALSE; + EXPECT_EQ_INT(LEPT_PARSE_EXPECT_VALUE, lept_parse(&v, "")); + EXPECT_EQ_INT(LEPT_NULL, lept_get_type(&v)); + + v.type = LEPT_FALSE; + EXPECT_EQ_INT(LEPT_PARSE_EXPECT_VALUE, lept_parse(&v, " ")); + EXPECT_EQ_INT(LEPT_NULL, lept_get_type(&v)); +} + +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)); +} + + +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)); +} + + + +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(); +} + +int main() { + test_parse(); + printf("%d/%d (%3.2f%%) passed\n", test_pass, test_count, test_pass * 100.0 / test_count); + return main_ret; +} From 51d53030ec57dc04cd37876068b45948a594505d Mon Sep 17 00:00:00 2001 From: zhangc Date: Mon, 26 Sep 2016 21:27:55 +0800 Subject: [PATCH 02/20] format code --- self01/leptjson.c | 65 ++++++++++++++++++++++++++++++----------------- self01/leptjson.h | 18 +++++++++---- self01/test.c | 45 ++++++++++++++++---------------- 3 files changed, 77 insertions(+), 51 deletions(-) diff --git a/self01/leptjson.c b/self01/leptjson.c index 0fb57b70..a55efd1c 100644 --- a/self01/leptjson.c +++ b/self01/leptjson.c @@ -2,25 +2,33 @@ #include #include -#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; +typedef struct +{ + const char *json; +} lept_context; -static void lept_parse_whitespace(lept_context* c) +static void lept_parse_whitespace(lept_context *c) { const char *p = c->json; - while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r') { + while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r') + { p++; } c->json = p; } -static int lept_parse_null(lept_context* c,lept_value* v) +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') { + if (c->json[0] != 'u' || c->json[1] != 'l' || c->json[2] != 'l') + { return LEPT_PARSE_INVALID_VALUE; } c->json += 3; @@ -28,10 +36,11 @@ static int lept_parse_null(lept_context* c,lept_value* v) return LEPT_PARSE_OK; } -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') { + if (c->json[0] != 'r' || c->json[1] != 'u' || c->json[2] != 'e') + { return LEPT_PARSE_INVALID_VALUE; } c->json += 3; @@ -39,10 +48,11 @@ static int lept_parse_true(lept_context* c,lept_value* v) return LEPT_PARSE_OK; } -static int lept_parse_false(lept_context* c,lept_value* v) +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') { + 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; @@ -50,19 +60,24 @@ static int lept_parse_false(lept_context* c,lept_value* v) return LEPT_PARSE_OK; } - -static int lept_parse_value(lept_context* c, lept_value* v) +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; + 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; } } -int lept_parse(lept_value* v, const char* json) +int lept_parse(lept_value *v, const char *json) { lept_context c; int ret; @@ -70,16 +85,18 @@ int lept_parse(lept_value* v, const char* json) c.json = json; v->type = LEPT_NULL; lept_parse_whitespace(&c); - if ((ret = lept_parse_value(&c, v)) == LEPT_PARSE_OK) { + if ((ret = lept_parse_value(&c, v)) == LEPT_PARSE_OK) + { lept_parse_whitespace(&c); - if (*c.json != '\0') { + if (*c.json != '\0') + { return LEPT_PARSE_ROOT_NOT_SINGULAR; } } return ret; } -lept_type lept_get_type(const lept_value* v) +lept_type lept_get_type(const lept_value *v) { assert(v != NULL); return v->type; diff --git a/self01/leptjson.h b/self01/leptjson.h index 83f9de70..ea9c54ee 100644 --- a/self01/leptjson.h +++ b/self01/leptjson.h @@ -1,20 +1,28 @@ #ifndef LEPTJSON_H__ #define LEPTJSON_H__ -typedef enum {LEPT_NULL, LEPT_FALSE, LEPT_TRUE, LEPT_NUMBER, LEPT_STRING, LEPT_ARRAY, LEPT_OBJECT } lept_type; +typedef enum { LEPT_NULL, + LEPT_FALSE, + LEPT_TRUE, + LEPT_NUMBER, + LEPT_STRING, + LEPT_ARRAY, + LEPT_OBJECT } lept_type; -typedef struct{ +typedef struct +{ lept_type type; -}lept_value; +} lept_value; -enum{ +enum +{ LEPT_PARSE_OK = 0, LEPT_PARSE_EXPECT_VALUE, LEPT_PARSE_INVALID_VALUE, LEPT_PARSE_ROOT_NOT_SINGULAR }; -int lept_parse(lept_value * v, const char * json); +int lept_parse(lept_value *v, const char *json); lept_type lept_get_type(const lept_value *v); diff --git a/self01/test.c b/self01/test.c index 2eaea043..4f352325 100644 --- a/self01/test.c +++ b/self01/test.c @@ -7,16 +7,18 @@ static int main_ret = 0; static int test_count = 0; static int test_pass = 0; -#define EXPECT_EQ_BASE(equality, expect, actual, format) \ -do {\ -test_count++;\ -if (equality)\ -test_pass++;\ -else {\ -fprintf(stderr, "%s:%d: expect: " format " actual: " format "\n", __FILE__, __LINE__, expect, actual);\ -main_ret = 1;\ -}\ -} while(0) +#define EXPECT_EQ_BASE(equality, expect, actual, format) \ + do \ + { \ + test_count++; \ + if (equality) \ + test_pass++; \ + else \ + { \ + fprintf(stderr, "%s:%d: expect: " format " actual: " format "\n", __FILE__, __LINE__, expect, actual); \ + main_ret = 1; \ + } \ + } while (0) #define EXPECT_EQ_INT(expect, actual) EXPECT_EQ_BASE((expect) == (actual), expect, actual, "%d") @@ -42,43 +44,41 @@ static void test_parse_false() 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() { +static void test_parse_expect_value() +{ lept_value v; - + v.type = LEPT_FALSE; EXPECT_EQ_INT(LEPT_PARSE_EXPECT_VALUE, lept_parse(&v, "")); EXPECT_EQ_INT(LEPT_NULL, lept_get_type(&v)); - + v.type = LEPT_FALSE; EXPECT_EQ_INT(LEPT_PARSE_EXPECT_VALUE, lept_parse(&v, " ")); EXPECT_EQ_INT(LEPT_NULL, lept_get_type(&v)); } -static void test_parse_invalid_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)); } - -static void test_parse_root_not_singular() { +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)); } - - static void test_parse() { test_parse_null(); @@ -89,7 +89,8 @@ static void test_parse() test_parse_root_not_singular(); } -int main() { +int main() +{ test_parse(); printf("%d/%d (%3.2f%%) passed\n", test_pass, test_count, test_pass * 100.0 / test_count); return main_ret; From 2c8ae1cfff0e807f881d740790888b0785c4991c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B6=85=20=E5=BC=A0?= Date: Tue, 27 Sep 2016 21:54:39 +0800 Subject: [PATCH 03/20] refactor test --- self01/leptjson.c | 65 +++++++++++++++++++----------- self01/leptjson.h | 19 ++++++--- self01/test.c | 100 ++++++++++++++++++++++------------------------ 3 files changed, 103 insertions(+), 81 deletions(-) diff --git a/self01/leptjson.c b/self01/leptjson.c index 0fb57b70..a55efd1c 100644 --- a/self01/leptjson.c +++ b/self01/leptjson.c @@ -2,25 +2,33 @@ #include #include -#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; +typedef struct +{ + const char *json; +} lept_context; -static void lept_parse_whitespace(lept_context* c) +static void lept_parse_whitespace(lept_context *c) { const char *p = c->json; - while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r') { + while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r') + { p++; } c->json = p; } -static int lept_parse_null(lept_context* c,lept_value* v) +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') { + if (c->json[0] != 'u' || c->json[1] != 'l' || c->json[2] != 'l') + { return LEPT_PARSE_INVALID_VALUE; } c->json += 3; @@ -28,10 +36,11 @@ static int lept_parse_null(lept_context* c,lept_value* v) return LEPT_PARSE_OK; } -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') { + if (c->json[0] != 'r' || c->json[1] != 'u' || c->json[2] != 'e') + { return LEPT_PARSE_INVALID_VALUE; } c->json += 3; @@ -39,10 +48,11 @@ static int lept_parse_true(lept_context* c,lept_value* v) return LEPT_PARSE_OK; } -static int lept_parse_false(lept_context* c,lept_value* v) +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') { + 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; @@ -50,19 +60,24 @@ static int lept_parse_false(lept_context* c,lept_value* v) return LEPT_PARSE_OK; } - -static int lept_parse_value(lept_context* c, lept_value* v) +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; + 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; } } -int lept_parse(lept_value* v, const char* json) +int lept_parse(lept_value *v, const char *json) { lept_context c; int ret; @@ -70,16 +85,18 @@ int lept_parse(lept_value* v, const char* json) c.json = json; v->type = LEPT_NULL; lept_parse_whitespace(&c); - if ((ret = lept_parse_value(&c, v)) == LEPT_PARSE_OK) { + if ((ret = lept_parse_value(&c, v)) == LEPT_PARSE_OK) + { lept_parse_whitespace(&c); - if (*c.json != '\0') { + if (*c.json != '\0') + { return LEPT_PARSE_ROOT_NOT_SINGULAR; } } return ret; } -lept_type lept_get_type(const lept_value* v) +lept_type lept_get_type(const lept_value *v) { assert(v != NULL); return v->type; diff --git a/self01/leptjson.h b/self01/leptjson.h index 83f9de70..46e61f3c 100644 --- a/self01/leptjson.h +++ b/self01/leptjson.h @@ -1,20 +1,29 @@ #ifndef LEPTJSON_H__ #define LEPTJSON_H__ -typedef enum {LEPT_NULL, LEPT_FALSE, LEPT_TRUE, LEPT_NUMBER, LEPT_STRING, LEPT_ARRAY, LEPT_OBJECT } lept_type; +typedef enum { LEPT_ERROR, + LEPT_NULL, + LEPT_FALSE, + LEPT_TRUE, + LEPT_NUMBER, + LEPT_STRING, + LEPT_ARRAY, + LEPT_OBJECT } lept_type; -typedef struct{ +typedef struct +{ lept_type type; -}lept_value; +} lept_value; -enum{ +enum +{ LEPT_PARSE_OK = 0, LEPT_PARSE_EXPECT_VALUE, LEPT_PARSE_INVALID_VALUE, LEPT_PARSE_ROOT_NOT_SINGULAR }; -int lept_parse(lept_value * v, const char * json); +int lept_parse(lept_value *v, const char *json); lept_type lept_get_type(const lept_value *v); diff --git a/self01/test.c b/self01/test.c index 2eaea043..833221b9 100644 --- a/self01/test.c +++ b/self01/test.c @@ -7,78 +7,73 @@ static int main_ret = 0; static int test_count = 0; static int test_pass = 0; -#define EXPECT_EQ_BASE(equality, expect, actual, format) \ -do {\ -test_count++;\ -if (equality)\ -test_pass++;\ -else {\ -fprintf(stderr, "%s:%d: expect: " format " actual: " format "\n", __FILE__, __LINE__, expect, actual);\ -main_ret = 1;\ -}\ -} while(0) +#define EXPECT_EQ_BASE(equality, expect, actual, format) \ + do \ + { \ + test_count++; \ + if (equality) \ + test_pass++; \ + else \ + { \ + fprintf(stderr, "%s:%d: expect: " format " actual: " format "\n", __FILE__, __LINE__, expect, actual); \ + main_ret = 1; \ + } \ + } while (0) #define EXPECT_EQ_INT(expect, actual) EXPECT_EQ_BASE((expect) == (actual), expect, actual, "%d") +#define EXPECT_UNEQ_INT(expect, actual) EXPECT_EQ_BASE((expect) != (actual), expect, actual, "%d") + +#define TEST_ERROR(error, json) \ + do \ + { \ + lept_value v; \ + v.type = LEPT_ERROR; \ + EXPECT_UNEQ_INT(error, lept_parse(&v, json)); \ + EXPECT_EQ_INT(LEPT_NULL, lept_get_type(&v)); \ + } while (0) + +#define TEST_RIGHT(right, json, value) \ + do \ + { \ + lept_value v; \ + v.type = LEPT_ERROR; \ + EXPECT_EQ_INT(right, lept_parse(&v, json)); \ + EXPECT_EQ_INT(value, lept_get_type(&v)); \ + } while (0) + static void test_parse_null() { - 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)); + TEST_RIGHT(LEPT_PARSE_OK, "null", LEPT_NULL); } 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_TRUE, lept_get_type(&v)); + TEST_RIGHT(LEPT_PARSE_OK, "true", LEPT_TRUE); } 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)); - + TEST_RIGHT(LEPT_PARSE_OK,"false", LEPT_FALSE); } - -static void test_parse_expect_value() { - lept_value v; - - v.type = LEPT_FALSE; - EXPECT_EQ_INT(LEPT_PARSE_EXPECT_VALUE, lept_parse(&v, "")); - EXPECT_EQ_INT(LEPT_NULL, lept_get_type(&v)); - - v.type = LEPT_FALSE; - EXPECT_EQ_INT(LEPT_PARSE_EXPECT_VALUE, lept_parse(&v, " ")); - EXPECT_EQ_INT(LEPT_NULL, lept_get_type(&v)); +static void test_parse_expect_value() +{ + TEST_RIGHT(LEPT_PARSE_EXPECT_VALUE, "", LEPT_NULL); + TEST_RIGHT(LEPT_PARSE_EXPECT_VALUE, " ", LEPT_NULL); } -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)); +static void test_parse_invalid_value() +{ + TEST_ERROR(LEPT_PARSE_EXPECT_VALUE, "nul"); + TEST_ERROR(LEPT_PARSE_EXPECT_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)); +static void test_parse_root_not_singular() +{ + TEST_RIGHT(LEPT_PARSE_ROOT_NOT_SINGULAR, "null x", LEPT_NULL); } - - static void test_parse() { test_parse_null(); @@ -89,7 +84,8 @@ static void test_parse() test_parse_root_not_singular(); } -int main() { +int main() +{ test_parse(); printf("%d/%d (%3.2f%%) passed\n", test_pass, test_count, test_pass * 100.0 / test_count); return main_ret; From f7e4df16c440bfae851e4a58a1c12629256f4575 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B6=85=20=E5=BC=A0?= Date: Wed, 12 Oct 2016 23:00:56 +0800 Subject: [PATCH 04/20] add parser number --- self01/leptjson.c | 20 +++++++++++++++++++- self01/leptjson.h | 3 +++ self01/test.c | 11 +++++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/self01/leptjson.c b/self01/leptjson.c index a55efd1c..e32b2e60 100644 --- a/self01/leptjson.c +++ b/self01/leptjson.c @@ -60,6 +60,19 @@ static int lept_parse_false(lept_context *c, lept_value *v) 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) @@ -73,7 +86,7 @@ static int lept_parse_value(lept_context *c, lept_value *v) case '\0': return LEPT_PARSE_EXPECT_VALUE; default: - return LEPT_PARSE_INVALID_VALUE; + return lept_parse_number(c, v); } } @@ -101,3 +114,8 @@ 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/self01/leptjson.h b/self01/leptjson.h index 46e61f3c..dcc7d2c9 100644 --- a/self01/leptjson.h +++ b/self01/leptjson.h @@ -12,6 +12,7 @@ typedef enum { LEPT_ERROR, typedef struct { + double n; lept_type type; } lept_value; @@ -27,4 +28,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 diff --git a/self01/test.c b/self01/test.c index 833221b9..afed7d52 100644 --- a/self01/test.c +++ b/self01/test.c @@ -22,6 +22,8 @@ static int test_pass = 0; #define EXPECT_EQ_INT(expect, actual) EXPECT_EQ_BASE((expect) == (actual), expect, actual, "%d") +#define EXPECT_EQ_DOUBLE(expect, actual) EXPECT_EQ_BASE((expect) == (actual), expect, actual, "%.17g") + #define EXPECT_UNEQ_INT(expect, actual) EXPECT_EQ_BASE((expect) != (actual), expect, actual, "%d") #define TEST_ERROR(error, json) \ @@ -42,6 +44,15 @@ static int test_pass = 0; EXPECT_EQ_INT(value, lept_get_type(&v)); \ } while (0) +#define TEST_NUMBER(expect, json) \ +do {\ + lept_value v; \ + v.type = LEPT_ERROR; \ + 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)); \ +} + static void test_parse_null() { TEST_RIGHT(LEPT_PARSE_OK, "null", LEPT_NULL); From 8e9c1a9a015cb5054763acae7f551ae7429edd74 Mon Sep 17 00:00:00 2001 From: zhangc Date: Mon, 7 Nov 2016 18:29:59 +0800 Subject: [PATCH 05/20] modify --- self01/leptjson.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/self01/leptjson.c b/self01/leptjson.c index e32b2e60..07898b1b 100644 --- a/self01/leptjson.c +++ b/self01/leptjson.c @@ -117,5 +117,5 @@ lept_type lept_get_type(const lept_value *v) double lept_get_number(const lept_value* v){ assert(v != NULL && v->type == LEPT_NUMBER); - return v.n; + return v->n; } From ea59ebe3422135005b3336dd3174f53b368f7c03 Mon Sep 17 00:00:00 2001 From: chao Date: Thu, 10 Nov 2016 18:50:09 +0800 Subject: [PATCH 06/20] add parse num --- self01/leptjson.c | 53 +++++++++++++++++++++++++++++++++++++++-------- self01/leptjson.h | 9 ++++---- self01/test.c | 26 ++++++++++++++++++++++- 3 files changed, 74 insertions(+), 14 deletions(-) diff --git a/self01/leptjson.c b/self01/leptjson.c index 07898b1b..43440e4d 100644 --- a/self01/leptjson.c +++ b/self01/leptjson.c @@ -1,6 +1,8 @@ #include "leptjson.h" #include #include +#include +#include #define EXPECT(c, ch) \ do \ @@ -9,6 +11,8 @@ c->json++; \ } while (0) +#define ISDIGIT(ch) ((ch) >= '0' && (ch) <= '9') +#define ISDIGIT1TO9(ch) ((ch) >= '0' && (ch) <= '9') typedef struct { const char *json; @@ -62,15 +66,46 @@ static int lept_parse_false(lept_context *c, lept_value *v) 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; + const char * p = c->json; + if (*p == '-') p++; + if (*p == '0') + { + p++; + } + else + { + + if (!ISDIGIT1TO9(*p)) return LEPT_PARSE_INVALID_VALUE; + p++; + for (; ISDIGIT(*p); p++); + } + + if (*p == '.') + { + p++; + if (!ISDIGIT(*p)) return LEPT_PARSE_INVALID_VALUE; + p++; + for (; ISDIGIT(*p); p++); + } + + if (*p == 'e' || *p == 'E') + { + p++; + if (*p == '+' || *p == '-') p++; + if (!ISDIGIT(*p)) return LEPT_PARSE_INVALID_VALUE; + p++; + for (; ISDIGIT(*p); p++); + } + + 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_value(lept_context *c, lept_value *v) diff --git a/self01/leptjson.h b/self01/leptjson.h index dcc7d2c9..541aba3c 100644 --- a/self01/leptjson.h +++ b/self01/leptjson.h @@ -18,10 +18,11 @@ typedef struct enum { - LEPT_PARSE_OK = 0, - LEPT_PARSE_EXPECT_VALUE, - LEPT_PARSE_INVALID_VALUE, - LEPT_PARSE_ROOT_NOT_SINGULAR + LEPT_PARSE_OK = 0, + LEPT_PARSE_EXPECT_VALUE, + LEPT_PARSE_INVALID_VALUE, + LEPT_PARSE_ROOT_NOT_SINGULAR, + LEPT_PARSE_NUMBER_TOO_BIG }; int lept_parse(lept_value *v, const char *json); diff --git a/self01/test.c b/self01/test.c index afed7d52..99a97543 100644 --- a/self01/test.c +++ b/self01/test.c @@ -51,7 +51,7 @@ do {\ 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() { @@ -85,6 +85,28 @@ static void test_parse_root_not_singular() TEST_RIGHT(LEPT_PARSE_ROOT_NOT_SINGULAR, "null x", LEPT_NULL); } +static void test_parse_number() { + TEST_NUMBER(0.0, "0"); + TEST_NUMBER(0.0, "-0"); + TEST_NUMBER(0.0, "-0.0"); + TEST_NUMBER(1.0, "1"); + TEST_NUMBER(-1.0, "-1"); + TEST_NUMBER(1.5, "1.5"); + TEST_NUMBER(-1.5, "-1.5"); + TEST_NUMBER(3.1416, "3.1416"); + TEST_NUMBER(1E10, "1E10"); + TEST_NUMBER(1e10, "1e10"); + TEST_NUMBER(1E+10, "1E+10"); + TEST_NUMBER(1E-10, "1E-10"); + TEST_NUMBER(-1E10, "-1E10"); + TEST_NUMBER(-1e10, "-1e10"); + TEST_NUMBER(-1E+10, "-1E+10"); + TEST_NUMBER(-1E-10, "-1E-10"); + TEST_NUMBER(1.234E+10, "1.234E+10"); + TEST_NUMBER(1.234E-10, "1.234E-10"); + TEST_NUMBER(0.0, "1e-10000"); /* must underflow */ +} + static void test_parse() { test_parse_null(); @@ -93,8 +115,10 @@ static void test_parse() test_parse_expect_value(); test_parse_invalid_value(); test_parse_root_not_singular(); + test_parse_number(); } + int main() { test_parse(); From c6a329ea9b18e8dad5e7f6724064229dcee9c692 Mon Sep 17 00:00:00 2001 From: chao Date: Thu, 10 Nov 2016 18:53:22 +0800 Subject: [PATCH 07/20] test --- self01/test.c | 1 + 1 file changed, 1 insertion(+) diff --git a/self01/test.c b/self01/test.c index 99a97543..c6c5b9e7 100644 --- a/self01/test.c +++ b/self01/test.c @@ -105,6 +105,7 @@ 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 */ + } static void test_parse() From 9f753f2454f1c8e11eed51a43bf7a6ef9f6b5989 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B6=85=20=E5=BC=A0?= Date: Sat, 12 Nov 2016 13:20:50 +0800 Subject: [PATCH 08/20] add literal --- self01/leptjson.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/self01/leptjson.c b/self01/leptjson.c index 43440e4d..5350f053 100644 --- a/self01/leptjson.c +++ b/self01/leptjson.c @@ -28,6 +28,12 @@ static void lept_parse_whitespace(lept_context *c) c->json = p; } +static int lept_perser_literal(lept_context* c, lept_value* v, const char* literal, lept_type type) +{ + size_t i; + EXPECT(c, literal[0]); +} + static int lept_parse_null(lept_context *c, lept_value *v) { EXPECT(c, 'n'); From 127a557e8bfc067d2aa7a28d0335f31fc45cdd13 Mon Sep 17 00:00:00 2001 From: chao Date: Sat, 12 Nov 2016 20:48:01 +0800 Subject: [PATCH 09/20] add literal --- self01/leptjson.c | 53 +++++++++++++---------------------------------- 1 file changed, 14 insertions(+), 39 deletions(-) diff --git a/self01/leptjson.c b/self01/leptjson.c index 5350f053..8ba73c66 100644 --- a/self01/leptjson.c +++ b/self01/leptjson.c @@ -28,46 +28,21 @@ static void lept_parse_whitespace(lept_context *c) c->json = p; } -static int lept_perser_literal(lept_context* c, lept_value* v, const char* literal, lept_type type) +static int lept_perse_literal(lept_context* c, lept_value* v, const char* literal, lept_type type) { size_t i; EXPECT(c, literal[0]); -} - -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; -} + for (i = 0; literal[i + 1]; i++) + { + if (c->json[i] != literal[i]) + { + return LEPT_PARSE_INVALID_VALUE; + } + } -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; + c->json += i; + v->type = type; + return LEPT_PARSE_OK; } static int lept_parse_number(lept_context* c, lept_value* v) @@ -119,11 +94,11 @@ static int lept_parse_value(lept_context *c, lept_value *v) switch (*c->json) { case 'n': - return lept_parse_null(c, v); + return lept_perse_literal(c, v, "null", LEPT_NULL); case 't': - return lept_parse_true(c, v); + return lept_perse_literal(c, v, "true", LEPT_TRUE); case 'f': - return lept_parse_false(c, v); + return lept_perse_literal(c, v, "false",LEPT_FALSE); case '\0': return LEPT_PARSE_EXPECT_VALUE; default: From 23426a642c7802f10505ef0c20e01097f09157bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B6=85=20=E5=BC=A0?= Date: Sat, 12 Nov 2016 21:19:49 +0800 Subject: [PATCH 10/20] fix literal --- self01/leptjson.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/self01/leptjson.c b/self01/leptjson.c index 8ba73c66..8727a377 100644 --- a/self01/leptjson.c +++ b/self01/leptjson.c @@ -34,7 +34,7 @@ static int lept_perse_literal(lept_context* c, lept_value* v, const char* litera EXPECT(c, literal[0]); for (i = 0; literal[i + 1]; i++) { - if (c->json[i] != literal[i]) + if (c->json[i] != literal[i + 1]) { return LEPT_PARSE_INVALID_VALUE; } From d4f76665310a69fc09ec4023d6c3b24bfdba58d2 Mon Sep 17 00:00:00 2001 From: chao Date: Mon, 14 Nov 2016 17:54:10 +0800 Subject: [PATCH 11/20] add set get --- self01/leptjson.c | 157 +++++++++++++++++++++++++++++++--------------- self01/leptjson.h | 35 ++++++++++- self01/test.c | 2 +- 3 files changed, 141 insertions(+), 53 deletions(-) diff --git a/self01/leptjson.c b/self01/leptjson.c index 8727a377..a0ced726 100644 --- a/self01/leptjson.c +++ b/self01/leptjson.c @@ -1,8 +1,9 @@ #include "leptjson.h" -#include -#include -#include -#include +#include /* assert() */ +#include /* errno, ERANGE */ +#include /* HUGE_VAL */ +#include /* NULL, malloc(), realloc(), free(), strtod() */ +#include /* memcpy() */ #define EXPECT(c, ch) \ do \ @@ -13,25 +14,21 @@ #define ISDIGIT(ch) ((ch) >= '0' && (ch) <= '9') #define ISDIGIT1TO9(ch) ((ch) >= '0' && (ch) <= '9') -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 *p = c->json; + while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r') + { + p++; + } + c->json = p; } static int lept_perse_literal(lept_context* c, lept_value* v, const char* literal, lept_type type) { - size_t i; - EXPECT(c, literal[0]); + size_t i; + EXPECT(c, literal[0]); for (i = 0; literal[i + 1]; i++) { if (c->json[i] != literal[i + 1]) @@ -79,9 +76,9 @@ static int lept_parse_number(lept_context* c, lept_value* v) } errno = 0; - v->n = strtod(c->json, NULL); - if(errno == ERANGE && (v->n == HUGE_VAL || v->n == -HUGE_VAL)) - { + v->u.n = strtod(c->json, NULL); + if (errno == ERANGE && (v->u.n == HUGE_VAL || v->u.n - HUGE_VAL)) + { return LEPT_PARSE_NUMBER_TOO_BIG; } v->type = LEPT_NUMBER; @@ -91,47 +88,107 @@ 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 'n': + switch (*c->json) + { + case 'n': return lept_perse_literal(c, v, "null", LEPT_NULL); - case 't': + case 't': return lept_perse_literal(c, v, "true", LEPT_TRUE); - case 'f': - return lept_perse_literal(c, v, "false",LEPT_FALSE); - case '\0': - return LEPT_PARSE_EXPECT_VALUE; - default: - return lept_parse_number(c, v); - } + case 'f': + return lept_perse_literal(c, v, "false", LEPT_FALSE); + case '\0': + return LEPT_PARSE_EXPECT_VALUE; + default: + return lept_parse_number(c, 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); - if ((ret = lept_parse_value(&c, v)) == LEPT_PARSE_OK) - { - lept_parse_whitespace(&c); - if (*c.json != '\0') - { - return LEPT_PARSE_ROOT_NOT_SINGULAR; - } - } - return ret; + lept_context c; + int ret; + assert(v != NULL); + c.json = json; + v->type = LEPT_NULL; + lept_parse_whitespace(&c); + if ((ret = lept_parse_value(&c, v)) == 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; + assert(v != NULL); + return v->type; +} + +double lept_get_number(const lept_value* v) { + + if (v == NULL || v->type != LEPT_NUMBER) + { + printf("---------"); + } + assert(v != NULL && v->type == LEPT_NUMBER); + return v->u.n; } -double lept_get_number(const lept_value* v){ - assert(v != NULL && v->type == LEPT_NUMBER); - return v->n; +void lept_free(lept_value *v) +{ + assert(v != NULL); + if (v->type == LEPT_STRING) + { + free(v->u.s.s); + } + v->type = LEPT_NULL; +} + +int lept_get_boolean(const lept_value *v) +{ + 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) +{ + lept_free(v); + v->type = b ? LEPT_TRUE : LEPT_FALSE; +} + +double lept_get_number(const lept_value *v) +{ + assert(v != NULL && v->type == LEPT_NUMBER); + return v->u.n; +} +void lept_set_number(lept_value *v, double n) +{ + lept_free(v); + v->u.n = n; + v->type = LEPT_NUMBER; +} + +const char * lept_get_string(const lept_value *v) +{ + assert(v != NULL && v->type == LEPT_STRING); + return v->u.s.s; +} +size_t lept_get_string_len(const lept_value *v) +{ + assert(v != NULL && v->type == LEPT_STRING); + return v->u.s.len; +} + +void lept_set_string(lept_value *v, const char *s, size_t len) +{ + assert(v != NULL && s != NULL && len != 0); + lept_free(v); + v->u.s.s = (char *)malloc(len + 1); + memcpy(v->u.s.s, s, len); + v->u.s.s[len] = '\0'; + v->u.s.len = len; + v->type = LEPT_STRING; } diff --git a/self01/leptjson.h b/self01/leptjson.h index 541aba3c..05331402 100644 --- a/self01/leptjson.h +++ b/self01/leptjson.h @@ -1,6 +1,8 @@ #ifndef LEPTJSON_H__ #define LEPTJSON_H__ +#include /* size_t */ + typedef enum { LEPT_ERROR, LEPT_NULL, LEPT_FALSE, @@ -12,10 +14,25 @@ typedef enum { LEPT_ERROR, typedef struct { - double n; + union + { + struct + { + char *s; + size_t len; + } s; + double n; + }u; lept_type type; } lept_value; +typedef struct +{ + const char *json; + char * stack; + size_t size, top; +} lept_context; + enum { LEPT_PARSE_OK = 0, @@ -25,10 +42,24 @@ enum LEPT_PARSE_NUMBER_TOO_BIG }; +#define lept_init(v) do {(v)->type = LEPT_NULL;} while (0); + int lept_parse(lept_value *v, const char *json); +void lept_free(lept_value *v); + lept_type lept_get_type(const lept_value *v); -double lept_get_number(const lept_value* v); +#define lept_set_null(v) lept_free(v) + +int lept_get_boolean(const lept_value *v); +void lept_set_boolean(lept_value *v, int b); + +double lept_get_number(const lept_value *v); +void lept_set_number(lept_value *v, double n); + +const char * lept_get_string(const lept_value *v); +size_t lept_get_string_len(const lept_value *v); +void lept_set_string(lept_value *v, const char *s, size_t len); #endif diff --git a/self01/test.c b/self01/test.c index c6c5b9e7..a8666a5f 100644 --- a/self01/test.c +++ b/self01/test.c @@ -104,7 +104,7 @@ static void test_parse_number() { TEST_NUMBER(-1E-10, "-1E-10"); 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(0.0, "1e-10000"); /* must underflow */ } From a236bd2fd5eea072a754dc8826b1198d1b039d50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E8=B6=85?= Date: Mon, 13 Mar 2017 11:31:09 +0800 Subject: [PATCH 12/20] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E8=87=AA=E5=B7=B1?= =?UTF-8?q?=E7=9A=84=E5=B7=A5=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 +++ self01/CMakeLists.txt | 8 ++++++++ self01/leptjson.cpp | 0 self01/leptjson.h | 6 ++++++ self01/test.c | 0 5 files changed, 17 insertions(+) create mode 100644 self01/CMakeLists.txt create mode 100644 self01/leptjson.cpp create mode 100644 self01/leptjson.h create mode 100644 self01/test.c diff --git a/.gitignore b/.gitignore index e3412016..15b0d4e3 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,4 @@ */build/ +/.vs +/.vs +.vs \ No newline at end of file diff --git a/self01/CMakeLists.txt b/self01/CMakeLists.txt new file mode 100644 index 00000000..9e4d36ac --- /dev/null +++ b/self01/CMakeLists.txt @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 2.6) +project(leptjson_test C) + +if(CMAKE_C_COMPILE_ID MATCHES "GNU|Clang") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ansi -pedantic -Wall") +endif() + +target_link_libraries(leptjson_test leptjson) \ No newline at end of file diff --git a/self01/leptjson.cpp b/self01/leptjson.cpp new file mode 100644 index 00000000..e69de29b diff --git a/self01/leptjson.h b/self01/leptjson.h new file mode 100644 index 00000000..f3382e31 --- /dev/null +++ b/self01/leptjson.h @@ -0,0 +1,6 @@ +#ifndef LEPTJSON_H__ +#define LEPTJSON_H__ + + +#endif // !LEPTJSON_H__ + diff --git a/self01/test.c b/self01/test.c new file mode 100644 index 00000000..e69de29b From 949e4c1df68894581b62c10daac32c29165d5fe5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E8=B6=85?= Date: Mon, 13 Mar 2017 15:57:04 +0800 Subject: [PATCH 13/20] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E8=87=AA=E5=B7=B1?= =?UTF-8?q?=E7=9A=84=E9=83=A8=E5=88=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- self01/CMakeLists.txt | 2 ++ self01/leptjson.cpp | 53 +++++++++++++++++++++++++++++++++++++++++++ self01/leptjson.h | 17 ++++++++++++++ self01/test.c | 35 ++++++++++++++++++++++++++++ 4 files changed, 107 insertions(+) diff --git a/self01/CMakeLists.txt b/self01/CMakeLists.txt index 9e4d36ac..61efe286 100644 --- a/self01/CMakeLists.txt +++ b/self01/CMakeLists.txt @@ -5,4 +5,6 @@ if(CMAKE_C_COMPILE_ID MATCHES "GNU|Clang") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ansi -pedantic -Wall") endif() +add_library(leptjson leptjson.c) +add_executable(leptjson_test test.c) target_link_libraries(leptjson_test leptjson) \ No newline at end of file diff --git a/self01/leptjson.cpp b/self01/leptjson.cpp index e69de29b..1c521cdd 100644 --- a/self01/leptjson.cpp +++ b/self01/leptjson.cpp @@ -0,0 +1,53 @@ +#include "leptjson.h" +#include /* assert() */ +#include /* NULL */ + +#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; +} + +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; +} + +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; + } +} + +int lept_parse(lept_value * v, const char * json) +{ + lept_context c; + assert(v != NULL); + c.json = json; + v->type = LEPT_NULL; + lept_parse_whitespace(&c); + return lept_parse_value(&c, v); +} + +lept_type lept_get_type(const lept_value * v) +{ + assert(v != NULL); + return v->type; +} diff --git a/self01/leptjson.h b/self01/leptjson.h index f3382e31..0eba6325 100644 --- a/self01/leptjson.h +++ b/self01/leptjson.h @@ -1,6 +1,23 @@ #ifndef LEPTJSON_H__ #define LEPTJSON_H__ +typedef enum {LEPT_NULL, LEPT_FALSE, LEPT_TRUE, LEPT_NUMBER, LEPT_STRING, LEPT_ARRAY, LEPT_OBJECT} lept_type; + +typedef struct { + lept_type type; +} lept_value; + +enum +{ + LEPT_PARSE_OK = 0, + LEPT_PARSE_EXPECT_VALUE, + LEPT_PARSE_INVALID_VALUE, + LEPT_PARSE_ROOT_NOT_SINGLAR +}; + +int lept_parse(lept_value * v, const char * json); + +lept_type lept_get_type(const lept_value * v); #endif // !LEPTJSON_H__ diff --git a/self01/test.c b/self01/test.c index e69de29b..cf26444f 100644 --- a/self01/test.c +++ b/self01/test.c @@ -0,0 +1,35 @@ +#include +#include +#include +#include "leptjson.h" + +static int main_ret = 0; +static int test_count = 0; +static int test_pass = 0; + +#define EXPECT_EQ_BASE(equality, expect, actual, format) \ +do { \ + test_count++; \ + if (equality) \ + test_pass++; \ + else { \ + fprintf(stderr, "%s:%d: expect: " format " actual�� " format "\n", __FILE__, __LINE__, expect, actual) \ + main_ret = 1; \ + } \ +} while (0) + +#define EXPECT_EQ_INT(expect, actual) EXPECT_EQ_BASE((expect) == (actual), expect, actual, "%d") + +static void test_parse_null() { + +} + +static void test_parse() +{ + test_parse_null(); +} + +int main() { + test_parse(); + printf("%d/%d (%3.2f%%) passed \n", test_pass, test_count, test_pass * 100.0 / test_count); +} \ No newline at end of file From bdd4a9fe135f84537fbb09bedf0588a13bc97f98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E8=B6=85?= Date: Mon, 13 Mar 2017 16:16:49 +0800 Subject: [PATCH 14/20] =?UTF-8?q?=E4=BF=AE=E8=AF=A5=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- self01/CMakeLists.txt | 6 +++--- self01/{leptjson.cpp => leptjson.c} | 3 +++ self01/test.c | 6 ++++-- 3 files changed, 10 insertions(+), 5 deletions(-) rename self01/{leptjson.cpp => leptjson.c} (94%) diff --git a/self01/CMakeLists.txt b/self01/CMakeLists.txt index 61efe286..01b82d54 100644 --- a/self01/CMakeLists.txt +++ b/self01/CMakeLists.txt @@ -1,10 +1,10 @@ cmake_minimum_required(VERSION 2.6) -project(leptjson_test C) +project(leptjson_test1 C) if(CMAKE_C_COMPILE_ID MATCHES "GNU|Clang") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ansi -pedantic -Wall") endif() add_library(leptjson leptjson.c) -add_executable(leptjson_test test.c) -target_link_libraries(leptjson_test leptjson) \ No newline at end of file +add_executable(leptjson_test1 test.c) +target_link_libraries(leptjson_test1 leptjson) \ No newline at end of file diff --git a/self01/leptjson.cpp b/self01/leptjson.c similarity index 94% rename from self01/leptjson.cpp rename to self01/leptjson.c index 1c521cdd..b590e465 100644 --- a/self01/leptjson.cpp +++ b/self01/leptjson.c @@ -24,6 +24,9 @@ static int lept_parse_null(lept_context * c, lept_value * v) 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) diff --git a/self01/test.c b/self01/test.c index cf26444f..6a955e0a 100644 --- a/self01/test.c +++ b/self01/test.c @@ -13,7 +13,7 @@ do { \ if (equality) \ test_pass++; \ else { \ - fprintf(stderr, "%s:%d: expect: " format " actual�� " format "\n", __FILE__, __LINE__, expect, actual) \ + fprintf(stderr, "%s:%d: expect: " format " actual�� " format "\n", __FILE__, __LINE__, expect, actual); \ main_ret = 1; \ } \ } while (0) @@ -21,7 +21,9 @@ do { \ #define EXPECT_EQ_INT(expect, actual) EXPECT_EQ_BASE((expect) == (actual), expect, actual, "%d") static void test_parse_null() { - + lept_value v; + v.type = LEPT_FALSE; + EXPECT_EQ_INT(LEPT_PARSE_OK, lept_parse(&v, "null")); } static void test_parse() From aeb37aad5311163a3fb971fce14ee977afef20f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E8=B6=85?= Date: Mon, 13 Mar 2017 17:38:16 +0800 Subject: [PATCH 15/20] add perse (true false) --- self01/leptjson.c | 24 ++++++++++++++++++++++++ self01/test.c | 19 +++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/self01/leptjson.c b/self01/leptjson.c index b590e465..f1823b61 100644 --- a/self01/leptjson.c +++ b/self01/leptjson.c @@ -29,11 +29,35 @@ static int lept_parse_null(lept_context * c, lept_value * v) 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_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; } diff --git a/self01/test.c b/self01/test.c index 6a955e0a..dbffc788 100644 --- a/self01/test.c +++ b/self01/test.c @@ -24,14 +24,33 @@ static void test_parse_null() { 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)); +} + +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_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() { test_parse_null(); + 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); + + return 0; } \ No newline at end of file From 57963dc57864137344a60e0a6220f55c277e3892 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E8=B6=85?= Date: Mon, 13 Mar 2017 22:40:16 +0800 Subject: [PATCH 16/20] =?UTF-8?q?=E6=B7=BB=E5=8A=A0number?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- self01/leptjson.c | 58 ++++++++++++++++++++--------------------------- self01/leptjson.h | 1 + 2 files changed, 26 insertions(+), 33 deletions(-) diff --git a/self01/leptjson.c b/self01/leptjson.c index f1823b61..e95a81f8 100644 --- a/self01/leptjson.c +++ b/self01/leptjson.c @@ -2,7 +2,10 @@ #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) +#define EXPECT(c, ch) do { assert(*c->json == (ch)); } while(0) +#define ISDIGIT(ch) ((ch) >= '0' && (ch) <= '9') +#define ISDIGIT1TO9(ch) ((ch) >= '1' && (ch) <= '9') typedef struct { const char * json; @@ -18,46 +21,30 @@ 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; - 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; +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]; i++) + { + if (c->json[i] != literal[i]) return LEPT_PARSE_INVALID_VALUE; + } + + c->json += i + 1; + 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; } 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 '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; } @@ -70,7 +57,12 @@ 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_SINGLAR; + } + return ret; } lept_type lept_get_type(const lept_value * v) diff --git a/self01/leptjson.h b/self01/leptjson.h index 0eba6325..fdd92a14 100644 --- a/self01/leptjson.h +++ b/self01/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; From f29cedbcf3fa0fac69360ee94214a3fe504ea5b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E8=B6=85?= Date: Tue, 14 Mar 2017 10:42:50 +0800 Subject: [PATCH 17/20] add number perser --- self01/leptjson.c | 67 +++++++++++++++++++++++++++++++++++++++++++++-- self01/leptjson.h | 5 +++- self01/test.c | 42 +++++++++++++++++++++++++++++ 3 files changed, 111 insertions(+), 3 deletions(-) diff --git a/self01/leptjson.c b/self01/leptjson.c index e95a81f8..a4b249e8 100644 --- a/self01/leptjson.c +++ b/self01/leptjson.c @@ -1,6 +1,9 @@ #include "leptjson.h" #include /* assert() */ -#include /* NULL */ +#include /* errno, ERANGE */ +#include /* HUGE_VAL */ +#include /* NULL strtod()*/ + //#define EXPECT(c, ch) do { assert(*c->json == (ch)); c->json++; } while(0) #define EXPECT(c, ch) do { assert(*c->json == (ch)); } while(0) @@ -36,6 +39,60 @@ static int lept_parse_literal(lept_context * c, lept_value * v, const char * lit 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)) { + p++; + } + else + { + return LEPT_PARSE_INVALID_VALUE; + } + + for (; ISDIGIT(*p); p++); + } + + if (*p == '.') { + p++; + if (ISDIGIT(*p)) { + p++; + for (; ISDIGIT(*p); p++); + } + else + { + return LEPT_PARSE_INVALID_VALUE; + } + } + + if (*p == 'e' || *p == 'E') + { + p++; + + if (*p == '+' || *p == '-') p++; + if (ISDIGIT(*p)) { + p++; + for (; ISDIGIT(*p); p++); + } + else + { + return LEPT_PARSE_INVALID_VALUE; + } + } + + 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_value(lept_context * c,lept_value * v) @@ -46,7 +103,7 @@ static int lept_parse_value(lept_context * c,lept_value * v) 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; + default: return lept_parse_number(c, v); } } @@ -70,3 +127,9 @@ 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); + return v->n; +} diff --git a/self01/leptjson.h b/self01/leptjson.h index fdd92a14..5765bdb3 100644 --- a/self01/leptjson.h +++ b/self01/leptjson.h @@ -8,11 +8,12 @@ typedef struct { lept_type type; } lept_value; -enum +enum { LEPT_PARSE_OK = 0, LEPT_PARSE_EXPECT_VALUE, LEPT_PARSE_INVALID_VALUE, + LEPT_PARSE_NUMBER_TOO_BIG, LEPT_PARSE_ROOT_NOT_SINGLAR }; @@ -20,5 +21,7 @@ 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/self01/test.c b/self01/test.c index dbffc788..436ed083 100644 --- a/self01/test.c +++ b/self01/test.c @@ -19,6 +19,7 @@ do { \ } while (0) #define EXPECT_EQ_INT(expect, actual) EXPECT_EQ_BASE((expect) == (actual), expect, actual, "%d") +#define EXPECT_EQ_DOUBLE(expect, actual) EXPECT_EQ_BASE((expect) == (actual), expect, actual, "%.17g") static void test_parse_null() { lept_value v; @@ -41,11 +42,52 @@ static void test_parse_false() { EXPECT_EQ_INT(LEPT_FALSE, lept_get_type(&v)); } +#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_number() { + TEST_NUMBER(0.0, "0"); + TEST_NUMBER(0.0, "-0"); + TEST_NUMBER(0.0, "-0.0"); + TEST_NUMBER(1.0, "1"); + TEST_NUMBER(-1.0, "-1"); + TEST_NUMBER(1.5, "1.5"); + TEST_NUMBER(-1.5, "-1.5"); + TEST_NUMBER(3.1416, "3.1416"); + TEST_NUMBER(1E10, "1E10"); + TEST_NUMBER(1e10, "1e10"); + TEST_NUMBER(1E+10, "1E+10"); + TEST_NUMBER(1E-10, "1E-10"); + TEST_NUMBER(-1E10, "-1E10"); + TEST_NUMBER(-1e10, "-1e10"); + TEST_NUMBER(-1E+10, "-1E+10"); + TEST_NUMBER(-1E-10, "-1E-10"); + 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"); +} + static void test_parse() { test_parse_null(); test_parse_true(); test_parse_false(); + test_parse_number(); } int main() { From d4ba63ff1da7d68a5cb6f29e2ddc6f1b26d71453 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E8=B6=85?= Date: Tue, 14 Mar 2017 18:29:54 +0800 Subject: [PATCH 18/20] =?UTF-8?q?=E6=B7=BB=E5=8A=A0string=E8=A7=A3?= =?UTF-8?q?=E6=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- self01/leptjson.c | 109 ++++++++++++++++++++++++++++++++++++++++++++-- self01/leptjson.h | 25 ++++++++++- self01/test.c | 22 ++++++++++ 3 files changed, 151 insertions(+), 5 deletions(-) diff --git a/self01/leptjson.c b/self01/leptjson.c index a4b249e8..50c74958 100644 --- a/self01/leptjson.c +++ b/self01/leptjson.c @@ -3,17 +3,49 @@ #include /* errno, ERANGE */ #include /* HUGE_VAL */ #include /* NULL strtod()*/ +#include /* memcpy() */ + +#ifndef LEPT_PARSE_STACK_INIT_SIZE +#define LEPT_PARSE_STACK_INIT_SIZE 256 +#endif // !LEPT_PARSE_STACK_INIT_SIZE + //#define EXPECT(c, ch) do { assert(*c->json == (ch)); c->json++; } while(0) #define EXPECT(c, ch) do { assert(*c->json == (ch)); } while(0) #define ISDIGIT(ch) ((ch) >= '0' && (ch) <= '9') #define ISDIGIT1TO9(ch) ((ch) >= '1' && (ch) <= '9') +#define PUTC(c, ch) do { *(char*)lept_context_push(c, sizeof(char)) = (ch);} while(0) typedef struct { const char * json; + char * stack; + size_t size, top; } lept_context; +static void* lept_context_push(lept_context* c, size_t size) +{ + void * ret; + assert(size > 0); + if (c->top + size >= c->size) { + if (c->size == 0) c->size = LEPT_PARSE_STACK_INIT_SIZE; + while (c->top + size >= c->size) + { + c->size += c->size >> 1; + } + c->stack = (char*)realloc(c->stack, c->size); + } + ret = c->stack + c->top; + c->top += size; + return ret; +} + +static void* lept_context_pop(lept_context* c, size_t size) +{ + assert(c->top >= size); + return c->stack + (c->top -= size); +} + static void lept_parse_whitespace(lept_context * c) { const char *p = c->json; @@ -85,8 +117,8 @@ static int lept_parse_number(lept_context *c, lept_value * v) { } errno = 0; - v->n = strtod(c->json, NULL); - if (errno == ERANGE && (v->n == HUGE_VAL || v->n == -HUGE_VAL)) + v->u.n = strtod(c->json, NULL); + if (errno == ERANGE && (v->u.n == HUGE_VAL || v->u.n == -HUGE_VAL)) { return LEPT_PARSE_NUMBER_TOO_BIG; } @@ -95,6 +127,31 @@ static int lept_parse_number(lept_context *c, lept_value * v) { return LEPT_PARSE_OK; } +static int lept_parse_string(lept_context* c, lept_value* v) { + size_t head = c->top, len; + const char* p; + EXPECT(c, '\"'); + p = c->json; + p++; + for (;;) + { + char ch = *p++; + switch (ch) + { + case '\"': + len = c->top - head; + lept_set_string(v, (const char*)lept_context_pop(c, len), len); + c->json = p; + return LEPT_PARSE_OK; + case '\0': + c->top = head; + return LEPT_PARSE_MISS_QUOTATION_MARK; + default: + PUTC(c, ch); + } + } +} + static int lept_parse_value(lept_context * c,lept_value * v) { switch (*c->json) @@ -103,6 +160,7 @@ static int lept_parse_value(lept_context * c,lept_value * v) 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; + case '\"': return lept_parse_string(c, v); default: return lept_parse_number(c, v); } } @@ -128,8 +186,53 @@ lept_type lept_get_type(const lept_value * v) return v->type; } + +void lept_free(lept_value * v) +{ + assert(v != NULL); + if (v->type == LEPT_STRING) free(v->u.s.s); + v->type = LEPT_NULL; +} + + +int lept_get_boolean(const lept_value * v) +{ + assert(v != NULL); + return v->type == LEPT_TRUE; +} +void lept_set_boolean(lept_value * v, int b) +{ + lept_free(v); + v->type = (b ? LEPT_TRUE : LEPT_FALSE); +} + double lept_get_number(const lept_value * v) { assert(v != NULL); - return v->n; + return v->u.n; +} +void lept_set_number(lept_value * v, double n) +{ + /* TODO */ +} + +const char * lept_get_string(const lept_value * v) +{ + assert(v != NULL && v->type == LEPT_STRING); + return v->u.s.s; +} +size_t lept_get_string_length(const lept_value * v) +{ + assert(v != NULL && v->type == LEPT_STRING); + return v->u.s.len; +} +void lept_set_string(lept_value * v, const char * s, size_t len) +{ + assert(v != NULL && (s != NULL || len == 0)); + lept_free(v); + v->u.s.s = (char*)malloc(len + 1); + memcpy(v->u.s.s, s, len); + v->u.s.s[len] = '\0'; + v->u.s.len = len; + v->type = LEPT_STRING; } diff --git a/self01/leptjson.h b/self01/leptjson.h index 5765bdb3..a9873724 100644 --- a/self01/leptjson.h +++ b/self01/leptjson.h @@ -1,10 +1,15 @@ #ifndef LEPTJSON_H__ #define LEPTJSON_H__ +#include /* size_t */ + typedef enum {LEPT_NULL, LEPT_FALSE, LEPT_TRUE, LEPT_NUMBER, LEPT_STRING, LEPT_ARRAY, LEPT_OBJECT} lept_type; typedef struct { - double n; + union { + struct { char * s; size_t len; } s; + double n; + } u; lept_type type; } lept_value; @@ -13,15 +18,31 @@ enum LEPT_PARSE_OK = 0, LEPT_PARSE_EXPECT_VALUE, LEPT_PARSE_INVALID_VALUE, + LEPT_PARSE_ROOT_NOT_SINGLAR, LEPT_PARSE_NUMBER_TOO_BIG, - LEPT_PARSE_ROOT_NOT_SINGLAR + LEPT_PARSE_MISS_QUOTATION_MARK, }; int lept_parse(lept_value * v, const char * json); lept_type lept_get_type(const lept_value * v); + +#define lept_init(v) do { (v)->type = LEPT_NULL; } while(0) + +void lept_free(lept_value * v); + +//#define lept_set_null(v) lept_free(v) + +int lept_get_boolean(const lept_value * v); +void lept_set_boolean(lept_value * v, int b); + double lept_get_number(const lept_value* v); +void lept_set_number(lept_value * v, double n); + +const char * lept_get_string(const lept_value * v); +size_t lept_get_string_length(const lept_value * v); +void lept_set_string(lept_value * v, const char * s, size_t len); #endif // !LEPTJSON_H__ diff --git a/self01/test.c b/self01/test.c index 436ed083..b80cb866 100644 --- a/self01/test.c +++ b/self01/test.c @@ -20,6 +20,8 @@ do { \ #define EXPECT_EQ_INT(expect, actual) EXPECT_EQ_BASE((expect) == (actual), expect, actual, "%d") #define EXPECT_EQ_DOUBLE(expect, actual) EXPECT_EQ_BASE((expect) == (actual), expect, actual, "%.17g") +#define EXPECT_EQ_STRING(expect, actual, alength) \ + EXPECT_EQ_BASE(sizeof(expect) - 1 == alength && memcmp(expect, actual, alength) == 0, expect, actual, "%s") static void test_parse_null() { lept_value v; @@ -82,12 +84,32 @@ static void test_parse_number() { TEST_NUMBER(-1.7976931348623157e+308, "-1.7976931348623157e+308"); } +#define TEST_STRING(expect, json)\ + do {\ + lept_value v;\ + lept_init(&v);\ + EXPECT_EQ_INT(LEPT_PARSE_OK, lept_parse(&v, json));\ + EXPECT_EQ_INT(LEPT_STRING, lept_get_type(&v));\ + EXPECT_EQ_STRING(expect, lept_get_string(&v), lept_get_string_length(&v));\ + lept_free(&v);\ + } while(0) + +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 +} + static void test_parse() { test_parse_null(); test_parse_true(); test_parse_false(); test_parse_number(); + test_parse_string(); } int main() { From 34858952fe3a1df133707f8f6a631d34273e4e0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E8=B6=85?= Date: Wed, 15 Mar 2017 18:56:14 +0800 Subject: [PATCH 19/20] utf-8 --- self01/leptjson.c | 88 +++++++++++++++++++++++++++++++++++++++++++++-- self01/leptjson.h | 4 +++ self01/test.c | 10 ++++-- 3 files changed, 96 insertions(+), 6 deletions(-) diff --git a/self01/leptjson.c b/self01/leptjson.c index 50c74958..5e1cc4a4 100644 --- a/self01/leptjson.c +++ b/self01/leptjson.c @@ -127,8 +127,54 @@ static int lept_parse_number(lept_context *c, lept_value * v) { return LEPT_PARSE_OK; } +static const char * lept_parse_hex4(const char* p, unsigned* u) +{ + int i; + *u = 0; + for (i = 0; i < 4; i++) + { + char ch = *p++; + *u <<= 4; + if (ch >= '0' && ch <= '9') *u |= ch - '0'; + else if (ch >= 'A' && ch <= 'F') *u |= ch - 'A' + 10; + else if (ch >= 'a' && ch <= 'f') *u |= ch - 'a' + 10; + else return NULL; + } + return p; +} + +static void lept_encode_utf8(lept_context* c, unsigned u) +{ + if (u <= 0xFF) + { + PUTC(c, u & 0xFF); + } + else if (u <= 0x7FF) + { + PUTC(c, 0xC0 | ((u >> 6) & 0xFF)); + PUTC(c, 0x80 | (u & 0x3F)); + } + else if (u <= 0xFFFF) + { + PUTC(c, 0xE0 | ((u >> 12) & 0xFF)); + PUTC(c, 0x80 | ((u >> 6) & 0x3F)); + PUTC(c, 0x80 | (u & 0x3F)); + } + else + { + assert(u <= 0x10FFFF); + PUTC(c, 0xF0 | ((u >> 18) & 0xFF)); + 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) + static int lept_parse_string(lept_context* c, lept_value* v) { size_t head = c->top, len; + unsigned u, u2; const char* p; EXPECT(c, '\"'); p = c->json; @@ -143,9 +189,38 @@ static int lept_parse_string(lept_context* c, lept_value* v) { lept_set_string(v, (const char*)lept_context_pop(c, len), len); c->json = p; return LEPT_PARSE_OK; + 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; + case 'u': + if (!(p = lept_parse_hex4(p, &u))) + STRING_ERROR(LEPT_PARSE_INVALID_UNICODE_HEX); + if (u >= 0xD800 && u <= 0xDBFF) { /* surrogate pair */ + if (*p++ != '\\') + STRING_ERROR(LEPT_PARSE_INVALID_UNICODE_SURROGATE); + if (*p++ != 'u') + STRING_ERROR(LEPT_PARSE_INVALID_UNICODE_SURROGATE); + if (!(p = lept_parse_hex4(p, &u2))) + STRING_ERROR(LEPT_PARSE_INVALID_UNICODE_HEX); + if (u2 < 0xDC00 || u2 > 0xDFFF) + STRING_ERROR(LEPT_PARSE_INVALID_UNICODE_SURROGATE); + u = (((u - 0xD800) << 10) | (u2 - 0xDC00)) + 0x10000; + } + lept_encode_utf8(c, u); + break; + default: + STRING_ERROR(LEPT_PARSE_INVALID_STRING_ESCAPE); + } case '\0': - c->top = head; - return LEPT_PARSE_MISS_QUOTATION_MARK; + STRING_ERROR(LEPT_PARSE_MISS_QUOTATION_MARK); default: PUTC(c, ch); } @@ -170,12 +245,19 @@ int lept_parse(lept_value * v, const char * json) lept_context c; assert(v != NULL); c.json = json; + c.stack = NULL; + c.size = c.top = 0; v->type = LEPT_NULL; + lept_init(v); lept_parse_whitespace(&c); 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_SINGLAR; + if (*c.json != '\0') + { + v->type = LEPT_NULL; + ret = LEPT_PARSE_ROOT_NOT_SINGLAR; + } } return ret; } diff --git a/self01/leptjson.h b/self01/leptjson.h index a9873724..86f38157 100644 --- a/self01/leptjson.h +++ b/self01/leptjson.h @@ -21,6 +21,10 @@ enum LEPT_PARSE_ROOT_NOT_SINGLAR, LEPT_PARSE_NUMBER_TOO_BIG, LEPT_PARSE_MISS_QUOTATION_MARK, + LEPT_PARSE_INVALID_STRING_ESCAPE, + LEPT_PARSE_INVALID_STRING_CHAR, + LEPT_PARSE_INVALID_UNICODE_HEX, + LEPT_PARSE_INVALID_UNICODE_SURROGATE }; int lept_parse(lept_value * v, const char * json); diff --git a/self01/test.c b/self01/test.c index b80cb866..95cbe961 100644 --- a/self01/test.c +++ b/self01/test.c @@ -96,11 +96,15 @@ static void test_parse_number() { static void test_parse_string() { TEST_STRING("", "\"\""); - //TEST_STRING("Hello", "\"Hello\""); -#if 0 + TEST_STRING("Hello", "\"Hello\""); TEST_STRING("Hello\nWorld", "\"Hello\\nWorld\""); TEST_STRING("\" \\ / \b \f \n \r \t", "\"\\\" \\\\ \\/ \\b \\f \\n \\r \\t\""); -#endif + TEST_STRING("Hello\0World", "\"Hello\\u0000World\""); + TEST_STRING("\x24", "\"\\u0024\""); /* Dollar sign U+0024 */ + TEST_STRING("\xC2\xA2", "\"\\u00A2\""); /* Cents sign U+00A2 */ + TEST_STRING("\xE2\x82\xAC", "\"\\u20AC\""); /* Euro sign U+20AC */ + TEST_STRING("\xF0\x9D\x84\x9E", "\"\\uD834\\uDD1E\""); /* G clef sign U+1D11E */ + TEST_STRING("\xF0\x9D\x84\x9E", "\"\\ud834\\udd1e\""); /* G clef sign U+1D11E */ } static void test_parse() From b9e6d998757cf3f183645c9dfafd28f1189b737e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E8=B6=85?= Date: Thu, 16 Mar 2017 16:43:32 +0800 Subject: [PATCH 20/20] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=95=B0=E7=BB=84?= =?UTF-8?q?=E8=A7=A3=E6=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- self01/leptjson.c | 98 +++++++++++++++++++++++++++++++++++++++++++---- self01/leptjson.h | 13 +++++-- self01/test.c | 57 ++++++++++++++++++++++++--- 3 files changed, 153 insertions(+), 15 deletions(-) diff --git a/self01/leptjson.c b/self01/leptjson.c index 5e1cc4a4..d46c6ee3 100644 --- a/self01/leptjson.c +++ b/self01/leptjson.c @@ -23,6 +23,8 @@ typedef struct { size_t size, top; } lept_context; +static int lept_parse_value(lept_context * c, lept_value * v); + static void* lept_context_push(lept_context* c, size_t size) { void * ret; @@ -219,6 +221,7 @@ static int lept_parse_string(lept_context* c, lept_value* v) { default: STRING_ERROR(LEPT_PARSE_INVALID_STRING_ESCAPE); } + break; case '\0': STRING_ERROR(LEPT_PARSE_MISS_QUOTATION_MARK); default: @@ -227,16 +230,69 @@ static int lept_parse_string(lept_context* c, lept_value* v) { } } +static int lept_parse_array(lept_context* c, lept_value* v) +{ + size_t i, size = 0; + int ret; + EXPECT(c, '['); + c->json++; + lept_parse_whitespace(c); + if (*c->json == ']') { + c->json++; + v->type = LEPT_ARRAY; + v->u.a.size = 0; + v->u.a.e = NULL; + return LEPT_PARSE_OK; + } + + for (;;) + { + lept_value e; + lept_init(&e); + if ((ret = lept_parse_value(c, &e)) != LEPT_PARSE_OK) break; + + memcpy(lept_context_push(c, sizeof(lept_value)), &e, sizeof(lept_value)); + size++; + lept_parse_whitespace(c); + if (*c->json == ',') + { + c->json++; + lept_parse_whitespace(c); + } + else if (*c->json == ']') + { + c->json++; + v->type = LEPT_ARRAY; + v->u.a.size = size; + size *= sizeof(lept_value); + memcpy(v->u.a.e = (lept_value*)malloc(size), lept_context_pop(c, size), size); + return LEPT_PARSE_OK; + } + else + { + ret = LEPT_PARSE_MISS_COMMA_OR_SQUARE_BRACKET; + break; + } + } + + for ( i = 0; i < size; i++) + { + lept_free((lept_value*)lept_context_pop(c, sizeof(lept_value))); + } + return ret; +} + static int lept_parse_value(lept_context * c,lept_value * v) { switch (*c->json) { - 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; - case '\"': return lept_parse_string(c, v); - default: return lept_parse_number(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; + case '\"': return lept_parse_string(c, v); + case '[': return lept_parse_array(c, v); + default: return lept_parse_number(c, v); } } @@ -272,7 +328,21 @@ lept_type lept_get_type(const lept_value * v) void lept_free(lept_value * v) { assert(v != NULL); - if (v->type == LEPT_STRING) free(v->u.s.s); + switch (v->type) + { + case LEPT_STRING: + free(v->u.s.s); + break; + case LEPT_ARRAY: + for (size_t i = 0; i < v->u.a.size; i++) + { + lept_free(&v->u.a.e[i]); + } + free(v->u.a.e); + break; + default: + break; + } v->type = LEPT_NULL; } @@ -318,3 +388,17 @@ void lept_set_string(lept_value * v, const char * s, size_t len) v->u.s.len = len; v->type = LEPT_STRING; } + +size_t lept_get_array_size(const lept_value* v) +{ + assert(v != NULL && v->type == LEPT_ARRAY); + return v->u.a.size; +} + +lept_value* lept_get_array_element(const lept_value* v, size_t index) +{ + assert(v != NULL && v->type == LEPT_ARRAY); + assert(index < v->u.a.size); + /* & ȡ��ַ�������ȼ����� -> . [] �ȴ���������*/ + return &v->u.a.e[index]; +} diff --git a/self01/leptjson.h b/self01/leptjson.h index 86f38157..97b73205 100644 --- a/self01/leptjson.h +++ b/self01/leptjson.h @@ -5,13 +5,16 @@ typedef enum {LEPT_NULL, LEPT_FALSE, LEPT_TRUE, LEPT_NUMBER, LEPT_STRING, LEPT_ARRAY, LEPT_OBJECT} lept_type; -typedef struct { +typedef struct lept_value lept_value; + +struct lept_value { union { + struct { lept_value* e; size_t size; }a; struct { char * s; size_t len; } s; double n; } u; lept_type type; -} lept_value; +}; enum { @@ -24,7 +27,8 @@ enum LEPT_PARSE_INVALID_STRING_ESCAPE, LEPT_PARSE_INVALID_STRING_CHAR, LEPT_PARSE_INVALID_UNICODE_HEX, - LEPT_PARSE_INVALID_UNICODE_SURROGATE + LEPT_PARSE_INVALID_UNICODE_SURROGATE, + LEPT_PARSE_MISS_COMMA_OR_SQUARE_BRACKET }; int lept_parse(lept_value * v, const char * json); @@ -48,5 +52,8 @@ const char * lept_get_string(const lept_value * v); size_t lept_get_string_length(const lept_value * v); void lept_set_string(lept_value * v, const char * s, size_t len); +size_t lept_get_array_size(const lept_value* v); +lept_value* lept_get_array_element(const lept_value* v, size_t index); + #endif // !LEPTJSON_H__ diff --git a/self01/test.c b/self01/test.c index 95cbe961..52859fa4 100644 --- a/self01/test.c +++ b/self01/test.c @@ -23,6 +23,12 @@ do { \ #define EXPECT_EQ_STRING(expect, actual, alength) \ EXPECT_EQ_BASE(sizeof(expect) - 1 == alength && memcmp(expect, actual, alength) == 0, expect, actual, "%s") +#if defined(_MSC_VER) +#define EXPECT_EQ_SIZE_T(expect, actual) EXPECT_EQ_BASE((expect) == (actual), (size_t)expect, (size_t)actual, "%Iu") +#else +#define EXPECT_EQ_SIZE_T(expect, actual) EXPECT_EQ_BASE((expect) == (actual), (size_t)expect, (size_t)actual, "%zu") +#endif + static void test_parse_null() { lept_value v; v.type = LEPT_FALSE; @@ -107,13 +113,54 @@ static void test_parse_string() { TEST_STRING("\xF0\x9D\x84\x9E", "\"\\ud834\\udd1e\""); /* G clef sign U+1D11E */ } +static void test_parse_array() { + size_t i, j; + lept_value v; + + lept_init(&v); + EXPECT_EQ_INT(LEPT_PARSE_OK, lept_parse(&v, "[ ]")); + EXPECT_EQ_INT(LEPT_ARRAY, lept_get_type(&v)); + EXPECT_EQ_SIZE_T(0, lept_get_array_size(&v)); + lept_free(&v); + + lept_init(&v); + EXPECT_EQ_INT(LEPT_PARSE_OK, lept_parse(&v, "[ null , false , true , 123 , \"abc\" ]")); + EXPECT_EQ_INT(LEPT_ARRAY, lept_get_type(&v)); + EXPECT_EQ_SIZE_T(5, lept_get_array_size(&v)); + EXPECT_EQ_INT(LEPT_NULL, lept_get_type(lept_get_array_element(&v, 0))); + EXPECT_EQ_INT(LEPT_FALSE, lept_get_type(lept_get_array_element(&v, 1))); + EXPECT_EQ_INT(LEPT_TRUE, lept_get_type(lept_get_array_element(&v, 2))); + EXPECT_EQ_INT(LEPT_NUMBER, lept_get_type(lept_get_array_element(&v, 3))); + EXPECT_EQ_INT(LEPT_STRING, lept_get_type(lept_get_array_element(&v, 4))); + EXPECT_EQ_DOUBLE(123.0, lept_get_number(lept_get_array_element(&v, 3))); + EXPECT_EQ_STRING("abc", lept_get_string(lept_get_array_element(&v, 4)), lept_get_string_length(lept_get_array_element(&v, 4))); + lept_free(&v); + + lept_init(&v); + EXPECT_EQ_INT(LEPT_PARSE_OK, lept_parse(&v, "[ [ ] , [ 0 ] , [ 0 , 1 ] , [ 0 , 1 , 2 ] ]")); + EXPECT_EQ_INT(LEPT_ARRAY, lept_get_type(&v)); + EXPECT_EQ_SIZE_T(4, lept_get_array_size(&v)); + for (i = 0; i < 4; i++) { + lept_value* a = lept_get_array_element(&v, i); + EXPECT_EQ_INT(LEPT_ARRAY, lept_get_type(a)); + EXPECT_EQ_SIZE_T(i, lept_get_array_size(a)); + for (j = 0; j < i; j++) { + lept_value* e = lept_get_array_element(a, j); + EXPECT_EQ_INT(LEPT_NUMBER, lept_get_type(e)); + EXPECT_EQ_DOUBLE((double)j, lept_get_number(e)); + } + } + lept_free(&v); +} + static void test_parse() { - test_parse_null(); - test_parse_true(); - test_parse_false(); - test_parse_number(); - test_parse_string(); + //test_parse_null(); + //test_parse_true(); + //test_parse_false(); + //test_parse_number(); + //test_parse_string(); + test_parse_array(); } int main() {