410{
411 fields.clear();
412 at_end = false;
413
415 bool quoted = false;
416 bool closed_quote = false;
417 bool field_start = true;
418 bool field_quoted = false;
419 bool saw_input = false;
420
421 while (true) {
422 const int next =
m_file.get();
423 if (next == std::char_traits<char>::eof()) {
426 return false;
427 }
428
429 if (quoted) {
431 return false;
432 }
433
434 if (!saw_input) {
435 at_end = true;
436 return true;
437 }
438
439 fields.push_back({ .value = std::move(
value), .quoted = field_quoted });
440 return true;
441 }
442
443 saw_input = true;
444 const char c = static_cast<char>(next);
445 if (quoted) {
446 if (c == '"') {
447 if (
m_file.peek() ==
'"') {
449 value.push_back(
'"');
450 } else {
451 quoted = false;
452 closed_quote = true;
453 }
454 } else {
456 }
457
458 continue;
459 }
460
462 fields.push_back({ .value = std::move(
value), .quoted = field_quoted });
464 field_start = true;
465 field_quoted = false;
466 closed_quote = false;
467 if (c ==
'\r' &&
m_file.peek() ==
'\n')
469
471 return true;
472
473 continue;
474 }
475
476 if (c == '"' && field_start) {
477 quoted = true;
478 field_start = false;
479 field_quoted = true;
480 continue;
481 }
482
483 if (c == '"' || closed_quote) {
484 m_last_error =
"Unexpected character after quoted field";
485 return false;
486 }
487
489 field_start = false;
490 }
491}