Initial commit
[yaffs-website] / node_modules / tar / lib / extended-header.js
1 // An Entry consisting of:
2 //
3 // "%d %s=%s\n", <length>, <keyword>, <value>
4 //
5 // The length is a decimal number, and includes itself and the \n
6 // \0 does not terminate anything.  Only the length terminates the string.
7 // Numeric values are decimal strings.
8
9 module.exports = ExtendedHeader
10
11 var Entry = require("./entry.js")
12   , inherits = require("inherits")
13   , tar = require("../tar.js")
14   , numeric = tar.numeric
15   , keyTrans = { "SCHILY.dev": "dev"
16                , "SCHILY.ino": "ino"
17                , "SCHILY.nlink": "nlink" }
18
19 function ExtendedHeader () {
20   Entry.apply(this, arguments)
21   this.on("data", this._parse)
22   this.fields = {}
23   this._position = 0
24   this._fieldPos = 0
25   this._state = SIZE
26   this._sizeBuf = []
27   this._keyBuf = []
28   this._valBuf = []
29   this._size = -1
30   this._key = ""
31 }
32
33 inherits(ExtendedHeader, Entry)
34 ExtendedHeader.prototype._parse = parse
35
36 var s = 0
37   , states = ExtendedHeader.states = {}
38   , SIZE = states.SIZE = s++
39   , KEY  = states.KEY  = s++
40   , VAL  = states.VAL  = s++
41   , ERR  = states.ERR  = s++
42
43 Object.keys(states).forEach(function (s) {
44   states[states[s]] = states[s]
45 })
46
47 states[s] = null
48
49 // char code values for comparison
50 var _0 = "0".charCodeAt(0)
51   , _9 = "9".charCodeAt(0)
52   , point = ".".charCodeAt(0)
53   , a = "a".charCodeAt(0)
54   , Z = "Z".charCodeAt(0)
55   , a = "a".charCodeAt(0)
56   , z = "z".charCodeAt(0)
57   , space = " ".charCodeAt(0)
58   , eq = "=".charCodeAt(0)
59   , cr = "\n".charCodeAt(0)
60
61 function parse (c) {
62   if (this._state === ERR) return
63
64   for ( var i = 0, l = c.length
65       ; i < l
66       ; this._position++, this._fieldPos++, i++) {
67     // console.error("top of loop, size="+this._size)
68
69     var b = c[i]
70
71     if (this._size >= 0 && this._fieldPos > this._size) {
72       error(this, "field exceeds length="+this._size)
73       return
74     }
75
76     switch (this._state) {
77       case ERR: return
78
79       case SIZE:
80         // console.error("parsing size, b=%d, rest=%j", b, c.slice(i).toString())
81         if (b === space) {
82           this._state = KEY
83           // this._fieldPos = this._sizeBuf.length
84           this._size = parseInt(new Buffer(this._sizeBuf).toString(), 10)
85           this._sizeBuf.length = 0
86           continue
87         }
88         if (b < _0 || b > _9) {
89           error(this, "expected [" + _0 + ".." + _9 + "], got " + b)
90           return
91         }
92         this._sizeBuf.push(b)
93         continue
94
95       case KEY:
96         // can be any char except =, not > size.
97         if (b === eq) {
98           this._state = VAL
99           this._key = new Buffer(this._keyBuf).toString()
100           if (keyTrans[this._key]) this._key = keyTrans[this._key]
101           this._keyBuf.length = 0
102           continue
103         }
104         this._keyBuf.push(b)
105         continue
106
107       case VAL:
108         // field must end with cr
109         if (this._fieldPos === this._size - 1) {
110           // console.error("finished with "+this._key)
111           if (b !== cr) {
112             error(this, "expected \\n at end of field")
113             return
114           }
115           var val = new Buffer(this._valBuf).toString()
116           if (numeric[this._key]) {
117             val = parseFloat(val)
118           }
119           this.fields[this._key] = val
120
121           this._valBuf.length = 0
122           this._state = SIZE
123           this._size = -1
124           this._fieldPos = -1
125           continue
126         }
127         this._valBuf.push(b)
128         continue
129     }
130   }
131 }
132
133 function error (me, msg) {
134   msg = "invalid header: " + msg
135       + "\nposition=" + me._position
136       + "\nfield position=" + me._fieldPos
137
138   me.error(msg)
139   me.state = ERR
140 }