Skip to content

Commit fdeca55

Browse files
author
crystalwind
committed
Do tutorial02 exercise
1 parent 5a01839 commit fdeca55

File tree

2 files changed

+75
-35
lines changed

2 files changed

+75
-35
lines changed

tutorial02/leptjson.c

Lines changed: 69 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
#include "leptjson.h"
22
#include <assert.h> /* assert() */
33
#include <stdlib.h> /* NULL, strtod() */
4-
4+
#include <math.h> /* HUGE_VAL*/
5+
#include <errno.h>
6+
#include <stdio.h>
57
#define EXPECT(c, ch) do { assert(*c->json == (ch)); c->json++; } while(0)
68

79
typedef struct {
@@ -15,49 +17,84 @@ static void lept_parse_whitespace(lept_context* c) {
1517
c->json = p;
1618
}
1719

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;
20+
static int lept_parse_literal(lept_context* c,lept_value* v, lept_type m){
21+
int i,len;
22+
const char* str;
23+
assert(m == LEPT_TRUE || m == LEPT_FALSE || m == LEPT_NULL);
24+
switch(m){
25+
case LEPT_TRUE: len=3; str="true"; break;
26+
case LEPT_FALSE: len=4; str="false"; break;
27+
case LEPT_NULL: len=3; str="null"; break;
28+
}
29+
EXPECT(c,str[0]);
30+
for(i=0;i<len;i++)
31+
if(c->json[i] != str[i+1])
32+
return LEPT_PARSE_INVALID_VALUE;
33+
c->json += len;
34+
v->type = m;
2435
return LEPT_PARSE_OK;
2536
}
2637

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-
}
35-
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-
}
38+
#define ISDIGIT(ch) ((ch) >= '0' && (ch) <= '9')
39+
#define ISDIGIT1TO9(ch) ((ch) >= '1' && (ch) <= '9')
4440

4541
static int lept_parse_number(lept_context* c, lept_value* v) {
46-
char* end;
47-
/* \TODO validate number */
42+
char* end;
43+
const char* cur = c->json;
44+
if (cur[0] == 'N' && cur[1] == 'A' && cur[2] == 'N'
45+
|| cur[0] == 'n' && cur[1] == 'a' && cur[2] == 'n'
46+
|| cur[0] == 'I' && cur[1] == 'N' && cur[2] == 'F'
47+
|| cur[0] == 'i' && cur[1] == 'n' && cur[2] == 'f')
48+
return LEPT_PARSE_INVALID_VALUE;
49+
if (*cur == '+')
50+
return LEPT_PARSE_INVALID_VALUE;
51+
if (*cur == '-')
52+
cur++;
53+
54+
if (*cur == '.')
55+
return LEPT_PARSE_INVALID_VALUE;
56+
if (*cur == '0') {
57+
cur++;
58+
if (ISDIGIT(*cur) || *cur == 'x' || *cur == 'X' )
59+
return LEPT_PARSE_ROOT_NOT_SINGULAR;
60+
}
61+
else if (ISDIGIT1TO9(*cur)) {
62+
for (cur++; ISDIGIT(*cur); cur++);
63+
}
64+
65+
if (*cur == '.') {
66+
cur++;
67+
if (!ISDIGIT(*cur))
68+
return LEPT_PARSE_INVALID_VALUE;
69+
else
70+
while (ISDIGIT(*++cur));
71+
}
72+
73+
if (*cur == 'e' || *cur == 'E') {
74+
cur++;
75+
if (*cur == '+' || *cur == '-')
76+
cur++;
77+
if (!ISDIGIT(*cur))
78+
return LEPT_PARSE_INVALID_VALUE;
79+
else
80+
for (cur++; ISDIGIT(*cur); cur++);
81+
}
82+
83+
errno = 0;
4884
v->n = strtod(c->json, &end);
49-
if (c->json == end)
50-
return LEPT_PARSE_INVALID_VALUE;
51-
c->json = end;
85+
if (c->json == end) return LEPT_PARSE_INVALID_VALUE;
86+
if ((v->n == HUGE_VAL ||v->n == -HUGE_VAL) && errno == ERANGE)
87+
return LEPT_PARSE_NUMBER_TOO_BIG;
88+
c->json = cur;
5289
v->type = LEPT_NUMBER;
5390
return LEPT_PARSE_OK;
5491
}
5592

5693
static int lept_parse_value(lept_context* c, lept_value* v) {
5794
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);
95+
case 't': return lept_parse_literal(c, v,LEPT_TRUE);
96+
case 'f': return lept_parse_literal(c, v,LEPT_FALSE);
97+
case 'n': return lept_parse_literal(c, v,LEPT_NULL);
6198
default: return lept_parse_number(c, v);
6299
case '\0': return LEPT_PARSE_EXPECT_VALUE;
63100
}

tutorial02/test.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,9 @@ static void test_parse_number() {
7070
TEST_NUMBER(1.234E+10, "1.234E+10");
7171
TEST_NUMBER(1.234E-10, "1.234E-10");
7272
TEST_NUMBER(0.0, "1e-10000"); /* must underflow */
73+
TEST_NUMBER(1.7976931348623158e+308, "1.7976931348623158e+308");
74+
TEST_NUMBER(2.2250738585072014e-308, "2.2250738585072014e-308");
75+
TEST_NUMBER(4.9406564584124654e-324, "4.9406564584124654e-324");
7376
}
7477

7578
#define TEST_ERROR(error, json)\
@@ -89,7 +92,7 @@ static void test_parse_invalid_value() {
8992
TEST_ERROR(LEPT_PARSE_INVALID_VALUE, "nul");
9093
TEST_ERROR(LEPT_PARSE_INVALID_VALUE, "?");
9194

92-
#if 0
95+
#if 1
9396
/* invalid number */
9497
TEST_ERROR(LEPT_PARSE_INVALID_VALUE, "+0");
9598
TEST_ERROR(LEPT_PARSE_INVALID_VALUE, "+1");
@@ -105,7 +108,7 @@ static void test_parse_invalid_value() {
105108
static void test_parse_root_not_singular() {
106109
TEST_ERROR(LEPT_PARSE_ROOT_NOT_SINGULAR, "null x");
107110

108-
#if 0
111+
#if 1
109112
/* invalid number */
110113
TEST_ERROR(LEPT_PARSE_ROOT_NOT_SINGULAR, "0123"); /* after zero should be '.' or nothing */
111114
TEST_ERROR(LEPT_PARSE_ROOT_NOT_SINGULAR, "0x0");
@@ -114,7 +117,7 @@ static void test_parse_root_not_singular() {
114117
}
115118

116119
static void test_parse_number_too_big() {
117-
#if 0
120+
#if 1
118121
TEST_ERROR(LEPT_PARSE_NUMBER_TOO_BIG, "1e309");
119122
TEST_ERROR(LEPT_PARSE_NUMBER_TOO_BIG, "-1e309");
120123
#endif

0 commit comments

Comments
 (0)