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