Read a single field of CSV text. Compatible with rfc4180 and extended ** with the option of having a separator other than ",". ** ** + Input comes from p->in. ** + Store results in p->z of length p->n. Space to hold p->z comes ** from sqlite3_malloc(). ** + Use p->cSep as the separator. The default is ",". ** + Keep track of the line number in p->nLine. ** + Store the charac
| 294 | ** + Report syntax errors on stderr |
| 295 | */ |
| 296 | static char *csv_read_one_field(CSVReader *p) |
| 297 | { |
| 298 | int c, pc, ppc; |
| 299 | int cSep = p->cSeparator; |
| 300 | p->n = 0; |
| 301 | // c = fgetc(p->in); |
| 302 | c = p->in[p->pos++]; |
| 303 | if (c == 0 /* || seenInterrupt */) { |
| 304 | p->cTerm = 0; |
| 305 | return 0; |
| 306 | } |
| 307 | if (c == '"') { |
| 308 | int startLine = p->nLine; |
| 309 | int cQuote = c; |
| 310 | pc = ppc = 0; |
| 311 | while (1) { |
| 312 | // c = fgetc(p->in); |
| 313 | c = p->in[p->pos++]; |
| 314 | if (c == '\n') p->nLine++; |
| 315 | if (c == cQuote) { |
| 316 | if (pc == cQuote) { |
| 317 | pc = 0; |
| 318 | continue; |
| 319 | } |
| 320 | } |
| 321 | if ((c == cSep && pc == cQuote) || (c == '\n' && pc == cQuote) || |
| 322 | (c == '\n' && pc == '\r' && ppc == cQuote) || |
| 323 | (c == 0 && pc == cQuote)) { |
| 324 | do { |
| 325 | p->n--; |
| 326 | } while (p->z[p->n] != cQuote); |
| 327 | p->cTerm = c; |
| 328 | break; |
| 329 | } |
| 330 | if (pc == cQuote && c != '\r') { |
| 331 | free(p->z); |
| 332 | luabb_error(p->lua, NULL, |
| 333 | "CSV line:%d: unescaped %c character\n", p->nLine, |
| 334 | cQuote); |
| 335 | } |
| 336 | if (c == 0) { |
| 337 | free(p->z); |
| 338 | luabb_error(p->lua, NULL, |
| 339 | "CSV line:%d: unterminated %c-quoted field\n", |
| 340 | p->nLine, startLine, cQuote); |
| 341 | p->cTerm = 0; |
| 342 | break; |
| 343 | } |
| 344 | csv_append_char(p, c); |
| 345 | ppc = pc; |
| 346 | pc = c; |
| 347 | } |
| 348 | } else { |
| 349 | while (c != 0 && c != cSep && c != '\n') { |
| 350 | csv_append_char(p, c); |
| 351 | // c = fgetc(p->in); |
| 352 | c = p->in[p->pos++]; |
| 353 | } |
no test coverage detected