diff --git a/README.md b/README.md index 9ea6a78..cface43 100644 --- a/README.md +++ b/README.md @@ -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. diff --git a/examples/03_parsing_database.c b/examples/03_parsing_database.c index 15e7aad..66876f4 100644 --- a/examples/03_parsing_database.c +++ b/examples/03_parsing_database.c @@ -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 { @@ -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; @@ -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; @@ -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 { @@ -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"); diff --git a/examples/database.json b/examples/database.json index 57356d8..7b6fffa 100644 --- a/examples/database.json +++ b/examples/database.json @@ -1,10 +1,10 @@ { - "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 }, @@ -12,55 +12,55 @@ "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 } ] } diff --git a/jimp.h b/jimp.h index 7667d97..e6534be 100644 --- a/jimp.h +++ b/jimp.h @@ -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; @@ -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; @@ -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. @@ -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;