| 81 | |
| 82 | |
| 83 | TArray<TArray<FString>> FStringTable::parseCSV(const char* buffer, size_t size) |
| 84 | { |
| 85 | const size_t bufLength = size; |
| 86 | TArray<TArray<FString>> data; |
| 87 | TArray<FString> row; |
| 88 | TArray<char> cell; |
| 89 | bool quoted = false; |
| 90 | |
| 91 | /* |
| 92 | auto myisspace = [](int ch) { return ch == '\t' || ch == '\r' || ch == '\n' || ch == ' '; }; |
| 93 | while (*vcopy && myisspace((unsigned char)*vcopy)) vcopy++; // skip over leaading whitespace; |
| 94 | auto vend = vcopy + strlen(vcopy); |
| 95 | while (vend > vcopy && myisspace((unsigned char)vend[-1])) *--vend = 0; // skip over trailing whitespace |
| 96 | */ |
| 97 | |
| 98 | for (size_t i = 0; i < bufLength; ++i) |
| 99 | { |
| 100 | if (buffer[i] == '"') |
| 101 | { |
| 102 | // Double quotes inside a quoted string count as an escaped quotation mark. |
| 103 | if (quoted && i < bufLength - 1 && buffer[i + 1] == '"') |
| 104 | { |
| 105 | cell.Push('"'); |
| 106 | i++; |
| 107 | } |
| 108 | else if (cell.Size() == 0 || quoted) |
| 109 | { |
| 110 | quoted = !quoted; |
| 111 | } |
| 112 | } |
| 113 | else if (buffer[i] == ',') |
| 114 | { |
| 115 | if (!quoted) |
| 116 | { |
| 117 | cell.Push(0); |
| 118 | ProcessEscapes(cell.Data()); |
| 119 | row.Push(cell.Data()); |
| 120 | cell.Clear(); |
| 121 | } |
| 122 | else |
| 123 | { |
| 124 | cell.Push(buffer[i]); |
| 125 | } |
| 126 | } |
| 127 | else if (buffer[i] == '\r') |
| 128 | { |
| 129 | // Ignore all CR's. |
| 130 | } |
| 131 | else if (buffer[i] == '\n' && !quoted) |
| 132 | { |
| 133 | cell.Push(0); |
| 134 | ProcessEscapes(cell.Data()); |
| 135 | row.Push(cell.Data()); |
| 136 | data.Push(std::move(row)); |
| 137 | cell.Clear(); |
| 138 | } |
| 139 | else |
| 140 | { |