summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Schmucker <ts@its1.de>2020-07-05 11:54:28 +0200
committerThomas Schmucker <ts@its1.de>2020-07-05 11:54:28 +0200
commitdb6807fd6644b1e129008ff9622384cef4e48654 (patch)
tree1e7869a413caedcea433e051987df80bbb445403
parent12b36ad95dc633648b6c93d7626e17a0016b4547 (diff)
downloadlibcsv-db6807fd6644b1e129008ff9622384cef4e48654.tar.gz
libcsv-db6807fd6644b1e129008ff9622384cef4e48654.tar.bz2
libcsv-db6807fd6644b1e129008ff9622384cef4e48654.zip
Formatiere den Quellcode mit clang-format
-rw-r--r--.clang-format45
-rw-r--r--csv-test.c496
-rw-r--r--csv.c108
-rw-r--r--csv.h26
4 files changed, 363 insertions, 312 deletions
diff --git a/.clang-format b/.clang-format
new file mode 100644
index 0000000..b32bad6
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,45 @@
1---
2AccessModifierOffset: -4
3AlignConsecutiveAssignments: 'true'
4AlignConsecutiveDeclarations: 'true'
5AlignEscapedNewlines: Left
6AlignTrailingComments: 'true'
7AlwaysBreakAfterReturnType: TopLevelDefinitions
8BreakBeforeBraces: Stroustrup
9BreakConstructorInitializers: BeforeComma
10BreakInheritanceList: BeforeComma
11ColumnLimit: '0'
12CompactNamespaces: 'false'
13Cpp11BracedListStyle: 'false'
14FixNamespaceComments: 'true'
15IncludeBlocks: Regroup
16IncludeCategories:
17 - Regex: '^.*(precomp|pch|stdafx)'
18 Priority: -1
19 - Regex: '^<.*>'
20 Priority: 1
21 - Regex: '^".*"'
22 Priority: 2
23 - Regex: '.*'
24 Priority: 3
25IndentCaseLabels: 'false'
26IndentPPDirectives: AfterHash
27IndentWidth: '4'
28IndentWrappedFunctionNames: 'false'
29KeepEmptyLinesAtTheStartOfBlocks: 'false'
30PointerAlignment: Right
31SortIncludes: 'true'
32SpaceAfterCStyleCast: 'true'
33SpaceAfterTemplateKeyword: 'false'
34SpaceBeforeAssignmentOperators: 'true'
35SpaceBeforeParens: ControlStatements
36SpaceBeforeRangeBasedForLoopColon: 'false'
37SpaceInEmptyParentheses: 'false'
38SpacesInAngles: 'false'
39SpacesInCStyleCastParentheses: 'false'
40SpacesInConditionalStatement: 'true'
41SpacesInParentheses: 'false'
42Standard: Auto
43TabWidth: '4'
44UseTab: ForIndentation
45...
diff --git a/csv-test.c b/csv-test.c
index 8fbcf42..238bf74 100644
--- a/csv-test.c
+++ b/csv-test.c
@@ -1,19 +1,19 @@
1#undef NDEBUG 1#undef NDEBUG
2 2
3#include <assert.h>
4#include <setjmp.h>
3#include <stdio.h> 5#include <stdio.h>
4#include <stdlib.h> 6#include <stdlib.h>
5#include <string.h> 7#include <string.h>
6#include <assert.h>
7#include <setjmp.h>
8 8
9#include "csv.h" 9#include "csv.h"
10 10
11#define FMEMOPEN(f, data) \ 11#define FMEMOPEN(f, data) \
12 f = fmemopen(data, sizeof(data)-1, "r"); \ 12 f = fmemopen(data, sizeof(data) - 1, "r"); \
13 assert(f != NULL) 13 assert(f != NULL)
14 14
15#define FMEMCLOSE(f) \ 15#define FMEMCLOSE(f) \
16 fclose(f); \ 16 fclose(f); \
17 f = NULL 17 f = NULL
18 18
19void 19void
@@ -21,13 +21,13 @@ test_empty_object(void)
21{ 21{
22 { 22 {
23 csv_t csv = { 0 }; 23 csv_t csv = { 0 };
24 assert( csv_nfields(&csv) == 0 ); 24 assert(csv_nfields(&csv) == 0);
25 } 25 }
26 26
27 { 27 {
28 csv_t csv; 28 csv_t csv;
29 csv_init(&csv); 29 csv_init(&csv);
30 assert( csv_nfields(&csv) == 0 ); 30 assert(csv_nfields(&csv) == 0);
31 } 31 }
32} 32}
33 33
@@ -42,19 +42,19 @@ test_line_endings1(void)
42 42
43 FMEMOPEN(f, data); 43 FMEMOPEN(f, data);
44 44
45 assert( csv_read(&csv, f) == 3 ); 45 assert(csv_read(&csv, f) == 3);
46 assert( csv_nfields(&csv) == 3 ), 46 assert(csv_nfields(&csv) == 3);
47 assert( strcmp(csv_field(&csv, 0), "A") == 0 ); 47 assert(strcmp(csv_field(&csv, 0), "A") == 0);
48 assert( strcmp(csv_field(&csv, 1), "B") == 0 ); 48 assert(strcmp(csv_field(&csv, 1), "B") == 0);
49 assert( strcmp(csv_field(&csv, 2), "C") == 0 ); 49 assert(strcmp(csv_field(&csv, 2), "C") == 0);
50 50
51 assert( csv_read(&csv, f) == 3 ); 51 assert(csv_read(&csv, f) == 3);
52 assert( csv_nfields(&csv) == 3 ), 52 assert(csv_nfields(&csv) == 3);
53 assert( strcmp(csv_field(&csv, 0), "D") == 0 ); 53 assert(strcmp(csv_field(&csv, 0), "D") == 0);
54 assert( strcmp(csv_field(&csv, 1), "E") == 0 ); 54 assert(strcmp(csv_field(&csv, 1), "E") == 0);
55 assert( strcmp(csv_field(&csv, 2), "F") == 0 ); 55 assert(strcmp(csv_field(&csv, 2), "F") == 0);
56 56
57 assert( csv_read(&csv, f) == EOF ); 57 assert(csv_read(&csv, f) == EOF);
58 58
59 FMEMCLOSE(f); 59 FMEMCLOSE(f);
60} 60}
@@ -70,19 +70,19 @@ test_line_endings2(void)
70 70
71 FMEMOPEN(f, data); 71 FMEMOPEN(f, data);
72 72
73 assert( csv_read(&csv, f) == 3 ); 73 assert(csv_read(&csv, f) == 3);
74 assert( csv_nfields(&csv) == 3 ), 74 assert(csv_nfields(&csv) == 3);
75 assert( strcmp(csv_field(&csv, 0), "A") == 0 ); 75 assert(strcmp(csv_field(&csv, 0), "A") == 0);
76 assert( strcmp(csv_field(&csv, 1), "B") == 0 ); 76 assert(strcmp(csv_field(&csv, 1), "B") == 0);
77 assert( strcmp(csv_field(&csv, 2), "C") == 0 ); 77 assert(strcmp(csv_field(&csv, 2), "C") == 0);
78 78
79 assert( csv_read(&csv, f) == 3 ); 79 assert(csv_read(&csv, f) == 3);
80 assert( csv_nfields(&csv) == 3 ), 80 assert(csv_nfields(&csv) == 3);
81 assert( strcmp(csv_field(&csv, 0), "D") == 0 ); 81 assert(strcmp(csv_field(&csv, 0), "D") == 0);
82 assert( strcmp(csv_field(&csv, 1), "E") == 0 ); 82 assert(strcmp(csv_field(&csv, 1), "E") == 0);
83 assert( strcmp(csv_field(&csv, 2), "F") == 0 ); 83 assert(strcmp(csv_field(&csv, 2), "F") == 0);
84 84
85 assert( csv_read(&csv, f) == EOF ); 85 assert(csv_read(&csv, f) == EOF);
86 86
87 FMEMCLOSE(f); 87 FMEMCLOSE(f);
88} 88}
@@ -95,143 +95,143 @@ test_empty_fields(void)
95 95
96 char data[] = "\n" 96 char data[] = "\n"
97 "\r" 97 "\r"
98 "\r\n" 98 "\r\n"
99 "\"\"\n" 99 "\"\"\n"
100 "\"\"\r" 100 "\"\"\r"
101 "\"\"\r\n" 101 "\"\"\r\n"
102 ",\n" 102 ",\n"
103 ",\r" 103 ",\r"
104 ",\r\n" 104 ",\r\n"
105 "\"\",\"\"\n" 105 "\"\",\"\"\n"
106 "\"\",\"\"\r" 106 "\"\",\"\"\r"
107 "\"\",\"\"\r\n" 107 "\"\",\"\"\r\n"
108 ",,\n" 108 ",,\n"
109 ",,\r" 109 ",,\r"
110 ",,\r\n" 110 ",,\r\n"
111 "\"\",\"\",\n" 111 "\"\",\"\",\n"
112 "\"\",\"\",\r" 112 "\"\",\"\",\r"
113 "\"\",\"\",\r\n" 113 "\"\",\"\",\r\n"
114 ",,"; 114 ",,";
115 115
116 FMEMOPEN(f, data); 116 FMEMOPEN(f, data);
117 117
118 // Line 1 118 // Line 1
119 assert( csv_read(&csv, f) == 1 ); 119 assert(csv_read(&csv, f) == 1);
120 assert( csv_nfields(&csv) == 1 ); 120 assert(csv_nfields(&csv) == 1);
121 assert( strcmp(csv_field(&csv, 0), "") == 0 ); 121 assert(strcmp(csv_field(&csv, 0), "") == 0);
122 122
123 // Line 2 123 // Line 2
124 assert( csv_read(&csv, f) == 1 ); 124 assert(csv_read(&csv, f) == 1);
125 assert( csv_nfields(&csv) == 1 ); 125 assert(csv_nfields(&csv) == 1);
126 assert( strcmp(csv_field(&csv, 0), "") == 0 ); 126 assert(strcmp(csv_field(&csv, 0), "") == 0);
127 127
128 // Line 3 128 // Line 3
129 assert( csv_read(&csv, f) == 1 ); 129 assert(csv_read(&csv, f) == 1);
130 assert( csv_nfields(&csv) == 1 ); 130 assert(csv_nfields(&csv) == 1);
131 assert( strcmp(csv_field(&csv, 0), "") == 0 ); 131 assert(strcmp(csv_field(&csv, 0), "") == 0);
132 132
133 // Line 4 133 // Line 4
134 assert( csv_read(&csv, f) == 1 ); 134 assert(csv_read(&csv, f) == 1);
135 assert( csv_nfields(&csv) == 1 ); 135 assert(csv_nfields(&csv) == 1);
136 assert( strcmp(csv_field(&csv, 0), "") == 0 ); 136 assert(strcmp(csv_field(&csv, 0), "") == 0);
137 137
138 // Line 5 138 // Line 5
139 assert( csv_read(&csv, f) == 1 ); 139 assert(csv_read(&csv, f) == 1);
140 assert( csv_nfields(&csv) == 1 ); 140 assert(csv_nfields(&csv) == 1);
141 assert( strcmp(csv_field(&csv, 0), "") == 0 ); 141 assert(strcmp(csv_field(&csv, 0), "") == 0);
142 142
143 // Line 6 143 // Line 6
144 assert( csv_read(&csv, f) == 1 ); 144 assert(csv_read(&csv, f) == 1);
145 assert( csv_nfields(&csv) == 1 ); 145 assert(csv_nfields(&csv) == 1);
146 assert( strcmp(csv_field(&csv, 0), "") == 0 ); 146 assert(strcmp(csv_field(&csv, 0), "") == 0);
147 147
148 // Line 7 148 // Line 7
149 assert( csv_read(&csv, f) == 2 ); 149 assert(csv_read(&csv, f) == 2);
150 assert( csv_nfields(&csv) == 2 ); 150 assert(csv_nfields(&csv) == 2);
151 assert( strcmp(csv_field(&csv, 0), "") == 0 ); 151 assert(strcmp(csv_field(&csv, 0), "") == 0);
152 assert( strcmp(csv_field(&csv, 1), "") == 0 ); 152 assert(strcmp(csv_field(&csv, 1), "") == 0);
153 153
154 // Line 8 154 // Line 8
155 assert( csv_read(&csv, f) == 2 ); 155 assert(csv_read(&csv, f) == 2);
156 assert( csv_nfields(&csv) == 2 ); 156 assert(csv_nfields(&csv) == 2);
157 assert( strcmp(csv_field(&csv, 0), "") == 0 ); 157 assert(strcmp(csv_field(&csv, 0), "") == 0);
158 assert( strcmp(csv_field(&csv, 1), "") == 0 ); 158 assert(strcmp(csv_field(&csv, 1), "") == 0);
159 159
160 // Line 9 160 // Line 9
161 assert( csv_read(&csv, f) == 2 ); 161 assert(csv_read(&csv, f) == 2);
162 assert( csv_nfields(&csv) == 2 ); 162 assert(csv_nfields(&csv) == 2);
163 assert( strcmp(csv_field(&csv, 0), "") == 0 ); 163 assert(strcmp(csv_field(&csv, 0), "") == 0);
164 assert( strcmp(csv_field(&csv, 1), "") == 0 ); 164 assert(strcmp(csv_field(&csv, 1), "") == 0);
165 165
166 // Line 10 166 // Line 10
167 assert( csv_read(&csv, f) == 2 ); 167 assert(csv_read(&csv, f) == 2);
168 assert( csv_nfields(&csv) == 2 ); 168 assert(csv_nfields(&csv) == 2);
169 assert( strcmp(csv_field(&csv, 0), "") == 0 ); 169 assert(strcmp(csv_field(&csv, 0), "") == 0);
170 assert( strcmp(csv_field(&csv, 1), "") == 0 ); 170 assert(strcmp(csv_field(&csv, 1), "") == 0);
171 171
172 // Line 11 172 // Line 11
173 assert( csv_read(&csv, f) == 2 ); 173 assert(csv_read(&csv, f) == 2);
174 assert( csv_nfields(&csv) == 2 ); 174 assert(csv_nfields(&csv) == 2);
175 assert( strcmp(csv_field(&csv, 0), "") == 0 ); 175 assert(strcmp(csv_field(&csv, 0), "") == 0);
176 assert( strcmp(csv_field(&csv, 1), "") == 0 ); 176 assert(strcmp(csv_field(&csv, 1), "") == 0);
177 177
178 // Line 12 178 // Line 12
179 assert( csv_read(&csv, f) == 2 ); 179 assert(csv_read(&csv, f) == 2);
180 assert( csv_nfields(&csv) == 2 ); 180 assert(csv_nfields(&csv) == 2);
181 assert( strcmp(csv_field(&csv, 0), "") == 0 ); 181 assert(strcmp(csv_field(&csv, 0), "") == 0);
182 assert( strcmp(csv_field(&csv, 1), "") == 0 ); 182 assert(strcmp(csv_field(&csv, 1), "") == 0);
183 183
184 // Line 13 184 // Line 13
185 assert( csv_read(&csv, f) == 3 ); 185 assert(csv_read(&csv, f) == 3);
186 assert( csv_nfields(&csv) == 3 ); 186 assert(csv_nfields(&csv) == 3);
187 assert( strcmp(csv_field(&csv, 0), "") == 0 ); 187 assert(strcmp(csv_field(&csv, 0), "") == 0);
188 assert( strcmp(csv_field(&csv, 1), "") == 0 ); 188 assert(strcmp(csv_field(&csv, 1), "") == 0);
189 assert( strcmp(csv_field(&csv, 2), "") == 0 ); 189 assert(strcmp(csv_field(&csv, 2), "") == 0);
190 190
191 // Line 14 191 // Line 14
192 assert( csv_read(&csv, f) == 3 ); 192 assert(csv_read(&csv, f) == 3);
193 assert( csv_nfields(&csv) == 3 ); 193 assert(csv_nfields(&csv) == 3);
194 assert( strcmp(csv_field(&csv, 0), "") == 0 ); 194 assert(strcmp(csv_field(&csv, 0), "") == 0);
195 assert( strcmp(csv_field(&csv, 1), "") == 0 ); 195 assert(strcmp(csv_field(&csv, 1), "") == 0);
196 assert( strcmp(csv_field(&csv, 2), "") == 0 ); 196 assert(strcmp(csv_field(&csv, 2), "") == 0);
197 197
198 // Line 15 198 // Line 15
199 assert( csv_read(&csv, f) == 3 ); 199 assert(csv_read(&csv, f) == 3);
200 assert( csv_nfields(&csv) == 3 ); 200 assert(csv_nfields(&csv) == 3);
201 assert( strcmp(csv_field(&csv, 0), "") == 0 ); 201 assert(strcmp(csv_field(&csv, 0), "") == 0);
202 assert( strcmp(csv_field(&csv, 1), "") == 0 ); 202 assert(strcmp(csv_field(&csv, 1), "") == 0);
203 assert( strcmp(csv_field(&csv, 2), "") == 0 ); 203 assert(strcmp(csv_field(&csv, 2), "") == 0);
204 204
205 // Line 16 205 // Line 16
206 assert( csv_read(&csv, f) == 3 ); 206 assert(csv_read(&csv, f) == 3);
207 assert( csv_nfields(&csv) == 3 ); 207 assert(csv_nfields(&csv) == 3);
208 assert( strcmp(csv_field(&csv, 0), "") == 0 ); 208 assert(strcmp(csv_field(&csv, 0), "") == 0);
209 assert( strcmp(csv_field(&csv, 1), "") == 0 ); 209 assert(strcmp(csv_field(&csv, 1), "") == 0);
210 assert( strcmp(csv_field(&csv, 2), "") == 0 ); 210 assert(strcmp(csv_field(&csv, 2), "") == 0);
211 211
212 // Line 17 212 // Line 17
213 assert( csv_read(&csv, f) == 3 ); 213 assert(csv_read(&csv, f) == 3);
214 assert( csv_nfields(&csv) == 3 ); 214 assert(csv_nfields(&csv) == 3);
215 assert( strcmp(csv_field(&csv, 0), "") == 0 ); 215 assert(strcmp(csv_field(&csv, 0), "") == 0);
216 assert( strcmp(csv_field(&csv, 1), "") == 0 ); 216 assert(strcmp(csv_field(&csv, 1), "") == 0);
217 assert( strcmp(csv_field(&csv, 2), "") == 0 ); 217 assert(strcmp(csv_field(&csv, 2), "") == 0);
218 218
219 // Line 18 219 // Line 18
220 assert( csv_read(&csv, f) == 3 ); 220 assert(csv_read(&csv, f) == 3);
221 assert( csv_nfields(&csv) == 3 ); 221 assert(csv_nfields(&csv) == 3);
222 assert( strcmp(csv_field(&csv, 0), "") == 0 ); 222 assert(strcmp(csv_field(&csv, 0), "") == 0);
223 assert( strcmp(csv_field(&csv, 1), "") == 0 ); 223 assert(strcmp(csv_field(&csv, 1), "") == 0);
224 assert( strcmp(csv_field(&csv, 2), "") == 0 ); 224 assert(strcmp(csv_field(&csv, 2), "") == 0);
225 225
226 // Line 19 226 // Line 19
227 assert( csv_read(&csv, f) == 3 ); 227 assert(csv_read(&csv, f) == 3);
228 assert( csv_nfields(&csv) == 3 ); 228 assert(csv_nfields(&csv) == 3);
229 assert( strcmp(csv_field(&csv, 0), "") == 0 ); 229 assert(strcmp(csv_field(&csv, 0), "") == 0);
230 assert( strcmp(csv_field(&csv, 1), "") == 0 ); 230 assert(strcmp(csv_field(&csv, 1), "") == 0);
231 assert( strcmp(csv_field(&csv, 2), "") == 0 ); 231 assert(strcmp(csv_field(&csv, 2), "") == 0);
232 232
233 // EOF 233 // EOF
234 assert( csv_read(&csv, f) == EOF ); 234 assert(csv_read(&csv, f) == EOF);
235 235
236 FMEMCLOSE(f); 236 FMEMCLOSE(f);
237} 237}
@@ -244,143 +244,143 @@ test_simple_fields(void)
244 244
245 char data[] = "A\n" 245 char data[] = "A\n"
246 "A\r" 246 "A\r"
247 "A\r\n" 247 "A\r\n"
248 "\"A\"\n" 248 "\"A\"\n"
249 "\"A\"\r" 249 "\"A\"\r"
250 "\"A\"\r\n" 250 "\"A\"\r\n"
251 "A,B\n" 251 "A,B\n"
252 "A,B\r" 252 "A,B\r"
253 "A,B\r\n" 253 "A,B\r\n"
254 "\"A\",\"B\"\n" 254 "\"A\",\"B\"\n"
255 "\"A\",\"B\"\r" 255 "\"A\",\"B\"\r"
256 "\"A\",\"B\"\r\n" 256 "\"A\",\"B\"\r\n"
257 "A,B,C\n" 257 "A,B,C\n"
258 "A,B,C\r" 258 "A,B,C\r"
259 "A,B,C\r\n" 259 "A,B,C\r\n"
260 "\"A\",\"B\",C\n" 260 "\"A\",\"B\",C\n"
261 "\"A\",\"B\",C\r" 261 "\"A\",\"B\",C\r"
262 "\"A\",\"B\",C\r\n" 262 "\"A\",\"B\",C\r\n"
263 "A,B,C"; 263 "A,B,C";
264 264
265 FMEMOPEN(f, data); 265 FMEMOPEN(f, data);
266 266
267 // Line 1 267 // Line 1
268 assert( csv_read(&csv, f) == 1 ); 268 assert(csv_read(&csv, f) == 1);
269 assert( csv_nfields(&csv) == 1 ); 269 assert(csv_nfields(&csv) == 1);
270 assert( strcmp(csv_field(&csv, 0), "A") == 0 ); 270 assert(strcmp(csv_field(&csv, 0), "A") == 0);
271 271
272 // Line 2 272 // Line 2
273 assert( csv_read(&csv, f) == 1 ); 273 assert(csv_read(&csv, f) == 1);
274 assert( csv_nfields(&csv) == 1 ); 274 assert(csv_nfields(&csv) == 1);
275 assert( strcmp(csv_field(&csv, 0), "A") == 0 ); 275 assert(strcmp(csv_field(&csv, 0), "A") == 0);
276 276
277 // Line 3 277 // Line 3
278 assert( csv_read(&csv, f) == 1 ); 278 assert(csv_read(&csv, f) == 1);
279 assert( csv_nfields(&csv) == 1 ); 279 assert(csv_nfields(&csv) == 1);
280 assert( strcmp(csv_field(&csv, 0), "A") == 0 ); 280 assert(strcmp(csv_field(&csv, 0), "A") == 0);
281 281
282 // Line 4 282 // Line 4
283 assert( csv_read(&csv, f) == 1 ); 283 assert(csv_read(&csv, f) == 1);
284 assert( csv_nfields(&csv) == 1 ); 284 assert(csv_nfields(&csv) == 1);
285 assert( strcmp(csv_field(&csv, 0), "A") == 0 ); 285 assert(strcmp(csv_field(&csv, 0), "A") == 0);
286 286
287 // Line 5 287 // Line 5
288 assert( csv_read(&csv, f) == 1 ); 288 assert(csv_read(&csv, f) == 1);
289 assert( csv_nfields(&csv) == 1 ); 289 assert(csv_nfields(&csv) == 1);
290 assert( strcmp(csv_field(&csv, 0), "A") == 0 ); 290 assert(strcmp(csv_field(&csv, 0), "A") == 0);
291 291
292 // Line 6 292 // Line 6
293 assert( csv_read(&csv, f) == 1 ); 293 assert(csv_read(&csv, f) == 1);
294 assert( csv_nfields(&csv) == 1 ); 294 assert(csv_nfields(&csv) == 1);
295 assert( strcmp(csv_field(&csv, 0), "A") == 0 ); 295 assert(strcmp(csv_field(&csv, 0), "A") == 0);
296 296
297 // Line 7 297 // Line 7
298 assert( csv_read(&csv, f) == 2 ); 298 assert(csv_read(&csv, f) == 2);
299 assert( csv_nfields(&csv) == 2 ); 299 assert(csv_nfields(&csv) == 2);
300 assert( strcmp(csv_field(&csv, 0), "A") == 0 ); 300 assert(strcmp(csv_field(&csv, 0), "A") == 0);
301 assert( strcmp(csv_field(&csv, 1), "B") == 0 ); 301 assert(strcmp(csv_field(&csv, 1), "B") == 0);
302 302
303 // Line 8 303 // Line 8
304 assert( csv_read(&csv, f) == 2 ); 304 assert(csv_read(&csv, f) == 2);
305 assert( csv_nfields(&csv) == 2 ); 305 assert(csv_nfields(&csv) == 2);
306 assert( strcmp(csv_field(&csv, 0), "A") == 0 ); 306 assert(strcmp(csv_field(&csv, 0), "A") == 0);
307 assert( strcmp(csv_field(&csv, 1), "B") == 0 ); 307 assert(strcmp(csv_field(&csv, 1), "B") == 0);
308 308
309 // Line 9 309 // Line 9
310 assert( csv_read(&csv, f) == 2 ); 310 assert(csv_read(&csv, f) == 2);
311 assert( csv_nfields(&csv) == 2 ); 311 assert(csv_nfields(&csv) == 2);
312 assert( strcmp(csv_field(&csv, 0), "A") == 0 ); 312 assert(strcmp(csv_field(&csv, 0), "A") == 0);
313 assert( strcmp(csv_field(&csv, 1), "B") == 0 ); 313 assert(strcmp(csv_field(&csv, 1), "B") == 0);
314 314
315 // Line 10 315 // Line 10
316 assert( csv_read(&csv, f) == 2 ); 316 assert(csv_read(&csv, f) == 2);
317 assert( csv_nfields(&csv) == 2 ); 317 assert(csv_nfields(&csv) == 2);
318 assert( strcmp(csv_field(&csv, 0), "A") == 0 ); 318 assert(strcmp(csv_field(&csv, 0), "A") == 0);
319 assert( strcmp(csv_field(&csv, 1), "B") == 0 ); 319 assert(strcmp(csv_field(&csv, 1), "B") == 0);
320 320
321 // Line 11 321 // Line 11
322 assert( csv_read(&csv, f) == 2 ); 322 assert(csv_read(&csv, f) == 2);
323 assert( csv_nfields(&csv) == 2 ); 323 assert(csv_nfields(&csv) == 2);
324 assert( strcmp(csv_field(&csv, 0), "A") == 0 ); 324 assert(strcmp(csv_field(&csv, 0), "A") == 0);
325 assert( strcmp(csv_field(&csv, 1), "B") == 0 ); 325 assert(strcmp(csv_field(&csv, 1), "B") == 0);
326 326
327 // Line 12 327 // Line 12
328 assert( csv_read(&csv, f) == 2 ); 328 assert(csv_read(&csv, f) == 2);
329 assert( csv_nfields(&csv) == 2 ); 329 assert(csv_nfields(&csv) == 2);
330 assert( strcmp(csv_field(&csv, 0), "A") == 0 ); 330 assert(strcmp(csv_field(&csv, 0), "A") == 0);
331 assert( strcmp(csv_field(&csv, 1), "B") == 0 ); 331 assert(strcmp(csv_field(&csv, 1), "B") == 0);
332 332
333 // Line 13 333 // Line 13
334 assert( csv_read(&csv, f) == 3 ); 334 assert(csv_read(&csv, f) == 3);
335 assert( csv_nfields(&csv) == 3 ); 335 assert(csv_nfields(&csv) == 3);
336 assert( strcmp(csv_field(&csv, 0), "A") == 0 ); 336 assert(strcmp(csv_field(&csv, 0), "A") == 0);
337 assert( strcmp(csv_field(&csv, 1), "B") == 0 ); 337 assert(strcmp(csv_field(&csv, 1), "B") == 0);
338 assert( strcmp(csv_field(&csv, 2), "C") == 0 ); 338 assert(strcmp(csv_field(&csv, 2), "C") == 0);
339 339
340 // Line 14 340 // Line 14
341 assert( csv_read(&csv, f) == 3 ); 341 assert(csv_read(&csv, f) == 3);
342 assert( csv_nfields(&csv) == 3 ); 342 assert(csv_nfields(&csv) == 3);
343 assert( strcmp(csv_field(&csv, 0), "A") == 0 ); 343 assert(strcmp(csv_field(&csv, 0), "A") == 0);
344 assert( strcmp(csv_field(&csv, 1), "B") == 0 ); 344 assert(strcmp(csv_field(&csv, 1), "B") == 0);
345 assert( strcmp(csv_field(&csv, 2), "C") == 0 ); 345 assert(strcmp(csv_field(&csv, 2), "C") == 0);
346 346
347 // Line 15 347 // Line 15
348 assert( csv_read(&csv, f) == 3 ); 348 assert(csv_read(&csv, f) == 3);
349 assert( csv_nfields(&csv) == 3 ); 349 assert(csv_nfields(&csv) == 3);
350 assert( strcmp(csv_field(&csv, 0), "A") == 0 ); 350 assert(strcmp(csv_field(&csv, 0), "A") == 0);
351 assert( strcmp(csv_field(&csv, 1), "B") == 0 ); 351 assert(strcmp(csv_field(&csv, 1), "B") == 0);
352 assert( strcmp(csv_field(&csv, 2), "C") == 0 ); 352 assert(strcmp(csv_field(&csv, 2), "C") == 0);
353 353
354 // Line 16 354 // Line 16
355 assert( csv_read(&csv, f) == 3 ); 355 assert(csv_read(&csv, f) == 3);
356 assert( csv_nfields(&csv) == 3 ); 356 assert(csv_nfields(&csv) == 3);
357 assert( strcmp(csv_field(&csv, 0), "A") == 0 ); 357 assert(strcmp(csv_field(&csv, 0), "A") == 0);
358 assert( strcmp(csv_field(&csv, 1), "B") == 0 ); 358 assert(strcmp(csv_field(&csv, 1), "B") == 0);
359 assert( strcmp(csv_field(&csv, 2), "C") == 0 ); 359 assert(strcmp(csv_field(&csv, 2), "C") == 0);
360 360
361 // Line 17 361 // Line 17
362 assert( csv_read(&csv, f) == 3 ); 362 assert(csv_read(&csv, f) == 3);
363 assert( csv_nfields(&csv) == 3 ); 363 assert(csv_nfields(&csv) == 3);
364 assert( strcmp(csv_field(&csv, 0), "A") == 0 ); 364 assert(strcmp(csv_field(&csv, 0), "A") == 0);
365 assert( strcmp(csv_field(&csv, 1), "B") == 0 ); 365 assert(strcmp(csv_field(&csv, 1), "B") == 0);
366 assert( strcmp(csv_field(&csv, 2), "C") == 0 ); 366 assert(strcmp(csv_field(&csv, 2), "C") == 0);
367 367
368 // Line 18 368 // Line 18
369 assert( csv_read(&csv, f) == 3 ); 369 assert(csv_read(&csv, f) == 3);
370 assert( csv_nfields(&csv) == 3 ); 370 assert(csv_nfields(&csv) == 3);
371 assert( strcmp(csv_field(&csv, 0), "A") == 0 ); 371 assert(strcmp(csv_field(&csv, 0), "A") == 0);
372 assert( strcmp(csv_field(&csv, 1), "B") == 0 ); 372 assert(strcmp(csv_field(&csv, 1), "B") == 0);
373 assert( strcmp(csv_field(&csv, 2), "C") == 0 ); 373 assert(strcmp(csv_field(&csv, 2), "C") == 0);
374 374
375 // Line 19 375 // Line 19
376 assert( csv_read(&csv, f) == 3 ); 376 assert(csv_read(&csv, f) == 3);
377 assert( csv_nfields(&csv) == 3 ); 377 assert(csv_nfields(&csv) == 3);
378 assert( strcmp(csv_field(&csv, 0), "A") == 0 ); 378 assert(strcmp(csv_field(&csv, 0), "A") == 0);
379 assert( strcmp(csv_field(&csv, 1), "B") == 0 ); 379 assert(strcmp(csv_field(&csv, 1), "B") == 0);
380 assert( strcmp(csv_field(&csv, 2), "C") == 0 ); 380 assert(strcmp(csv_field(&csv, 2), "C") == 0);
381 381
382 // EOF 382 // EOF
383 assert( csv_read(&csv, f) == EOF ); 383 assert(csv_read(&csv, f) == EOF);
384 384
385 FMEMCLOSE(f); 385 FMEMCLOSE(f);
386} 386}
@@ -395,15 +395,15 @@ test_quoted_fields(void)
395 395
396 FMEMOPEN(f, data); 396 FMEMOPEN(f, data);
397 397
398 assert( csv_read(&csv, f) == 5 ); 398 assert(csv_read(&csv, f) == 5);
399 assert( csv_nfields(&csv) == 5 ), 399 assert(csv_nfields(&csv) == 5);
400 assert( strcmp(csv_field(&csv, 0), "foo \"baz\" bar") == 0 ); 400 assert(strcmp(csv_field(&csv, 0), "foo \"baz\" bar") == 0);
401 assert( strcmp(csv_field(&csv, 1), "foo \"\"baz\"\" bar") == 0 ); 401 assert(strcmp(csv_field(&csv, 1), "foo \"\"baz\"\" bar") == 0);
402 assert( strcmp(csv_field(&csv, 2), "foo \"baz\" bar") == 0 ); 402 assert(strcmp(csv_field(&csv, 2), "foo \"baz\" bar") == 0);
403 assert( strcmp(csv_field(&csv, 3), "foo \"baz\" bar") == 0 ); 403 assert(strcmp(csv_field(&csv, 3), "foo \"baz\" bar") == 0);
404 assert( strcmp(csv_field(&csv, 4), "foo \"baz\", bar") == 0 ); 404 assert(strcmp(csv_field(&csv, 4), "foo \"baz\", bar") == 0);
405 405
406 assert( csv_read(&csv, f) == EOF ); 406 assert(csv_read(&csv, f) == EOF);
407 407
408 FMEMCLOSE(f); 408 FMEMCLOSE(f);
409} 409}
@@ -418,11 +418,11 @@ test_wrong_quoted_field(void)
418 418
419 FMEMOPEN(f, data); 419 FMEMOPEN(f, data);
420 420
421 assert( csv_read(&csv, f) == 1 ); 421 assert(csv_read(&csv, f) == 1);
422 assert( csv_nfields(&csv) == 1 ), 422 assert(csv_nfields(&csv) == 1);
423 assert( strcmp(csv_field(&csv, 0), "foo") == 0 ); 423 assert(strcmp(csv_field(&csv, 0), "foo") == 0);
424 424
425 assert( csv_read(&csv, f) == EOF ); 425 assert(csv_read(&csv, f) == EOF);
426 426
427 FMEMCLOSE(f); 427 FMEMCLOSE(f);
428} 428}
@@ -436,26 +436,26 @@ cb_error(csv_err_t err, void *cb_arg)
436void 436void
437test_out_of_range_error(void) 437test_out_of_range_error(void)
438{ 438{
439 jmp_buf env; 439 jmp_buf env;
440 csv_options_t csv_options = csv_default_options; 440 csv_options_t csv_options = csv_default_options;
441 csv_options.cb_error = cb_error; 441 csv_options.cb_error = cb_error;
442 csv_options.cb_error_arg = &env; 442 csv_options.cb_error_arg = &env;
443 443
444 csv_t csv; 444 csv_t csv;
445 csv_init_opt(&csv, &csv_options); 445 csv_init_opt(&csv, &csv_options);
446 446
447 FILE *f; 447 FILE *f;
448 char data[] = ","; 448 char data[] = ",";
449 449
450 FMEMOPEN(f, data); 450 FMEMOPEN(f, data);
451 451
452 switch ( setjmp(env) ) { 452 switch ( setjmp(env) ) {
453 case CSV_ERR_OK: 453 case CSV_ERR_OK:
454 assert( csv_read(&csv, f) == 2 ); 454 assert(csv_read(&csv, f) == 2);
455 assert( csv_nfields(&csv) == 2 ); 455 assert(csv_nfields(&csv) == 2);
456 456
457 // force an "out of range"-Exception! 457 // force an "out of range"-Exception!
458 assert( strcmp(csv_field(&csv, 2), "will fail") == 0 ); 458 assert(strcmp(csv_field(&csv, 2), "will fail") == 0);
459 break; 459 break;
460 460
461 case CSV_ERR_OUT_OF_RANGE: 461 case CSV_ERR_OUT_OF_RANGE:
@@ -472,21 +472,21 @@ test_out_of_range_error(void)
472void 472void
473test_read_error(void) 473test_read_error(void)
474{ 474{
475 jmp_buf env; 475 jmp_buf env;
476 csv_options_t csv_options = csv_default_options; 476 csv_options_t csv_options = csv_default_options;
477 csv_options.cb_error = cb_error; 477 csv_options.cb_error = cb_error;
478 csv_options.cb_error_arg = &env; 478 csv_options.cb_error_arg = &env;
479 479
480 csv_t csv; 480 csv_t csv;
481 csv_init_opt(&csv, &csv_options); 481 csv_init_opt(&csv, &csv_options);
482 482
483 FILE *f = fopen("/dev/null", "r"); 483 FILE *f = fopen("/dev/null", "r");
484 assert(f != NULL); 484 assert(f != NULL);
485 fputc('T', f); // Set Error-Flag! 485 fputc('T', f); // Set Error-Flag!
486 486
487 switch ( setjmp(env) ) { 487 switch ( setjmp(env) ) {
488 case CSV_ERR_OK: 488 case CSV_ERR_OK:
489 assert( csv_read(&csv, f) == EOF ); 489 assert(csv_read(&csv, f) == EOF);
490 break; 490 break;
491 491
492 case CSV_ERR_IO_READ: 492 case CSV_ERR_IO_READ:
@@ -546,11 +546,11 @@ test_allocation_error1(void)
546 jmp_buf env; 546 jmp_buf env;
547 547
548 csv_options_t csv_options = csv_default_options; 548 csv_options_t csv_options = csv_default_options;
549 csv_options.cb_error = cb_error; 549 csv_options.cb_error = cb_error;
550 csv_options.cb_error_arg = &env; 550 csv_options.cb_error_arg = &env;
551 csv_options.cb_allocate = my_allocate; 551 csv_options.cb_allocate = my_allocate;
552 csv_options.cb_reallocate = my_reallocate; 552 csv_options.cb_reallocate = my_reallocate;
553 csv_options.cb_free = my_free; 553 csv_options.cb_free = my_free;
554 554
555 csv_t csv; 555 csv_t csv;
556 csv_init_opt(&csv, &csv_options); 556 csv_init_opt(&csv, &csv_options);
@@ -563,7 +563,7 @@ test_allocation_error1(void)
563 563
564 switch ( setjmp(env) ) { 564 switch ( setjmp(env) ) {
565 case CSV_ERR_OK: 565 case CSV_ERR_OK:
566 assert( csv_read(&csv, f) == 20 ); 566 assert(csv_read(&csv, f) == 20);
567 assert(!"this should not be happen!"); 567 assert(!"this should not be happen!");
568 break; 568 break;
569 569
diff --git a/csv.c b/csv.c
index 71c0e0f..2948911 100644
--- a/csv.c
+++ b/csv.c
@@ -1,29 +1,30 @@
1#include "csv.h"
2
3#include <assert.h>
1#include <stdio.h> 4#include <stdio.h>
2#include <stdlib.h> 5#include <stdlib.h>
3#include <assert.h>
4#include <string.h> 6#include <string.h>
5#include "csv.h"
6 7
7#ifndef CSV_DEFAULT_DELIMITER 8#ifndef CSV_DEFAULT_DELIMITER
8#define CSV_DEFAULT_DELIMITER '"' 9# define CSV_DEFAULT_DELIMITER '"'
9#endif 10#endif
10 11
11#ifndef CSV_DEFAULT_SEPARATOR 12#ifndef CSV_DEFAULT_SEPARATOR
12#define CSV_DEFAULT_SEPARATOR ',' 13# define CSV_DEFAULT_SEPARATOR ','
13#endif 14#endif
14 15
15#if defined(__GNUC__) || defined(__clang__) 16#if defined(__GNUC__) || defined(__clang__)
16#define mul_overflow __builtin_mul_overflow 17# define mul_overflow __builtin_mul_overflow
17#else 18#else
18static inline int 19static inline int
19mul_overflow(size_t a, size_t b, size_t *out) 20mul_overflow(size_t a, size_t b, size_t *out)
20{ 21{
21 *out = a * b; 22 *out = a * b;
22 return ( a != 0 && (*out / a) != b ); 23 return (a != 0 && (*out / a) != b);
23} 24}
24#endif 25#endif
25 26
26#define UNUSED(x) (void)(sizeof((x), 0)) 27#define UNUSED(x) (void) (sizeof((x), 0))
27 28
28// === CSV-MEMORY Interface === 29// === CSV-MEMORY Interface ===
29 30
@@ -66,16 +67,16 @@ csv_mem_free(void *ptr, size_t n, size_t sz, void *cb_arg)
66const csv_options_t csv_default_options = { 67const csv_options_t csv_default_options = {
67 .field_delimiter = CSV_DEFAULT_DELIMITER, 68 .field_delimiter = CSV_DEFAULT_DELIMITER,
68 .field_separator = CSV_DEFAULT_SEPARATOR, 69 .field_separator = CSV_DEFAULT_SEPARATOR,
69 .cb_error = NULL, 70 .cb_error = NULL,
70 .cb_allocate = csv_mem_allocate, 71 .cb_allocate = csv_mem_allocate,
71 .cb_reallocate = csv_mem_reallocate, 72 .cb_reallocate = csv_mem_reallocate,
72 .cb_free = csv_mem_free 73 .cb_free = csv_mem_free
73}; 74};
74 75
75// === CSV-ERROR Interface === 76// === CSV-ERROR Interface ===
76 77
77static void 78static void
78csv_fatal_error(csv_err_t csv_err, const csv_options_t * const csv_options) 79csv_fatal_error(csv_err_t csv_err, const csv_options_t *const csv_options)
79{ 80{
80 if ( csv_options->cb_error != NULL ) { 81 if ( csv_options->cb_error != NULL ) {
81 (*csv_options->cb_error)(csv_err, csv_options->cb_error_arg); 82 (*csv_options->cb_error)(csv_err, csv_options->cb_error_arg);
@@ -109,27 +110,27 @@ csv_string_empty(csv_string_t *csv_string)
109{ 110{
110 assert(csv_string != NULL); 111 assert(csv_string != NULL);
111 112
112 return ( csv_string->pos == 0 ) ? 1 : 0; 113 return (csv_string->pos == 0) ? 1 : 0;
113} 114}
114 115
115static inline void 116static inline void
116csv_string_append(csv_string_t *csv_string, char ch, const csv_options_t * const csv_options) 117csv_string_append(csv_string_t *csv_string, char ch, const csv_options_t *const csv_options)
117{ 118{
118 assert(csv_string != NULL); 119 assert(csv_string != NULL);
119 assert(csv_options != NULL); 120 assert(csv_options != NULL);
120 121
121 static const int INITIAL_CAP = 16; 122 static const int INITIAL_CAP = 16;
122 123
123 if ( csv_string->pos == csv_string->cap ) { // grow if needed 124 if ( csv_string->pos == csv_string->cap ) { // grow if needed
124 if ( csv_string->str == NULL ) { // first call? 125 if ( csv_string->str == NULL ) { // first call?
125 if ( (csv_string->str = csv_options->cb_allocate(INITIAL_CAP, 1, csv_options->cb_memory_arg)) == NULL ) { 126 if ( (csv_string->str = csv_options->cb_allocate(INITIAL_CAP, 1, csv_options->cb_memory_arg)) == NULL ) {
126 csv_fatal_error(CSV_ERR_OUT_OF_MEMORY, csv_options); 127 csv_fatal_error(CSV_ERR_OUT_OF_MEMORY, csv_options);
127 return; 128 return;
128 } 129 }
129 csv_string->cap = INITIAL_CAP; 130 csv_string->cap = INITIAL_CAP;
130 } 131 }
131 else { // subsequent call 132 else { // subsequent call
132 int cap = (csv_string->cap * 3) / 2; // *= 1.5 133 int cap = (csv_string->cap * 3) / 2; // *= 1.5
133 char *str = csv_options->cb_reallocate(csv_string->str, cap, 1, csv_options->cb_memory_arg); 134 char *str = csv_options->cb_reallocate(csv_string->str, cap, 1, csv_options->cb_memory_arg);
134 if ( str == NULL ) { 135 if ( str == NULL ) {
135 csv_fatal_error(CSV_ERR_OUT_OF_MEMORY, csv_options); 136 csv_fatal_error(CSV_ERR_OUT_OF_MEMORY, csv_options);
@@ -140,11 +141,11 @@ csv_string_append(csv_string_t *csv_string, char ch, const csv_options_t * const
140 } 141 }
141 } 142 }
142 143
143 csv_string->str[csv_string->pos++] = ch; // append char 144 csv_string->str[csv_string->pos++] = ch; // append char
144} 145}
145 146
146static inline void 147static inline void
147csv_string_free(csv_string_t *csv_string, const csv_options_t * const csv_options) 148csv_string_free(csv_string_t *csv_string, const csv_options_t *const csv_options)
148{ 149{
149 assert(csv_string != NULL); 150 assert(csv_string != NULL);
150 assert(csv_options != NULL); 151 assert(csv_options != NULL);
@@ -163,8 +164,8 @@ csv_field_init(csv_field_t *csv_field)
163 assert(csv_field != NULL); 164 assert(csv_field != NULL);
164 165
165 csv_field->fields = NULL; 166 csv_field->fields = NULL;
166 csv_field->cap = 0; 167 csv_field->cap = 0;
167 csv_field->pos = 0; 168 csv_field->pos = 0;
168} 169}
169 170
170static inline void 171static inline void
@@ -176,30 +177,30 @@ csv_field_reset(csv_field_t *csv_field)
176} 177}
177 178
178static inline void 179static inline void
179csv_field_append(csv_field_t *csv_field, int idx, const csv_options_t * const csv_options) 180csv_field_append(csv_field_t *csv_field, int idx, const csv_options_t *const csv_options)
180{ 181{
181 assert(csv_field != NULL); 182 assert(csv_field != NULL);
182 assert(csv_options != NULL); 183 assert(csv_options != NULL);
183 184
184 static const size_t INITIAL_CAP = 16; 185 static const size_t INITIAL_CAP = 16;
185 186
186 if ( csv_field->pos == csv_field->cap ) { // grow if needed 187 if ( csv_field->pos == csv_field->cap ) { // grow if needed
187 if ( csv_field->fields == NULL ) { // first call 188 if ( csv_field->fields == NULL ) { // first call
188 if ( (csv_field->fields = csv_options->cb_allocate(INITIAL_CAP, sizeof(csv_field->fields[0]), csv_options->cb_memory_arg)) == NULL ) { 189 if ( (csv_field->fields = csv_options->cb_allocate(INITIAL_CAP, sizeof(csv_field->fields[0]), csv_options->cb_memory_arg)) == NULL ) {
189 csv_fatal_error(CSV_ERR_OUT_OF_MEMORY, csv_options); 190 csv_fatal_error(CSV_ERR_OUT_OF_MEMORY, csv_options);
190 return; 191 return;
191 } 192 }
192 csv_field->cap = INITIAL_CAP; 193 csv_field->cap = INITIAL_CAP;
193 } 194 }
194 else { // subsequent call 195 else { // subsequent call
195 int cap = (csv_field->cap * 3) / 2; // *= 1.5 196 int cap = (csv_field->cap * 3) / 2; // *= 1.5
196 int *fields = csv_options->cb_reallocate(csv_field->fields, cap, sizeof(csv_field->fields[0]), csv_options->cb_memory_arg); 197 int *fields = csv_options->cb_reallocate(csv_field->fields, cap, sizeof(csv_field->fields[0]), csv_options->cb_memory_arg);
197 if ( fields == NULL ) { 198 if ( fields == NULL ) {
198 csv_fatal_error(CSV_ERR_OUT_OF_MEMORY, csv_options); 199 csv_fatal_error(CSV_ERR_OUT_OF_MEMORY, csv_options);
199 return; 200 return;
200 } 201 }
201 csv_field->fields = fields; 202 csv_field->fields = fields;
202 csv_field->cap = cap; 203 csv_field->cap = cap;
203 } 204 }
204 } 205 }
205 206
@@ -207,7 +208,7 @@ csv_field_append(csv_field_t *csv_field, int idx, const csv_options_t * const cs
207} 208}
208 209
209static inline void 210static inline void
210csv_field_free(csv_field_t *csv_field, const csv_options_t * const csv_options) 211csv_field_free(csv_field_t *csv_field, const csv_options_t *const csv_options)
211{ 212{
212 assert(csv_field != NULL); 213 assert(csv_field != NULL);
213 assert(csv_options != NULL); 214 assert(csv_options != NULL);
@@ -228,7 +229,7 @@ csv_init(csv_t *csv)
228} 229}
229 230
230void 231void
231csv_init_opt(csv_t *csv, const csv_options_t * const csv_options) 232csv_init_opt(csv_t *csv, const csv_options_t *const csv_options)
232{ 233{
233 assert(csv != NULL); 234 assert(csv != NULL);
234 235
@@ -255,7 +256,7 @@ csv_cleanup(csv_t *csv)
255} 256}
256 257
257int 258int
258csv_nfields(const csv_t * const csv) 259csv_nfields(const csv_t *const csv)
259{ 260{
260 assert(csv != NULL); 261 assert(csv != NULL);
261 262
@@ -266,7 +267,7 @@ csv_nfields(const csv_t * const csv)
266} 267}
267 268
268const char * 269const char *
269csv_field(const csv_t * const csv, int idx) 270csv_field(const csv_t *const csv, int idx)
270{ 271{
271 assert(csv != NULL); 272 assert(csv != NULL);
272 assert(idx >= 0 && idx < csv->csv_field.pos); 273 assert(idx >= 0 && idx < csv->csv_field.pos);
@@ -310,12 +311,12 @@ csv_read(csv_t *csv, FILE *in)
310 }; 311 };
311 312
312 register const int DELIM = csv->csv_options->field_delimiter; 313 register const int DELIM = csv->csv_options->field_delimiter;
313 register const int SEP = csv->csv_options->field_separator; 314 register const int SEP = csv->csv_options->field_separator;
314 315
315 csv_string_reset(&csv->csv_string); 316 csv_string_reset(&csv->csv_string);
316 csv_field_reset(&csv->csv_field); 317 csv_field_reset(&csv->csv_field);
317 318
318 for ( int state = STATE_START_FIELD; ; ) { 319 for ( int state = STATE_START_FIELD;; ) {
319 int ch; 320 int ch;
320 321
321 switch ( state ) { 322 switch ( state ) {
@@ -326,9 +327,9 @@ csv_read(csv_t *csv, FILE *in)
326 if ( ch == EOF ) { 327 if ( ch == EOF ) {
327 state = STATE_END_FILE; 328 state = STATE_END_FILE;
328 } 329 }
329 else if ( ch == '\r' ) { // test for CR.. 330 else if ( ch == '\r' ) { // test for CR..
330 ch = getc(in); 331 ch = getc(in);
331 if ( ch != '\n' ) { // ..LF 332 if ( ch != '\n' ) { // ..LF
332 ungetc(ch, in); 333 ungetc(ch, in);
333 } 334 }
334 state = STATE_END_LINE; 335 state = STATE_END_LINE;
@@ -379,7 +380,7 @@ csv_read(csv_t *csv, FILE *in)
379 } 380 }
380 else { 381 else {
381 csv_string_append(&csv->csv_string, DELIM, csv->csv_options); 382 csv_string_append(&csv->csv_string, DELIM, csv->csv_options);
382 ungetc(ch, in); // we have read too far... Put the character back! 383 ungetc(ch, in); // we have read too far... Put the character back!
383 } 384 }
384 } 385 }
385 else { 386 else {
@@ -434,7 +435,7 @@ csv_read(csv_t *csv, FILE *in)
434 435
435 if ( csv_string_empty(&csv->csv_string) ) { 436 if ( csv_string_empty(&csv->csv_string) ) {
436 csv_cleanup(csv); 437 csv_cleanup(csv);
437 return EOF; // EOF reached 438 return EOF; // EOF reached
438 } 439 }
439 440
440 /* 441 /*
@@ -458,18 +459,24 @@ const char *
458csv_err_str(csv_err_t csv_err) 459csv_err_str(csv_err_t csv_err)
459{ 460{
460 switch ( csv_err ) { 461 switch ( csv_err ) {
461 case CSV_ERR_OK: return "no error"; 462 case CSV_ERR_OK:
462 case CSV_ERR_OUT_OF_MEMORY: return "out of memory"; 463 return "no error";
463 case CSV_ERR_OUT_OF_RANGE: return "index out of range"; 464 case CSV_ERR_OUT_OF_MEMORY:
464 case CSV_ERR_IO_READ: return "read error"; 465 return "out of memory";
465 case CSV_ERR_IO_WRITE: return "write error"; 466 case CSV_ERR_OUT_OF_RANGE:
466 default: return "unknown error"; 467 return "index out of range";
468 case CSV_ERR_IO_READ:
469 return "read error";
470 case CSV_ERR_IO_WRITE:
471 return "write error";
472 default:
473 return "unknown error";
467 } 474 }
468 // NOT REACHED 475 // NOT REACHED
469} 476}
470 477
471static void 478static void
472csv_write_field(FILE *out, const char *field, const csv_options_t * const csv_options) 479csv_write_field(FILE *out, const char *field, const csv_options_t *const csv_options)
473{ 480{
474 assert(csv_options != NULL); 481 assert(csv_options != NULL);
475 assert(field != NULL); 482 assert(field != NULL);
@@ -499,7 +506,7 @@ csv_write_field(FILE *out, const char *field, const csv_options_t * const csv_op
499} 506}
500 507
501void 508void
502csv_write(FILE *out, const csv_t * const csv) 509csv_write(FILE *out, const csv_t *const csv)
503{ 510{
504 assert(out != NULL); 511 assert(out != NULL);
505 assert(csv != NULL); 512 assert(csv != NULL);
@@ -510,8 +517,8 @@ csv_write(FILE *out, const csv_t * const csv)
510 register const int SEP = csv->csv_options->field_separator; 517 register const int SEP = csv->csv_options->field_separator;
511 518
512 if ( 0 < csv->csv_field.pos ) { 519 if ( 0 < csv->csv_field.pos ) {
513 const char *str = csv->csv_string.str; 520 const char *str = csv->csv_string.str;
514 const int *field = csv->csv_field.fields; 521 const int * field = csv->csv_field.fields;
515 522
516 csv_write_field(out, &str[*field++], csv->csv_options); 523 csv_write_field(out, &str[*field++], csv->csv_options);
517 524
@@ -529,7 +536,7 @@ csv_write(FILE *out, const csv_t * const csv)
529} 536}
530 537
531void 538void
532csv_write_ex(FILE *out, int n, const char *fields[], const csv_options_t * csv_options) 539csv_write_ex(FILE *out, int n, const char *fields[], const csv_options_t *csv_options)
533{ 540{
534 assert(out != NULL); 541 assert(out != NULL);
535 assert(fields != NULL); 542 assert(fields != NULL);
@@ -558,4 +565,3 @@ csv_write_ex(FILE *out, int n, const char *fields[], const csv_options_t * csv_o
558 csv_fatal_error(CSV_ERR_IO_WRITE, csv_options); 565 csv_fatal_error(CSV_ERR_IO_WRITE, csv_options);
559 } 566 }
560} 567}
561
diff --git a/csv.h b/csv.h
index 5ee7695..8abeb18 100644
--- a/csv.h
+++ b/csv.h
@@ -1,14 +1,14 @@
1#pragma once 1#pragma once
2 2
3#include <stdio.h> /* FILE */ 3#include <stddef.h> /* size_t */
4#include <stddef.h> /* size_t */ 4#include <stdio.h> /* FILE */
5 5
6#ifdef __cplusplus 6#ifdef __cplusplus
7extern "C" { 7extern "C" {
8#endif 8#endif
9 9
10typedef enum { 10typedef enum {
11 CSV_ERR_OK = 0, 11 CSV_ERR_OK = 0,
12 CSV_ERR_OUT_OF_MEMORY = -1, 12 CSV_ERR_OUT_OF_MEMORY = -1,
13 CSV_ERR_OUT_OF_RANGE = -2, 13 CSV_ERR_OUT_OF_RANGE = -2,
14 CSV_ERR_IO_READ = -3, 14 CSV_ERR_IO_READ = -3,
@@ -32,23 +32,23 @@ extern const csv_options_t csv_default_options;
32 32
33typedef struct { 33typedef struct {
34 char *str; 34 char *str;
35 int cap, pos; 35 int cap, pos;
36} csv_string_t; 36} csv_string_t;
37 37
38typedef struct { 38typedef struct {
39 int *fields; 39 int *fields;
40 int cap, pos; 40 int cap, pos;
41} csv_field_t; 41} csv_field_t;
42 42
43typedef struct { 43typedef struct {
44 const csv_options_t *csv_options; 44 const csv_options_t *csv_options;
45 csv_string_t csv_string; 45 csv_string_t csv_string;
46 csv_field_t csv_field; 46 csv_field_t csv_field;
47} csv_t; 47} csv_t;
48 48
49/* initialization */ 49/* initialization */
50void csv_init(csv_t *csv); 50void csv_init(csv_t *csv);
51void csv_init_opt(csv_t *csv, const csv_options_t * const csv_options); 51void csv_init_opt(csv_t *csv, const csv_options_t *const csv_options);
52 52
53/* cleanup after error */ 53/* cleanup after error */
54void csv_cleanup(csv_t *csv); 54void csv_cleanup(csv_t *csv);
@@ -57,15 +57,15 @@ void csv_cleanup(csv_t *csv);
57int csv_read(csv_t *csv, FILE *in); 57int csv_read(csv_t *csv, FILE *in);
58 58
59/* field access */ 59/* field access */
60int csv_nfields(const csv_t * const csv); 60int csv_nfields(const csv_t *const csv);
61const char * csv_field(const csv_t * const csv, int idx); 61const char *csv_field(const csv_t *const csv, int idx);
62 62
63/* write */ 63/* write */
64void csv_write(FILE *out, const csv_t * const csv); 64void csv_write(FILE *out, const csv_t *const csv);
65void csv_write_ex(FILE *out, int n, const char *fields[], const csv_options_t * const csv_options); 65void csv_write_ex(FILE *out, int n, const char *fields[], const csv_options_t *const csv_options);
66 66
67/* error handling */ 67/* error handling */
68const char * csv_err_str(csv_err_t csv_err); 68const char *csv_err_str(csv_err_t csv_err);
69 69
70#ifdef __cplusplus 70#ifdef __cplusplus
71} 71}