(input: string)
| 205 | return result; |
| 206 | } |
| 207 | parse(input: string): string[][] { |
| 208 | this.#input = input.startsWith(BYTE_ORDER_MARK) ? input.slice(1) : input; |
| 209 | this.#cursor = 0; |
| 210 | const result: string[][] = []; |
| 211 | |
| 212 | let lineResult: string[]; |
| 213 | let first = true; |
| 214 | let lineIndex = 0; |
| 215 | |
| 216 | const INVALID_RUNE = ["\r", "\n", '"']; |
| 217 | |
| 218 | const options = this.#options; |
| 219 | if ( |
| 220 | INVALID_RUNE.includes(options.separator) || |
| 221 | (typeof options.comment === "string" && |
| 222 | INVALID_RUNE.includes(options.comment)) || |
| 223 | options.separator === options.comment |
| 224 | ) { |
| 225 | throw new Error("Cannot parse input: invalid delimiter"); |
| 226 | } |
| 227 | |
| 228 | // The number of fields per record that is either inferred from the first |
| 229 | // row (when options.fieldsPerRecord = 0), or set by the caller (when |
| 230 | // options.fieldsPerRecord > 0). |
| 231 | // |
| 232 | // Each possible variant means the following: |
| 233 | // "ANY": Variable number of fields is allowed. |
| 234 | // "UNINITIALIZED": The first row has not been read yet. Once it's read, the |
| 235 | // number of fields will be set. |
| 236 | // <number>: The number of fields per record that every record must follow. |
| 237 | let _nbFields: "ANY" | "UNINITIALIZED" | number; |
| 238 | if (options.fieldsPerRecord === undefined || options.fieldsPerRecord < 0) { |
| 239 | _nbFields = "ANY"; |
| 240 | } else if (options.fieldsPerRecord === 0) { |
| 241 | _nbFields = "UNINITIALIZED"; |
| 242 | } else { |
| 243 | // TODO: Should we check if it's a valid integer? |
| 244 | _nbFields = options.fieldsPerRecord; |
| 245 | } |
| 246 | |
| 247 | while (true) { |
| 248 | const r = this.#parseRecord(lineIndex); |
| 249 | if (r === null) break; |
| 250 | lineResult = r; |
| 251 | lineIndex++; |
| 252 | // If fieldsPerRecord is 0, Read sets it to |
| 253 | // the number of fields in the first record |
| 254 | if (first) { |
| 255 | first = false; |
| 256 | if (_nbFields === "UNINITIALIZED") { |
| 257 | _nbFields = lineResult.length; |
| 258 | } |
| 259 | } |
| 260 | |
| 261 | if (lineResult.length > 0) { |
| 262 | if (typeof _nbFields === "number" && _nbFields !== lineResult.length) { |
| 263 | throw new SyntaxError( |
| 264 | `Syntax error on line ${lineIndex}: expected ${_nbFields} fields but got ${lineResult.length}`, |
no test coverage detected