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