From ee9dab6ba9b48c0bd3b700347d95063285565201 Mon Sep 17 00:00:00 2001 From: Thomas Schmucker Date: Wed, 17 Jun 2020 15:59:37 +0200 Subject: Vereinfache den Code an mehreren Stellen. Speicherverwaltung ist nun zentralisiert und wo nicht notwendig, wird auf einen Returncode verzichtet! --- csv-test.c | 118 ++++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 65 insertions(+), 53 deletions(-) (limited to 'csv-test.c') diff --git a/csv-test.c b/csv-test.c index e16091c..220337e 100644 --- a/csv-test.c +++ b/csv-test.c @@ -15,21 +15,14 @@ typedef struct { int cap, pos; } csv_string_t; -INLINE bool +INLINE void csv_string_init(csv_string_t *csv_string) { assert(csv_string != NULL); - static const int INITIAL_CAP = 16; - - if ( (csv_string->str = malloc(INITIAL_CAP)) == NULL ) { - return false; - } - - csv_string->cap = INITIAL_CAP; + csv_string->str = NULL; + csv_string->cap = 0; csv_string->pos = 0; - - return true; } INLINE void @@ -53,14 +46,25 @@ csv_string_append(csv_string_t *csv_string, char ch) { assert(csv_string != NULL); + static const int INITIAL_CAP = 16; + if ( csv_string->pos == csv_string->cap ) { /* grow if needed */ - int cap = (csv_string->cap * 3) / 2; /* *= 1.5 */ - char *str = realloc(csv_string->str, cap); - if ( str == NULL ) { - return false; + if ( csv_string->str == NULL ) { /* first call? */ + if ( (csv_string->str = malloc(INITIAL_CAP)) == NULL ) { + return false; + } + + csv_string->cap = INITIAL_CAP; + } + else { /* subsequent call */ + int cap = (csv_string->cap * 3) / 2; /* *= 1.5 */ + char *str = realloc(csv_string->str, cap); + if ( str == NULL ) { + return false; + } + csv_string->str = str; + csv_string->cap = cap; } - csv_string->str = str; - csv_string->cap = cap; } csv_string->str[csv_string->pos++] = ch; /* append char */ @@ -74,6 +78,9 @@ csv_string_free(csv_string_t *csv_string) assert(csv_string != NULL); free(csv_string->str); + + /* call *_init() for sane default values; prevent possible double-free */ + csv_string_init(csv_string); } /* === CSV-FIELD Interface === */ @@ -83,21 +90,14 @@ typedef struct { int cap, pos; } csv_field_t; -INLINE bool +INLINE void csv_field_init(csv_field_t *csv_field) { assert(csv_field != NULL); - static const size_t INITIAL_CAP = 16; - - if ( (csv_field->fields = calloc(INITIAL_CAP, sizeof(csv_field->fields[0]))) == NULL ) { - return false; - } - - csv_field->cap = INITIAL_CAP; + csv_field->fields = NULL; + csv_field->cap = 0; csv_field->pos = 0; - - return true; } INLINE void @@ -113,14 +113,25 @@ csv_field_append(csv_field_t *csv_field, int idx) { assert(csv_field != NULL); + static const size_t INITIAL_CAP = 16; + if ( csv_field->pos == csv_field->cap ) { /* grow if needed */ - int cap = (csv_field->cap * 3) / 2; /* *= 1.5 */ - int *fields = reallocarray(csv_field->fields, cap, sizeof(csv_field->fields[0])); - if ( fields == NULL ) { - return false; + if ( csv_field->fields == NULL ) { + if ( (csv_field->fields = calloc(INITIAL_CAP, sizeof(csv_field->fields[0]))) == NULL ) { + return false; + } + + csv_field->cap = INITIAL_CAP; + } + else { + int cap = (csv_field->cap * 3) / 2; /* *= 1.5 */ + int *fields = reallocarray(csv_field->fields, cap, sizeof(csv_field->fields[0])); + if ( fields == NULL ) { + return false; + } + csv_field->fields = fields; + csv_field->cap = cap; } - csv_field->fields = fields; - csv_field->cap = cap; } csv_field->fields[csv_field->pos++] = idx; /* append idx */ @@ -134,6 +145,8 @@ csv_field_free(csv_field_t *csv_field) assert(csv_field != NULL); free(csv_field->fields); + + csv_field_init(csv_field); } /* === CSV Interface === */ @@ -154,38 +167,31 @@ typedef struct { csv_field_t csv_field; } csv_t; -int csv_init(csv_t *csv); -int csv_init_opt(csv_t *csv, csv_options_t *csv_options); +void csv_init(csv_t *csv); +void csv_init_opt(csv_t *csv, csv_options_t *csv_options); 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); -int +void csv_init(csv_t *csv) { assert(csv != NULL); - return csv_init_opt(csv, &default_csv_options); + csv_init_opt(csv, &default_csv_options); } -int +void csv_init_opt(csv_t *csv, csv_options_t *csv_options) { assert(csv != NULL); csv->csv_options = ( csv_options != NULL ) ? csv_options : &default_csv_options; - if ( !csv_string_init(&csv->csv_string) ) { - return -1; - } - if ( !csv_field_init(&csv->csv_field) ) { - csv_string_free(&csv->csv_string); - return -1; - } - - return 0; + csv_string_init(&csv->csv_string); + csv_field_init(&csv->csv_field); } void @@ -418,19 +424,25 @@ main(void) csv_t csv[1]; int n, line = 0; + FILE *in = fopen("500000 Records.csv", "r"); + if ( in == NULL ) { + fprintf(stderr, "failed to open testfile...\n"); + return EXIT_FAILURE; + } + clock_t start = clock(); - int err = csv_init(csv); - if ( !err ) { - while ( (n = csv_read(csv, stdin)) != -1 ) { - //csv_field(csv, -1); - ++line; - } - csv_free(csv); + csv_init(csv); + while ( (n = csv_read(csv, in)) != -1 ) { + //csv_field(csv, -1); + ++line; } + csv_free(csv); clock_t end = clock(); + fclose(in); + printf("%d lines processed, duration: %.3lf sec\n", line, ((double)(end - start)) / CLOCKS_PER_SEC); return EXIT_SUCCESS; -- cgit v1.3