text: // Generated by CoffeeScript 1.9.1
  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];
    } 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) {
      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, 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).skip_empty_lines == null) {
      base11.skip_empty_lines = false;
    }
    this.lines = 0;
    this.count = 0;
    this.regexp_int = /^(\-|\+)?([1-9]+[0-9]*)$/;
    this.regexp_float = /^(\-|\+)?([0-9]+(\.[0-9]+)?([eE][0-9]+)?|Infinity)$/;
    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, areNextCharsRowDelimiters, char, escapeIsQuote, i, isDelimiter, isEscape, isNextCharAComment, isNextCharADelimiter, isQuote, isRowDelimiter, l, ltrim, nextCharPos, ref, results, rowDelimiter, rowDelimiterLength, rtrim, wasCommenting;
    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;
          isNextCharADelimiter = chars.substr(i + 1, this.options.delimiter.length) === this.options.delimiter;
          isNextCharAComment = this.nextChar === this.options.comment;
          if (this.nextChar && !areNextCharsRowDelimiters && !isNextCharADelimiter && !isNextCharAComment) {
            if (this.options.relax) {
              this.quoting = false;
              this.field = "" + this.options.quote + this.field;
            } else {
              throw new 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(this.field);
            }
            continue;
          }
        } else if (!this.field) {
          this.quoting = true;
          i++;
          continue;
        } else if (this.field && !this.options.relax) {
          throw new 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();
          }
        }
        if (this.options.auto_parse && this.regexp_int.test(this.field)) {
          this.line.push(parseInt(this.field));
        } else if (this.options.auto_parse && this.regexp_float.test(this.field)) {
          this.line.push(parseFloat(this.field));
        } else {
          this.line.push(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(this.field);
        }
        i++;
      } else if (!this.commenting) {
        this.field += char;
        i++;
        if (end && i === l) {
          this.line.push(this.field);
        }
      } else {
        i++;
      }
    }
    this.buf = '';
    results = [];
    while (i < l) {
      this.buf += chars.charAt(i);
      results.push(i++);
    }
    return results;
  };
  