csv.cpp 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. #include "csv.h"
  2. TStringBuf NCsvFormat::CsvSplitter::Consume() {
  3. if (Begin == End) {
  4. return nullptr;
  5. }
  6. TString::iterator TokenStart = Begin;
  7. TString::iterator TokenEnd = Begin;
  8. if (Quote == '\0') {
  9. while (1) {
  10. if (TokenEnd == End || *TokenEnd == Delimeter) {
  11. Begin = TokenEnd;
  12. return TStringBuf(TokenStart, TokenEnd);
  13. }
  14. ++TokenEnd;
  15. }
  16. } else {
  17. bool Escape = false;
  18. if (*Begin == Quote) {
  19. Escape = true;
  20. ++TokenStart;
  21. ++TokenEnd;
  22. Y_ENSURE(TokenStart != End, TStringBuf("RFC4180 violation: quotation mark must be followed by something"));
  23. }
  24. while (1) {
  25. if (TokenEnd == End || (!Escape && *TokenEnd == Delimeter)) {
  26. Begin = TokenEnd;
  27. return TStringBuf(TokenStart, TokenEnd);
  28. } else if (*TokenEnd == Quote) {
  29. Y_ENSURE(Escape, TStringBuf("RFC4180 violation: quotation mark must be in the escaped string only"));
  30. if (TokenEnd + 1 == End) {
  31. Begin = TokenEnd + 1;
  32. } else if (*(TokenEnd + 1) == Delimeter) {
  33. Begin = TokenEnd + 1;
  34. } else if (*(TokenEnd + 1) == Quote) {
  35. CustomStringBufs.push_back(TStringBuf(TokenStart, (TokenEnd + 1)));
  36. TokenEnd += 2;
  37. TokenStart = TokenEnd;
  38. continue;
  39. } else {
  40. Y_ENSURE(false, TStringBuf("RFC4180 violation: in escaped string quotation mark must be followed by a delimiter, EOL or another quotation mark"));
  41. }
  42. if (CustomStringBufs.size()) {
  43. CustomString.clear();
  44. for (auto CustomStringBuf : CustomStringBufs) {
  45. CustomString += TString{ CustomStringBuf };
  46. }
  47. CustomString += TString{ TStringBuf(TokenStart, TokenEnd) };
  48. CustomStringBufs.clear();
  49. return TStringBuf(CustomString);
  50. } else {
  51. return TStringBuf(TokenStart, TokenEnd);
  52. }
  53. }
  54. ++TokenEnd;
  55. }
  56. }
  57. }
  58. TString NCsvFormat::TLinesSplitter::ConsumeLine() {
  59. bool Escape = false;
  60. TString result;
  61. TString line;
  62. while (Input.ReadLine(line)) {
  63. for (auto it = line.begin(); it != line.end(); ++it) {
  64. if (*it == Quote) {
  65. Escape = !Escape;
  66. }
  67. }
  68. if (!result) {
  69. result = line;
  70. } else {
  71. result += line;
  72. }
  73. if (!Escape) {
  74. break;
  75. } else {
  76. result += "\n";
  77. }
  78. }
  79. return result;
  80. }