Skip to content

Commit f06394f

Browse files
committed
support parsing numbers as integers
1 parent 2a71751 commit f06394f

File tree

3 files changed

+77
-27
lines changed

3 files changed

+77
-27
lines changed

examples/03_parsing_database.c

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@
88

99
typedef struct {
1010
const char *name;
11-
double age;
11+
long long age;
1212
const char *location;
13-
double body_count;
13+
double cash;
1414
} Person;
1515

1616
typedef struct {
@@ -27,14 +27,14 @@ bool parse_person(Jimp *jimp, Person *p)
2727
if (!jimp_string(jimp)) return false;
2828
p->name = strdup(jimp->string);
2929
} else if (strcmp(jimp->string, "age") == 0) {
30-
if (!jimp_number(jimp)) return false;
31-
p->age = jimp->number;
30+
if (!jimp_integer(jimp)) return false;
31+
p->age = jimp->integer;
3232
} else if (strcmp(jimp->string, "location") == 0) {
3333
if (!jimp_string(jimp)) return false;
3434
p->location = strdup(jimp->string);
35-
} else if (strcmp(jimp->string, "body_count") == 0) {
36-
if (!jimp_number(jimp)) return false;
37-
p->body_count = jimp->number;
35+
} else if (strcmp(jimp->string, "cash") == 0) {
36+
if (!jimp_float(jimp)) return false;
37+
p->cash = jimp->floating;
3838
} else {
3939
jimp_unknown_member(jimp);
4040
return false;
@@ -58,14 +58,14 @@ bool parse_people(Jimp *jimp, People *ps)
5858

5959
void print_person(const Person *p)
6060
{
61-
printf("name = %s\n", p->name);
62-
printf("age = %lf\n", p->age);
63-
printf("location = %s\n", p->location);
64-
printf("body_count = %lf\n", p->body_count);
61+
printf("name = %s\n", p->name);
62+
printf("age = %lld\n", p->age);
63+
printf("location = %s\n", p->location);
64+
printf("cash = $%.2lf\n", p->cash);
6565
}
6666

6767
typedef struct {
68-
long *items;
68+
JimpNumber *items;
6969
size_t count;
7070
size_t capacity;
7171
} Numbers;
@@ -105,8 +105,11 @@ int main(void)
105105
printf("\n");
106106
}
107107
printf("------------------------------\n");
108-
da_foreach(long, x, &xs) {
109-
printf("%ld ", *x);
108+
da_foreach(JimpNumber, x, &xs) {
109+
if (x->type == JIMP_INTEGER)
110+
printf("%lld ", x->value.i);
111+
else
112+
printf("%lf ", x->value.f);
110113
}
111114
printf("\n");
112115

examples/database.json

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,66 @@
11
{
2-
"number": [69, 420, 1337, 80085],
2+
"number": [69, 420, 1337, 80085, .69, 42.123, 123., 9007199254740993, 9007199254740993.0],
33
"profile": [
44
{
55
"location": "Wonderland",
66
"location": "Wonderland",
7-
"body_count": 150,
7+
"cash": 1.5,
88
"name": "Alice Smith",
99
"age": 34
1010
},
1111
{
1212
"name": "Bob Johnson",
1313
"age": 45,
1414
"location": "Atlantis",
15-
"body_count": 300
15+
"cash": 3
1616
},
1717
{
1818
"name": "Charlie Brown",
1919
"age": 28,
2020
"location": "Chocolate Factory",
21-
"body_count": 200
21+
"cash": 2
2222
},
2323
{
2424
"name": "Diana Prince",
2525
"age": 32,
2626
"location": "Themyscira",
27-
"body_count": 250
27+
"cash": 2.5
2828
},
2929
{
3030
"name": "Ethan Hunt",
3131
"age": 40,
3232
"location": "Mission HQ",
33-
"body_count": 350
33+
"cash": 3.5
3434
},
3535
{
3636
"name": "Fiona Apple",
3737
"age": 37,
3838
"location": "Music City",
39-
"body_count": 180
39+
"cash": 1.8
4040
},
4141
{
4242
"name": "George Lucas",
4343
"age": 75,
4444
"location": "Galaxy Far Far Away",
45-
"body_count": 500
45+
"cash": 5
4646
},
4747
{
4848
"name": "Hannah Montana",
4949
"age": 25,
5050
"location": "Nashville",
51-
"body_count": 100
51+
"cash": 1
5252
},
5353
{
5454
"name": "Ian Malcolm",
5555
"age": 60,
5656
"location": "Jurassic Park",
57-
"body_count": 400
57+
"cash": 4
5858
},
5959
{
6060
"name": "Jessica Rabbit",
6161
"age": 30,
6262
"location": "Toontown",
63-
"body_count": 220
63+
"cash": 2.2
6464
}
6565
]
6666
}

jimp.h

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,21 @@ typedef enum {
3535
JIMP_NUMBER,
3636
} Jimp_Token;
3737

38+
typedef enum {
39+
JIMP_FLOATING,
40+
JIMP_INTEGER
41+
} JimpNumberType;
42+
43+
union JimpNumberValue {
44+
double f;
45+
long long i;
46+
};
47+
48+
typedef struct {
49+
JimpNumberType type;
50+
union JimpNumberValue value;
51+
} JimpNumber;
52+
3853
typedef struct {
3954
const char *file_path;
4055
const char *start;
@@ -47,7 +62,9 @@ typedef struct {
4762
char *string;
4863
size_t string_count;
4964
size_t string_capacity;
50-
double number;
65+
JimpNumber number;
66+
double floating;
67+
long long integer;
5168
bool boolean;
5269
} Jimp;
5370

@@ -63,6 +80,14 @@ bool jimp_boolean(Jimp *jimp);
6380
/// Any consequent calls to the jimp_* functions may invalidate jimp->number.
6481
bool jimp_number(Jimp *jimp);
6582

83+
/// If succeeds puts the freshly parsed number into jimp->number and jimp->floating.
84+
/// Any consequent calls to the jimp_* functions may invalidate jimp->number and jimp->floating.
85+
bool jimp_float(Jimp *jimp);
86+
87+
/// If succeeds puts the freshly parsed number into jimp->number and jimp->integer.
88+
/// Any consequent calls to the jimp_* functions may invalidate jimp->number and jimp->integer.
89+
bool jimp_integer(Jimp *jimp);
90+
6691
/// If succeeds puts the freshly parsed string into jimp->string as a NULL-terminated string.
6792
/// Any consequent calls to the jimp_* functions may invalidate jimp->string.
6893
/// strdup it if you don't wanna lose it (memory management is on you at that point).
@@ -175,8 +200,16 @@ static bool jimp__get_token(Jimp *jimp)
175200
}
176201

177202
char *endptr = NULL;
178-
jimp->number = strtod(jimp->point, &endptr); // TODO: This implies that jimp->end is a valid address and *jimp->end == 0
203+
jimp->number.value.i = strtoull(jimp->point, &endptr, 0); // TODO: This implies that jimp->end is a valid address and *jimp->end == 0
204+
if (jimp->point != endptr && *endptr != '.') {
205+
jimp->number.type = JIMP_INTEGER;
206+
jimp->point = endptr;
207+
jimp->token = JIMP_NUMBER;
208+
return true;
209+
}
210+
jimp->number.value.f = strtod(jimp->point, &endptr);
179211
if (jimp->point != endptr) {
212+
jimp->number.type = JIMP_FLOATING;
180213
jimp->point = endptr;
181214
jimp->token = JIMP_NUMBER;
182215
return true;
@@ -370,6 +403,20 @@ bool jimp_number(Jimp *jimp)
370403
return jimp__get_and_expect_token(jimp, JIMP_NUMBER);
371404
}
372405

406+
bool jimp_float(Jimp *jimp)
407+
{
408+
if (!jimp__get_and_expect_token(jimp, JIMP_NUMBER)) return false;
409+
jimp->floating = jimp->number.type == JIMP_FLOATING ? jimp->number.value.f : jimp->number.value.i;
410+
return true;
411+
}
412+
413+
bool jimp_integer(Jimp *jimp)
414+
{
415+
if (!jimp__get_and_expect_token(jimp, JIMP_NUMBER) || jimp->number.type != JIMP_INTEGER) return false;
416+
jimp->integer = jimp->number.value.i;
417+
return true;
418+
}
419+
373420
static bool jimp__get_and_expect_token(Jimp *jimp, Jimp_Token token)
374421
{
375422
if (!jimp__get_token(jimp)) return false;

0 commit comments

Comments
 (0)