1
|
var inherits = require('inherits');
|
2
|
var Reporter = require('../base').Reporter;
|
3
|
var Buffer = require('buffer').Buffer;
|
4
|
|
5
|
function DecoderBuffer(base, options) {
|
6
|
Reporter.call(this, options);
|
7
|
if (!Buffer.isBuffer(base)) {
|
8
|
this.error('Input not Buffer');
|
9
|
return;
|
10
|
}
|
11
|
|
12
|
this.base = base;
|
13
|
this.offset = 0;
|
14
|
this.length = base.length;
|
15
|
}
|
16
|
inherits(DecoderBuffer, Reporter);
|
17
|
exports.DecoderBuffer = DecoderBuffer;
|
18
|
|
19
|
DecoderBuffer.prototype.save = function save() {
|
20
|
return { offset: this.offset, reporter: Reporter.prototype.save.call(this) };
|
21
|
};
|
22
|
|
23
|
DecoderBuffer.prototype.restore = function restore(save) {
|
24
|
// Return skipped data
|
25
|
var res = new DecoderBuffer(this.base);
|
26
|
res.offset = save.offset;
|
27
|
res.length = this.offset;
|
28
|
|
29
|
this.offset = save.offset;
|
30
|
Reporter.prototype.restore.call(this, save.reporter);
|
31
|
|
32
|
return res;
|
33
|
};
|
34
|
|
35
|
DecoderBuffer.prototype.isEmpty = function isEmpty() {
|
36
|
return this.offset === this.length;
|
37
|
};
|
38
|
|
39
|
DecoderBuffer.prototype.readUInt8 = function readUInt8(fail) {
|
40
|
if (this.offset + 1 <= this.length)
|
41
|
return this.base.readUInt8(this.offset++, true);
|
42
|
else
|
43
|
return this.error(fail || 'DecoderBuffer overrun');
|
44
|
}
|
45
|
|
46
|
DecoderBuffer.prototype.skip = function skip(bytes, fail) {
|
47
|
if (!(this.offset + bytes <= this.length))
|
48
|
return this.error(fail || 'DecoderBuffer overrun');
|
49
|
|
50
|
var res = new DecoderBuffer(this.base);
|
51
|
|
52
|
// Share reporter state
|
53
|
res._reporterState = this._reporterState;
|
54
|
|
55
|
res.offset = this.offset;
|
56
|
res.length = this.offset + bytes;
|
57
|
this.offset += bytes;
|
58
|
return res;
|
59
|
}
|
60
|
|
61
|
DecoderBuffer.prototype.raw = function raw(save) {
|
62
|
return this.base.slice(save ? save.offset : this.offset, this.length);
|
63
|
}
|
64
|
|
65
|
function EncoderBuffer(value, reporter) {
|
66
|
if (Array.isArray(value)) {
|
67
|
this.length = 0;
|
68
|
this.value = value.map(function(item) {
|
69
|
if (!(item instanceof EncoderBuffer))
|
70
|
item = new EncoderBuffer(item, reporter);
|
71
|
this.length += item.length;
|
72
|
return item;
|
73
|
}, this);
|
74
|
} else if (typeof value === 'number') {
|
75
|
if (!(0 <= value && value <= 0xff))
|
76
|
return reporter.error('non-byte EncoderBuffer value');
|
77
|
this.value = value;
|
78
|
this.length = 1;
|
79
|
} else if (typeof value === 'string') {
|
80
|
this.value = value;
|
81
|
this.length = Buffer.byteLength(value);
|
82
|
} else if (Buffer.isBuffer(value)) {
|
83
|
this.value = value;
|
84
|
this.length = value.length;
|
85
|
} else {
|
86
|
return reporter.error('Unsupported type: ' + typeof value);
|
87
|
}
|
88
|
}
|
89
|
exports.EncoderBuffer = EncoderBuffer;
|
90
|
|
91
|
EncoderBuffer.prototype.join = function join(out, offset) {
|
92
|
if (!out)
|
93
|
out = new Buffer(this.length);
|
94
|
if (!offset)
|
95
|
offset = 0;
|
96
|
|
97
|
if (this.length === 0)
|
98
|
return out;
|
99
|
|
100
|
if (Array.isArray(this.value)) {
|
101
|
this.value.forEach(function(item) {
|
102
|
item.join(out, offset);
|
103
|
offset += item.length;
|
104
|
});
|
105
|
} else {
|
106
|
if (typeof this.value === 'number')
|
107
|
out[offset] = this.value;
|
108
|
else if (typeof this.value === 'string')
|
109
|
out.write(this.value, offset);
|
110
|
else if (Buffer.isBuffer(this.value))
|
111
|
this.value.copy(out, offset);
|
112
|
offset += this.length;
|
113
|
}
|
114
|
|
115
|
return out;
|
116
|
};
|