Skip to content

Commit

Permalink
make fmt
Browse files Browse the repository at this point in the history
  • Loading branch information
trentm committed Sep 25, 2020
1 parent a350937 commit ee0d0c3
Show file tree
Hide file tree
Showing 2 changed files with 232 additions and 199 deletions.
272 changes: 148 additions & 124 deletions lib/csvrow.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
* csvrow -- parsing a single CSV string
*/

var DEFAULT_DELIMITER = ',' // \t also tested
var format = format || require('util').format
var DEFAULT_DELIMITER = ','; // \t also tested
var format = format || require('util').format;

/**
* Parse a CSV row (i.e. a single row) into an array of strings.
Expand All @@ -23,155 +23,179 @@ var format = format || require('util').format
* @throws {TypeError} if the given CSV row is invalid
*/
function parseCSVRow(s, delimiter) {
delimiter = delimiter || DEFAULT_DELIMITER;
var DEBUG = false;
var row = [];
var i = 0;
var ch;

if (s.indexOf('\n') !== -1 || s.indexOf('\r') !== -1) {
throw new TypeError(
format('illegal char: newlines not supported: "%s"', s));
}

DEBUG && console.warn('--\ns: %j', s);
while (i < s.length) {
DEBUG && console.warn('start cell');
var cell = [];
var quoted = false;
var iQuote;

// Find first non-whitespace cell char.
while (i < s.length) {
ch = s[i];
if (ch === ' ') {
cell.push(ch);
} else if (ch === '"') {
quoted = true;
iQuote = i;
cell = [ch]; // wipe out leading whitespace
i++;
break;
} else if (ch === delimiter) {
// Empty cell.
break;
} else {
cell.push(ch);
i++;
break;
}
i++;
delimiter = delimiter || DEFAULT_DELIMITER;
var DEBUG = false;
var row = [];
var i = 0;
var ch;

if (s.indexOf('\n') !== -1 || s.indexOf('\r') !== -1) {
throw new TypeError(
format('illegal char: newlines not supported: "%s"', s)
);
}
DEBUG && console.warn('after first non-ws char: cell=%j, quoted=%j, i=%j', cell, quoted, i);

if (quoted) {
// Slurp up until end of string or close-quote.
while (true) { // eslint-disable-line no-constant-condition
if (i >= s.length) {
throw new TypeError(format(
"unterminated quoted string starting at position %d: '%s'",
iQuote, s));
}
ch = s[i];
cell.push(ch);
if (ch === '"') {
if (i + 1 < s.length && s[i + 1] === '"') {
// Escaped quote.
i++;
} else {
// End of quoted string.
DEBUG && console.warn('--\ns: %j', s);
while (i < s.length) {
DEBUG && console.warn('start cell');
var cell = [];
var quoted = false;
var iQuote;

// Find first non-whitespace cell char.
while (i < s.length) {
ch = s[i];
if (ch === ' ') {
cell.push(ch);
} else if (ch === '"') {
quoted = true;
iQuote = i;
cell = [ch]; // wipe out leading whitespace
i++;
break;
} else if (ch === delimiter) {
// Empty cell.
break;
} else {
cell.push(ch);
i++;
break;
}
i++;
break;
}
}
i++;
}

// Advance to comma (or end of string).
while (i < s.length) {
ch = s[i];
if (ch === delimiter) {
i++;
break;
} else if (ch !== ' ') {
throw new TypeError(format(
"illegal char outside of quoted cell at position %d: '%s'",
i, s));
DEBUG &&
console.warn(
'after first non-ws char: cell=%j, quoted=%j, i=%j',
cell,
quoted,
i
);

if (quoted) {
// Slurp up until end of string or close-quote.
// eslint-disable-next-line no-constant-condition
while (true) {
if (i >= s.length) {
throw new TypeError(
format(
"unterminated quoted string starting at position %d: '%s'",
iQuote,
s
)
);
}
ch = s[i];
cell.push(ch);
if (ch === '"') {
if (i + 1 < s.length && s[i + 1] === '"') {
// Escaped quote.
i++;
} else {
// End of quoted string.
i++;
break;
}
}
i++;
}

// Advance to comma (or end of string).
while (i < s.length) {
ch = s[i];
if (ch === delimiter) {
i++;
break;
} else if (ch !== ' ') {
throw new TypeError(
format(
"illegal char outside of quoted cell at position %d: '%s'",
i,
s
)
);
}
i++;
}
} else {
// Slurp up cell until end of string or comma.
while (i < s.length) {
ch = s[i];
if (ch === delimiter) {
i++;
break;
} else if (ch === '"') {
throw new TypeError(
format(
"illegal double-quote at position %d: '%s'",
i,
s
)
);
} else {
cell.push(ch);
}
i++;
}
}
i++;
}
} else {
// Slurp up cell until end of string or comma.
while (i < s.length) {
ch = s[i];
if (ch === delimiter) {
i++;
break;
} else if (ch === '"') {
throw new TypeError(
format("illegal double-quote at position %d: '%s'", i, s));

// Post-process cell.
if (quoted) {
cell = cell.slice(1, cell.length - 1); // drop the quotes
cell = cell.join('');
} else {
cell.push(ch);
cell = cell.join('').trim();
}
i++;
}
DEBUG && console.warn('cell: cell=%j i=%j', cell, i);
row.push(cell);
}

// Post-process cell.
if (quoted) {
cell = cell.slice(1, cell.length - 1); // drop the quotes
cell = cell.join('');
} else {
cell = cell.join('').trim();
// Special case for trailing ','.
if (s[s.length - 1] === delimiter) {
DEBUG && console.warn('special case: add cell for trailing comma');
row.push('');
}
DEBUG && console.warn('cell: cell=%j i=%j', cell, i);
row.push(cell);
}

// Special case for trailing ','.
if (s[s.length - 1] === delimiter) {
DEBUG && console.warn('special case: add cell for trailing comma');
row.push('');
}

DEBUG && console.warn('return: %j\n', row);
return row;
DEBUG && console.warn('return: %j\n', row);
return row;
}

/**
* Serialize the given array to a CSV row.
*/
function serializeCSVRow(a, delimiter) {
delimiter = delimiter || DEFAULT_DELIMITER
var row = [];
for (var i = 0; i < a.length; i++) {
var elem = a[i];
if (elem.indexOf(' ') !== -1 || elem.indexOf('\t') !== -1 ||
elem.indexOf(',') !== -1 || elem.indexOf('"') !== -1) {
row.push('"' + elem.replace(/"/g, '""') + '"')
} else {
row.push(elem);
delimiter = delimiter || DEFAULT_DELIMITER;
var row = [];
for (var i = 0; i < a.length; i++) {
var elem = a[i];
if (
elem.indexOf(' ') !== -1 ||
elem.indexOf('\t') !== -1 ||
elem.indexOf(',') !== -1 ||
elem.indexOf('"') !== -1
) {
row.push('"' + elem.replace(/"/g, '""') + '"');
} else {
row.push(elem);
}
}
}
return row.join(delimiter);
return row.join(delimiter);
}

/**
* Normalize the given CSV line.
*/
function normalizeCSVRow(s) {
var row = parseCSVRow(s);
var noEmpties = row.filter(function onElem(elem) { return !!elem });
return serializeCSVRow(noEmpties);
var row = parseCSVRow(s);
var noEmpties = row.filter(function onElem(elem) {
return !!elem;
});
return serializeCSVRow(noEmpties);
}




//---- exports

module.exports = {
parse: parseCSVRow,
stringify: serializeCSVRow,
normalize: normalizeCSVRow
parse: parseCSVRow,
stringify: serializeCSVRow,
normalize: normalizeCSVRow
};
Loading

0 comments on commit ee0d0c3

Please sign in to comment.