aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--csv.c63
1 files changed, 32 insertions, 31 deletions
diff --git a/csv.c b/csv.c
index 863d31d..49e1c02 100644
--- a/csv.c
+++ b/csv.c
@@ -12,7 +12,7 @@
12#define CSV_DEFAULT_SEPARATOR ',' 12#define CSV_DEFAULT_SEPARATOR ','
13#endif 13#endif
14 14
15/* === CSV-MEMORY Interface === */ 15// === CSV-MEMORY Interface ===
16 16
17static void * 17static void *
18csv_mem_allocate(size_t n, size_t sz, void *cb_arg) 18csv_mem_allocate(size_t n, size_t sz, void *cb_arg)
@@ -39,7 +39,7 @@ csv_mem_free(void *ptr, size_t sz, void *cb_arg)
39 free(ptr); 39 free(ptr);
40} 40}
41 41
42/* === CSV-OPTIONS Interface === */ 42// === CSV-OPTIONS Interface ===
43 43
44const csv_options_t csv_default_options = { 44const csv_options_t csv_default_options = {
45 .field_delimiter = CSV_DEFAULT_DELIMITER, 45 .field_delimiter = CSV_DEFAULT_DELIMITER,
@@ -50,7 +50,7 @@ const csv_options_t csv_default_options = {
50 .cb_free = csv_mem_free 50 .cb_free = csv_mem_free
51}; 51};
52 52
53/* === CSV-ERROR Interface === */ 53// === CSV-ERROR Interface ===
54 54
55static void 55static void
56csv_fatal_error(csv_err_t csv_err, const csv_options_t * const csv_options) 56csv_fatal_error(csv_err_t csv_err, const csv_options_t * const csv_options)
@@ -63,7 +63,7 @@ csv_fatal_error(csv_err_t csv_err, const csv_options_t * const csv_options)
63 abort(); 63 abort();
64} 64}
65 65
66/* === CSV-STRING Interface === */ 66// === CSV-STRING Interface ===
67 67
68static inline void 68static inline void
69csv_string_init(csv_string_t *csv_string) 69csv_string_init(csv_string_t *csv_string)
@@ -99,8 +99,8 @@ csv_string_append(csv_string_t *csv_string, char ch, const csv_options_t * const
99 99
100 static const int INITIAL_CAP = 16; 100 static const int INITIAL_CAP = 16;
101 101
102 if ( csv_string->pos == csv_string->cap ) { /* grow if needed */ 102 if ( csv_string->pos == csv_string->cap ) { // grow if needed
103 if ( csv_string->str == NULL ) { /* first call? */ 103 if ( csv_string->str == NULL ) { // first call?
104 if ( (csv_string->str = csv_options->cb_allocate(INITIAL_CAP, 1, csv_options->cb_memory_arg)) == NULL ) { 104 if ( (csv_string->str = csv_options->cb_allocate(INITIAL_CAP, 1, csv_options->cb_memory_arg)) == NULL ) {
105 csv_fatal_error(CSV_ERR_OUT_OF_MEMORY, csv_options); 105 csv_fatal_error(CSV_ERR_OUT_OF_MEMORY, csv_options);
106 return; 106 return;
@@ -108,8 +108,8 @@ csv_string_append(csv_string_t *csv_string, char ch, const csv_options_t * const
108 108
109 csv_string->cap = INITIAL_CAP; 109 csv_string->cap = INITIAL_CAP;
110 } 110 }
111 else { /* subsequent call */ 111 else { // subsequent call
112 int cap = (csv_string->cap * 3) / 2; /* *= 1.5 */ 112 int cap = (csv_string->cap * 3) / 2; // *= 1.5
113 char *str = csv_options->cb_reallocate(csv_string->str, cap, 1, csv_options->cb_memory_arg); 113 char *str = csv_options->cb_reallocate(csv_string->str, cap, 1, csv_options->cb_memory_arg);
114 if ( str == NULL ) { 114 if ( str == NULL ) {
115 csv_fatal_error(CSV_ERR_OUT_OF_MEMORY, csv_options); 115 csv_fatal_error(CSV_ERR_OUT_OF_MEMORY, csv_options);
@@ -120,7 +120,7 @@ csv_string_append(csv_string_t *csv_string, char ch, const csv_options_t * const
120 } 120 }
121 } 121 }
122 122
123 csv_string->str[csv_string->pos++] = ch; /* append char */ 123 csv_string->str[csv_string->pos++] = ch; // append char
124} 124}
125 125
126static inline void 126static inline void
@@ -131,11 +131,11 @@ csv_string_free(csv_string_t *csv_string, const csv_options_t * const csv_option
131 131
132 csv_options->cb_free(csv_string->str, csv_string->cap, csv_options->cb_memory_arg); 132 csv_options->cb_free(csv_string->str, csv_string->cap, csv_options->cb_memory_arg);
133 133
134 /* call *_init() for sane default values; prevent possible double-free */ 134 // call *_init() for sane default values; prevent possible double-free
135 csv_string_init(csv_string); 135 csv_string_init(csv_string);
136} 136}
137 137
138/* === CSV-FIELD Interface === */ 138// === CSV-FIELD Interface ===
139 139
140static inline void 140static inline void
141csv_field_init(csv_field_t *csv_field) 141csv_field_init(csv_field_t *csv_field)
@@ -163,8 +163,8 @@ csv_field_append(csv_field_t *csv_field, int idx, const csv_options_t * const cs
163 163
164 static const size_t INITIAL_CAP = 16; 164 static const size_t INITIAL_CAP = 16;
165 165
166 if ( csv_field->pos == csv_field->cap ) { /* grow if needed */ 166 if ( csv_field->pos == csv_field->cap ) { // grow if needed
167 if ( csv_field->fields == NULL ) { 167 if ( csv_field->fields == NULL ) { // first call
168 if ( (csv_field->fields = csv_options->cb_allocate(INITIAL_CAP, sizeof(csv_field->fields[0]), csv_options->cb_memory_arg)) == NULL ) { 168 if ( (csv_field->fields = csv_options->cb_allocate(INITIAL_CAP, sizeof(csv_field->fields[0]), csv_options->cb_memory_arg)) == NULL ) {
169 csv_fatal_error(CSV_ERR_OUT_OF_MEMORY, csv_options); 169 csv_fatal_error(CSV_ERR_OUT_OF_MEMORY, csv_options);
170 return; 170 return;
@@ -172,8 +172,8 @@ csv_field_append(csv_field_t *csv_field, int idx, const csv_options_t * const cs
172 172
173 csv_field->cap = INITIAL_CAP; 173 csv_field->cap = INITIAL_CAP;
174 } 174 }
175 else { 175 else { // subsequent call
176 int cap = (csv_field->cap * 3) / 2; /* *= 1.5 */ 176 int cap = (csv_field->cap * 3) / 2; // *= 1.5
177 int *fields = csv_options->cb_reallocate(csv_field->fields, cap, sizeof(csv_field->fields[0]), csv_options->cb_memory_arg); 177 int *fields = csv_options->cb_reallocate(csv_field->fields, cap, sizeof(csv_field->fields[0]), csv_options->cb_memory_arg);
178 if ( fields == NULL ) { 178 if ( fields == NULL ) {
179 csv_fatal_error(CSV_ERR_OUT_OF_MEMORY, csv_options); 179 csv_fatal_error(CSV_ERR_OUT_OF_MEMORY, csv_options);
@@ -184,7 +184,7 @@ csv_field_append(csv_field_t *csv_field, int idx, const csv_options_t * const cs
184 } 184 }
185 } 185 }
186 186
187 csv_field->fields[csv_field->pos++] = idx; /* append idx */ 187 csv_field->fields[csv_field->pos++] = idx; // append idx
188} 188}
189 189
190static inline void 190static inline void
@@ -198,7 +198,7 @@ csv_field_free(csv_field_t *csv_field, const csv_options_t * const csv_options)
198 csv_field_init(csv_field); 198 csv_field_init(csv_field);
199} 199}
200 200
201/* === CSV Interface === */ 201// === CSV Interface ===
202 202
203void 203void
204csv_init(csv_t *csv) 204csv_init(csv_t *csv)
@@ -264,12 +264,12 @@ csv_read(csv_t *csv, FILE *in)
264 assert(csv != NULL); 264 assert(csv != NULL);
265 assert(in != NULL); 265 assert(in != NULL);
266 266
267 /* initialze if needed... */ 267 // initialze if needed...
268 if ( csv->csv_options == NULL ) { 268 if ( csv->csv_options == NULL ) {
269 csv_init(csv); 269 csv_init(csv);
270 } 270 }
271 271
272 /* do not try to read if EOF has already been seen */ 272 // do not try to read if EOF has already been seen
273 if ( feof(in) ) { 273 if ( feof(in) ) {
274 csv_cleanup(csv); 274 csv_cleanup(csv);
275 return -1; 275 return -1;
@@ -305,9 +305,9 @@ csv_read(csv_t *csv, FILE *in)
305 if ( ch == EOF ) { 305 if ( ch == EOF ) {
306 state = STATE_END_FILE; 306 state = STATE_END_FILE;
307 } 307 }
308 else if ( ch == '\r' ) { /* Teste auf CR.. */ 308 else if ( ch == '\r' ) { // test for CR..
309 ch = getc(in); 309 ch = getc(in);
310 if ( ch != '\n' ) { /* ... LF */ 310 if ( ch != '\n' ) { // ..LF
311 ungetc(ch, in); 311 ungetc(ch, in);
312 } 312 }
313 state = STATE_END_LINE; 313 state = STATE_END_LINE;
@@ -356,7 +356,7 @@ csv_read(csv_t *csv, FILE *in)
356 } 356 }
357 else { 357 else {
358 csv_string_append(&csv->csv_string, DELIM, csv->csv_options); 358 csv_string_append(&csv->csv_string, DELIM, csv->csv_options);
359 ungetc(ch, in); /* zuviel gelesenes Zeichen zurückstellen */ 359 ungetc(ch, in); // we have read too far... Put the character back!
360 } 360 }
361 } 361 }
362 else { 362 else {
@@ -406,14 +406,16 @@ csv_read(csv_t *csv, FILE *in)
406 406
407 if ( csv_string_empty(&csv->csv_string) ) { 407 if ( csv_string_empty(&csv->csv_string) ) {
408 csv_cleanup(csv); 408 csv_cleanup(csv);
409 return -1; /* EOF reached */ 409 return -1; // EOF reached
410 } 410 }
411 411
412 /* EOF wurde gelesen, allerdings sind Daten zur Vearbeitung vorhanden! */ 412 /*
413 /* => aktuelles Feld abschließen... */ 413 * The last data record was not terminated with a NEWLINE-Symbol.
414 * So we can't signal End-Of-File for now. Terminate the current
415 * field and return the numbor of fields processed so far.
416 */
414 csv_string_append(&csv->csv_string, '\0', csv->csv_options); 417 csv_string_append(&csv->csv_string, '\0', csv->csv_options);
415 418
416 /* ... und die Anzahl der Felder zurückliefern! */
417 return csv->csv_field.pos; 419 return csv->csv_field.pos;
418 420
419 default: 421 default:
@@ -421,7 +423,7 @@ csv_read(csv_t *csv, FILE *in)
421 break; 423 break;
422 } 424 }
423 } 425 }
424 /* NOT REACHED */ 426 // NOT REACHED
425} 427}
426 428
427const char * 429const char *
@@ -435,7 +437,7 @@ csv_err_str(csv_err_t csv_err)
435 case CSV_ERR_IO_WRITE: return "write error"; 437 case CSV_ERR_IO_WRITE: return "write error";
436 default: return "unknown error"; 438 default: return "unknown error";
437 } 439 }
438 /* NOT REACHED */ 440 // NOT REACHED
439} 441}
440 442
441static void 443static void
@@ -479,7 +481,6 @@ csv_write(FILE *out, const csv_t * const csv)
479 481
480 const char SEP = csv->csv_options->field_separator; 482 const char SEP = csv->csv_options->field_separator;
481 483
482
483 if ( 0 < csv->csv_field.pos ) { 484 if ( 0 < csv->csv_field.pos ) {
484 const char *str = csv->csv_string.str; 485 const char *str = csv->csv_string.str;
485 const int *field = csv->csv_field.fields; 486 const int *field = csv->csv_field.fields;
@@ -511,12 +512,12 @@ csv_write_ex(FILE *out, int n, const char *fields[], const csv_options_t * csv_o
511 512
512 const char SEP = csv_options->field_separator; 513 const char SEP = csv_options->field_separator;
513 514
514 /* process first field */ 515 // process first field
515 if ( 0 != n && *fields != NULL ) { 516 if ( 0 != n && *fields != NULL ) {
516 --n; 517 --n;
517 csv_write_field(out, *fields++, csv_options); 518 csv_write_field(out, *fields++, csv_options);
518 519
519 /* process next fields */ 520 // process next fields
520 for ( ; n && *fields != NULL; --n, ++fields ) { 521 for ( ; n && *fields != NULL; --n, ++fields ) {
521 putc(SEP, out); 522 putc(SEP, out);
522 csv_write_field(out, *fields, csv_options); 523 csv_write_field(out, *fields, csv_options);