Projekt

Obecné

Profil

Stáhnout (8.62 KB) Statistiky
| Větev: | Revize:
1
var Buffer = require('buffer').Buffer;
2

    
3
function OffsetBuffer() {
4
  this.offset = 0;
5
  this.size = 0;
6
  this.buffers = [];
7
}
8
module.exports = OffsetBuffer;
9

    
10
OffsetBuffer.prototype.isEmpty = function isEmpty() {
11
  return this.size === 0;
12
};
13

    
14
OffsetBuffer.prototype.clone = function clone(size) {
15
  var r = new OffsetBuffer();
16
  r.offset = this.offset;
17
  r.size = size;
18
  r.buffers = this.buffers.slice();
19
  return r;
20
};
21

    
22
OffsetBuffer.prototype.toChunks = function toChunks() {
23
  if (this.size === 0)
24
    return [];
25

    
26
  // We are going to slice it anyway
27
  if (this.offset !== 0) {
28
    this.buffers[0] = this.buffers[0].slice(this.offset);
29
    this.offset = 0;
30
  }
31

    
32
  var chunks = [ ];
33
  var off = 0;
34
  for (var i = 0; off <= this.size && i < this.buffers.length; i++) {
35
    var buf = this.buffers[i];
36
    off += buf.length;
37

    
38
    // Slice off last buffer
39
    if (off > this.size) {
40
      buf = buf.slice(0, buf.length - (off - this.size));
41
      this.buffers[i] = buf;
42
    }
43

    
44
    chunks.push(buf);
45
  }
46

    
47
  // If some buffers were skipped - trim length
48
  if (i < this.buffers.length)
49
    this.buffers.length = i;
50

    
51
  return chunks;
52
};
53

    
54
OffsetBuffer.prototype.toString = function toString(enc) {
55
  return this.toChunks().map(function(c) {
56
    return c.toString(enc);
57
  }).join('');
58
};
59

    
60
OffsetBuffer.prototype.use = function use(buf, off, n) {
61
  this.buffers = [ buf ];
62
  this.offset = off;
63
  this.size = n;
64
};
65

    
66
OffsetBuffer.prototype.push = function push(data) {
67
  // Ignore empty writes
68
  if (data.length === 0)
69
    return;
70

    
71
  this.size += data.length;
72
  this.buffers.push(data);
73
};
74

    
75
OffsetBuffer.prototype.has = function has(n) {
76
  return this.size >= n;
77
};
78

    
79
OffsetBuffer.prototype.skip = function skip(n) {
80
  if (this.size === 0)
81
    return;
82

    
83
  this.size -= n;
84

    
85
  // Fast case, skip bytes in a first buffer
86
  if (this.offset + n < this.buffers[0].length) {
87
    this.offset += n;
88
    return;
89
  }
90

    
91
  var left = n - (this.buffers[0].length - this.offset);
92
  this.offset = 0;
93

    
94
  for (var shift = 1; left > 0 && shift < this.buffers.length; shift++) {
95
    var buf = this.buffers[shift];
96
    if (buf.length > left) {
97
      this.offset = left;
98
      break;
99
    }
100
    left -= buf.length;
101
  }
102
  this.buffers = this.buffers.slice(shift);
103
};
104

    
105
OffsetBuffer.prototype.copy = function copy(target, targetOff, off, n) {
106
  if (this.size === 0)
107
    return;
108
  if (off !== 0)
109
    throw new Error('Unsupported offset in .copy()');
110

    
111
  var toff = targetOff;
112
  var first = this.buffers[0];
113
  var toCopy = Math.min(n, first.length - this.offset);
114
  first.copy(target, toff, this.offset, this.offset + toCopy);
115

    
116
  toff += toCopy;
117
  var left = n - toCopy;
118
  for (var i = 1; left > 0 && i < this.buffers.length; i++) {
119
    var buf = this.buffers[i];
120
    var toCopy = Math.min(left, buf.length);
121

    
122
    buf.copy(target, toff, 0, toCopy);
123

    
124
    toff += toCopy;
125
    left -= toCopy;
126
  }
127
};
128

    
129
OffsetBuffer.prototype.take = function take(n) {
130
  if (n === 0)
131
    return new Buffer(0);
132

    
133
  this.size -= n;
134

    
135
  // Fast cases
136
  var first = this.buffers[0].length - this.offset;
137
  if (first === n) {
138
    var r = this.buffers.shift();
139
    if (this.offset !== 0) {
140
      r = r.slice(this.offset);
141
      this.offset = 0;
142
    }
143
    return r;
144
  } else if (first > n) {
145
    var r = this.buffers[0].slice(this.offset, this.offset + n);
146
    this.offset += n;
147
    return r;
148
  }
149

    
150
  // Allocate and fill buffer
151
  var out = new Buffer(n);
152
  var toOff = 0;
153
  var startOff = this.offset;
154
  for (var i = 0; toOff !== n && i < this.buffers.length; i++) {
155
    var buf = this.buffers[i];
156
    var toCopy = Math.min(buf.length - startOff, n - toOff);
157

    
158
    buf.copy(out, toOff, startOff, startOff + toCopy);
159
    if (startOff + toCopy < buf.length) {
160
      this.offset = startOff + toCopy;
161
      break;
162
    } else {
163
      toOff += toCopy;
164
      startOff = 0;
165
    }
166
  }
167

    
168
  this.buffers = this.buffers.slice(i);
169
  if (this.buffers.length === 0)
170
    this.offset = 0;
171

    
172
  return out;
173
};
174

    
175
OffsetBuffer.prototype.peekUInt8 = function peekUInt8() {
176
  return this.buffers[0][this.offset];
177
};
178

    
179
OffsetBuffer.prototype.readUInt8 = function readUInt8() {
180
  this.size -= 1;
181
  var first = this.buffers[0];
182
  var r = first[this.offset];
183
  if (++this.offset === first.length) {
184
    this.offset = 0;
185
    this.buffers.shift();
186
  }
187

    
188
  return r;
189
};
190

    
191
OffsetBuffer.prototype.readUInt16LE = function readUInt16LE() {
192
  var first = this.buffers[0];
193
  this.size -= 2;
194

    
195
  var r;
196
  var shift;
197

    
198
  // Fast case - first buffer has all bytes
199
  if (first.length - this.offset >= 2) {
200
    r = first.readUInt16LE(this.offset);
201
    shift = 0;
202
    this.offset += 2;
203

    
204
  // One byte here - one byte there
205
  } else {
206
    r = first[this.offset] | (this.buffers[1][0] << 8);
207
    shift = 1;
208
    this.offset = 1;
209
  }
210

    
211
  if (this.offset === this.buffers[shift].length) {
212
    this.offset = 0;
213
    shift++;
214
  }
215
  if (shift !== 0)
216
    this.buffers = this.buffers.slice(shift);
217

    
218
  return r;
219
};
220

    
221
OffsetBuffer.prototype.readUInt24LE = function readUInt24LE() {
222
  var first = this.buffers[0];
223

    
224
  var r;
225
  var shift;
226
  var firstHas = first.length - this.offset;
227

    
228
  // Fast case - first buffer has all bytes
229
  if (firstHas >= 3) {
230
    r = first.readUInt16LE(this.offset) | (first[this.offset + 2] << 16);
231
    shift = 0;
232
    this.offset += 3;
233

    
234
  // First buffer has 2 of 3 bytes
235
  } else if (firstHas >= 2) {
236
    r = first.readUInt16LE(this.offset) | (this.buffers[1][0] << 16);
237
    shift = 1;
238
    this.offset = 1;
239

    
240
  // Slow case: First buffer has 1 of 3 bytes
241
  } else {
242
    r = first[this.offset];
243
    this.offset = 0;
244
    this.buffers.shift();
245
    this.size -= 1;
246

    
247
    r |= this.readUInt16LE() << 8;
248
    return r;
249
  }
250

    
251
  this.size -= 3;
252
  if (this.offset === this.buffers[shift].length) {
253
    this.offset = 0;
254
    shift++;
255
  }
256
  if (shift !== 0)
257
    this.buffers = this.buffers.slice(shift);
258

    
259
  return r;
260
};
261

    
262
OffsetBuffer.prototype.readUInt32LE = function readUInt32LE() {
263
  var first = this.buffers[0];
264

    
265
  var r;
266
  var shift;
267
  var firstHas = first.length - this.offset;
268

    
269
  // Fast case - first buffer has all bytes
270
  if (firstHas >= 4) {
271
    r = first.readUInt32LE(this.offset);
272
    shift = 0;
273
    this.offset += 4;
274

    
275
  // First buffer has 3 of 4 bytes
276
  } else if (firstHas >= 3) {
277
    r = (first.readUInt16LE(this.offset) |
278
         (first[this.offset + 2] << 16)) +
279
        (this.buffers[1][0] * 0x1000000);
280
    shift = 1;
281
    this.offset = 1;
282

    
283
  // Slow case: First buffer has 2 of 4 bytes
284
  } else if (firstHas >= 2) {
285
    r = first.readUInt16LE(this.offset);
286
    this.offset = 0;
287
    this.buffers.shift();
288
    this.size -= 2;
289

    
290
    r += this.readUInt16LE() * 0x10000;
291
    return r;
292

    
293
  // Slow case: First buffer has 1 of 4 bytes
294
  } else {
295
    r = first[this.offset];
296
    this.offset = 0;
297
    this.buffers.shift();
298
    this.size -= 1;
299

    
300
    r += this.readUInt24LE() * 0x100;
301
    return r;
302
  }
303

    
304
  this.size -= 4;
305
  if (this.offset === this.buffers[shift].length) {
306
    this.offset = 0;
307
    shift++;
308
  }
309
  if (shift !== 0)
310
    this.buffers = this.buffers.slice(shift);
311

    
312
  return r;
313
};
314

    
315
OffsetBuffer.prototype.readUInt16BE = function readUInt16BE() {
316
  var r = this.readUInt16LE();
317

    
318
  return ((r & 0xff) << 8) | (r >> 8);
319
};
320

    
321
OffsetBuffer.prototype.readUInt24BE = function readUInt24BE() {
322
  var r = this.readUInt24LE();
323

    
324
  return ((r & 0xff) << 16) | (((r >> 8) & 0xff) << 8) | (r >> 16);
325
};
326

    
327
OffsetBuffer.prototype.readUInt32BE = function readUInt32BE() {
328
  var r = this.readUInt32LE();
329

    
330
  return (((r & 0xff) << 24) |
331
          (((r >>> 8) & 0xff) << 16) |
332
          (((r >>> 16) & 0xff) << 8) |
333
          (r >>> 24)) >>> 0;
334
};
335

    
336
// Signed number APIs
337

    
338
function signedInt8(num) {
339
  if (num >= 0x80)
340
    return -(0xff ^ num) - 1;
341
  else
342
    return num;
343
}
344

    
345
OffsetBuffer.prototype.peekInt8 = function peekInt8() {
346
  return signedInt8(this.peekUInt8());
347
};
348

    
349
OffsetBuffer.prototype.readInt8 = function readInt8() {
350
  return signedInt8(this.readUInt8());
351
};
352

    
353
function signedInt16(num) {
354
  if (num >= 0x8000)
355
    return -(0xffff ^ num) - 1;
356
  else
357
    return num;
358
}
359

    
360
OffsetBuffer.prototype.readInt16BE = function readInt16BE() {
361
  return signedInt16(this.readUInt16BE());
362
};
363

    
364
OffsetBuffer.prototype.readInt16LE = function readInt16LE() {
365
  return signedInt16(this.readUInt16LE());
366
};
367

    
368
function signedInt24(num) {
369
  if (num >= 0x800000)
370
    return -(0xffffff ^ num) - 1;
371
  else
372
    return num;
373
}
374

    
375
OffsetBuffer.prototype.readInt24BE = function readInt24BE() {
376
  return signedInt24(this.readUInt24BE());
377
};
378

    
379
OffsetBuffer.prototype.readInt24LE = function readInt24LE() {
380
  return signedInt24(this.readUInt24LE());
381
};
382

    
383
function signedInt32(num) {
384
  if (num >= 0x80000000)
385
    return -(0xffffffff ^ num) - 1;
386
  else
387
    return num;
388
}
389

    
390
OffsetBuffer.prototype.readInt32BE = function readInt32BE() {
391
  return signedInt32(this.readUInt32BE());
392
};
393

    
394
OffsetBuffer.prototype.readInt32LE = function readInt32LE() {
395
  return signedInt32(this.readUInt32LE());
396
};
(3-3/4)