From 076ebd53209016038c1905ae9f95ad2b7fc11fa0 Mon Sep 17 00:00:00 2001 From: Thomas Schmucker Date: Thu, 18 Jun 2020 08:24:31 +0200 Subject: übergebe die Fehlermeldung auch an den CLient-Error-Handler; Reorg Code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- csv-test.c | 97 ++++++++++++++++++++++++++++++++++---------------------------- 1 file changed, 54 insertions(+), 43 deletions(-) diff --git a/csv-test.c b/csv-test.c index 85e0e91..6c32a04 100644 --- a/csv-test.c +++ b/csv-test.c @@ -9,6 +9,34 @@ #define INLINE static inline +/* === CSV Options Interface === */ + +typedef struct { + char quote_symbol; + char sep_symbol; + void *cb_arg; + void (*cb_func)(const char *, void *); +} csv_options_t; + +static csv_options_t default_csv_options = { + .quote_symbol = '"', + .sep_symbol = ',', + .cb_func = NULL +}; + +/* === CSV-ERROR Interface === */ + +INLINE void +csv_fatal_error(const char *msg, const csv_options_t * const csv_options) +{ + if ( csv_options->cb_func != NULL ) { + (*csv_options->cb_func)(msg, csv_options->cb_arg); + } + + fprintf(stderr, "fatal error: %s\n", msg); + abort(); +} + /* === CSV-STRING Interface === */ typedef struct { @@ -43,14 +71,7 @@ csv_string_empty(csv_string_t *csv_string) } INLINE void -csv_fatal_error(const char *msg) -{ - fprintf(stderr, "fatal error: %s\n", msg); - abort(); -} - -INLINE void -csv_string_append(csv_string_t *csv_string, char ch) +csv_string_append(csv_string_t *csv_string, char ch, const csv_options_t * const csv_options) { assert(csv_string != NULL); @@ -59,7 +80,7 @@ csv_string_append(csv_string_t *csv_string, char ch) if ( csv_string->pos == csv_string->cap ) { /* grow if needed */ if ( csv_string->str == NULL ) { /* first call? */ if ( (csv_string->str = malloc(INITIAL_CAP)) == NULL ) { - csv_fatal_error("out of memory..."); + csv_fatal_error("out of memory...", csv_options); return; } @@ -69,7 +90,7 @@ csv_string_append(csv_string_t *csv_string, char ch) int cap = (csv_string->cap * 3) / 2; /* *= 1.5 */ char *str = realloc(csv_string->str, cap); if ( str == NULL ) { - csv_fatal_error("out of memory..."); + csv_fatal_error("out of memory...", csv_options); return; } csv_string->str = str; @@ -117,7 +138,7 @@ csv_field_reset(csv_field_t *csv_field) } INLINE void -csv_field_append(csv_field_t *csv_field, int idx) +csv_field_append(csv_field_t *csv_field, int idx, const csv_options_t * const csv_options) { assert(csv_field != NULL); @@ -126,7 +147,7 @@ csv_field_append(csv_field_t *csv_field, int idx) if ( csv_field->pos == csv_field->cap ) { /* grow if needed */ if ( csv_field->fields == NULL ) { if ( (csv_field->fields = calloc(INITIAL_CAP, sizeof(csv_field->fields[0]))) == NULL ) { - csv_fatal_error("out of memory"); + csv_fatal_error("out of memory", csv_options); return; } @@ -136,7 +157,7 @@ csv_field_append(csv_field_t *csv_field, int idx) int cap = (csv_field->cap * 3) / 2; /* *= 1.5 */ int *fields = reallocarray(csv_field->fields, cap, sizeof(csv_field->fields[0])); if ( fields == NULL ) { - csv_fatal_error("out of memory"); + csv_fatal_error("out of memory", csv_options); return; } csv_field->fields = fields; @@ -159,16 +180,6 @@ csv_field_free(csv_field_t *csv_field) /* === CSV Interface === */ -typedef struct { - char quote_symbol; - char sep_symbol; -} csv_options_t; - -static csv_options_t default_csv_options = { - .quote_symbol = '"', - .sep_symbol = ',' -}; - typedef struct { csv_options_t *csv_options; csv_string_t csv_string; @@ -181,7 +192,7 @@ void csv_free(csv_t *csv); int csv_nfields(csv_t *csv); const char * csv_field(csv_t *csv, int idx); int csv_read(csv_t *csv, FILE *in); -void csv_write(csv_t *csv, int n, const char *fields[], FILE *out); +void csv_write(const csv_options_t * const csv_options, int n, const char *fields[], FILE *out); void csv_init(csv_t *csv) @@ -229,7 +240,7 @@ csv_field(csv_t *csv, int idx) assert(idx >= 0 && idx < csv->csv_field.pos); if ( idx < 0 || idx >= csv->csv_field.pos ) { - csv_fatal_error("range error"); + csv_fatal_error("range error", csv->csv_options); } return &csv->csv_string.str[csv->csv_field.fields[idx]]; @@ -260,7 +271,7 @@ csv_read(csv_t *csv, FILE *in) switch ( state ) { case STATE_START_FIELD: - csv_field_append(&csv->csv_field, csv->csv_string.pos); + csv_field_append(&csv->csv_field, csv->csv_string.pos, csv->csv_options); ch = getc(in); if ( ch == EOF ) { @@ -283,7 +294,7 @@ csv_read(csv_t *csv, FILE *in) state = STATE_QUOTED_FIELD; } else { - csv_string_append(&csv->csv_string, ch); + csv_string_append(&csv->csv_string, ch, csv->csv_options); state = STATE_SIMPLE_FIELD; } break; @@ -300,7 +311,7 @@ csv_read(csv_t *csv, FILE *in) state = STATE_END_FILE; } else if ( ch == QUOTE ) { - csv_string_append(&csv->csv_string, QUOTE); + csv_string_append(&csv->csv_string, QUOTE, csv->csv_options); } else if ( ch == SEP ) { state = STATE_END_FIELD; @@ -316,12 +327,12 @@ csv_read(csv_t *csv, FILE *in) state = STATE_END_LINE; } else { - csv_string_append(&csv->csv_string, QUOTE); + csv_string_append(&csv->csv_string, QUOTE, csv->csv_options); ungetc(ch, in); /* zuviel gelesenes Zeichen zurückstellen */ } } else { - csv_string_append(&csv->csv_string, ch); + csv_string_append(&csv->csv_string, ch, csv->csv_options); } } while ( state == STATE_QUOTED_FIELD ); break; @@ -346,18 +357,18 @@ csv_read(csv_t *csv, FILE *in) state = STATE_END_LINE; } else { - csv_string_append(&csv->csv_string, ch); + csv_string_append(&csv->csv_string, ch, csv->csv_options); } } while ( state == STATE_SIMPLE_FIELD ); break; case STATE_END_FIELD: - csv_string_append(&csv->csv_string, '\0'); + csv_string_append(&csv->csv_string, '\0', csv->csv_options); state = STATE_START_FIELD; break; case STATE_END_LINE: - csv_string_append(&csv->csv_string, '\0'); + csv_string_append(&csv->csv_string, '\0', csv->csv_options); return csv->csv_field.pos; case STATE_END_FILE: @@ -367,7 +378,7 @@ csv_read(csv_t *csv, FILE *in) /* EOF wurde gelesen, allerdings sind Daten zur Vearbeitung vorhanden! */ /* => aktuelles Feld abschließen... */ - csv_string_append(&csv->csv_string, '\0'); + csv_string_append(&csv->csv_string, '\0', csv->csv_options); /* ... und die Anzahl der Felder zurückliefern! */ return csv->csv_field.pos; @@ -381,11 +392,11 @@ csv_read(csv_t *csv, FILE *in) } static void -csv_write_field(csv_t *csv, const char *field, FILE *out) +csv_write_field(const csv_options_t * const csv_options, const char *field, FILE *out) { - assert(csv != NULL); + assert(csv_options != NULL); - const char QUOTE = csv->csv_options->quote_symbol; + const char QUOTE = csv_options->quote_symbol; if ( *field != '\0' ) { putc(QUOTE, out); @@ -405,20 +416,20 @@ csv_write_field(csv_t *csv, const char *field, FILE *out) } void -csv_write(csv_t *csv, int n, const char *fields[], FILE *out) +csv_write(const csv_options_t * const csv_options, int n, const char *fields[], FILE *out) { - assert(csv != NULL); + assert(csv_options != NULL); - const char SEP = csv->csv_options->quote_symbol; + const char SEP = csv_options->quote_symbol; /* process first field */ if ( 0 != n && fields[0] != NULL ) { - csv_write_field(csv, fields[0], out); + csv_write_field(csv_options, fields[0], out); /* process next fields */ for ( int i = 1; i != n && fields[i] != NULL; ++i ) { putc(SEP, out); - csv_write_field(csv, fields[i], out); + csv_write_field(csv_options, fields[i], out); } } fprintf(out, "\r\n"); @@ -451,7 +462,7 @@ main(void) csv_init(csv); if ( setjmp(env) == 0 ) { while ( (n = csv_read(csv, in)) != -1 ) { - csv_field(csv, -1); + //if ( line == 500000 ) csv_field(csv, -1); ++line; } } -- cgit v1.3