| // Generated by CoffeeScript 1.9.3 |
| var Parser, StringDecoder, stream, util; |
| |
| stream = require('stream'); |
| |
| util = require('util'); |
| |
| StringDecoder = require('string_decoder').StringDecoder; |
| |
| module.exports = function() { |
| var callback, called, chunks, data, options, parser; |
| if (arguments.length === 3) { |
| data = arguments[0]; |
| options = arguments[1]; |
| callback = arguments[2]; |
| if (typeof callback !== 'function') { |
| throw Error("Invalid callback argument: " + (JSON.stringify(callback))); |
| } |
| if (typeof data !== 'string') { |
| return callback(Error("Invalid data argument: " + (JSON.stringify(data)))); |
| } |
| } else if (arguments.length === 2) { |
| if (typeof arguments[0] === 'string' || Buffer.isBuffer(arguments[0])) { |
| data = arguments[0]; |
| } else { |
| options = arguments[0]; |
| } |
| if (typeof arguments[1] === 'function') { |
| callback = arguments[1]; |
| } else { |
| options = arguments[1]; |
| } |
| } else if (arguments.length === 1) { |
| if (typeof arguments[0] === 'function') { |
| callback = arguments[0]; |
| } else { |
| options = arguments[0]; |
| } |
| } |
| if (options == null) { |
| options = {}; |
| } |
| parser = new Parser(options); |
| if (data != null) { |
| process.nextTick(function() { |
| parser.write(data); |
| return parser.end(); |
| }); |
| } |
| if (callback) { |
| called = false; |
| chunks = options.objname ? {} : []; |
| parser.on('readable', function() { |
| var chunk, results; |
| results = []; |
| while (chunk = parser.read()) { |
| if (options.objname) { |
| results.push(chunks[chunk[0]] = chunk[1]); |
| } else { |
| results.push(chunks.push(chunk)); |
| } |
| } |
| return results; |
| }); |
| parser.on('error', function(err) { |
| called = true; |
| return callback(err); |
| }); |
| parser.on('end', function() { |
| if (!called) { |
| return callback(null, chunks); |
| } |
| }); |
| } |
| return parser; |
| }; |
| |
| Parser = function(options) { |
| var base, base1, base10, base11, base12, base2, base3, base4, base5, base6, base7, base8, base9, k, v; |
| if (options == null) { |
| options = {}; |
| } |
| options.objectMode = true; |
| this.options = {}; |
| for (k in options) { |
| v = options[k]; |
| this.options[k] = v; |
| } |
| stream.Transform.call(this, this.options); |
| if ((base = this.options).rowDelimiter == null) { |
| base.rowDelimiter = null; |
| } |
| if ((base1 = this.options).delimiter == null) { |
| base1.delimiter = ','; |
| } |
| if ((base2 = this.options).quote == null) { |
| base2.quote = '"'; |
| } |
| if ((base3 = this.options).escape == null) { |
| base3.escape = '"'; |
| } |
| if ((base4 = this.options).columns == null) { |
| base4.columns = null; |
| } |
| if ((base5 = this.options).comment == null) { |
| base5.comment = ''; |
| } |
| if ((base6 = this.options).objname == null) { |
| base6.objname = false; |
| } |
| if ((base7 = this.options).trim == null) { |
| base7.trim = false; |
| } |
| if ((base8 = this.options).ltrim == null) { |
| base8.ltrim = false; |
| } |
| if ((base9 = this.options).rtrim == null) { |
| base9.rtrim = false; |
| } |
| if ((base10 = this.options).auto_parse == null) { |
| base10.auto_parse = false; |
| } |
| if ((base11 = this.options).auto_parse_date == null) { |
| base11.auto_parse_date = false; |
| } |
| if ((base12 = this.options).skip_empty_lines == null) { |
| base12.skip_empty_lines = false; |
| } |
| this.lines = 0; |
| this.count = 0; |
| this.is_int = /^(\-|\+)?([1-9]+[0-9]*)$/; |
| this.is_float = function(value) { |
| return (value - parseFloat(value) + 1) >= 0; |
| }; |
| this.decoder = new StringDecoder(); |
| this.buf = ''; |
| this.quoting = false; |
| this.commenting = false; |
| this.field = ''; |
| this.nextChar = null; |
| this.closingQuote = 0; |
| this.line = []; |
| this.chunks = []; |
| return this; |
| }; |
| |
| util.inherits(Parser, stream.Transform); |
| |
| module.exports.Parser = Parser; |
| |
| Parser.prototype._transform = function(chunk, encoding, callback) { |
| var err; |
| if (chunk instanceof Buffer) { |
| chunk = this.decoder.write(chunk); |
| } |
| try { |
| this.__write(chunk, false); |
| return callback(); |
| } catch (_error) { |
| err = _error; |
| return this.emit('error', err); |
| } |
| }; |
| |
| Parser.prototype._flush = function(callback) { |
| var err; |
| try { |
| this.__write(this.decoder.end(), true); |
| if (this.quoting) { |
| this.emit('error', new Error("Quoted field not terminated at line " + (this.lines + 1))); |
| return; |
| } |
| if (this.line.length > 0) { |
| this.__push(this.line); |
| } |
| return callback(); |
| } catch (_error) { |
| err = _error; |
| return this.emit('error', err); |
| } |
| }; |
| |
| Parser.prototype.__push = function(line) { |
| var field, i, j, len, lineAsColumns; |
| if (this.options.columns === true) { |
| this.options.columns = line; |
| return; |
| } else if (typeof this.options.columns === 'function') { |
| this.options.columns = this.options.columns(line); |
| return; |
| } |
| this.count++; |
| if (this.options.columns != null) { |
| lineAsColumns = {}; |
| for (i = j = 0, len = line.length; j < len; i = ++j) { |
| field = line[i]; |
| lineAsColumns[this.options.columns[i]] = field; |
| } |
| if (this.options.objname) { |
| return this.push([lineAsColumns[this.options.objname], lineAsColumns]); |
| } else { |
| return this.push(lineAsColumns); |
| } |
| } else { |
| return this.push(line); |
| } |
| }; |
| |
| Parser.prototype.__write = function(chars, end, callback) { |
| var acceptedLength, areNextCharsDelimiter, areNextCharsRowDelimiters, auto_parse, char, escapeIsQuote, i, isDelimiter, isEscape, isNextCharAComment, isQuote, isRowDelimiter, is_float, is_int, l, ltrim, nextCharPos, ref, results, rowDelimiter, rowDelimiterLength, rtrim, wasCommenting; |
| is_int = (function(_this) { |
| return function(value) { |
| if (typeof _this.is_int === 'function') { |
| return _this.is_int(value); |
| } else { |
| return _this.is_int.test(value); |
| } |
| }; |
| })(this); |
| is_float = (function(_this) { |
| return function(value) { |
| if (typeof _this.is_float === 'function') { |
| return _this.is_float(value); |
| } else { |
| return _this.is_float.test(value); |
| } |
| }; |
| })(this); |
| auto_parse = (function(_this) { |
| return function(value) { |
| var m; |
| if (_this.options.auto_parse && is_int(_this.field)) { |
| _this.field = parseInt(_this.field); |
| } else if (_this.options.auto_parse && is_float(_this.field)) { |
| _this.field = parseFloat(_this.field); |
| } else if (_this.options.auto_parse && _this.options.auto_parse_date) { |
| m = Date.parse(_this.field); |
| if (!isNaN(m)) { |
| _this.field = new Date(m); |
| } |
| } |
| return _this.field; |
| }; |
| })(this); |
| ltrim = this.options.trim || this.options.ltrim; |
| rtrim = this.options.trim || this.options.rtrim; |
| chars = this.buf + chars; |
| l = chars.length; |
| rowDelimiterLength = this.options.rowDelimiter ? this.options.rowDelimiter.length : 0; |
| i = 0; |
| if (this.lines === 0 && 0xFEFF === chars.charCodeAt(0)) { |
| i++; |
| } |
| while (i < l) { |
| acceptedLength = rowDelimiterLength + this.options.comment.length + this.options.escape.length + this.options.delimiter.length; |
| if (this.quoting) { |
| acceptedLength += this.options.quote.length; |
| } |
| if (!end && (i + acceptedLength >= l)) { |
| break; |
| } |
| char = this.nextChar ? this.nextChar : chars.charAt(i); |
| this.nextChar = chars.charAt(i + 1); |
| if (this.options.rowDelimiter == null) { |
| if ((this.field === '') && (char === '\n' || char === '\r')) { |
| rowDelimiter = char; |
| nextCharPos = i + 1; |
| } else if (this.nextChar === '\n' || this.nextChar === '\r') { |
| rowDelimiter = this.nextChar; |
| nextCharPos = i + 2; |
| } |
| if (rowDelimiter) { |
| if (rowDelimiter === '\r' && chars.charAt(nextCharPos) === '\n') { |
| rowDelimiter += '\n'; |
| } |
| this.options.rowDelimiter = rowDelimiter; |
| rowDelimiterLength = this.options.rowDelimiter.length; |
| } |
| } |
| if (!this.commenting && char === this.options.escape) { |
| escapeIsQuote = this.options.escape === this.options.quote; |
| isEscape = this.nextChar === this.options.escape; |
| isQuote = this.nextChar === this.options.quote; |
| if (!(escapeIsQuote && !this.field && !this.quoting) && (isEscape || isQuote)) { |
| i++; |
| char = this.nextChar; |
| this.nextChar = chars.charAt(i + 1); |
| this.field += char; |
| i++; |
| continue; |
| } |
| } |
| if (!this.commenting && char === this.options.quote) { |
| if (this.quoting) { |
| areNextCharsRowDelimiters = this.options.rowDelimiter && chars.substr(i + 1, this.options.rowDelimiter.length) === this.options.rowDelimiter; |
| areNextCharsDelimiter = chars.substr(i + 1, this.options.delimiter.length) === this.options.delimiter; |
| isNextCharAComment = this.nextChar === this.options.comment; |
| if (this.nextChar && !areNextCharsRowDelimiters && !areNextCharsDelimiter && !isNextCharAComment) { |
| if (this.options.relax) { |
| this.quoting = false; |
| this.field = "" + this.options.quote + this.field; |
| } else { |
| throw Error("Invalid closing quote at line " + (this.lines + 1) + "; found " + (JSON.stringify(this.nextChar)) + " instead of delimiter " + (JSON.stringify(this.options.delimiter))); |
| } |
| } else { |
| this.quoting = false; |
| this.closingQuote = this.options.quote.length; |
| i++; |
| if (end && i === l) { |
| this.line.push(auto_parse(this.field)); |
| } |
| continue; |
| } |
| } else if (!this.field) { |
| this.quoting = true; |
| i++; |
| continue; |
| } else if (this.field && !this.options.relax) { |
| throw Error("Invalid opening quote at line " + (this.lines + 1)); |
| } |
| } |
| isRowDelimiter = this.options.rowDelimiter && chars.substr(i, this.options.rowDelimiter.length) === this.options.rowDelimiter; |
| if (isRowDelimiter) { |
| this.lines++; |
| } |
| wasCommenting = false; |
| if (!this.commenting && !this.quoting && this.options.comment && chars.substr(i, this.options.comment.length) === this.options.comment) { |
| this.commenting = true; |
| } else if (this.commenting && isRowDelimiter) { |
| wasCommenting = true; |
| this.commenting = false; |
| } |
| isDelimiter = chars.substr(i, this.options.delimiter.length) === this.options.delimiter; |
| if (!this.commenting && !this.quoting && (isDelimiter || isRowDelimiter)) { |
| if (isRowDelimiter && this.line.length === 0 && this.field === '') { |
| if (wasCommenting || this.options.skip_empty_lines) { |
| i += this.options.rowDelimiter.length; |
| this.nextChar = chars.charAt(i); |
| continue; |
| } |
| } |
| if (rtrim) { |
| if (!this.closingQuote) { |
| this.field = this.field.trimRight(); |
| } |
| } |
| this.line.push(auto_parse(this.field)); |
| this.closingQuote = 0; |
| this.field = ''; |
| if (isDelimiter) { |
| i += this.options.delimiter.length; |
| this.nextChar = chars.charAt(i); |
| if (end && !this.nextChar) { |
| isRowDelimiter = true; |
| this.line.push(''); |
| } |
| } |
| if (isRowDelimiter) { |
| this.__push(this.line); |
| this.line = []; |
| i += (ref = this.options.rowDelimiter) != null ? ref.length : void 0; |
| this.nextChar = chars.charAt(i); |
| continue; |
| } |
| } else if (!this.commenting && !this.quoting && (char === ' ' || char === '\t')) { |
| if (!(ltrim && !this.field)) { |
| this.field += char; |
| } |
| if (end && i + 1 === l) { |
| if (this.options.trim || this.options.rtrim) { |
| this.field = this.field.trimRight(); |
| } |
| this.line.push(auto_parse(this.field)); |
| } |
| i++; |
| } else if (!this.commenting) { |
| this.field += char; |
| i++; |
| if (end && i === l) { |
| this.line.push(auto_parse(this.field)); |
| } |
| } else { |
| i++; |
| } |
| } |
| this.buf = ''; |
| results = []; |
| while (i < l) { |
| this.buf += chars.charAt(i); |
| results.push(i++); |
| } |
| return results; |
| }; |