bb3047579bbf1bdaa0c05e14093239dee7230c32
[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.fill = function fill(val, start, end) {
307   start = start >> 0;
308   end = (end === undefined) ? this.length : end >> 0;
309
310   if (start < 0 || end > this.length)
311     throw new RangeError('out of range index');
312   if (end <= start)
313     return this;
314
315   if (typeof val !== 'string') {
316     val = val >>> 0;
317   } else if (val.length === 1) {
318     var code = val.charCodeAt(0);
319     if (code < 256)
320       val = code;
321   }
322
323   binding.fill(this, val, start, end);
324
325   return this;
326 };
327
328
329 // XXX remove in v0.13
330 Buffer.prototype.get = util.deprecate(function get(offset) {
331   offset = ~~offset;
332   if (offset < 0 || offset >= this.length)
333     throw new RangeError('index out of range');
334   return this[offset];
335 }, '.get() is deprecated. Access using array indexes instead.');
336
337
338 // XXX remove in v0.13
339 Buffer.prototype.set = util.deprecate(function set(offset, v) {
340   offset = ~~offset;
341   if (offset < 0 || offset >= this.length)
342     throw new RangeError('index out of range');
343   return this[offset] = v;
344 }, '.set() is deprecated. Set using array indexes instead.');
345
346
347 // TODO(trevnorris): fix these checks to follow new standard
348 // write(string, offset = 0, length = buffer.length, encoding = 'utf8')
349 var writeWarned = false;
350 const writeMsg = '.write(string, encoding, offset, length) is deprecated.' +
351                  ' Use write(string[, offset[, length]][, encoding]) instead.';
352 Buffer.prototype.write = function(string, offset, length, encoding) {
353   // Buffer#write(string);
354   if (offset === undefined) {
355     encoding = 'utf8';
356     length = this.length;
357     offset = 0;
358
359   // Buffer#write(string, encoding)
360   } else if (length === undefined && typeof offset === 'string') {
361     encoding = offset;
362     length = this.length;
363     offset = 0;
364
365   // Buffer#write(string, offset[, length][, encoding])
366   } else if (isFinite(offset)) {
367     offset = offset >>> 0;
368     if (isFinite(length)) {
369       length = length >>> 0;
370       if (encoding === undefined)
371         encoding = 'utf8';
372     } else {
373       encoding = length;
374       length = undefined;
375     }
376
377   // XXX legacy write(string, encoding, offset, length) - remove in v0.13
378   } else {
379     if (!writeWarned) {
380       if (process.throwDeprecation)
381         throw new Error(writeMsg);
382       else if (process.traceDeprecation)
383         console.trace(writeMsg);
384       else
385         console.error(writeMsg);
386       writeWarned = true;
387     }
388
389     var swap = encoding;
390     encoding = offset;
391     offset = length >>> 0;
392     length = swap;
393   }
394
395   var remaining = this.length - offset;
396   if (length === undefined || length > remaining)
397     length = remaining;
398
399   encoding = !!encoding ? (encoding + '').toLowerCase() : 'utf8';
400
401   if (string.length > 0 && (length < 0 || offset < 0))
402     throw new RangeError('attempt to write outside buffer bounds');
403
404   var ret;
405   switch (encoding) {
406     case 'hex':
407       ret = this.hexWrite(string, offset, length);
408       break;
409
410     case 'utf8':
411     case 'utf-8':
412       ret = this.utf8Write(string, offset, length);
413       break;
414
415     case 'ascii':
416       ret = this.asciiWrite(string, offset, length);
417       break;
418
419     case 'binary':
420       ret = this.binaryWrite(string, offset, length);
421       break;
422
423     case 'base64':
424       // Warning: maxLength not taken into account in base64Write
425       ret = this.base64Write(string, offset, length);
426       break;
427
428     case 'ucs2':
429     case 'ucs-2':
430     case 'utf16le':
431     case 'utf-16le':
432       ret = this.ucs2Write(string, offset, length);
433       break;
434
435     default:
436       throw new TypeError('Unknown encoding: ' + encoding);
437   }
438
439   return ret;
440 };
441
442
443 Buffer.prototype.toJSON = function() {
444   return {
445     type: 'Buffer',
446     data: Array.prototype.slice.call(this, 0)
447   };
448 };
449
450
451 // TODO(trevnorris): currently works like Array.prototype.slice(), which
452 // doesn't follow the new standard for throwing on out of range indexes.
453 Buffer.prototype.slice = function(start, end) {
454   var len = this.length;
455   start = ~~start;
456   end = end === undefined ? len : ~~end;
457
458   if (start < 0) {
459     start += len;
460     if (start < 0)
461       start = 0;
462   } else if (start > len) {
463     start = len;
464   }
465
466   if (end < 0) {
467     end += len;
468     if (end < 0)
469       end = 0;
470   } else if (end > len) {
471     end = len;
472   }
473
474   if (end < start)
475     end = start;
476
477   var buf = new NativeBuffer();
478   sliceOnto(this, buf, start, end);
479   buf.length = end - start;
480   if (buf.length > 0)
481     buf.parent = this.parent === undefined ? this : this.parent;
482
483   return buf;
484 };
485
486
487 function checkOffset(offset, ext, length) {
488   if (offset + ext > length)
489     throw new RangeError('index out of range');
490 }
491
492
493 Buffer.prototype.readUIntLE = function(offset, byteLength, noAssert) {
494   offset = offset >>> 0;
495   byteLength = byteLength >>> 0;
496   if (!noAssert)
497     checkOffset(offset, byteLength, this.length);
498
499   var val = this[offset];
500   var mul = 1;
501   var i = 0;
502   while (++i < byteLength && (mul *= 0x100))
503     val += this[offset + i] * mul;
504
505   return val;
506 };
507
508
509 Buffer.prototype.readUIntBE = function(offset, byteLength, noAssert) {
510   offset = offset >>> 0;
511   byteLength = byteLength >>> 0;
512   if (!noAssert)
513     checkOffset(offset, byteLength, this.length);
514
515   var val = this[offset + --byteLength];
516   var mul = 1;
517   while (byteLength > 0 && (mul *= 0x100))
518     val += this[offset + --byteLength] * mul;
519
520   return val;
521 };
522
523
524 Buffer.prototype.readUInt8 = function(offset, noAssert) {
525   offset = offset >>> 0;
526   if (!noAssert)
527     checkOffset(offset, 1, this.length);
528   return this[offset];
529 };
530
531
532 Buffer.prototype.readUInt16LE = function(offset, noAssert) {
533   offset = offset >>> 0;
534   if (!noAssert)
535     checkOffset(offset, 2, this.length);
536   return this[offset] | (this[offset + 1] << 8);
537 };
538
539
540 Buffer.prototype.readUInt16BE = function(offset, noAssert) {
541   offset = offset >>> 0;
542   if (!noAssert)
543     checkOffset(offset, 2, this.length);
544   return (this[offset] << 8) | this[offset + 1];
545 };
546
547
548 Buffer.prototype.readUInt32LE = function(offset, noAssert) {
549   offset = offset >>> 0;
550   if (!noAssert)
551     checkOffset(offset, 4, this.length);
552
553   return ((this[offset]) |
554       (this[offset + 1] << 8) |
555       (this[offset + 2] << 16)) +
556       (this[offset + 3] * 0x1000000);
557 };
558
559
560 Buffer.prototype.readUInt32BE = function(offset, noAssert) {
561   offset = offset >>> 0;
562   if (!noAssert)
563     checkOffset(offset, 4, this.length);
564
565   return (this[offset] * 0x1000000) +
566       ((this[offset + 1] << 16) |
567       (this[offset + 2] << 8) |
568       this[offset + 3]);
569 };
570
571
572 Buffer.prototype.readIntLE = function(offset, byteLength, noAssert) {
573   offset = offset >>> 0;
574   byteLength = byteLength >>> 0;
575   if (!noAssert)
576     checkOffset(offset, byteLength, this.length);
577
578   var val = this[offset];
579   var mul = 1;
580   var i = 0;
581   while (++i < byteLength && (mul *= 0x100))
582     val += this[offset + i] * mul;
583   mul *= 0x80;
584
585   if (val >= mul)
586     val -= Math.pow(2, 8 * byteLength);
587
588   return val;
589 };
590
591
592 Buffer.prototype.readIntBE = function(offset, byteLength, noAssert) {
593   offset = offset >>> 0;
594   byteLength = byteLength >>> 0;
595   if (!noAssert)
596     checkOffset(offset, byteLength, this.length);
597
598   var i = byteLength;
599   var mul = 1;
600   var val = this[offset + --i];
601   while (i > 0 && (mul *= 0x100))
602     val += this[offset + --i] * mul;
603   mul *= 0x80;
604
605   if (val >= mul)
606     val -= Math.pow(2, 8 * byteLength);
607
608   return val;
609 };
610
611
612 Buffer.prototype.readInt8 = function(offset, noAssert) {
613   offset = offset >>> 0;
614   if (!noAssert)
615     checkOffset(offset, 1, this.length);
616   var val = this[offset];
617   return !(val & 0x80) ? val : (0xff - val + 1) * -1;
618 };
619
620
621 Buffer.prototype.readInt16LE = function(offset, noAssert) {
622   offset = offset >>> 0;
623   if (!noAssert)
624     checkOffset(offset, 2, this.length);
625   var val = this[offset] | (this[offset + 1] << 8);
626   return (val & 0x8000) ? val | 0xFFFF0000 : val;
627 };
628
629
630 Buffer.prototype.readInt16BE = function(offset, noAssert) {
631   offset = offset >>> 0;
632   if (!noAssert)
633     checkOffset(offset, 2, this.length);
634   var val = this[offset + 1] | (this[offset] << 8);
635   return (val & 0x8000) ? val | 0xFFFF0000 : val;
636 };
637
638
639 Buffer.prototype.readInt32LE = function(offset, noAssert) {
640   offset = offset >>> 0;
641   if (!noAssert)
642     checkOffset(offset, 4, this.length);
643
644   return (this[offset]) |
645       (this[offset + 1] << 8) |
646       (this[offset + 2] << 16) |
647       (this[offset + 3] << 24);
648 };
649
650
651 Buffer.prototype.readInt32BE = function(offset, noAssert) {
652   offset = offset >>> 0;
653   if (!noAssert)
654     checkOffset(offset, 4, this.length);
655
656   return (this[offset] << 24) |
657       (this[offset + 1] << 16) |
658       (this[offset + 2] << 8) |
659       (this[offset + 3]);
660 };
661
662
663 Buffer.prototype.readFloatLE = function readFloatLE(offset, noAssert) {
664   offset = offset >>> 0;
665   if (!noAssert)
666     checkOffset(offset, 4, this.length);
667   return binding.readFloatLE(this, offset);
668 };
669
670
671 Buffer.prototype.readFloatBE = function readFloatBE(offset, noAssert) {
672   offset = offset >>> 0;
673   if (!noAssert)
674     checkOffset(offset, 4, this.length);
675   return binding.readFloatBE(this, offset);
676 };
677
678
679 Buffer.prototype.readDoubleLE = function readDoubleLE(offset, noAssert) {
680   offset = offset >>> 0;
681   if (!noAssert)
682     checkOffset(offset, 8, this.length);
683   return binding.readDoubleLE(this, offset);
684 };
685
686
687 Buffer.prototype.readDoubleBE = function readDoubleBE(offset, noAssert) {
688   offset = offset >>> 0;
689   if (!noAssert)
690     checkOffset(offset, 8, this.length);
691   return binding.readDoubleBE(this, offset);
692 };
693
694
695 function checkInt(buffer, value, offset, ext, max, min) {
696   if (!(buffer instanceof Buffer))
697     throw new TypeError('buffer must be a Buffer instance');
698   if (value > max || value < min)
699     throw new TypeError('value is out of bounds');
700   if (offset + ext > buffer.length)
701     throw new RangeError('index out of range');
702 }
703
704
705 Buffer.prototype.writeUIntLE = function(value, offset, byteLength, noAssert) {
706   value = +value;
707   offset = offset >>> 0;
708   byteLength = byteLength >>> 0;
709   if (!noAssert)
710     checkInt(this, value, offset, byteLength, Math.pow(2, 8 * byteLength), 0);
711
712   var mul = 1;
713   var i = 0;
714   this[offset] = value;
715   while (++i < byteLength && (mul *= 0x100))
716     this[offset + i] = (value / mul) >>> 0;
717
718   return offset + byteLength;
719 };
720
721
722 Buffer.prototype.writeUIntBE = function(value, offset, byteLength, noAssert) {
723   value = +value;
724   offset = offset >>> 0;
725   byteLength = byteLength >>> 0;
726   if (!noAssert)
727     checkInt(this, value, offset, byteLength, Math.pow(2, 8 * byteLength), 0);
728
729   var i = byteLength - 1;
730   var mul = 1;
731   this[offset + i] = value;
732   while (--i >= 0 && (mul *= 0x100))
733     this[offset + i] = (value / mul) >>> 0;
734
735   return offset + byteLength;
736 };
737
738
739 Buffer.prototype.writeUInt8 = function(value, offset, noAssert) {
740   value = +value;
741   offset = offset >>> 0;
742   if (!noAssert)
743     checkInt(this, value, offset, 1, 0xff, 0);
744   this[offset] = value;
745   return offset + 1;
746 };
747
748
749 Buffer.prototype.writeUInt16LE = function(value, offset, noAssert) {
750   value = +value;
751   offset = offset >>> 0;
752   if (!noAssert)
753     checkInt(this, value, offset, 2, 0xffff, 0);
754   this[offset] = value;
755   this[offset + 1] = (value >>> 8);
756   return offset + 2;
757 };
758
759
760 Buffer.prototype.writeUInt16BE = function(value, offset, noAssert) {
761   value = +value;
762   offset = offset >>> 0;
763   if (!noAssert)
764     checkInt(this, value, offset, 2, 0xffff, 0);
765   this[offset] = (value >>> 8);
766   this[offset + 1] = value;
767   return offset + 2;
768 };
769
770
771 Buffer.prototype.writeUInt32LE = function(value, offset, noAssert) {
772   value = +value;
773   offset = offset >>> 0;
774   if (!noAssert)
775     checkInt(this, value, offset, 4, 0xffffffff, 0);
776   this[offset + 3] = (value >>> 24);
777   this[offset + 2] = (value >>> 16);
778   this[offset + 1] = (value >>> 8);
779   this[offset] = value;
780   return offset + 4;
781 };
782
783
784 Buffer.prototype.writeUInt32BE = function(value, offset, noAssert) {
785   value = +value;
786   offset = offset >>> 0;
787   if (!noAssert)
788     checkInt(this, value, offset, 4, 0xffffffff, 0);
789   this[offset] = (value >>> 24);
790   this[offset + 1] = (value >>> 16);
791   this[offset + 2] = (value >>> 8);
792   this[offset + 3] = value;
793   return offset + 4;
794 };
795
796
797 Buffer.prototype.writeIntLE = function(value, offset, byteLength, noAssert) {
798   value = +value;
799   offset = offset >>> 0;
800   if (!noAssert) {
801     checkInt(this,
802              value,
803              offset,
804              byteLength,
805              Math.pow(2, 8 * byteLength - 1) - 1,
806              -Math.pow(2, 8 * byteLength - 1));
807   }
808
809   var i = 0;
810   var mul = 1;
811   var sub = value < 0 ? 1 : 0;
812   this[offset] = value;
813   while (++i < byteLength && (mul *= 0x100))
814     this[offset + i] = ((value / mul) >> 0) - sub;
815
816   return offset + byteLength;
817 };
818
819
820 Buffer.prototype.writeIntBE = function(value, offset, byteLength, noAssert) {
821   value = +value;
822   offset = offset >>> 0;
823   if (!noAssert) {
824     checkInt(this,
825              value,
826              offset,
827              byteLength,
828              Math.pow(2, 8 * byteLength - 1) - 1,
829              -Math.pow(2, 8 * byteLength - 1));
830   }
831
832   var i = byteLength - 1;
833   var mul = 1;
834   var sub = value < 0 ? 1 : 0;
835   this[offset + i] = value;
836   while (--i >= 0 && (mul *= 0x100))
837     this[offset + i] = ((value / mul) >> 0) - sub;
838
839   return offset + byteLength;
840 };
841
842
843 Buffer.prototype.writeInt8 = function(value, offset, noAssert) {
844   value = +value;
845   offset = offset >>> 0;
846   if (!noAssert)
847     checkInt(this, value, offset, 1, 0x7f, -0x80);
848   this[offset] = value;
849   return offset + 1;
850 };
851
852
853 Buffer.prototype.writeInt16LE = function(value, offset, noAssert) {
854   value = +value;
855   offset = offset >>> 0;
856   if (!noAssert)
857     checkInt(this, value, offset, 2, 0x7fff, -0x8000);
858   this[offset] = value;
859   this[offset + 1] = (value >>> 8);
860   return offset + 2;
861 };
862
863
864 Buffer.prototype.writeInt16BE = function(value, offset, noAssert) {
865   value = +value;
866   offset = offset >>> 0;
867   if (!noAssert)
868     checkInt(this, value, offset, 2, 0x7fff, -0x8000);
869   this[offset] = (value >>> 8);
870   this[offset + 1] = value;
871   return offset + 2;
872 };
873
874
875 Buffer.prototype.writeInt32LE = function(value, offset, noAssert) {
876   value = +value;
877   offset = offset >>> 0;
878   if (!noAssert)
879     checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000);
880   this[offset] = value;
881   this[offset + 1] = (value >>> 8);
882   this[offset + 2] = (value >>> 16);
883   this[offset + 3] = (value >>> 24);
884   return offset + 4;
885 };
886
887
888 Buffer.prototype.writeInt32BE = function(value, offset, noAssert) {
889   value = +value;
890   offset = offset >>> 0;
891   if (!noAssert)
892     checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000);
893   this[offset] = (value >>> 24);
894   this[offset + 1] = (value >>> 16);
895   this[offset + 2] = (value >>> 8);
896   this[offset + 3] = value;
897   return offset + 4;
898 };
899
900
901 function checkFloat(buffer, value, offset, ext) {
902   if (!(buffer instanceof Buffer))
903     throw new TypeError('buffer must be a Buffer instance');
904   if (offset + ext > buffer.length)
905     throw new RangeError('index out of range');
906 }
907
908
909 Buffer.prototype.writeFloatLE = function writeFloatLE(val, offset, noAssert) {
910   val = +val;
911   offset = offset >>> 0;
912   if (!noAssert)
913     checkFloat(this, val, offset, 4);
914   binding.writeFloatLE(this, val, offset);
915   return offset + 4;
916 };
917
918
919 Buffer.prototype.writeFloatBE = function writeFloatBE(val, offset, noAssert) {
920   val = +val;
921   offset = offset >>> 0;
922   if (!noAssert)
923     checkFloat(this, val, offset, 4);
924   binding.writeFloatBE(this, val, offset);
925   return offset + 4;
926 };
927
928
929 Buffer.prototype.writeDoubleLE = function writeDoubleLE(val, offset, noAssert) {
930   val = +val;
931   offset = offset >>> 0;
932   if (!noAssert)
933     checkFloat(this, val, offset, 8);
934   binding.writeDoubleLE(this, val, offset);
935   return offset + 8;
936 };
937
938
939 Buffer.prototype.writeDoubleBE = function writeDoubleBE(val, offset, noAssert) {
940   val = +val;
941   offset = offset >>> 0;
942   if (!noAssert)
943     checkFloat(this, val, offset, 8);
944   binding.writeDoubleBE(this, val, offset);
945   return offset + 8;
946 };
947
948 // ES6 iterator
949
950 var ITERATOR_KIND_KEYS = 1;
951 var ITERATOR_KIND_ENTRIES = 3;
952
953 function BufferIteratorResult(value, done) {
954   this.value = value;
955   this.done = done;
956 }
957
958 var resultCache = new Array(256);
959
960 for (var i = 0; i < 256; i++)
961   resultCache[i] = Object.freeze(new BufferIteratorResult(i, false));
962
963 var finalResult = Object.freeze(new BufferIteratorResult(undefined, true));
964
965 function BufferIterator(buffer, kind) {
966   this._buffer = buffer;
967   this._kind = kind;
968   this._index = 0;
969 }
970
971 BufferIterator.prototype.next = function() {
972   var buffer = this._buffer;
973   var kind = this._kind;
974   var index = this._index;
975
976   if (index >= buffer.length)
977     return finalResult;
978
979   this._index++;
980
981   if (kind === ITERATOR_KIND_ENTRIES)
982     return new BufferIteratorResult([index, buffer[index]], false);
983
984   return new BufferIteratorResult(index, false);
985 };
986
987 function BufferValueIterator(buffer) {
988   BufferIterator.call(this, buffer, null);
989 }
990
991 BufferValueIterator.prototype.next = function() {
992   var buffer = this._buffer;
993   var index = this._index;
994
995   if (index >= buffer.length)
996     return finalResult;
997
998   this._index++;
999
1000   return resultCache[buffer[index]];
1001 };
1002
1003
1004 BufferIterator.prototype[Symbol.iterator] = function() {
1005   return this;
1006 };
1007
1008 BufferValueIterator.prototype[Symbol.iterator] =
1009     BufferIterator.prototype[Symbol.iterator];
1010
1011 Buffer.prototype.keys = function() {
1012   return new BufferIterator(this, ITERATOR_KIND_KEYS);
1013 };
1014
1015 Buffer.prototype.entries = function() {
1016   return new BufferIterator(this, ITERATOR_KIND_ENTRIES);
1017 };
1018
1019 Buffer.prototype.values = function() {
1020   return new BufferValueIterator(this);
1021 };
1022
1023 Buffer.prototype[Symbol.iterator] = Buffer.prototype.values;