text: // An Entry consisting of:
  //
  // "%d %s=%s\n", <length>, <keyword>, <value>
  //
  // The length is a decimal number, and includes itself and the \n
  // \0 does not terminate anything.  Only the length terminates the string.
  // Numeric values are decimal strings.
  
  module.exports = ExtendedHeader
  
  var Entry = require("./entry.js")
    , inherits = require("../vendor/inherits/inherits.js")
    , tar = require("../tar.js")
    , numeric = tar.numeric
    , keyTrans = { "SCHILY.dev": "dev"
                 , "SCHILY.ino": "ino"
                 , "SCHILY.nlink": "nlink" }
  
  function ExtendedHeader () {
    Entry.apply(this, arguments)
    this.on("data", this._parse)
    this.fields = {}
    this._position = 0
    this._fieldPos = 0
    this._state = SIZE
    this._sizeBuf = []
    this._keyBuf = []
    this._valBuf = []
    this._size = -1
    this._key = ""
  }
  
  inherits(ExtendedHeader, Entry, { _parse: parse })
  
  var s = 0
    , states = ExtendedHeader.states = {}
    , SIZE = states.SIZE = s++
    , KEY  = states.KEY  = s++
    , VAL  = states.VAL  = s++
    , ERR  = states.ERR  = s++
  
  Object.keys(states).forEach(function (s) {
    states[states[s]] = states[s]
  })
  
  states[s] = null
  
  // char code values for comparison
  var _0 = "0".charCodeAt(0)
    , _9 = "9".charCodeAt(0)
    , point = ".".charCodeAt(0)
    , a = "a".charCodeAt(0)
    , Z = "Z".charCodeAt(0)
    , a = "a".charCodeAt(0)
    , z = "z".charCodeAt(0)
    , space = " ".charCodeAt(0)
    , eq = "=".charCodeAt(0)
    , cr = "\n".charCodeAt(0)
  
  function parse (c) {
    if (this._state === ERR) return
  
    for ( var i = 0, l = c.length
        ; i < l
        ; this._position++, this._fieldPos++, i++) {
      // console.error("top of loop, size="+this._size)
  
      var b = c[i]
  
      if (this._size >= 0 && this._fieldPos > this._size) {
        error(this, "field exceeds length="+this._size)
        return
      }
  
      switch (this._state) {
        case ERR: return
  
        case SIZE:
          // console.error("parsing size, b=%d, rest=%j", b, c.slice(i).toString())
          if (b === space) {
            this._state = KEY
            // this._fieldPos = this._sizeBuf.length
            this._size = parseInt(new Buffer(this._sizeBuf).toString(), 10)
            this._sizeBuf.length = 0
            continue
          }
          if (b < _0 || b > _9) {
            error(this, "expected [" + _0 + ".." + _9 + "], got " + b)
            return
          }
          this._sizeBuf.push(b)
          continue
  
        case KEY:
          // can be any char except =, not > size.
          if (b === eq) {
            this._state = VAL
            this._key = new Buffer(this._keyBuf).toString()
            if (keyTrans[this._key]) this._key = keyTrans[this._key]
            this._keyBuf.length = 0
            continue
          }
          this._keyBuf.push(b)
          continue
  
        case VAL:
          // field must end with cr
          if (this._fieldPos === this._size - 1) {
            // console.error("finished with "+this._key)
            if (b !== cr) {
              error(this, "expected \\n at end of field")
              return
            }
            var val = new Buffer(this._valBuf).toString()
            if (numeric[this._key]) {
              val = parseFloat(val)
            }
            this.fields[this._key] = val
  
            this._valBuf.length = 0
            this._state = SIZE
            this._size = -1
            this._fieldPos = -1
            continue
          }
          this._valBuf.push(b)
          continue
      }
    }
  }
  
  function error (me, msg) {
    msg = "invalid header: " + msg
        + "\nposition=" + me._position
        + "\nfield position=" + me._fieldPos
  
    me.error(msg)
    me.state = ERR
  }
  