aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--csv-tutorial.c36
-rw-r--r--csv.c89
2 files changed, 48 insertions, 77 deletions
diff --git a/csv-tutorial.c b/csv-tutorial.c
index 17b95c8..9bdb7e6 100644
--- a/csv-tutorial.c
+++ b/csv-tutorial.c
@@ -8,9 +8,9 @@
8bool 8bool
9processFile(const char *filename) 9processFile(const char *filename)
10{ 10{
11 FILE *in; 11 FILE *in = fopen(filename, "r");
12 12
13 if ( (in = fopen(filename, "r")) == NULL ) { 13 if ( in == NULL ) {
14 return false; 14 return false;
15 } 15 }
16 16
@@ -18,22 +18,21 @@ processFile(const char *filename)
18 csv_init(&csv); 18 csv_init(&csv);
19 19
20 while ( csv_read(&csv, in) ) { 20 while ( csv_read(&csv, in) ) {
21 const size_t nf = csv_nfields(&csv); 21 const size_t nfields = csv_nfields(&csv);
22 (void) nf;
23 // ... 22 // ...
24 } 23 }
25 csv_cleanup(&csv); 24 csv_cleanup(&csv);
26 25
27 fclose(in); 26 (void) fclose(in);
28 return true; 27 return true;
29} 28}
30 29
31bool 30bool
32processFile_options(const char *filename) 31processFile_options(const char *filename)
33{ 32{
34 FILE *in; 33 FILE *in = fopen(filename, "r");
35 34
36 if ( (in = fopen(filename, "r")) == NULL ) { 35 if ( in == NULL ) {
37 return false; 36 return false;
38 } 37 }
39 38
@@ -45,13 +44,12 @@ processFile_options(const char *filename)
45 csv_init_opt(&csv, &csv_options); 44 csv_init_opt(&csv, &csv_options);
46 45
47 while ( csv_read(&csv, in) ) { 46 while ( csv_read(&csv, in) ) {
48 const size_t nf = csv_nfields(&csv); 47 const size_t nfields = csv_nfields(&csv);
49 (void) nf;
50 // ... 48 // ...
51 } 49 }
52 csv_cleanup(&csv); 50 csv_cleanup(&csv);
53 51
54 fclose(in); 52 (void) fclose(in);
55 return true; 53 return true;
56} 54}
57 55
@@ -64,9 +62,9 @@ csvErrorHandler(csv_err_t err, void *cb_arg)
64bool 62bool
65processFile_error(const char *filename) 63processFile_error(const char *filename)
66{ 64{
67 FILE *in; 65 FILE *in = fopen(filename, "r");
68 66
69 if ( (in = fopen(filename, "r")) == NULL ) { 67 if ( in == NULL ) {
70 return false; 68 return false;
71 } 69 }
72 70
@@ -84,30 +82,20 @@ processFile_error(const char *filename)
84 switch ( setjmp(env) ) { 82 switch ( setjmp(env) ) {
85 case CSV_ERR_OK: 83 case CSV_ERR_OK:
86 while ( csv_read(&csv, in) ) { 84 while ( csv_read(&csv, in) ) {
87 const size_t nf = csv_nfields(&csv); 85 const size_t nfields = csv_nfields(&csv);
88 (void) nf;
89 // ... 86 // ...
90 } 87 }
91 break; 88 break;
92 89
93 case CSV_ERR_OUT_OF_MEMORY: 90 case CSV_ERR_OUT_OF_MEMORY:
94 csv_cleanup(&csv);
95 break;
96
97 case CSV_ERR_OUT_OF_RANGE: 91 case CSV_ERR_OUT_OF_RANGE:
98 csv_cleanup(&csv);
99 break;
100
101 case CSV_ERR_IO_READ: 92 case CSV_ERR_IO_READ:
102 csv_cleanup(&csv);
103 break;
104
105 case CSV_ERR_IO_WRITE: 93 case CSV_ERR_IO_WRITE:
106 csv_cleanup(&csv); 94 csv_cleanup(&csv);
107 break; 95 break;
108 } 96 }
109 97
110 fclose(in); 98 (void) fclose(in);
111 return true; 99 return true;
112} 100}
113 101
diff --git a/csv.c b/csv.c
index 4f3cd14..b68189b 100644
--- a/csv.c
+++ b/csv.c
@@ -44,18 +44,6 @@ mul_overflow(size_t a, size_t b, size_t *out)
44#endif 44#endif
45 45
46static void * 46static void *
47csv_mem_allocate(size_t number, size_t size, void *cb_arg)
48{
49 UNUSED(cb_arg);
50
51 size_t len = 0;
52 if ( number == 0 || size == 0 || mul_overflow(number, size, &len) ) {
53 return NULL;
54 }
55 return malloc(len);
56}
57
58static void *
59csv_mem_reallocate(void *ptr, size_t number, size_t size, void *cb_arg) 47csv_mem_reallocate(void *ptr, size_t number, size_t size, void *cb_arg)
60{ 48{
61 UNUSED(cb_arg); 49 UNUSED(cb_arg);
@@ -83,7 +71,6 @@ const csv_options_t csv_default_options = {
83 .field_delimiter = CSV_DEFAULT_DELIMITER, 71 .field_delimiter = CSV_DEFAULT_DELIMITER,
84 .field_separator = CSV_DEFAULT_SEPARATOR, 72 .field_separator = CSV_DEFAULT_SEPARATOR,
85 .cb_error = NULL, 73 .cb_error = NULL,
86 .cb_allocate = csv_mem_allocate,
87 .cb_reallocate = csv_mem_reallocate, 74 .cb_reallocate = csv_mem_reallocate,
88 .cb_free = csv_mem_free 75 .cb_free = csv_mem_free
89}; 76};
@@ -129,34 +116,32 @@ csv_string_isempty(csv_string_t *csv_string)
129} 116}
130 117
131static inline void 118static inline void
132csv_string_append(csv_string_t *csv_string, int ch, const csv_options_t *const csv_options) 119csv_string_grow_if_needed(csv_string_t *csv_string, const csv_options_t *const csv_options)
133{ 120{
134 assert(csv_string != NULL); 121 assert(csv_string != NULL);
135 assert(csv_options != NULL); 122 assert(csv_options != NULL);
136 123
137 static const size_t INITIAL_CAP = 16; 124 static const size_t INITIAL_CAP = 16;
138 125
139 if ( csv_string->pos == csv_string->cap ) { // grow if needed 126 if ( csv_string->pos == csv_string->cap ) {
140 if ( csv_string->str == NULL ) { // first call? 127 size_t cap = (csv_string->str == NULL) ? INITIAL_CAP : (csv_string->cap * 3) / 2;
141 char *str = csv_options->cb_allocate(INITIAL_CAP, 1, csv_options->cb_memory_arg); 128 char *str = csv_options->cb_reallocate(csv_string->str, cap, 1, csv_options->cb_memory_arg);
142 if ( str == NULL ) { 129 if ( str == NULL ) {
143 csv_fatal_error(CSV_ERR_OUT_OF_MEMORY, csv_options); 130 csv_fatal_error(CSV_ERR_OUT_OF_MEMORY, csv_options);
144 return; 131 return;
145 }
146 csv_string->str = str;
147 csv_string->cap = INITIAL_CAP;
148 }
149 else { // subsequent call
150 size_t cap = (csv_string->cap * 3) / 2; // *= 1.5
151 char *str = csv_options->cb_reallocate(csv_string->str, cap, 1, csv_options->cb_memory_arg);
152 if ( str == NULL ) {
153 csv_fatal_error(CSV_ERR_OUT_OF_MEMORY, csv_options);
154 return;
155 }
156 csv_string->str = str;
157 csv_string->cap = cap;
158 } 132 }
133 csv_string->str = str;
134 csv_string->cap = cap;
159 } 135 }
136}
137
138static inline void
139csv_string_append(csv_string_t *csv_string, int ch, const csv_options_t *const csv_options)
140{
141 assert(csv_string != NULL);
142 assert(csv_options != NULL);
143
144 csv_string_grow_if_needed(csv_string, csv_options);
160 145
161 csv_string->str[csv_string->pos++] = (char) ch; // append char 146 csv_string->str[csv_string->pos++] = (char) ch; // append char
162} 147}
@@ -194,34 +179,32 @@ csv_field_reset(csv_field_t *csv_field)
194} 179}
195 180
196static inline void 181static inline void
197csv_field_append(csv_field_t *csv_field, size_t idx, const csv_options_t *const csv_options) 182csv_field_grow_if_needed(csv_field_t *csv_field, const csv_options_t *const csv_options)
198{ 183{
199 assert(csv_field != NULL); 184 assert(csv_field != NULL);
200 assert(csv_options != NULL); 185 assert(csv_options != NULL);
201 186
202 static const size_t INITIAL_CAP = 16; 187 static const size_t INITIAL_CAP = 16;
203 188
204 if ( csv_field->pos == csv_field->cap ) { // grow if needed 189 if ( csv_field->pos == csv_field->cap ) {
205 if ( csv_field->fields == NULL ) { // first call 190 size_t cap = (csv_field->fields == NULL) ? INITIAL_CAP : (csv_field->cap * 3) / 2;
206 size_t *fields = csv_options->cb_allocate(INITIAL_CAP, sizeof(csv_field->fields[0]), csv_options->cb_memory_arg); 191 size_t *fields = csv_options->cb_reallocate(csv_field->fields, cap, sizeof(csv_field->fields[0]), csv_options->cb_memory_arg);
207 if ( fields == NULL ) { 192 if ( fields == NULL ) {
208 csv_fatal_error(CSV_ERR_OUT_OF_MEMORY, csv_options); 193 csv_fatal_error(CSV_ERR_OUT_OF_MEMORY, csv_options);
209 return; 194 return;
210 }
211 csv_field->fields = fields;
212 csv_field->cap = INITIAL_CAP;
213 }
214 else { // subsequent call
215 size_t cap = (csv_field->cap * 3) / 2; // *= 1.5
216 size_t *fields = csv_options->cb_reallocate(csv_field->fields, cap, sizeof(csv_field->fields[0]), csv_options->cb_memory_arg);
217 if ( fields == NULL ) {
218 csv_fatal_error(CSV_ERR_OUT_OF_MEMORY, csv_options);
219 return;
220 }
221 csv_field->fields = fields;
222 csv_field->cap = cap;
223 } 195 }
196 csv_field->fields = fields;
197 csv_field->cap = cap;
224 } 198 }
199}
200
201static inline void
202csv_field_append(csv_field_t *csv_field, size_t idx, const csv_options_t *const csv_options)
203{
204 assert(csv_field != NULL);
205 assert(csv_options != NULL);
206
207 csv_field_grow_if_needed(csv_field, csv_options);
225 208
226 csv_field->fields[csv_field->pos++] = idx; // append index 209 csv_field->fields[csv_field->pos++] = idx; // append index
227} 210}