| 109256 | return rows; |
| 109257 | } |
| 109258 | function parseRows(text, f) { |
| 109259 | var rows = [], N = text.length, I = 0, n = 0, t, eof = N <= 0, eol = false; // current token followed by EOL? |
| 109260 | // Strip the trailing newline. |
| 109261 | if (text.charCodeAt(N - 1) === NEWLINE) --N; |
| 109262 | if (text.charCodeAt(N - 1) === RETURN) --N; |
| 109263 | function token() { |
| 109264 | if (eof) return EOF; |
| 109265 | if (eol) return eol = false, EOL; |
| 109266 | // Unescape quotes. |
| 109267 | var i, j = I, c; |
| 109268 | if (text.charCodeAt(j) === QUOTE) { |
| 109269 | while((I++) < N && text.charCodeAt(I) !== QUOTE || text.charCodeAt(++I) === QUOTE); |
| 109270 | if ((i = I) >= N) eof = true; |
| 109271 | else if ((c = text.charCodeAt(I++)) === NEWLINE) eol = true; |
| 109272 | else if (c === RETURN) { |
| 109273 | eol = true; |
| 109274 | if (text.charCodeAt(I) === NEWLINE) ++I; |
| 109275 | } |
| 109276 | return text.slice(j + 1, i - 1).replace(/""/g, '"'); |
| 109277 | } |
| 109278 | // Find next delimiter or newline. |
| 109279 | while(I < N){ |
| 109280 | if ((c = text.charCodeAt(i = I++)) === NEWLINE) eol = true; |
| 109281 | else if (c === RETURN) { |
| 109282 | eol = true; |
| 109283 | if (text.charCodeAt(I) === NEWLINE) ++I; |
| 109284 | } else if (c !== DELIMITER) continue; |
| 109285 | return text.slice(j, i); |
| 109286 | } |
| 109287 | // Return last token before EOF. |
| 109288 | return eof = true, text.slice(j, N); |
| 109289 | } |
| 109290 | while((t = token()) !== EOF){ |
| 109291 | var row = []; |
| 109292 | while(t !== EOL && t !== EOF)row.push(t), t = token(); |
| 109293 | if (f && (row = f(row, n++)) == null) continue; |
| 109294 | rows.push(row); |
| 109295 | } |
| 109296 | return rows; |
| 109297 | } |
| 109298 | function preformatBody(rows, columns) { |
| 109299 | return rows.map(function(row) { |
| 109300 | return columns.map(function(column) { |