source: trip-planner-front/node_modules/wbuf/index.js@ eed0bf8

Last change on this file since eed0bf8 was 6a3a178, checked in by Ema <ema_spirova@…>, 3 years ago

initial commit

  • Property mode set to 100644
File size: 9.0 KB
Line 
1var assert = require('minimalistic-assert');
2var Buffer = require('buffer').Buffer;
3
4function WBuf() {
5 this.buffers = [];
6 this.toReserve = 0;
7 this.size = 0;
8 this.maxSize = 0;
9 this.avail = 0;
10
11 this.last = null;
12 this.offset = 0;
13
14 // Used in slicing
15 this.sliceQueue = null;
16
17 this.forceReserve = false;
18
19 // Mostly a constant
20 this.reserveRate = 64;
21}
22module.exports = WBuf;
23
24WBuf.prototype.reserve = function reserve(n) {
25 this.toReserve += n;
26
27 // Force reservation of extra bytes
28 if (this.forceReserve)
29 this.toReserve = Math.max(this.toReserve, this.reserveRate);
30};
31
32WBuf.prototype._ensure = function _ensure(n) {
33 if (this.avail >= n)
34 return;
35
36 if (this.toReserve === 0)
37 this.toReserve = this.reserveRate;
38
39 this.toReserve = Math.max(n - this.avail, this.toReserve);
40
41 if (this.avail === 0)
42 this._next();
43};
44
45WBuf.prototype._next = function _next() {
46 var buf;
47 if (this.sliceQueue === null) {
48 // Most common case
49 buf = new Buffer(this.toReserve);
50 } else {
51 // Only for `.slice()` results
52 buf = this.sliceQueue.shift();
53 if (this.sliceQueue.length === 0)
54 this.sliceQueue = null;
55 }
56
57 this.toReserve = 0;
58
59 this.buffers.push(buf);
60 this.avail = buf.length;
61 this.offset = 0;
62 this.last = buf;
63};
64
65WBuf.prototype._rangeCheck = function _rangeCheck() {
66 if (this.maxSize !== 0 && this.size > this.maxSize)
67 throw new RangeError('WBuf overflow');
68};
69
70WBuf.prototype._move = function _move(n) {
71 this.size += n;
72 if (this.avail === 0)
73 this.last = null;
74
75 this._rangeCheck();
76};
77
78WBuf.prototype.slice = function slice(start, end) {
79 assert(0 <= start && start <= this.size);
80 assert(0 <= end && end <= this.size);
81
82 if (this.last === null)
83 this._next();
84
85 var res = new WBuf();
86
87 // Only last chunk is requested
88 if (start >= this.size - this.offset) {
89 res.buffers.push(this.last);
90 res.last = this.last;
91 res.offset = start - this.size + this.offset;
92 res.maxSize = end - start;
93 res.avail = res.maxSize;
94
95 return res;
96 }
97
98 var startIndex = -1;
99 var startOffset = 0;
100 var endIndex = -1;
101
102 // Find buffer indices
103 var offset = 0;
104 for (var i = 0; i < this.buffers.length; i++) {
105 var buf = this.buffers[i];
106 var next = offset + buf.length;
107
108 // Found the start
109 if (start >= offset && start <= next) {
110 startIndex = i;
111 startOffset = start - offset;
112 if (endIndex !== -1)
113 break;
114 }
115 if (end >= offset && end <= next) {
116 endIndex = i;
117 if (startIndex !== -1)
118 break;
119 }
120
121 offset = next;
122 }
123
124 res.last = this.buffers[startIndex];
125 res.offset = startOffset;
126 res.maxSize = end - start;
127
128 // Multi-buffer slice
129 if (startIndex < endIndex) {
130 res.sliceQueue = this.buffers.slice(startIndex + 1, endIndex + 1);
131
132 res.last = res.last.slice(res.offset);
133 res.offset = 0;
134 }
135
136 res.avail = res.last.length - res.offset;
137 res.buffers.push(res.last);
138
139 return res;
140};
141
142WBuf.prototype.skip = function skip(n) {
143 if (n === 0)
144 return this.slice(this.size, this.size);
145
146 this._ensure(n);
147
148 var left = n;
149 while (left > 0) {
150 var toSkip = Math.min(left, this.avail);
151 left -= toSkip;
152 this.size += toSkip;
153 if (toSkip === this.avail) {
154 if (left !== 0) {
155 this._next();
156 } else {
157 this.avail -= toSkip;
158 this.offset += toSkip;
159 }
160 } else {
161 this.offset += toSkip;
162 this.avail -= toSkip;
163 }
164 }
165
166 this._rangeCheck();
167
168 return this.slice(this.size - n, this.size);
169};
170
171WBuf.prototype.write = function write(str) {
172 var len = 0;
173 for (var i = 0; i < str.length; i++) {
174 var c = str.charCodeAt(i);
175 if (c > 255)
176 len += 2;
177 else
178 len += 1;
179 }
180 this.reserve(len);
181 for (var i = 0; i < str.length; i++) {
182 var c = str.charCodeAt(i);
183 var hi = c >>> 8;
184 var lo = c & 0xff;
185
186 if (hi)
187 this.writeUInt8(hi);
188 this.writeUInt8(lo);
189 }
190};
191
192WBuf.prototype.copyFrom = function copyFrom(buf, start, end) {
193 var off = start === undefined ? 0 : start;
194 var len = end === undefined ? buf.length : end;
195 if (off === len)
196 return;
197
198 this._ensure(len - off);
199 while (off < len) {
200 var toCopy = Math.min(len - off, this.avail);
201 buf.copy(this.last, this.offset, off, off + toCopy);
202 off += toCopy;
203 this.size += toCopy;
204 if (toCopy === this.avail) {
205 if (off !== len) {
206 this._next();
207 } else {
208 this.avail = 0;
209 this.offset += toCopy;
210 }
211 } else {
212 this.offset += toCopy;
213 this.avail -= toCopy;
214 }
215 }
216
217 this._rangeCheck();
218};
219
220WBuf.prototype.writeUInt8 = function writeUInt8(v) {
221 this._ensure(1);
222
223 this.last[this.offset++] = v;
224 this.avail--;
225 this._move(1);
226};
227
228WBuf.prototype.writeUInt16BE = function writeUInt16BE(v) {
229 this._ensure(2);
230
231 // Fast case - everything fits into the last buffer
232 if (this.avail >= 2) {
233 this.last.writeUInt16BE(v, this.offset);
234 this.offset += 2;
235 this.avail -= 2;
236
237 // One byte here, one byte there
238 } else {
239 this.last[this.offset] = (v >>> 8);
240 this._next();
241 this.last[this.offset++] = v & 0xff;
242 this.avail--;
243 }
244
245 this._move(2);
246};
247
248WBuf.prototype.writeUInt24BE = function writeUInt24BE(v) {
249 this._ensure(3);
250
251 // Fast case - everything fits into the last buffer
252 if (this.avail >= 3) {
253 this.last.writeUInt16BE(v >>> 8, this.offset);
254 this.last[this.offset + 2] = v & 0xff;
255 this.offset += 3;
256 this.avail -= 3;
257 this._move(3);
258
259 // Two bytes here
260 } else if (this.avail >= 2) {
261 this.last.writeUInt16BE(v >>> 8, this.offset);
262 this._next();
263 this.last[this.offset++] = v & 0xff;
264 this.avail--;
265 this._move(3);
266
267 // Just one byte here
268 } else {
269 this.last[this.offset] = v >>> 16;
270 this._move(1);
271 this._next();
272 this.writeUInt16BE(v & 0xffff);
273 }
274};
275
276WBuf.prototype.writeUInt32BE = function writeUInt32BE(v) {
277 this._ensure(4);
278
279 // Fast case - everything fits into the last buffer
280 if (this.avail >= 4) {
281 this.last.writeUInt32BE(v, this.offset);
282 this.offset += 4;
283 this.avail -= 4;
284 this._move(4);
285
286 // Three bytes here
287 } else if (this.avail >= 3) {
288 this.writeUInt24BE(v >>> 8);
289 this._next();
290 this.last[this.offset++] = v & 0xff;
291 this.avail--;
292 this._move(1);
293
294 // Slow case, who cares
295 } else {
296 this.writeUInt16BE(v >>> 16);
297 this.writeUInt16BE(v & 0xffff);
298 }
299};
300
301WBuf.prototype.writeUInt16LE = function writeUInt16LE(num) {
302 var r = ((num & 0xff) << 8) | (num >>> 8);
303 this.writeUInt16BE(r);
304};
305
306WBuf.prototype.writeUInt24LE = function writeUInt24LE(num) {
307 var r = ((num & 0xff) << 16) | (((num >>> 8) & 0xff) << 8) | (num >>> 16);
308 this.writeUInt24BE(r);
309};
310
311WBuf.prototype.writeUInt32LE = function writeUInt32LE(num) {
312 this._ensure(4);
313
314 // Fast case - everything fits into the last buffer
315 if (this.avail >= 4) {
316 this.last.writeUInt32LE(num, this.offset);
317 this.offset += 4;
318 this.avail -= 4;
319 this._move(4);
320
321 // Three bytes here
322 } else if (this.avail >= 3) {
323 this.writeUInt24LE(num & 0xffffff);
324 this._next();
325 this.last[this.offset++] = num >>> 24;
326 this.avail--;
327 this._move(1);
328
329 // Slow case, who cares
330 } else {
331 this.writeUInt16LE(num & 0xffff);
332 this.writeUInt16LE(num >>> 16);
333 }
334};
335
336WBuf.prototype.render = function render() {
337 var left = this.size;
338 var out = [];
339
340 for (var i = 0; i < this.buffers.length && left >= 0; i++) {
341 var buf = this.buffers[i];
342 left -= buf.length;
343 if (left >= 0) {
344 out.push(buf);
345 } else {
346 out.push(buf.slice(0, buf.length + left));
347 }
348 }
349
350 return out;
351};
352
353// Signed APIs
354WBuf.prototype.writeInt8 = function writeInt8(num) {
355 if (num < 0)
356 return this.writeUInt8(0x100 + num);
357 else
358 return this.writeUInt8(num);
359};
360
361function toUnsigned16(num) {
362 if (num < 0)
363 return 0x10000 + num;
364 else
365 return num;
366}
367
368WBuf.prototype.writeInt16LE = function writeInt16LE(num) {
369 this.writeUInt16LE(toUnsigned16(num));
370};
371
372WBuf.prototype.writeInt16BE = function writeInt16BE(num) {
373 this.writeUInt16BE(toUnsigned16(num));
374};
375
376function toUnsigned24(num) {
377 if (num < 0)
378 return 0x1000000 + num;
379 else
380 return num;
381}
382
383WBuf.prototype.writeInt24LE = function writeInt24LE(num) {
384 this.writeUInt24LE(toUnsigned24(num));
385};
386
387WBuf.prototype.writeInt24BE = function writeInt24BE(num) {
388 this.writeUInt24BE(toUnsigned24(num));
389};
390
391function toUnsigned32(num) {
392 if (num < 0)
393 return (0xffffffff + num) + 1;
394 else
395 return num;
396}
397
398WBuf.prototype.writeInt32LE = function writeInt32LE(num) {
399 this.writeUInt32LE(toUnsigned32(num));
400};
401
402WBuf.prototype.writeInt32BE = function writeInt32BE(num) {
403 this.writeUInt32BE(toUnsigned32(num));
404};
405
406WBuf.prototype.writeComb = function writeComb(size, endian, value) {
407 if (size === 1)
408 return this.writeUInt8(value);
409
410 if (endian === 'le') {
411 if (size === 2)
412 this.writeUInt16LE(value);
413 else if (size === 3)
414 this.writeUInt24LE(value);
415 else if (size === 4)
416 this.writeUInt32LE(value);
417 } else {
418 if (size === 2)
419 this.writeUInt16BE(value);
420 else if (size === 3)
421 this.writeUInt24BE(value);
422 else if (size === 4)
423 this.writeUInt32BE(value);
424 }
425};
Note: See TracBrowser for help on using the repository browser.