buffer: add indexOf() method
[platform/upstream/nodejs.git] / lib / buffer.js
1 'use strict';
2
3 const binding = process.binding('buffer');
4 const smalloc = process.binding('smalloc');
5 const util = require('util');
6 const alloc = smalloc.alloc;
7 const truncate = smalloc.truncate;
8 const sliceOnto = smalloc.sliceOnto;
9 const kMaxLength = smalloc.kMaxLength;
10
11 exports.Buffer = Buffer;
12 exports.SlowBuffer = SlowBuffer;
13 exports.INSPECT_MAX_BYTES = 50;
14
15
16 Buffer.poolSize = 8 * 1024;
17 var poolSize, poolOffset, allocPool;
18
19
20 function createPool() {
21   poolSize = Buffer.poolSize;
22   allocPool = alloc({}, poolSize);
23   poolOffset = 0;
24 }
25 createPool();
26
27
28 function Buffer(subject, encoding) {
29   if (!(this instanceof Buffer))
30     return new Buffer(subject, encoding);
31
32   if (typeof subject === 'number') {
33     this.length = +subject;
34
35   } else if (typeof subject === 'string') {
36     if (typeof encoding !== 'string' || encoding.length === 0)
37       encoding = 'utf8';
38     this.length = Buffer.byteLength(subject, encoding);
39
40   // Handle Arrays, Buffers, Uint8Arrays or JSON.
41   } else if (subject !== null && typeof subject === 'object') {
42     if (subject.type === 'Buffer' && Array.isArray(subject.data))
43       subject = subject.data;
44     this.length = +subject.length;
45
46   } else {
47     throw new TypeError('must start with number, buffer, array or string');
48   }
49
50   if (this.length > kMaxLength) {
51     throw new RangeError('Attempt to allocate Buffer larger than maximum ' +
52                          'size: 0x' + kMaxLength.toString(16) + ' bytes');
53   }
54
55   if (this.length < 0)
56     this.length = 0;
57   else
58     this.length >>>= 0;  // Coerce to uint32.
59
60   this.parent = undefined;
61   if (this.length <= (Buffer.poolSize >>> 1) && this.length > 0) {
62     if (this.length > poolSize - poolOffset)
63       createPool();
64     this.parent = sliceOnto(allocPool,
65                             this,
66                             poolOffset,
67                             poolOffset + this.length);
68     poolOffset += this.length;
69   } else {
70     alloc(this, this.length);
71   }
72
73   if (typeof subject === 'number') {
74     return;
75   }
76
77   if (typeof subject === 'string') {
78     // In the case of base64 it's possible that the size of the buffer
79     // allocated was slightly too large. In this case we need to rewrite
80     // the length to the actual length written.
81     var len = this.write(subject, encoding);
82     // Buffer was truncated after decode, realloc internal ExternalArray
83     if (len !== this.length) {
84       var prevLen = this.length;
85       this.length = len;
86       truncate(this, this.length);
87       // Only need to readjust the poolOffset if the allocation is a slice.
88       if (this.parent != undefined)
89         poolOffset -= (prevLen - len);
90     }
91
92   } else if (subject instanceof Buffer) {
93     subject.copy(this, 0, 0, this.length);
94
95   } else if (typeof subject.length === 'number' || Array.isArray(subject)) {
96     // Really crappy way to handle Uint8Arrays, but V8 doesn't give a simple
97     // way to access the data from the C++ API.
98     for (var i = 0; i < this.length; i++)
99       this[i] = subject[i];
100   }
101 }
102
103
104 function SlowBuffer(length) {
105   length = length >>> 0;
106   if (length > kMaxLength) {
107     throw new RangeError('Attempt to allocate Buffer larger than maximum ' +
108                          'size: 0x' + kMaxLength.toString(16) + ' bytes');
109   }
110   var b = new NativeBuffer(length);
111   alloc(b, length);
112   return b;
113 }
114
115
116 // Bypass all checks for instantiating unallocated Buffer required for
117 // Objects created in C++. Significantly faster than calling the Buffer
118 // function.
119 function NativeBuffer(length) {
120   this.length = length >>> 0;
121   // Set this to keep the object map the same.
122   this.parent = undefined;
123 }
124 NativeBuffer.prototype = Buffer.prototype;
125
126
127 // add methods to Buffer prototype
128 binding.setupBufferJS(NativeBuffer);
129
130
131 // Static methods
132
133 Buffer.isBuffer = function isBuffer(b) {
134   return b instanceof Buffer;
135 };
136
137
138 Buffer.compare = function compare(a, b) {
139   if (!(a instanceof Buffer) ||
140       !(b instanceof Buffer))
141     throw new TypeError('Arguments must be Buffers');
142
143   if (a === b)
144     return 0;
145
146   return binding.compare(a, b);
147 };
148
149
150 Buffer.isEncoding = function(encoding) {
151   switch ((encoding + '').toLowerCase()) {
152     case 'hex':
153     case 'utf8':
154     case 'utf-8':
155     case 'ascii':
156     case 'binary':
157     case 'base64':
158     case 'ucs2':
159     case 'ucs-2':
160     case 'utf16le':
161     case 'utf-16le':
162     case 'raw':
163       return true;
164
165     default:
166       return false;
167   }
168 };
169
170
171 Buffer.concat = function(list, length) {
172   if (!Array.isArray(list))
173     throw new TypeError('Usage: Buffer.concat(list[, length])');
174
175   if (length === undefined) {
176     length = 0;
177     for (var i = 0; i < list.length; i++)
178       length += list[i].length;
179   } else {
180     length = length >>> 0;
181   }
182
183   if (list.length === 0)
184     return new Buffer(0);
185   else if (list.length === 1)
186     return list[0];
187
188   var buffer = new Buffer(length);
189   var pos = 0;
190   for (var i = 0; i < list.length; i++) {
191     var buf = list[i];
192     buf.copy(buffer, pos);
193     pos += buf.length;
194   }
195
196   return buffer;
197 };
198
199
200 Buffer.byteLength = function(str, enc) {
201   var ret;
202   str = str + '';
203   switch (enc) {
204     case 'ascii':
205     case 'binary':
206     case 'raw':
207       ret = str.length;
208       break;
209     case 'ucs2':
210     case 'ucs-2':
211     case 'utf16le':
212     case 'utf-16le':
213       ret = str.length * 2;
214       break;
215     case 'hex':
216       ret = str.length >>> 1;
217       break;
218     default:
219       ret = binding.byteLength(str, enc);
220   }
221   return ret;
222 };
223
224
225 // toString(encoding, start=0, end=buffer.length)
226 Buffer.prototype.toString = function(encoding, start, end) {
227   var loweredCase = false;
228
229   start = start >>> 0;
230   end = end === undefined || end === Infinity ? this.length : end >>> 0;
231
232   if (!encoding) encoding = 'utf8';
233   if (start < 0) start = 0;
234   if (end > this.length) end = this.length;
235   if (end <= start) return '';
236
237   while (true) {
238     switch (encoding) {
239       case 'hex':
240         return this.hexSlice(start, end);
241
242       case 'utf8':
243       case 'utf-8':
244         return this.utf8Slice(start, end);
245
246       case 'ascii':
247         return this.asciiSlice(start, end);
248
249       case 'binary':
250         return this.binarySlice(start, end);
251
252       case 'base64':
253         return this.base64Slice(start, end);
254
255       case 'ucs2':
256       case 'ucs-2':
257       case 'utf16le':
258       case 'utf-16le':
259         return this.ucs2Slice(start, end);
260
261       default:
262         if (loweredCase)
263           throw new TypeError('Unknown encoding: ' + encoding);
264         encoding = (encoding + '').toLowerCase();
265         loweredCase = true;
266     }
267   }
268 };
269
270
271 Buffer.prototype.equals = function equals(b) {
272   if (!(b instanceof Buffer))
273     throw new TypeError('Argument must be a Buffer');
274
275   if (this === b)
276     return true;
277
278   return binding.compare(this, b) === 0;
279 };
280
281
282 // Inspect
283 Buffer.prototype.inspect = function inspect() {
284   var str = '';
285   var max = exports.INSPECT_MAX_BYTES;
286   if (this.length > 0) {
287     str = this.toString('hex', 0, max).match(/.{2}/g).join(' ');
288     if (this.length > max)
289       str += ' ... ';
290   }
291   return '<' + this.constructor.name + ' ' + str + '>';
292 };
293
294
295 Buffer.prototype.compare = function compare(b) {
296   if (!(b instanceof Buffer))
297     throw new TypeError('Argument must be a Buffer');
298
299   if (this === b)
300     return 0;
301
302   return binding.compare(this, b);
303 };
304
305
306 Buffer.prototype.indexOf = function indexOf(val, byteOffset) {
307   if (byteOffset > 0x7fffffff)
308     byteOffset = 0x7fffffff;
309   else if (byteOffset < -0x80000000)
310     byteOffset = -0x80000000;
311   byteOffset >>= 0;
312
313   if (typeof val === 'string')
314     return binding.indexOfString(this, val, byteOffset);
315   if (val instanceof Buffer)
316     return binding.indexOfBuffer(this, val, byteOffset);
317   if (typeof val === 'number')
318     return binding.indexOfNumber(this, val, byteOffset);
319
320   throw new TypeError('val must be string, number or Buffer');
321 };
322
323
324 Buffer.prototype.fill = function fill(val, start, end) {
325   start = start >> 0;
326   end = (end === undefined) ? this.length : end >> 0;
327
328   if (start < 0 || end > this.length)
329     throw new RangeError('out of range index');
330   if (end <= start)
331     return this;
332
333   if (typeof val !== 'string') {
334     val = val >>> 0;
335   } else if (val.length === 1) {
336     var code = val.charCodeAt(0);
337     if (code < 256)
338       val = code;
339   }
340
341   binding.fill(this, val, start, end);
342
343   return this;
344 };
345
346
347 // XXX remove in v0.13
348 Buffer.prototype.get = util.deprecate(function get(offset) {
349   offset = ~~offset;
350   if (offset < 0 || offset >= this.length)
351     throw new RangeError('index out of range');
352   return this[offset];
353 }, '.get() is deprecated. Access using array indexes instead.');
354
355
356 // XXX remove in v0.13
357 Buffer.prototype.set = util.deprecate(function set(offset, v) {
358   offset = ~~offset;
359   if (offset < 0 || offset >= this.length)
360     throw new RangeError('index out of range');
361   return this[offset] = v;
362 }, '.set() is deprecated. Set using array indexes instead.');
363
364
365 // TODO(trevnorris): fix these checks to follow new standard
366 // write(string, offset = 0, length = buffer.length, encoding = 'utf8')
367 var writeWarned = false;
368 const writeMsg = '.write(string, encoding, offset, length) is deprecated.' +
369                  ' Use write(string[, offset[, length]][, encoding]) instead.';
370 Buffer.prototype.write = function(string, offset, length, encoding) {
371   // Buffer#write(string);
372   if (offset === undefined) {
373     encoding = 'utf8';
374     length = this.length;
375     offset = 0;
376
377   // Buffer#write(string, encoding)
378   } else if (length === undefined && typeof offset === 'string') {
379     encoding = offset;
380     length = this.length;
381     offset = 0;
382
383   // Buffer#write(string, offset[, length][, encoding])
384   } else if (isFinite(offset)) {
385     offset = offset >>> 0;
386     if (isFinite(length)) {
387       length = length >>> 0;
388       if (encoding === undefined)
389         encoding = 'utf8';
390     } else {
391       encoding = length;
392       length = undefined;
393     }
394
395   // XXX legacy write(string, encoding, offset, length) - remove in v0.13
396   } else {
397     if (!writeWarned) {
398       if (process.throwDeprecation)
399         throw new Error(writeMsg);
400       else if (process.traceDeprecation)
401         console.trace(writeMsg);
402       else
403         console.error(writeMsg);
404       writeWarned = true;
405     }
406
407     var swap = encoding;
408     encoding = offset;
409     offset = length >>> 0;
410     length = swap;
411   }
412
413   var remaining = this.length - offset;
414   if (length === undefined || length > remaining)
415     length = remaining;
416
417   encoding = !!encoding ? (encoding + '').toLowerCase() : 'utf8';
418
419   if (string.length > 0 && (length < 0 || offset < 0))
420     throw new RangeError('attempt to write outside buffer bounds');
421
422   var ret;
423   switch (encoding) {
424     case 'hex':
425       ret = this.hexWrite(string, offset, length);
426       break;
427
428     case 'utf8':
429     case 'utf-8':
430       ret = this.utf8Write(string, offset, length);
431       break;
432
433     case 'ascii':
434       ret = this.asciiWrite(string, offset, length);
435       break;
436
437     case 'binary':
438       ret = this.binaryWrite(string, offset, length);
439       break;
440
441     case 'base64':
442       // Warning: maxLength not taken into account in base64Write
443       ret = this.base64Write(string, offset, length);
444       break;
445
446     case 'ucs2':
447     case 'ucs-2':
448     case 'utf16le':
449     case 'utf-16le':
450       ret = this.ucs2Write(string, offset, length);
451       break;
452
453     default:
454       throw new TypeError('Unknown encoding: ' + encoding);
455   }
456
457   return ret;
458 };
459
460
461 Buffer.prototype.toJSON = function() {
462   return {
463     type: 'Buffer',
464     data: Array.prototype.slice.call(this, 0)
465   };
466 };
467
468
469 // TODO(trevnorris): currently works like Array.prototype.slice(), which
470 // doesn't follow the new standard for throwing on out of range indexes.
471 Buffer.prototype.slice = function(start, end) {
472   var len = this.length;
473   start = ~~start;
474   end = end === undefined ? len : ~~end;
475
476   if (start < 0) {
477     start += len;
478     if (start < 0)
479       start = 0;
480   } else if (start > len) {
481     start = len;
482   }
483
484   if (end < 0) {
485     end += len;
486     if (end < 0)
487       end = 0;
488   } else if (end > len) {
489     end = len;
490   }
491
492   if (end < start)
493     end = start;
494
495   var buf = new NativeBuffer();
496   sliceOnto(this, buf, start, end);
497   buf.length = end - start;
498   if (buf.length > 0)
499     buf.parent = this.parent === undefined ? this : this.parent;
500
501   return buf;
502 };
503
504
505 function checkOffset(offset, ext, length) {
506   if (offset + ext > length)
507     throw new RangeError('index out of range');
508 }
509
510
511 Buffer.prototype.readUIntLE = function(offset, byteLength, noAssert) {
512   offset = offset >>> 0;
513   byteLength = byteLength >>> 0;
514   if (!noAssert)
515     checkOffset(offset, byteLength, this.length);
516
517   var val = this[offset];
518   var mul = 1;
519   var i = 0;
520   while (++i < byteLength && (mul *= 0x100))
521     val += this[offset + i] * mul;
522
523   return val;
524 };
525
526
527 Buffer.prototype.readUIntBE = function(offset, byteLength, noAssert) {
528   offset = offset >>> 0;
529   byteLength = byteLength >>> 0;
530   if (!noAssert)
531     checkOffset(offset, byteLength, this.length);
532
533   var val = this[offset + --byteLength];
534   var mul = 1;
535   while (byteLength > 0 && (mul *= 0x100))
536     val += this[offset + --byteLength] * mul;
537
538   return val;
539 };
540
541
542 Buffer.prototype.readUInt8 = function(offset, noAssert) {
543   offset = offset >>> 0;
544   if (!noAssert)
545     checkOffset(offset, 1, this.length);
546   return this[offset];
547 };
548
549
550 Buffer.prototype.readUInt16LE = function(offset, noAssert) {
551   offset = offset >>> 0;
552   if (!noAssert)
553     checkOffset(offset, 2, this.length);
554   return this[offset] | (this[offset + 1] << 8);
555 };
556
557
558 Buffer.prototype.readUInt16BE = function(offset, noAssert) {
559   offset = offset >>> 0;
560   if (!noAssert)
561     checkOffset(offset, 2, this.length);
562   return (this[offset] << 8) | this[offset + 1];
563 };
564
565
566 Buffer.prototype.readUInt32LE = function(offset, noAssert) {
567   offset = offset >>> 0;
568   if (!noAssert)
569     checkOffset(offset, 4, this.length);
570
571   return ((this[offset]) |
572       (this[offset + 1] << 8) |
573       (this[offset + 2] << 16)) +
574       (this[offset + 3] * 0x1000000);
575 };
576
577
578 Buffer.prototype.readUInt32BE = function(offset, noAssert) {
579   offset = offset >>> 0;
580   if (!noAssert)
581     checkOffset(offset, 4, this.length);
582
583   return (this[offset] * 0x1000000) +
584       ((this[offset + 1] << 16) |
585       (this[offset + 2] << 8) |
586       this[offset + 3]);
587 };
588
589
590 Buffer.prototype.readIntLE = function(offset, byteLength, noAssert) {
591   offset = offset >>> 0;
592   byteLength = byteLength >>> 0;
593   if (!noAssert)
594     checkOffset(offset, byteLength, this.length);
595
596   var val = this[offset];
597   var mul = 1;
598   var i = 0;
599   while (++i < byteLength && (mul *= 0x100))
600     val += this[offset + i] * mul;
601   mul *= 0x80;
602
603   if (val >= mul)
604     val -= Math.pow(2, 8 * byteLength);
605
606   return val;
607 };
608
609
610 Buffer.prototype.readIntBE = function(offset, byteLength, noAssert) {
611   offset = offset >>> 0;
612   byteLength = byteLength >>> 0;
613   if (!noAssert)
614     checkOffset(offset, byteLength, this.length);
615
616   var i = byteLength;
617   var mul = 1;
618   var val = this[offset + --i];
619   while (i > 0 && (mul *= 0x100))
620     val += this[offset + --i] * mul;
621   mul *= 0x80;
622
623   if (val >= mul)
624     val -= Math.pow(2, 8 * byteLength);
625
626   return val;
627 };
628
629
630 Buffer.prototype.readInt8 = function(offset, noAssert) {
631   offset = offset >>> 0;
632   if (!noAssert)
633     checkOffset(offset, 1, this.length);
634   var val = this[offset];
635   return !(val & 0x80) ? val : (0xff - val + 1) * -1;
636 };
637
638
639 Buffer.prototype.readInt16LE = function(offset, noAssert) {
640   offset = offset >>> 0;
641   if (!noAssert)
642     checkOffset(offset, 2, this.length);
643   var val = this[offset] | (this[offset + 1] << 8);
644   return (val & 0x8000) ? val | 0xFFFF0000 : val;
645 };
646
647
648 Buffer.prototype.readInt16BE = function(offset, noAssert) {
649   offset = offset >>> 0;
650   if (!noAssert)
651     checkOffset(offset, 2, this.length);
652   var val = this[offset + 1] | (this[offset] << 8);
653   return (val & 0x8000) ? val | 0xFFFF0000 : val;
654 };
655
656
657 Buffer.prototype.readInt32LE = function(offset, noAssert) {
658   offset = offset >>> 0;
659   if (!noAssert)
660     checkOffset(offset, 4, this.length);
661
662   return (this[offset]) |
663       (this[offset + 1] << 8) |
664       (this[offset + 2] << 16) |
665       (this[offset + 3] << 24);
666 };
667
668
669 Buffer.prototype.readInt32BE = function(offset, noAssert) {
670   offset = offset >>> 0;
671   if (!noAssert)
672     checkOffset(offset, 4, this.length);
673
674   return (this[offset] << 24) |
675       (this[offset + 1] << 16) |
676       (this[offset + 2] << 8) |
677       (this[offset + 3]);
678 };
679
680
681 Buffer.prototype.readFloatLE = function readFloatLE(offset, noAssert) {
682   offset = offset >>> 0;
683   if (!noAssert)
684     checkOffset(offset, 4, this.length);
685   return binding.readFloatLE(this, offset);
686 };
687
688
689 Buffer.prototype.readFloatBE = function readFloatBE(offset, noAssert) {
690   offset = offset >>> 0;
691   if (!noAssert)
692     checkOffset(offset, 4, this.length);
693   return binding.readFloatBE(this, offset);
694 };
695
696
697 Buffer.prototype.readDoubleLE = function readDoubleLE(offset, noAssert) {
698   offset = offset >>> 0;
699   if (!noAssert)
700     checkOffset(offset, 8, this.length);
701   return binding.readDoubleLE(this, offset);
702 };
703
704
705 Buffer.prototype.readDoubleBE = function readDoubleBE(offset, noAssert) {
706   offset = offset >>> 0;
707   if (!noAssert)
708     checkOffset(offset, 8, this.length);
709   return binding.readDoubleBE(this, offset);
710 };
711
712
713 function checkInt(buffer, value, offset, ext, max, min) {
714   if (!(buffer instanceof Buffer))
715     throw new TypeError('buffer must be a Buffer instance');
716   if (value > max || value < min)
717     throw new TypeError('value is out of bounds');
718   if (offset + ext > buffer.length)
719     throw new RangeError('index out of range');
720 }
721
722
723 Buffer.prototype.writeUIntLE = function(value, offset, byteLength, noAssert) {
724   value = +value;
725   offset = offset >>> 0;
726   byteLength = byteLength >>> 0;
727   if (!noAssert)
728     checkInt(this, value, offset, byteLength, Math.pow(2, 8 * byteLength), 0);
729
730   var mul = 1;
731   var i = 0;
732   this[offset] = value;
733   while (++i < byteLength && (mul *= 0x100))
734     this[offset + i] = (value / mul) >>> 0;
735
736   return offset + byteLength;
737 };
738
739
740 Buffer.prototype.writeUIntBE = function(value, offset, byteLength, noAssert) {
741   value = +value;
742   offset = offset >>> 0;
743   byteLength = byteLength >>> 0;
744   if (!noAssert)
745     checkInt(this, value, offset, byteLength, Math.pow(2, 8 * byteLength), 0);
746
747   var i = byteLength - 1;
748   var mul = 1;
749   this[offset + i] = value;
750   while (--i >= 0 && (mul *= 0x100))
751     this[offset + i] = (value / mul) >>> 0;
752
753   return offset + byteLength;
754 };
755
756
757 Buffer.prototype.writeUInt8 = function(value, offset, noAssert) {
758   value = +value;
759   offset = offset >>> 0;
760   if (!noAssert)
761     checkInt(this, value, offset, 1, 0xff, 0);
762   this[offset] = value;
763   return offset + 1;
764 };
765
766
767 Buffer.prototype.writeUInt16LE = function(value, offset, noAssert) {
768   value = +value;
769   offset = offset >>> 0;
770   if (!noAssert)
771     checkInt(this, value, offset, 2, 0xffff, 0);
772   this[offset] = value;
773   this[offset + 1] = (value >>> 8);
774   return offset + 2;
775 };
776
777
778 Buffer.prototype.writeUInt16BE = function(value, offset, noAssert) {
779   value = +value;
780   offset = offset >>> 0;
781   if (!noAssert)
782     checkInt(this, value, offset, 2, 0xffff, 0);
783   this[offset] = (value >>> 8);
784   this[offset + 1] = value;
785   return offset + 2;
786 };
787
788
789 Buffer.prototype.writeUInt32LE = function(value, offset, noAssert) {
790   value = +value;
791   offset = offset >>> 0;
792   if (!noAssert)
793     checkInt(this, value, offset, 4, 0xffffffff, 0);
794   this[offset + 3] = (value >>> 24);
795   this[offset + 2] = (value >>> 16);
796   this[offset + 1] = (value >>> 8);
797   this[offset] = value;
798   return offset + 4;
799 };
800
801
802 Buffer.prototype.writeUInt32BE = function(value, offset, noAssert) {
803   value = +value;
804   offset = offset >>> 0;
805   if (!noAssert)
806     checkInt(this, value, offset, 4, 0xffffffff, 0);
807   this[offset] = (value >>> 24);
808   this[offset + 1] = (value >>> 16);
809   this[offset + 2] = (value >>> 8);
810   this[offset + 3] = value;
811   return offset + 4;
812 };
813
814
815 Buffer.prototype.writeIntLE = function(value, offset, byteLength, noAssert) {
816   value = +value;
817   offset = offset >>> 0;
818   if (!noAssert) {
819     checkInt(this,
820              value,
821              offset,
822              byteLength,
823              Math.pow(2, 8 * byteLength - 1) - 1,
824              -Math.pow(2, 8 * byteLength - 1));
825   }
826
827   var i = 0;
828   var mul = 1;
829   var sub = value < 0 ? 1 : 0;
830   this[offset] = value;
831   while (++i < byteLength && (mul *= 0x100))
832     this[offset + i] = ((value / mul) >> 0) - sub;
833
834   return offset + byteLength;
835 };
836
837
838 Buffer.prototype.writeIntBE = function(value, offset, byteLength, noAssert) {
839   value = +value;
840   offset = offset >>> 0;
841   if (!noAssert) {
842     checkInt(this,
843              value,
844              offset,
845              byteLength,
846              Math.pow(2, 8 * byteLength - 1) - 1,
847              -Math.pow(2, 8 * byteLength - 1));
848   }
849
850   var i = byteLength - 1;
851   var mul = 1;
852   var sub = value < 0 ? 1 : 0;
853   this[offset + i] = value;
854   while (--i >= 0 && (mul *= 0x100))
855     this[offset + i] = ((value / mul) >> 0) - sub;
856
857   return offset + byteLength;
858 };
859
860
861 Buffer.prototype.writeInt8 = function(value, offset, noAssert) {
862   value = +value;
863   offset = offset >>> 0;
864   if (!noAssert)
865     checkInt(this, value, offset, 1, 0x7f, -0x80);
866   this[offset] = value;
867   return offset + 1;
868 };
869
870
871 Buffer.prototype.writeInt16LE = function(value, offset, noAssert) {
872   value = +value;
873   offset = offset >>> 0;
874   if (!noAssert)
875     checkInt(this, value, offset, 2, 0x7fff, -0x8000);
876   this[offset] = value;
877   this[offset + 1] = (value >>> 8);
878   return offset + 2;
879 };
880
881
882 Buffer.prototype.writeInt16BE = function(value, offset, noAssert) {
883   value = +value;
884   offset = offset >>> 0;
885   if (!noAssert)
886     checkInt(this, value, offset, 2, 0x7fff, -0x8000);
887   this[offset] = (value >>> 8);
888   this[offset + 1] = value;
889   return offset + 2;
890 };
891
892
893 Buffer.prototype.writeInt32LE = function(value, offset, noAssert) {
894   value = +value;
895   offset = offset >>> 0;
896   if (!noAssert)
897     checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000);
898   this[offset] = value;
899   this[offset + 1] = (value >>> 8);
900   this[offset + 2] = (value >>> 16);
901   this[offset + 3] = (value >>> 24);
902   return offset + 4;
903 };
904
905
906 Buffer.prototype.writeInt32BE = function(value, offset, noAssert) {
907   value = +value;
908   offset = offset >>> 0;
909   if (!noAssert)
910     checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000);
911   this[offset] = (value >>> 24);
912   this[offset + 1] = (value >>> 16);
913   this[offset + 2] = (value >>> 8);
914   this[offset + 3] = value;
915   return offset + 4;
916 };
917
918
919 function checkFloat(buffer, value, offset, ext) {
920   if (!(buffer instanceof Buffer))
921     throw new TypeError('buffer must be a Buffer instance');
922   if (offset + ext > buffer.length)
923     throw new RangeError('index out of range');
924 }
925
926
927 Buffer.prototype.writeFloatLE = function writeFloatLE(val, offset, noAssert) {
928   val = +val;
929   offset = offset >>> 0;
930   if (!noAssert)
931     checkFloat(this, val, offset, 4);
932   binding.writeFloatLE(this, val, offset);
933   return offset + 4;
934 };
935
936
937 Buffer.prototype.writeFloatBE = function writeFloatBE(val, offset, noAssert) {
938   val = +val;
939   offset = offset >>> 0;
940   if (!noAssert)
941     checkFloat(this, val, offset, 4);
942   binding.writeFloatBE(this, val, offset);
943   return offset + 4;
944 };
945
946
947 Buffer.prototype.writeDoubleLE = function writeDoubleLE(val, offset, noAssert) {
948   val = +val;
949   offset = offset >>> 0;
950   if (!noAssert)
951     checkFloat(this, val, offset, 8);
952   binding.writeDoubleLE(this, val, offset);
953   return offset + 8;
954 };
955
956
957 Buffer.prototype.writeDoubleBE = function writeDoubleBE(val, offset, noAssert) {
958   val = +val;
959   offset = offset >>> 0;
960   if (!noAssert)
961     checkFloat(this, val, offset, 8);
962   binding.writeDoubleBE(this, val, offset);
963   return offset + 8;
964 };
965
966 // ES6 iterator
967
968 var ITERATOR_KIND_KEYS = 1;
969 var ITERATOR_KIND_ENTRIES = 3;
970
971 function BufferIteratorResult(value, done) {
972   this.value = value;
973   this.done = done;
974 }
975
976 var resultCache = new Array(256);
977
978 for (var i = 0; i < 256; i++)
979   resultCache[i] = Object.freeze(new BufferIteratorResult(i, false));
980
981 var finalResult = Object.freeze(new BufferIteratorResult(undefined, true));
982
983 function BufferIterator(buffer, kind) {
984   this._buffer = buffer;
985   this._kind = kind;
986   this._index = 0;
987 }
988
989 BufferIterator.prototype.next = function() {
990   var buffer = this._buffer;
991   var kind = this._kind;
992   var index = this._index;
993
994   if (index >= buffer.length)
995     return finalResult;
996
997   this._index++;
998
999   if (kind === ITERATOR_KIND_ENTRIES)
1000     return new BufferIteratorResult([index, buffer[index]], false);
1001
1002   return new BufferIteratorResult(index, false);
1003 };
1004
1005 function BufferValueIterator(buffer) {
1006   BufferIterator.call(this, buffer, null);
1007 }
1008
1009 BufferValueIterator.prototype.next = function() {
1010   var buffer = this._buffer;
1011   var index = this._index;
1012
1013   if (index >= buffer.length)
1014     return finalResult;
1015
1016   this._index++;
1017
1018   return resultCache[buffer[index]];
1019 };
1020
1021
1022 BufferIterator.prototype[Symbol.iterator] = function() {
1023   return this;
1024 };
1025
1026 BufferValueIterator.prototype[Symbol.iterator] =
1027     BufferIterator.prototype[Symbol.iterator];
1028
1029 Buffer.prototype.keys = function() {
1030   return new BufferIterator(this, ITERATOR_KIND_KEYS);
1031 };
1032
1033 Buffer.prototype.entries = function() {
1034   return new BufferIterator(this, ITERATOR_KIND_ENTRIES);
1035 };
1036
1037 Buffer.prototype.values = function() {
1038   return new BufferValueIterator(this);
1039 };
1040
1041 Buffer.prototype[Symbol.iterator] = Buffer.prototype.values;