3 var buffer = process.binding('buffer');
4 var smalloc = process.binding('smalloc');
5 var util = require('util');
6 var alloc = smalloc.alloc;
7 var truncate = smalloc.truncate;
8 var sliceOnto = smalloc.sliceOnto;
9 var kMaxLength = smalloc.kMaxLength;
12 exports.Buffer = Buffer;
13 exports.SlowBuffer = SlowBuffer;
14 exports.INSPECT_MAX_BYTES = 50;
17 Buffer.poolSize = 8 * 1024;
18 var poolSize, poolOffset, allocPool;
21 function createPool() {
22 poolSize = Buffer.poolSize;
23 allocPool = alloc({}, poolSize);
29 function Buffer(subject, encoding) {
30 if (!util.isBuffer(this))
31 return new Buffer(subject, encoding);
33 if (util.isNumber(subject)) {
34 this.length = subject > 0 ? subject >>> 0 : 0;
36 } else if (util.isString(subject)) {
37 if (!util.isString(encoding) || encoding.length === 0)
39 this.length = Buffer.byteLength(subject, encoding);
41 // Handle Arrays, Buffers, Uint8Arrays or JSON.
42 } else if (util.isObject(subject)) {
43 if (subject.type === 'Buffer' && util.isArray(subject.data))
44 subject = subject.data;
45 // Must use floor() because array length may be > kMaxLength.
46 this.length = +subject.length > 0 ? Math.floor(+subject.length) : 0;
49 throw new TypeError('must start with number, buffer, array or string');
52 if (this.length > kMaxLength) {
53 throw new RangeError('Attempt to allocate Buffer larger than maximum ' +
54 'size: 0x' + kMaxLength.toString(16) + ' bytes');
57 this.parent = undefined;
58 if (this.length <= (Buffer.poolSize >>> 1) && this.length > 0) {
59 if (this.length > poolSize - poolOffset)
61 this.parent = sliceOnto(allocPool,
64 poolOffset + this.length);
65 poolOffset += this.length;
67 alloc(this, this.length);
70 if (util.isNumber(subject)) {
74 if (util.isString(subject)) {
75 // In the case of base64 it's possible that the size of the buffer
76 // allocated was slightly too large. In this case we need to rewrite
77 // the length to the actual length written.
78 var len = this.write(subject, encoding);
79 // Buffer was truncated after decode, realloc internal ExternalArray
80 if (len !== this.length) {
81 var prevLen = this.length;
83 truncate(this, this.length);
84 poolOffset -= (prevLen - len);
87 } else if (util.isBuffer(subject)) {
88 subject.copy(this, 0, 0, this.length);
90 } else if (util.isNumber(subject.length) || util.isArray(subject)) {
91 // Really crappy way to handle Uint8Arrays, but V8 doesn't give a simple
92 // way to access the data from the C++ API.
93 for (var i = 0; i < this.length; i++)
99 function SlowBuffer(length) {
100 length = length >>> 0;
101 if (length > kMaxLength) {
102 throw new RangeError('Attempt to allocate Buffer larger than maximum ' +
103 'size: 0x' + kMaxLength.toString(16) + ' bytes');
105 var b = new NativeBuffer(length);
111 // Bypass all checks for instantiating unallocated Buffer required for
112 // Objects created in C++. Significantly faster than calling the Buffer
114 function NativeBuffer(length) {
115 this.length = length >>> 0;
116 // Set this to keep the object map the same.
117 this.parent = undefined;
119 NativeBuffer.prototype = Buffer.prototype;
122 // add methods to Buffer prototype
123 buffer.setupBufferJS(NativeBuffer, internal);
128 Buffer.isBuffer = function isBuffer(b) {
129 return util.isBuffer(b);
133 Buffer.compare = function compare(a, b) {
134 if (!(a instanceof Buffer) ||
135 !(b instanceof Buffer))
136 throw new TypeError('Arguments must be Buffers');
138 return internal.compare(a, b);
142 Buffer.isEncoding = function(encoding) {
143 switch ((encoding + '').toLowerCase()) {
163 Buffer.concat = function(list, length) {
164 if (!util.isArray(list))
165 throw new TypeError('Usage: Buffer.concat(list[, length])');
167 if (util.isUndefined(length)) {
169 for (var i = 0; i < list.length; i++)
170 length += list[i].length;
172 length = length >>> 0;
175 if (list.length === 0)
176 return new Buffer(0);
177 else if (list.length === 1)
180 var buffer = new Buffer(length);
182 for (var i = 0; i < list.length; i++) {
184 buf.copy(buffer, pos);
192 Buffer.byteLength = function(str, enc) {
205 ret = str.length * 2;
208 ret = str.length >>> 1;
211 ret = internal.byteLength(str, enc);
217 // toString(encoding, start=0, end=buffer.length)
218 Buffer.prototype.toString = function(encoding, start, end) {
219 var loweredCase = false;
222 end = util.isUndefined(end) || end === Infinity ? this.length : end >>> 0;
224 if (!encoding) encoding = 'utf8';
225 if (start < 0) start = 0;
226 if (end > this.length) end = this.length;
227 if (end <= start) return '';
232 return this.hexSlice(start, end);
236 return this.utf8Slice(start, end);
239 return this.asciiSlice(start, end);
242 return this.binarySlice(start, end);
245 return this.base64Slice(start, end);
251 return this.ucs2Slice(start, end);
255 throw new TypeError('Unknown encoding: ' + encoding);
256 encoding = (encoding + '').toLowerCase();
263 Buffer.prototype.equals = function equals(b) {
264 if (!(b instanceof Buffer))
265 throw new TypeError('Argument must be a Buffer');
267 return internal.compare(this, b) === 0;
272 Buffer.prototype.inspect = function inspect() {
274 var max = exports.INSPECT_MAX_BYTES;
275 if (this.length > 0) {
276 str = this.toString('hex', 0, max).match(/.{2}/g).join(' ');
277 if (this.length > max)
280 return '<' + this.constructor.name + ' ' + str + '>';
284 Buffer.prototype.compare = function compare(b) {
285 if (!(b instanceof Buffer))
286 throw new TypeError('Argument must be a Buffer');
288 return internal.compare(this, b);
292 Buffer.prototype.fill = function fill(val, start, end) {
294 end = (end === undefined) ? this.length : end >> 0;
296 if (start < 0 || end > this.length)
297 throw new RangeError('out of range index');
301 if (typeof val !== 'string') {
303 } else if (val.length === 1) {
304 var code = val.charCodeAt(0);
309 internal.fill(this, val, start, end);
315 // XXX remove in v0.13
316 Buffer.prototype.get = util.deprecate(function get(offset) {
318 if (offset < 0 || offset >= this.length)
319 throw new RangeError('index out of range');
321 }, '.get() is deprecated. Access using array indexes instead.');
324 // XXX remove in v0.13
325 Buffer.prototype.set = util.deprecate(function set(offset, v) {
327 if (offset < 0 || offset >= this.length)
328 throw new RangeError('index out of range');
329 return this[offset] = v;
330 }, '.set() is deprecated. Set using array indexes instead.');
333 // TODO(trevnorris): fix these checks to follow new standard
334 // write(string, offset = 0, length = buffer.length, encoding = 'utf8')
335 var writeWarned = false;
336 var writeMsg = '.write(string, encoding, offset, length) is deprecated.' +
337 ' Use write(string[, offset[, length]][, encoding]) instead.';
338 Buffer.prototype.write = function(string, offset, length, encoding) {
339 // Buffer#write(string);
340 if (util.isUndefined(offset)) {
342 length = this.length;
345 // Buffer#write(string, encoding)
346 } else if (util.isUndefined(length) && util.isString(offset)) {
348 length = this.length;
351 // Buffer#write(string, offset[, length][, encoding])
352 } else if (isFinite(offset)) {
353 offset = offset >>> 0;
354 if (isFinite(length)) {
355 length = length >>> 0;
356 if (util.isUndefined(encoding))
363 // XXX legacy write(string, encoding, offset, length) - remove in v0.13
366 if (process.throwDeprecation)
367 throw new Error(writeMsg);
368 else if (process.traceDeprecation)
369 console.trace(writeMsg);
371 console.error(writeMsg);
377 offset = length >>> 0;
381 var remaining = this.length - offset;
382 if (util.isUndefined(length) || length > remaining)
385 encoding = !!encoding ? (encoding + '').toLowerCase() : 'utf8';
387 if (string.length > 0 && (length < 0 || offset < 0))
388 throw new RangeError('attempt to write outside buffer bounds');
393 ret = this.hexWrite(string, offset, length);
398 ret = this.utf8Write(string, offset, length);
402 ret = this.asciiWrite(string, offset, length);
406 ret = this.binaryWrite(string, offset, length);
410 // Warning: maxLength not taken into account in base64Write
411 ret = this.base64Write(string, offset, length);
418 ret = this.ucs2Write(string, offset, length);
422 throw new TypeError('Unknown encoding: ' + encoding);
429 Buffer.prototype.toJSON = function() {
432 data: Array.prototype.slice.call(this, 0)
437 // TODO(trevnorris): currently works like Array.prototype.slice(), which
438 // doesn't follow the new standard for throwing on out of range indexes.
439 Buffer.prototype.slice = function(start, end) {
440 var len = this.length;
442 end = util.isUndefined(end) ? len : ~~end;
448 } else if (start > len) {
456 } else if (end > len) {
463 var buf = new NativeBuffer();
464 sliceOnto(this, buf, start, end);
465 buf.length = end - start;
467 buf.parent = util.isUndefined(this.parent) ? this : this.parent;
473 function checkOffset(offset, ext, length) {
474 if (offset + ext > length)
475 throw new RangeError('index out of range');
479 Buffer.prototype.readUIntLE = function(offset, byteLength, noAssert) {
480 offset = offset >>> 0;
481 byteLength = byteLength >>> 0;
483 checkOffset(offset, byteLength, this.length);
485 var val = this[offset];
488 while (++i < byteLength && (mul *= 0x100))
489 val += this[offset + i] * mul;
495 Buffer.prototype.readUIntBE = function(offset, byteLength, noAssert) {
496 offset = offset >>> 0;
497 byteLength = byteLength >>> 0;
499 checkOffset(offset, byteLength, this.length);
501 var val = this[offset + --byteLength];
503 while (byteLength > 0 && (mul *= 0x100))
504 val += this[offset + --byteLength] * mul;
510 Buffer.prototype.readUInt8 = function(offset, noAssert) {
511 offset = offset >>> 0;
513 checkOffset(offset, 1, this.length);
518 Buffer.prototype.readUInt16LE = function(offset, noAssert) {
519 offset = offset >>> 0;
521 checkOffset(offset, 2, this.length);
522 return this[offset] | (this[offset + 1] << 8);
526 Buffer.prototype.readUInt16BE = function(offset, noAssert) {
527 offset = offset >>> 0;
529 checkOffset(offset, 2, this.length);
530 return (this[offset] << 8) | this[offset + 1];
534 Buffer.prototype.readUInt32LE = function(offset, noAssert) {
535 offset = offset >>> 0;
537 checkOffset(offset, 4, this.length);
539 return ((this[offset]) |
540 (this[offset + 1] << 8) |
541 (this[offset + 2] << 16)) +
542 (this[offset + 3] * 0x1000000);
546 Buffer.prototype.readUInt32BE = function(offset, noAssert) {
547 offset = offset >>> 0;
549 checkOffset(offset, 4, this.length);
551 return (this[offset] * 0x1000000) +
552 ((this[offset + 1] << 16) |
553 (this[offset + 2] << 8) |
558 Buffer.prototype.readIntLE = function(offset, byteLength, noAssert) {
559 offset = offset >>> 0;
560 byteLength = byteLength >>> 0;
562 checkOffset(offset, byteLength, this.length);
564 var val = this[offset];
567 while (++i < byteLength && (mul *= 0x100))
568 val += this[offset + i] * mul;
572 val -= Math.pow(2, 8 * byteLength);
578 Buffer.prototype.readIntBE = function(offset, byteLength, noAssert) {
579 offset = offset >>> 0;
580 byteLength = byteLength >>> 0;
582 checkOffset(offset, byteLength, this.length);
586 var val = this[offset + --i];
587 while (i > 0 && (mul *= 0x100))
588 val += this[offset + --i] * mul;
592 val -= Math.pow(2, 8 * byteLength);
598 Buffer.prototype.readInt8 = function(offset, noAssert) {
599 offset = offset >>> 0;
601 checkOffset(offset, 1, this.length);
602 var val = this[offset];
603 return !(val & 0x80) ? val : (0xff - val + 1) * -1;
607 Buffer.prototype.readInt16LE = function(offset, noAssert) {
608 offset = offset >>> 0;
610 checkOffset(offset, 2, this.length);
611 var val = this[offset] | (this[offset + 1] << 8);
612 return (val & 0x8000) ? val | 0xFFFF0000 : val;
616 Buffer.prototype.readInt16BE = function(offset, noAssert) {
617 offset = offset >>> 0;
619 checkOffset(offset, 2, this.length);
620 var val = this[offset + 1] | (this[offset] << 8);
621 return (val & 0x8000) ? val | 0xFFFF0000 : val;
625 Buffer.prototype.readInt32LE = function(offset, noAssert) {
626 offset = offset >>> 0;
628 checkOffset(offset, 4, this.length);
630 return (this[offset]) |
631 (this[offset + 1] << 8) |
632 (this[offset + 2] << 16) |
633 (this[offset + 3] << 24);
637 Buffer.prototype.readInt32BE = function(offset, noAssert) {
638 offset = offset >>> 0;
640 checkOffset(offset, 4, this.length);
642 return (this[offset] << 24) |
643 (this[offset + 1] << 16) |
644 (this[offset + 2] << 8) |
649 Buffer.prototype.readFloatLE = function readFloatLE(offset, noAssert) {
650 offset = offset >>> 0;
652 checkOffset(offset, 4, this.length);
653 return internal.readFloatLE(this, offset);
657 Buffer.prototype.readFloatBE = function readFloatBE(offset, noAssert) {
658 offset = offset >>> 0;
660 checkOffset(offset, 4, this.length);
661 return internal.readFloatBE(this, offset);
665 Buffer.prototype.readDoubleLE = function readDoubleLE(offset, noAssert) {
666 offset = offset >>> 0;
668 checkOffset(offset, 8, this.length);
669 return internal.readDoubleLE(this, offset);
673 Buffer.prototype.readDoubleBE = function readDoubleBE(offset, noAssert) {
674 offset = offset >>> 0;
676 checkOffset(offset, 8, this.length);
677 return internal.readDoubleBE(this, offset);
681 function checkInt(buffer, value, offset, ext, max, min) {
682 if (!(buffer instanceof Buffer))
683 throw new TypeError('buffer must be a Buffer instance');
684 if (value > max || value < min)
685 throw new TypeError('value is out of bounds');
686 if (offset + ext > buffer.length)
687 throw new RangeError('index out of range');
691 Buffer.prototype.writeUIntLE = function(value, offset, byteLength, noAssert) {
693 offset = offset >>> 0;
694 byteLength = byteLength >>> 0;
696 checkInt(this, value, offset, byteLength, Math.pow(2, 8 * byteLength), 0);
700 this[offset] = value;
701 while (++i < byteLength && (mul *= 0x100))
702 this[offset + i] = (value / mul) >>> 0;
704 return offset + byteLength;
708 Buffer.prototype.writeUIntBE = function(value, offset, byteLength, noAssert) {
710 offset = offset >>> 0;
711 byteLength = byteLength >>> 0;
713 checkInt(this, value, offset, byteLength, Math.pow(2, 8 * byteLength), 0);
715 var i = byteLength - 1;
717 this[offset + i] = value;
718 while (--i >= 0 && (mul *= 0x100))
719 this[offset + i] = (value / mul) >>> 0;
721 return offset + byteLength;
725 Buffer.prototype.writeUInt8 = function(value, offset, noAssert) {
727 offset = offset >>> 0;
729 checkInt(this, value, offset, 1, 0xff, 0);
730 this[offset] = value;
735 Buffer.prototype.writeUInt16LE = function(value, offset, noAssert) {
737 offset = offset >>> 0;
739 checkInt(this, value, offset, 2, 0xffff, 0);
740 this[offset] = value;
741 this[offset + 1] = (value >>> 8);
746 Buffer.prototype.writeUInt16BE = function(value, offset, noAssert) {
748 offset = offset >>> 0;
750 checkInt(this, value, offset, 2, 0xffff, 0);
751 this[offset] = (value >>> 8);
752 this[offset + 1] = value;
757 Buffer.prototype.writeUInt32LE = function(value, offset, noAssert) {
759 offset = offset >>> 0;
761 checkInt(this, value, offset, 4, 0xffffffff, 0);
762 this[offset + 3] = (value >>> 24);
763 this[offset + 2] = (value >>> 16);
764 this[offset + 1] = (value >>> 8);
765 this[offset] = value;
770 Buffer.prototype.writeUInt32BE = function(value, offset, noAssert) {
772 offset = offset >>> 0;
774 checkInt(this, value, offset, 4, 0xffffffff, 0);
775 this[offset] = (value >>> 24);
776 this[offset + 1] = (value >>> 16);
777 this[offset + 2] = (value >>> 8);
778 this[offset + 3] = value;
783 Buffer.prototype.writeIntLE = function(value, offset, byteLength, noAssert) {
785 offset = offset >>> 0;
791 Math.pow(2, 8 * byteLength - 1) - 1,
792 -Math.pow(2, 8 * byteLength - 1));
797 var sub = value < 0 ? 1 : 0;
798 this[offset] = value;
799 while (++i < byteLength && (mul *= 0x100))
800 this[offset + i] = ((value / mul) >> 0) - sub;
802 return offset + byteLength;
806 Buffer.prototype.writeIntBE = function(value, offset, byteLength, noAssert) {
808 offset = offset >>> 0;
814 Math.pow(2, 8 * byteLength - 1) - 1,
815 -Math.pow(2, 8 * byteLength - 1));
818 var i = byteLength - 1;
820 var sub = value < 0 ? 1 : 0;
821 this[offset + i] = value;
822 while (--i >= 0 && (mul *= 0x100))
823 this[offset + i] = ((value / mul) >> 0) - sub;
825 return offset + byteLength;
829 Buffer.prototype.writeInt8 = function(value, offset, noAssert) {
831 offset = offset >>> 0;
833 checkInt(this, value, offset, 1, 0x7f, -0x80);
834 this[offset] = value;
839 Buffer.prototype.writeInt16LE = function(value, offset, noAssert) {
841 offset = offset >>> 0;
843 checkInt(this, value, offset, 2, 0x7fff, -0x8000);
844 this[offset] = value;
845 this[offset + 1] = (value >>> 8);
850 Buffer.prototype.writeInt16BE = function(value, offset, noAssert) {
852 offset = offset >>> 0;
854 checkInt(this, value, offset, 2, 0x7fff, -0x8000);
855 this[offset] = (value >>> 8);
856 this[offset + 1] = value;
861 Buffer.prototype.writeInt32LE = function(value, offset, noAssert) {
863 offset = offset >>> 0;
865 checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000);
866 this[offset] = value;
867 this[offset + 1] = (value >>> 8);
868 this[offset + 2] = (value >>> 16);
869 this[offset + 3] = (value >>> 24);
874 Buffer.prototype.writeInt32BE = function(value, offset, noAssert) {
876 offset = offset >>> 0;
878 checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000);
879 this[offset] = (value >>> 24);
880 this[offset + 1] = (value >>> 16);
881 this[offset + 2] = (value >>> 8);
882 this[offset + 3] = value;
887 function checkFloat(buffer, value, offset, ext) {
888 if (!(buffer instanceof Buffer))
889 throw new TypeError('buffer must be a Buffer instance');
890 if (offset + ext > buffer.length)
891 throw new RangeError('index out of range');
895 Buffer.prototype.writeFloatLE = function writeFloatLE(val, offset, noAssert) {
897 offset = offset >>> 0;
899 checkFloat(this, val, offset, 4);
900 internal.writeFloatLE(this, val, offset);
905 Buffer.prototype.writeFloatBE = function writeFloatBE(val, offset, noAssert) {
907 offset = offset >>> 0;
909 checkFloat(this, val, offset, 4);
910 internal.writeFloatBE(this, val, offset);
915 Buffer.prototype.writeDoubleLE = function writeDoubleLE(val, offset, noAssert) {
917 offset = offset >>> 0;
919 checkFloat(this, val, offset, 8);
920 internal.writeDoubleLE(this, val, offset);
925 Buffer.prototype.writeDoubleBE = function writeDoubleBE(val, offset, noAssert) {
927 offset = offset >>> 0;
929 checkFloat(this, val, offset, 8);
930 internal.writeDoubleBE(this, val, offset);