diff options
| author | Thomas Schmucker <ts@its1.de> | 2020-06-17 16:30:03 +0200 |
|---|---|---|
| committer | Thomas Schmucker <ts@its1.de> | 2020-06-17 16:30:03 +0200 |
| commit | fb6562779b76997d5207c2f2115d8965da926164 (patch) | |
| tree | ecb9eda4e9a2140a97dc8d245b2b4c429c1471d2 | |
| parent | d3fb6485ce962b795323cb2d1f19be9674349a0e (diff) | |
| download | libcsv-fb6562779b76997d5207c2f2115d8965da926164.tar.gz libcsv-fb6562779b76997d5207c2f2115d8965da926164.tar.bz2 libcsv-fb6562779b76997d5207c2f2115d8965da926164.zip | |
mit abort() lässt sich eine bessere Fehlerbehandlung durchführen, wenn das zugehörige Signal in einem Handler abgefangen wird!
| -rw-r--r-- | csv-test.c | 59 |
1 files changed, 40 insertions, 19 deletions
| @@ -5,6 +5,7 @@ | |||
| 5 | #include <stdbool.h> | 5 | #include <stdbool.h> |
| 6 | #include <setjmp.h> | 6 | #include <setjmp.h> |
| 7 | #include <assert.h> | 7 | #include <assert.h> |
| 8 | #include <signal.h> | ||
| 8 | 9 | ||
| 9 | #define INLINE static inline | 10 | #define INLINE static inline |
| 10 | 11 | ||
| @@ -41,7 +42,14 @@ csv_string_empty(csv_string_t *csv_string) | |||
| 41 | return ( csv_string->pos == 0 ) ? true : false; | 42 | return ( csv_string->pos == 0 ) ? true : false; |
| 42 | } | 43 | } |
| 43 | 44 | ||
| 44 | INLINE bool | 45 | INLINE void |
| 46 | csv_fatal_error(const char *msg) | ||
| 47 | { | ||
| 48 | fprintf(stderr, "fatal error: %s\n", msg); | ||
| 49 | abort(); | ||
| 50 | } | ||
| 51 | |||
| 52 | INLINE void | ||
| 45 | csv_string_append(csv_string_t *csv_string, char ch) | 53 | csv_string_append(csv_string_t *csv_string, char ch) |
| 46 | { | 54 | { |
| 47 | assert(csv_string != NULL); | 55 | assert(csv_string != NULL); |
| @@ -51,7 +59,8 @@ csv_string_append(csv_string_t *csv_string, char ch) | |||
| 51 | if ( csv_string->pos == csv_string->cap ) { /* grow if needed */ | 59 | if ( csv_string->pos == csv_string->cap ) { /* grow if needed */ |
| 52 | if ( csv_string->str == NULL ) { /* first call? */ | 60 | if ( csv_string->str == NULL ) { /* first call? */ |
| 53 | if ( (csv_string->str = malloc(INITIAL_CAP)) == NULL ) { | 61 | if ( (csv_string->str = malloc(INITIAL_CAP)) == NULL ) { |
| 54 | return false; | 62 | csv_fatal_error("out of memory..."); |
| 63 | return; | ||
| 55 | } | 64 | } |
| 56 | 65 | ||
| 57 | csv_string->cap = INITIAL_CAP; | 66 | csv_string->cap = INITIAL_CAP; |
| @@ -60,7 +69,8 @@ csv_string_append(csv_string_t *csv_string, char ch) | |||
| 60 | int cap = (csv_string->cap * 3) / 2; /* *= 1.5 */ | 69 | int cap = (csv_string->cap * 3) / 2; /* *= 1.5 */ |
| 61 | char *str = realloc(csv_string->str, cap); | 70 | char *str = realloc(csv_string->str, cap); |
| 62 | if ( str == NULL ) { | 71 | if ( str == NULL ) { |
| 63 | return false; | 72 | csv_fatal_error("out of memory..."); |
| 73 | return; | ||
| 64 | } | 74 | } |
| 65 | csv_string->str = str; | 75 | csv_string->str = str; |
| 66 | csv_string->cap = cap; | 76 | csv_string->cap = cap; |
| @@ -68,8 +78,6 @@ csv_string_append(csv_string_t *csv_string, char ch) | |||
| 68 | } | 78 | } |
| 69 | 79 | ||
| 70 | csv_string->str[csv_string->pos++] = ch; /* append char */ | 80 | csv_string->str[csv_string->pos++] = ch; /* append char */ |
| 71 | |||
| 72 | return true; | ||
| 73 | } | 81 | } |
| 74 | 82 | ||
| 75 | INLINE void | 83 | INLINE void |
| @@ -108,7 +116,7 @@ csv_field_reset(csv_field_t *csv_field) | |||
| 108 | csv_field->pos = 0; | 116 | csv_field->pos = 0; |
| 109 | } | 117 | } |
| 110 | 118 | ||
| 111 | INLINE bool | 119 | INLINE void |
| 112 | csv_field_append(csv_field_t *csv_field, int idx) | 120 | csv_field_append(csv_field_t *csv_field, int idx) |
| 113 | { | 121 | { |
| 114 | assert(csv_field != NULL); | 122 | assert(csv_field != NULL); |
| @@ -118,7 +126,8 @@ csv_field_append(csv_field_t *csv_field, int idx) | |||
| 118 | if ( csv_field->pos == csv_field->cap ) { /* grow if needed */ | 126 | if ( csv_field->pos == csv_field->cap ) { /* grow if needed */ |
| 119 | if ( csv_field->fields == NULL ) { | 127 | if ( csv_field->fields == NULL ) { |
| 120 | if ( (csv_field->fields = calloc(INITIAL_CAP, sizeof(csv_field->fields[0]))) == NULL ) { | 128 | if ( (csv_field->fields = calloc(INITIAL_CAP, sizeof(csv_field->fields[0]))) == NULL ) { |
| 121 | return false; | 129 | csv_fatal_error("out of memory"); |
| 130 | return; | ||
| 122 | } | 131 | } |
| 123 | 132 | ||
| 124 | csv_field->cap = INITIAL_CAP; | 133 | csv_field->cap = INITIAL_CAP; |
| @@ -127,7 +136,8 @@ csv_field_append(csv_field_t *csv_field, int idx) | |||
| 127 | int cap = (csv_field->cap * 3) / 2; /* *= 1.5 */ | 136 | int cap = (csv_field->cap * 3) / 2; /* *= 1.5 */ |
| 128 | int *fields = reallocarray(csv_field->fields, cap, sizeof(csv_field->fields[0])); | 137 | int *fields = reallocarray(csv_field->fields, cap, sizeof(csv_field->fields[0])); |
| 129 | if ( fields == NULL ) { | 138 | if ( fields == NULL ) { |
| 130 | return false; | 139 | csv_fatal_error("out of memory"); |
| 140 | return; | ||
| 131 | } | 141 | } |
| 132 | csv_field->fields = fields; | 142 | csv_field->fields = fields; |
| 133 | csv_field->cap = cap; | 143 | csv_field->cap = cap; |
| @@ -135,8 +145,6 @@ csv_field_append(csv_field_t *csv_field, int idx) | |||
| 135 | } | 145 | } |
| 136 | 146 | ||
| 137 | csv_field->fields[csv_field->pos++] = idx; /* append idx */ | 147 | csv_field->fields[csv_field->pos++] = idx; /* append idx */ |
| 138 | |||
| 139 | return true; | ||
| 140 | } | 148 | } |
| 141 | 149 | ||
| 142 | INLINE void | 150 | INLINE void |
| @@ -220,13 +228,11 @@ csv_field(csv_t *csv, int idx) | |||
| 220 | assert(csv != NULL); | 228 | assert(csv != NULL); |
| 221 | assert(idx >= 0 && idx < csv->csv_field.pos); | 229 | assert(idx >= 0 && idx < csv->csv_field.pos); |
| 222 | 230 | ||
| 223 | if ( idx >= 0 && idx < csv->csv_field.pos) { | 231 | if ( idx < 0 || idx >= csv->csv_field.pos ) { |
| 224 | return &csv->csv_string.str[csv->csv_field.fields[idx]]; | 232 | csv_fatal_error("range error"); |
| 225 | } | ||
| 226 | else { | ||
| 227 | /* TODO: error handling */ | ||
| 228 | return NULL; | ||
| 229 | } | 233 | } |
| 234 | |||
| 235 | return &csv->csv_string.str[csv->csv_field.fields[idx]]; | ||
| 230 | } | 236 | } |
| 231 | 237 | ||
| 232 | int | 238 | int |
| @@ -418,12 +424,22 @@ csv_write(csv_t *csv, int n, const char *fields[], FILE *out) | |||
| 418 | fprintf(out, "\r\n"); | 424 | fprintf(out, "\r\n"); |
| 419 | } | 425 | } |
| 420 | 426 | ||
| 427 | jmp_buf env; | ||
| 428 | |||
| 429 | static void sig_handler(int sig) | ||
| 430 | { | ||
| 431 | (void) sig; | ||
| 432 | longjmp(env, 1); | ||
| 433 | } | ||
| 434 | |||
| 421 | int | 435 | int |
| 422 | main(void) | 436 | main(void) |
| 423 | { | 437 | { |
| 424 | csv_t csv[1]; | 438 | csv_t csv[1]; |
| 425 | int n, line = 0; | 439 | int n, line = 0; |
| 426 | 440 | ||
| 441 | signal(SIGABRT, sig_handler); | ||
| 442 | |||
| 427 | FILE *in = fopen("500000 Records.csv", "r"); | 443 | FILE *in = fopen("500000 Records.csv", "r"); |
| 428 | if ( in == NULL ) { | 444 | if ( in == NULL ) { |
| 429 | fprintf(stderr, "failed to open testfile...\n"); | 445 | fprintf(stderr, "failed to open testfile...\n"); |
| @@ -433,9 +449,14 @@ main(void) | |||
| 433 | clock_t start = clock(); | 449 | clock_t start = clock(); |
| 434 | 450 | ||
| 435 | csv_init(csv); | 451 | csv_init(csv); |
| 436 | while ( (n = csv_read(csv, in)) != -1 ) { | 452 | if ( setjmp(env) == 0 ) { |
| 437 | //csv_field(csv, -1); | 453 | while ( (n = csv_read(csv, in)) != -1 ) { |
| 438 | ++line; | 454 | csv_field(csv, -1); |
| 455 | ++line; | ||
| 456 | } | ||
| 457 | } | ||
| 458 | else { | ||
| 459 | printf("Fehler beim Verarbeiten der Datei...\n"); | ||
| 439 | } | 460 | } |
| 440 | csv_free(csv); | 461 | csv_free(csv); |
| 441 | 462 | ||
