| 263 | } |
| 264 | |
| 265 | size_t csv_parse(struct csv_parser *p, const void *s, size_t len, |
| 266 | void (*cb1)(void *, size_t, void *), |
| 267 | void (*cb2)(int c, void *), void *data) { |
| 268 | unsigned const char *us = s; /* Access input data as array of unsigned char */ |
| 269 | unsigned char c; /* The character we are currently processing */ |
| 270 | size_t pos = 0; /* The number of characters we have processed in this call */ |
| 271 | |
| 272 | /* Store key fields into local variables for performance */ |
| 273 | unsigned char delim = p->delim_char; |
| 274 | unsigned char quote = p->quote_char; |
| 275 | int (*is_space)(unsigned char) = p->is_space; |
| 276 | int (*is_term)(unsigned char) = p->is_term; |
| 277 | int quoted = p->quoted; |
| 278 | int pstate = p->pstate; |
| 279 | size_t spaces = p->spaces; |
| 280 | size_t entry_pos = p->entry_pos; |
| 281 | |
| 282 | if (!p->entry_buf && pos < len) { |
| 283 | /* Buffer hasn't been allocated yet and len > 0 */ |
| 284 | if (csv_increase_buffer(p) != 0) { |
| 285 | p->quoted = quoted, p->pstate = pstate, p->spaces = spaces, |
| 286 | p->entry_pos = entry_pos; |
| 287 | return pos; |
| 288 | } |
| 289 | } |
| 290 | |
| 291 | while (pos < len) { |
| 292 | /* Check memory usage, increase buffer if necessary */ |
| 293 | if (entry_pos == |
| 294 | ((p->options & CSV_APPEND_NULL) ? p->entry_size - 1 : p->entry_size)) { |
| 295 | if (csv_increase_buffer(p) != 0) { |
| 296 | p->quoted = quoted, p->pstate = pstate, p->spaces = spaces, |
| 297 | p->entry_pos = entry_pos; |
| 298 | return pos; |
| 299 | } |
| 300 | } |
| 301 | |
| 302 | c = us[pos++]; |
| 303 | |
| 304 | switch (pstate) { |
| 305 | case ROW_NOT_BEGUN: |
| 306 | case FIELD_NOT_BEGUN: |
| 307 | if ((is_space ? is_space(c) : c == CSV_SPACE || c == CSV_TAB) && |
| 308 | c != delim) { /* Space or Tab */ |
| 309 | continue; |
| 310 | } else if (is_term |
| 311 | ? is_term(c) |
| 312 | : c == CSV_CR || |
| 313 | c == CSV_LF) { /* Carriage Return or Line Feed */ |
| 314 | if (pstate == FIELD_NOT_BEGUN) { |
| 315 | SUBMIT_FIELD(p); |
| 316 | SUBMIT_ROW(p, (unsigned char)c); |
| 317 | } else { /* ROW_NOT_BEGUN */ |
| 318 | /* Don't submit empty rows by default */ |
| 319 | if (p->options & CSV_REPALL_NL) { |
| 320 | SUBMIT_ROW(p, (unsigned char)c); |
| 321 | } |
| 322 | } |
no test coverage detected