Skip to content

Commit 0bb8c4b

Browse files
committed
My answer
1 parent 3941dcc commit 0bb8c4b

File tree

2 files changed

+51
-38
lines changed

2 files changed

+51
-38
lines changed

tutorial02/leptjson.c

Lines changed: 47 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
#include "leptjson.h"
22
#include <assert.h> /* assert() */
3+
#include <errno.h> /* errno, ERANGE */
4+
#include <math.h> /* HUGE_VAL */
35
#include <stdlib.h> /* NULL, strtod() */
46

57
#define EXPECT(c, ch) do { assert(*c->json == (ch)); c->json++; } while(0)
8+
#define ISDIGIT(ch) ((ch) >= '0' && (ch) <= '9')
9+
#define ISDIGIT1TO9(ch) ((ch) >= '1' && (ch) <= '9')
610

711
typedef struct {
812
const char* json;
@@ -15,49 +19,57 @@ static void lept_parse_whitespace(lept_context* c) {
1519
c->json = p;
1620
}
1721

18-
static int lept_parse_true(lept_context* c, lept_value* v) {
19-
EXPECT(c, 't');
20-
if (c->json[0] != 'r' || c->json[1] != 'u' || c->json[2] != 'e')
21-
return LEPT_PARSE_INVALID_VALUE;
22-
c->json += 3;
23-
v->type = LEPT_TRUE;
24-
return LEPT_PARSE_OK;
22+
static int lept_parse_literal(lept_context* c, lept_value* v, const char* literal, lept_type type)
23+
{
24+
size_t i;
25+
EXPECT(c, literal[0]);
26+
for (i = 0; literal[i + 1] != '\0'; i++)
27+
if (c->json[i] != literal[i + 1])
28+
return LEPT_PARSE_INVALID_VALUE;
29+
c->json += i;
30+
v->type = type;
31+
return LEPT_PARSE_OK;
2532
}
2633

27-
static int lept_parse_false(lept_context* c, lept_value* v) {
28-
EXPECT(c, 'f');
29-
if (c->json[0] != 'a' || c->json[1] != 'l' || c->json[2] != 's' || c->json[3] != 'e')
30-
return LEPT_PARSE_INVALID_VALUE;
31-
c->json += 4;
32-
v->type = LEPT_FALSE;
33-
return LEPT_PARSE_OK;
34-
}
34+
static int lept_parse_number(lept_context* c, lept_value* v) {
35+
36+
const char* p=c->json;
37+
if (*p == '-') p++;
38+
if (*p == '0') p++;
39+
else
40+
{
41+
if (!ISDIGIT1TO9(*p)) return LEPT_PARSE_INVALID_VALUE;
42+
for (p++; ISDIGIT(*p); p++);
43+
}
44+
if (*p == '.')
45+
{
46+
p++;
47+
if (!ISDIGIT(*p)) return LEPT_PARSE_INVALID_VALUE;
48+
for (p++; ISDIGIT(*p);p++);
49+
}
50+
if (*p == 'E' || *p == 'e')
51+
{
52+
p++;
53+
if (*p == '-' || *p == '+') p++;
54+
if (!ISDIGIT(*p)) return LEPT_PARSE_INVALID_VALUE;
55+
for (p++; ISDIGIT(*p); p++);
56+
}
3557

36-
static int lept_parse_null(lept_context* c, lept_value* v) {
37-
EXPECT(c, 'n');
38-
if (c->json[0] != 'u' || c->json[1] != 'l' || c->json[2] != 'l')
39-
return LEPT_PARSE_INVALID_VALUE;
40-
c->json += 3;
41-
v->type = LEPT_NULL;
42-
return LEPT_PARSE_OK;
43-
}
58+
errno = 0;
59+
v->n = strtod(c->json, NULL);
60+
if (errno == ERANGE && (v->n == HUGE_VAL || v->n == -HUGE_VAL))
61+
return LEPT_PARSE_NUMBER_TOO_BIG;
62+
v->type = LEPT_NUMBER;
63+
c->json = p;
64+
return LEPT_PARSE_OK;
4465

45-
static int lept_parse_number(lept_context* c, lept_value* v) {
46-
char* end;
47-
/* \TODO validate number */
48-
v->n = strtod(c->json, &end);
49-
if (c->json == end)
50-
return LEPT_PARSE_INVALID_VALUE;
51-
c->json = end;
52-
v->type = LEPT_NUMBER;
53-
return LEPT_PARSE_OK;
5466
}
5567

5668
static int lept_parse_value(lept_context* c, lept_value* v) {
5769
switch (*c->json) {
58-
case 't': return lept_parse_true(c, v);
59-
case 'f': return lept_parse_false(c, v);
60-
case 'n': return lept_parse_null(c, v);
70+
case 't': return lept_parse_literal(c,v,"true",LEPT_TRUE);
71+
case 'f': return lept_parse_literal(c, v, "false", LEPT_FALSE);
72+
case 'n': return lept_parse_literal(c, v, "null", LEPT_NULL);
6173
default: return lept_parse_number(c, v);
6274
case '\0': return LEPT_PARSE_EXPECT_VALUE;
6375
}

tutorial02/test.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ static void test_parse_invalid_value() {
8989
TEST_ERROR(LEPT_PARSE_INVALID_VALUE, "nul");
9090
TEST_ERROR(LEPT_PARSE_INVALID_VALUE, "?");
9191

92-
#if 0
92+
#if 1
9393
/* invalid number */
9494
TEST_ERROR(LEPT_PARSE_INVALID_VALUE, "+0");
9595
TEST_ERROR(LEPT_PARSE_INVALID_VALUE, "+1");
@@ -105,7 +105,7 @@ static void test_parse_invalid_value() {
105105
static void test_parse_root_not_singular() {
106106
TEST_ERROR(LEPT_PARSE_ROOT_NOT_SINGULAR, "null x");
107107

108-
#if 0
108+
#if 1
109109
/* invalid number */
110110
TEST_ERROR(LEPT_PARSE_ROOT_NOT_SINGULAR, "0123"); /* after zero should be '.' or nothing */
111111
TEST_ERROR(LEPT_PARSE_ROOT_NOT_SINGULAR, "0x0");
@@ -114,7 +114,7 @@ static void test_parse_root_not_singular() {
114114
}
115115

116116
static void test_parse_number_too_big() {
117-
#if 0
117+
#if 1
118118
TEST_ERROR(LEPT_PARSE_NUMBER_TOO_BIG, "1e309");
119119
TEST_ERROR(LEPT_PARSE_NUMBER_TOO_BIG, "-1e309");
120120
#endif
@@ -134,5 +134,6 @@ static void test_parse() {
134134
int main() {
135135
test_parse();
136136
printf("%d/%d (%3.2f%%) passed\n", test_pass, test_count, test_pass * 100.0 / test_count);
137+
system("PAUSE");
137138
return main_ret;
138139
}

0 commit comments

Comments
 (0)