Skip to content

Parse numbers as either integer or floating type #20

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ $ ./test record

## Notes

1. Does not depends on libc. Could be theoretically used in embedded, but I know nothing about embedded, so maybe not.
2. `jim_float()` is quite likely very stupid and imprecise
1. Does not depend on libc. Could be theoretically used in embedded, but I know nothing about embedded, so maybe not.
2. `jim_float()` is quite likely very stupid and imprecise.

<!-- TODO: document jimp.h here -->
35 changes: 22 additions & 13 deletions examples/03_parsing_database.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@

typedef struct {
const char *name;
double age;
long long age;
const char *location;
double body_count;
double cash;
} Person;

typedef struct {
Expand All @@ -28,13 +28,13 @@ bool parse_person(Jimp *jimp, Person *p)
p->name = strdup(jimp->string);
} else if (strcmp(jimp->string, "age") == 0) {
if (!jimp_number(jimp)) return false;
p->age = jimp->number;
p->age = jimp->integer;
} else if (strcmp(jimp->string, "location") == 0) {
if (!jimp_string(jimp)) return false;
p->location = strdup(jimp->string);
} else if (strcmp(jimp->string, "body_count") == 0) {
} else if (strcmp(jimp->string, "cash") == 0) {
if (!jimp_number(jimp)) return false;
p->body_count = jimp->number;
p->cash = jimp->decimal;
} else {
jimp_unknown_member(jimp);
return false;
Expand All @@ -58,14 +58,20 @@ bool parse_people(Jimp *jimp, People *ps)

void print_person(const Person *p)
{
printf("name = %s\n", p->name);
printf("age = %lf\n", p->age);
printf("location = %s\n", p->location);
printf("body_count = %lf\n", p->body_count);
printf("name = %s\n", p->name);
printf("age = %lld\n", p->age);
printf("location = %s\n", p->location);
printf("cash = $%.2lf\n", p->cash);
}

typedef struct {
long *items;
JimpNumberType type;
long long integer;
double decimal;
} Number;

typedef struct {
Number *items;
size_t count;
size_t capacity;
} Numbers;
Expand All @@ -90,7 +96,7 @@ int main(void)
if (!jimp_array_begin(&jimp)) return 1;
while (jimp_array_item(&jimp)) {
if (!jimp_number(&jimp)) return 1;
da_append(&xs, jimp.number);
da_append(&xs, {.type = jimp.number_type, .integer = jimp.integer, .decimal = jimp.decimal});
}
if (!jimp_array_end(&jimp)) return 1;
} else {
Expand All @@ -105,8 +111,11 @@ int main(void)
printf("\n");
}
printf("------------------------------\n");
da_foreach(long, x, &xs) {
printf("%ld ", *x);
da_foreach(JimpNumber, x, &xs) {
if (x->type == JIMP_INTEGER)
printf("%lld ", x->integer);
else
printf("%lf ", x->decimal);
}
printf("\n");

Expand Down
22 changes: 11 additions & 11 deletions examples/database.json
Original file line number Diff line number Diff line change
@@ -1,66 +1,66 @@
{
"number": [69, 420, 1337, 80085],
"number": [69, 420, 1337, 80085, .69, 42.123, 123., 9007199254740993, 9007199254740993.0, +1, -1, +1.0, -1.0, +.1, -.0, 5e5, 5E5, +5e+5, -5e-5],
"profile": [
{
"location": "Wonderland",
"location": "Wonderland",
"body_count": 150,
"cash": 1.5,
"name": "Alice Smith",
"age": 34
},
{
"name": "Bob Johnson",
"age": 45,
"location": "Atlantis",
"body_count": 300
"cash": 3
},
{
"name": "Charlie Brown",
"age": 28,
"location": "Chocolate Factory",
"body_count": 200
"cash": 2
},
{
"name": "Diana Prince",
"age": 32,
"location": "Themyscira",
"body_count": 250
"cash": 2.5
},
{
"name": "Ethan Hunt",
"age": 40,
"location": "Mission HQ",
"body_count": 350
"cash": 3.5
},
{
"name": "Fiona Apple",
"age": 37,
"location": "Music City",
"body_count": 180
"cash": 1.8
},
{
"name": "George Lucas",
"age": 75,
"location": "Galaxy Far Far Away",
"body_count": 500
"cash": 5
},
{
"name": "Hannah Montana",
"age": 25,
"location": "Nashville",
"body_count": 100
"cash": 1
},
{
"name": "Ian Malcolm",
"age": 60,
"location": "Jurassic Park",
"body_count": 400
"cash": 4
},
{
"name": "Jessica Rabbit",
"age": 30,
"location": "Toontown",
"body_count": 220
"cash": 2.2
}
]
}
25 changes: 21 additions & 4 deletions jimp.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ typedef enum {
JIMP_NUMBER,
} Jimp_Token;

typedef enum {
JIMP_DECIMAL,
JIMP_INTEGER
} JimpNumberType;

typedef struct {
const char *file_path;
const char *start;
Expand All @@ -47,7 +52,9 @@ typedef struct {
char *string;
size_t string_count;
size_t string_capacity;
double number;
JimpNumberType number_type;
double decimal;
long long integer;
bool boolean;
} Jimp;

Expand All @@ -59,8 +66,8 @@ void jimp_begin(Jimp *jimp, const char *file_path, const char *input, size_t inp
/// Any consequent calls to the jimp_* functions may invalidate jimp->boolean.
bool jimp_boolean(Jimp *jimp);

/// If succeeds puts the freshly parsed number into jimp->number.
/// Any consequent calls to the jimp_* functions may invalidate jimp->number.
/// If succeeds puts the freshly parsed number into jimp->number_type, jimp->decimal and jimp->integer.
/// Any consequent calls to the jimp_* functions may invalidate jimp->number_type, jimp->decimal and jimp->integer.
bool jimp_number(Jimp *jimp);

/// If succeeds puts the freshly parsed string into jimp->string as a NULL-terminated string.
Expand Down Expand Up @@ -175,8 +182,18 @@ static bool jimp__get_token(Jimp *jimp)
}

char *endptr = NULL;
jimp->number = strtod(jimp->point, &endptr); // TODO: This implies that jimp->end is a valid address and *jimp->end == 0
jimp->integer = strtoull(jimp->point, &endptr, 0); // TODO: This implies that jimp->end is a valid address and *jimp->end == 0
if (jimp->point != endptr && (*endptr != '.' && *endptr != 'E' && *endptr != 'e')) {
jimp->number_type = JIMP_INTEGER;
jimp->decimal = jimp->integer;
jimp->point = endptr;
jimp->token = JIMP_NUMBER;
return true;
}
jimp->decimal = strtod(jimp->point, &endptr);
if (jimp->point != endptr) {
jimp->number_type = JIMP_DECIMAL;
jimp->integer = jimp->decimal;
jimp->point = endptr;
jimp->token = JIMP_NUMBER;
return true;
Expand Down