text: 
  /**
   * Module dependencies.
   */
  
  var debug = require('debug')('socket.io-parser');
  var json = JSON;//require('json3');//marked by JP
  var Emitter = require('component-emitter');
  var binary = require('./binary');
  var isBuf = require('./is-buffer');
  
  /**
   * Protocol version.
   *
   * @api public
   */
  
  exports.protocol = 4;
  
  /**
   * Packet types.
   *
   * @api public
   */
  
  exports.types = [
    'CONNECT',
    'DISCONNECT',
    'EVENT',
    'ACK',
    'ERROR',
    'BINARY_EVENT',
    'BINARY_ACK'
  ];
  
  /**
   * Packet type `connect`.
   *
   * @api public
   */
  
  exports.CONNECT = 0;
  
  /**
   * Packet type `disconnect`.
   *
   * @api public
   */
  
  exports.DISCONNECT = 1;
  
  /**
   * Packet type `event`.
   *
   * @api public
   */
  
  exports.EVENT = 2;
  
  /**
   * Packet type `ack`.
   *
   * @api public
   */
  
  exports.ACK = 3;
  
  /**
   * Packet type `error`.
   *
   * @api public
   */
  
  exports.ERROR = 4;
  
  /**
   * Packet type 'binary event'
   *
   * @api public
   */
  
  exports.BINARY_EVENT = 5;
  
  /**
   * Packet type `binary ack`. For acks with binary arguments.
   *
   * @api public
   */
  
  exports.BINARY_ACK = 6;
  
  /**
   * Encoder constructor.
   *
   * @api public
   */
  
  exports.Encoder = Encoder;
  
  /**
   * Decoder constructor.
   *
   * @api public
   */
  
  exports.Decoder = Decoder;
  
  /**
   * A socket.io Encoder instance
   *
   * @api public
   */
  
  function Encoder() {}
  
  /**
   * Encode a packet as a single string if non-binary, or as a
   * buffer sequence, depending on packet type.
   *
   * @param {Object} obj - packet object
   * @param {Function} callback - function to handle encodings (likely engine.write)
   * @return Calls callback with Array of encodings
   * @api public
   */
  
  Encoder.prototype.encode = function(obj, callback){
    debug('encoding packet %j', obj);
  
    if (exports.BINARY_EVENT == obj.type || exports.BINARY_ACK == obj.type) {
      encodeAsBinary(obj, callback);
    }
    else {
      var encoding = encodeAsString(obj);
      callback([encoding]);
    }
  };
  
  /**
   * Encode packet as string.
   *
   * @param {Object} packet
   * @return {String} encoded
   * @api private
   */
  
  function encodeAsString(obj) {
    var str = '';
    var nsp = false;
  
    // first is type
    str += obj.type;
  
    // attachments if we have them
    if (exports.BINARY_EVENT == obj.type || exports.BINARY_ACK == obj.type) {
      str += obj.attachments;
      str += '-';
    }
  
    // if we have a namespace other than `/`
    // we append it followed by a comma `,`
    if (obj.nsp && '/' != obj.nsp) {
      nsp = true;
      str += obj.nsp;
    }
  
    // immediately followed by the id
    if (null != obj.id) {
      if (nsp) {
        str += ',';
        nsp = false;
      }
      str += obj.id;
    }
  
    // json data
    if (null != obj.data) {
      if (nsp) str += ',';
      str += json.stringify(obj.data);
    }
  
    debug('encoded %j as %s', obj, str);
    return str;
  }
  
  /**
   * Encode packet as 'buffer sequence' by removing blobs, and
   * deconstructing packet into object with placeholders and
   * a list of buffers.
   *
   * @param {Object} packet
   * @return {Buffer} encoded
   * @api private
   */
  
  function encodeAsBinary(obj, callback) {
  
    function writeEncoding(bloblessData) {
      var deconstruction = binary.deconstructPacket(bloblessData);
      var pack = encodeAsString(deconstruction.packet);
      var buffers = deconstruction.buffers;
  
      buffers.unshift(pack); // add packet info to beginning of data list
      callback(buffers); // write all the buffers
    }
  
    binary.removeBlobs(obj, writeEncoding);
  }
  
  /**
   * A socket.io Decoder instance
   *
   * @return {Object} decoder
   * @api public
   */
  
  function Decoder() {
    this.reconstructor = null;
  }
  
  /**
   * Mix in `Emitter` with Decoder.
   */
  
  Emitter(Decoder.prototype);
  
  /**
   * Decodes an ecoded packet string into packet JSON.
   *
   * @param {String} obj - encoded packet
   * @return {Object} packet
   * @api public
   */
  
  Decoder.prototype.add = function(obj) {
    var packet;
    if ('string' == typeof obj) {
      packet = decodeString(obj);
      if (exports.BINARY_EVENT == packet.type || exports.BINARY_ACK == packet.type) { // binary packet's json
        this.reconstructor = new BinaryReconstructor(packet);
  
        // no attachments, labeled binary but no binary data to follow
        if (this.reconstructor.reconPack.attachments === 0) {
          this.emit('decoded', packet);
        }
      } else { // non-binary full packet
        this.emit('decoded', packet);
      }
    }
    else if (isBuf(obj) || obj.base64) { // raw binary data
      if (!this.reconstructor) {
        throw new Error('got binary data when not reconstructing a packet');
      } else {
        packet = this.reconstructor.takeBinaryData(obj);
        if (packet) { // received final buffer
          this.reconstructor = null;
          this.emit('decoded', packet);
        }
      }
    }
    else {
      throw new Error('Unknown type: ' + obj);
    }
  };
  
  /**
   * Decode a packet String (JSON data)
   *
   * @param {String} str
   * @return {Object} packet
   * @api private
   */
  
  function decodeString(str) {
    var p = {};
    var i = 0;
  
    // look up type
    p.type = Number(str.charAt(0));
    if (null == exports.types[p.type]) return error();
  
    // look up attachments if type binary
    if (exports.BINARY_EVENT == p.type || exports.BINARY_ACK == p.type) {
      var buf = '';
      while (str.charAt(++i) != '-') {
        buf += str.charAt(i);
        if (i == str.length) break;
      }
      if (buf != Number(buf) || str.charAt(i) != '-') {
        throw new Error('Illegal attachments');
      }
      p.attachments = Number(buf);
    }
  
    // look up namespace (if any)
    if ('/' == str.charAt(i + 1)) {
      p.nsp = '';
      while (++i) {
        var c = str.charAt(i);
        if (',' == c) break;
        p.nsp += c;
        if (i == str.length) break;
      }
    } else {
      p.nsp = '/';
    }
  
    // look up id
    var next = str.charAt(i + 1);
    if ('' !== next && Number(next) == next) {
      p.id = '';
      while (++i) {
        var c = str.charAt(i);
        if (null == c || Number(c) != c) {
          --i;
          break;
        }
        p.id += str.charAt(i);
        if (i == str.length) break;
      }
      p.id = Number(p.id);
    }
  
    // look up json data
    if (str.charAt(++i)) {
      p = tryParse(p, str.substr(i));
    }
  
    debug('decoded %s as %j', str, p);
    return p;
  }
  
  function tryParse(p, str) {
    try {
      p.data = json.parse(str);
    } catch(e){
      return error();
    }
    return p; 
  };
  
  /**
   * Deallocates a parser's resources
   *
   * @api public
   */
  
  Decoder.prototype.destroy = function() {
    if (this.reconstructor) {
      this.reconstructor.finishedReconstruction();
    }
  };
  
  /**
   * A manager of a binary event's 'buffer sequence'. Should
   * be constructed whenever a packet of type BINARY_EVENT is
   * decoded.
   *
   * @param {Object} packet
   * @return {BinaryReconstructor} initialized reconstructor
   * @api private
   */
  
  function BinaryReconstructor(packet) {
    this.reconPack = packet;
    this.buffers = [];
  }
  
  /**
   * Method to be called when binary data received from connection
   * after a BINARY_EVENT packet.
   *
   * @param {Buffer | ArrayBuffer} binData - the raw binary data received
   * @return {null | Object} returns null if more binary data is expected or
   *   a reconstructed packet object if all buffers have been received.
   * @api private
   */
  
  BinaryReconstructor.prototype.takeBinaryData = function(binData) {
    this.buffers.push(binData);
    if (this.buffers.length == this.reconPack.attachments) { // done with buffer list
      var packet = binary.reconstructPacket(this.reconPack, this.buffers);
      this.finishedReconstruction();
      return packet;
    }
    return null;
  };
  
  /**
   * Cleans up binary packet reconstruction variables.
   *
   * @api private
   */
  
  BinaryReconstructor.prototype.finishedReconstruction = function() {
    this.reconPack = null;
    this.buffers = [];
  };
  
  function error(data){
    return {
      type: exports.ERROR,
      data: 'parser error'
    };
  }
  