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_malloc64(). ** + Use p->cSep as the column separator. The default is ",". ** + Use p->rSep as the row separator. The default is "\n". **
| 15154 | ** + Report syntax errors on stderr |
| 15155 | */ |
| 15156 | static char *SQLITE_CDECL csv_read_one_field(ImportCtx *p){ |
| 15157 | int c; |
| 15158 | int cSep = p->cColSep; |
| 15159 | int rSep = p->cRowSep; |
| 15160 | p->n = 0; |
| 15161 | c = fgetc(p->in); |
| 15162 | if( c==EOF || seenInterrupt ){ |
| 15163 | p->cTerm = EOF; |
| 15164 | return 0; |
| 15165 | } |
| 15166 | if( c=='"' ){ |
| 15167 | int pc, ppc; |
| 15168 | int startLine = p->nLine; |
| 15169 | int cQuote = c; |
| 15170 | pc = ppc = 0; |
| 15171 | while( 1 ){ |
| 15172 | c = fgetc(p->in); |
| 15173 | if( c==rSep ) p->nLine++; |
| 15174 | if( c==cQuote ){ |
| 15175 | if( pc==cQuote ){ |
| 15176 | pc = 0; |
| 15177 | continue; |
| 15178 | } |
| 15179 | } |
| 15180 | if( (c==cSep && pc==cQuote) |
| 15181 | || (c==rSep && pc==cQuote) |
| 15182 | || (c==rSep && pc=='\r' && ppc==cQuote) |
| 15183 | || (c==EOF && pc==cQuote) |
| 15184 | ){ |
| 15185 | do{ p->n--; }while( p->z[p->n]!=cQuote ); |
| 15186 | p->cTerm = c; |
| 15187 | break; |
| 15188 | } |
| 15189 | if( pc==cQuote && c!='\r' ){ |
| 15190 | utf8_printf(stderr, "%s:%d: unescaped %c character\n", |
| 15191 | p->zFile, p->nLine, cQuote); |
| 15192 | } |
| 15193 | if( c==EOF ){ |
| 15194 | utf8_printf(stderr, "%s:%d: unterminated %c-quoted field\n", |
| 15195 | p->zFile, startLine, cQuote); |
| 15196 | p->cTerm = c; |
| 15197 | break; |
| 15198 | } |
| 15199 | import_append_char(p, c); |
| 15200 | ppc = pc; |
| 15201 | pc = c; |
| 15202 | } |
| 15203 | }else{ |
| 15204 | /* If this is the first field being parsed and it begins with the |
| 15205 | ** UTF-8 BOM (0xEF BB BF) then skip the BOM */ |
| 15206 | if( (c&0xff)==0xef && p->bNotFirst==0 ){ |
| 15207 | import_append_char(p, c); |
| 15208 | c = fgetc(p->in); |
| 15209 | if( (c&0xff)==0xbb ){ |
| 15210 | import_append_char(p, c); |
| 15211 | c = fgetc(p->in); |
| 15212 | if( (c&0xff)==0xbf ){ |
| 15213 | p->bNotFirst = 1; |
nothing calls this directly
no test coverage detected