1 // Copyright Joyent, Inc. and other Node contributors.
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:
11 // The above copyright notice and this permission notice shall be included
12 // in all copies or substantial portions of the Software.
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.
22 var SlowBuffer = process.binding('buffer').SlowBuffer;
23 var assert = require('assert');
25 exports.INSPECT_MAX_BYTES = 50;
29 if (n < 16) return '0' + n.toString(16);
30 return n.toString(16);
34 SlowBuffer.prototype.inspect = function() {
37 for (var i = 0; i < len; i++) {
38 out[i] = toHex(this[i]);
39 if (i == exports.INSPECT_MAX_BYTES) {
44 return '<SlowBuffer ' + out.join(' ') + '>';
48 SlowBuffer.prototype.hexSlice = function(start, end) {
49 var len = this.length;
51 if (!start || start < 0) start = 0;
52 if (!end || end < 0 || end > len) end = len;
55 for (var i = start; i < end; i++) {
56 out += toHex(this[i]);
63 SlowBuffer.prototype.toString = function(encoding, start, end) {
64 encoding = String(encoding || 'utf8').toLowerCase();
66 if (typeof end == 'undefined') end = this.length;
68 // Fastpath empty strings
75 return this.hexSlice(start, end);
79 return this.utf8Slice(start, end);
82 return this.asciiSlice(start, end);
85 return this.binarySlice(start, end);
88 return this.base64Slice(start, end);
92 return this.ucs2Slice(start, end);
95 throw new Error('Unknown encoding');
100 SlowBuffer.prototype.hexWrite = function(string, offset, length) {
101 offset = +offset || 0;
102 var remaining = this.length - offset;
107 if (length > remaining) {
112 // must be an even number of digits
113 var strLen = string.length;
115 throw new Error('Invalid hex string');
117 if (length > strLen / 2) {
120 for (var i = 0; i < length; i++) {
121 var byte = parseInt(string.substr(i * 2, 2), 16);
122 if (isNaN(byte)) throw new Error('Invalid hex string');
123 this[offset + i] = byte;
129 SlowBuffer.prototype.write = function(string, offset, length, encoding) {
130 // Support both (string, offset, length, encoding)
131 // and the legacy (string, encoding, offset, length)
132 if (isFinite(offset)) {
133 if (!isFinite(length)) {
144 offset = +offset || 0;
145 var remaining = this.length - offset;
150 if (length > remaining) {
154 encoding = String(encoding || 'utf8').toLowerCase();
158 return this.hexWrite(string, offset, length);
162 return this.utf8Write(string, offset, length);
165 return this.asciiWrite(string, offset, length);
168 return this.binaryWrite(string, offset, length);
171 return this.base64Write(string, offset, length);
175 return this.ucs2Write(string, offset, length);
178 throw new Error('Unknown encoding');
184 SlowBuffer.prototype.slice = function(start, end) {
185 if (end === undefined) end = this.length;
187 if (end > this.length) {
188 throw new Error('oob');
191 throw new Error('oob');
194 return new Buffer(this, end - start, +start);
200 function Buffer(subject, encoding, offset) {
201 if (!(this instanceof Buffer)) {
202 return new Buffer(subject, encoding, offset);
208 if (typeof offset === 'number') {
209 this.length = encoding;
210 this.parent = subject;
211 this.offset = offset;
214 switch (type = typeof subject) {
216 this.length = subject;
220 this.length = Buffer.byteLength(subject, encoding);
223 case 'object': // Assume object is an array
224 this.length = subject.length;
228 throw new Error('First argument needs to be a number, ' +
232 if (this.length > Buffer.poolSize) {
233 // Big buffer, just alloc one.
234 this.parent = new SlowBuffer(this.length);
239 if (!pool || pool.length - pool.used < this.length) allocPool();
241 this.offset = pool.used;
242 pool.used += this.length;
245 // Treat array-ish objects as a byte array.
246 if (isArrayIsh(subject)) {
247 for (var i = 0; i < this.length; i++) {
248 this.parent[i + this.offset] = subject[i];
250 } else if (type == 'string') {
252 this.length = this.write(subject, 0, encoding);
256 SlowBuffer.makeFastBuffer(this.parent, this, this.offset, this.length);
259 function isArrayIsh(subject) {
260 return Array.isArray(subject) || Buffer.isBuffer(subject) ||
261 subject && typeof subject === 'object' &&
262 typeof subject.length === 'number';
265 exports.SlowBuffer = SlowBuffer;
266 exports.Buffer = Buffer;
268 Buffer.poolSize = 8 * 1024;
271 function allocPool() {
272 pool = new SlowBuffer(Buffer.poolSize);
278 Buffer.isBuffer = function isBuffer(b) {
279 return b instanceof Buffer || b instanceof SlowBuffer;
284 Buffer.prototype.inspect = function inspect() {
288 for (var i = 0; i < len; i++) {
289 out[i] = toHex(this.parent[i + this.offset]);
290 if (i == exports.INSPECT_MAX_BYTES) {
296 return '<Buffer ' + out.join(' ') + '>';
300 Buffer.prototype.get = function get(i) {
301 if (i < 0 || i >= this.length) throw new Error('oob');
302 return this.parent[this.offset + i];
306 Buffer.prototype.set = function set(i, v) {
307 if (i < 0 || i >= this.length) throw new Error('oob');
308 return this.parent[this.offset + i] = v;
312 // write(string, offset = 0, length = buffer.length-offset, encoding = 'utf8')
313 Buffer.prototype.write = function(string, offset, length, encoding) {
314 // Support both (string, offset, length, encoding)
315 // and the legacy (string, encoding, offset, length)
316 if (isFinite(offset)) {
317 if (!isFinite(length)) {
328 offset = +offset || 0;
329 var remaining = this.length - offset;
334 if (length > remaining) {
338 encoding = String(encoding || 'utf8').toLowerCase();
343 ret = this.parent.hexWrite(string, this.offset + offset, length);
348 ret = this.parent.utf8Write(string, this.offset + offset, length);
352 ret = this.parent.asciiWrite(string, this.offset + offset, length);
356 ret = this.parent.binaryWrite(string, this.offset + offset, length);
360 // Warning: maxLength not taken into account in base64Write
361 ret = this.parent.base64Write(string, this.offset + offset, length);
366 ret = this.parent.ucs2Write(string, this.offset + offset, length);
370 throw new Error('Unknown encoding');
373 Buffer._charsWritten = SlowBuffer._charsWritten;
379 // toString(encoding, start=0, end=buffer.length)
380 Buffer.prototype.toString = function(encoding, start, end) {
381 encoding = String(encoding || 'utf8').toLowerCase();
383 if (typeof start == 'undefined' || start < 0) {
385 } else if (start > this.length) {
389 if (typeof end == 'undefined' || end > this.length) {
391 } else if (end < 0) {
395 start = start + this.offset;
396 end = end + this.offset;
400 return this.parent.hexSlice(start, end);
404 return this.parent.utf8Slice(start, end);
407 return this.parent.asciiSlice(start, end);
410 return this.parent.binarySlice(start, end);
413 return this.parent.base64Slice(start, end);
417 return this.parent.ucs2Slice(start, end);
420 throw new Error('Unknown encoding');
426 Buffer.byteLength = SlowBuffer.byteLength;
429 // fill(value, start=0, end=buffer.length)
430 Buffer.prototype.fill = function fill(value, start, end) {
431 value || (value = 0);
432 start || (start = 0);
433 end || (end = this.length);
435 if (typeof value === 'string') {
436 value = value.charCodeAt(0);
438 if (!(typeof value === 'number') || isNaN(value)) {
439 throw new Error('value is not a number');
442 if (end < start) throw new Error('end < start');
444 // Fill 0 bytes; we're done
445 if (end === start) return 0;
446 if (this.length == 0) return 0;
448 if (start < 0 || start >= this.length) {
449 throw new Error('start out of bounds');
452 if (end < 0 || end > this.length) {
453 throw new Error('end out of bounds');
456 return this.parent.fill(value,
462 // copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)
463 Buffer.prototype.copy = function(target, target_start, start, end) {
465 start || (start = 0);
466 end || (end = this.length);
467 target_start || (target_start = 0);
469 if (end < start) throw new Error('sourceEnd < sourceStart');
471 // Copy 0 bytes; we're done
472 if (end === start) return 0;
473 if (target.length == 0 || source.length == 0) return 0;
475 if (target_start < 0 || target_start >= target.length) {
476 throw new Error('targetStart out of bounds');
479 if (start < 0 || start >= source.length) {
480 throw new Error('sourceStart out of bounds');
483 if (end < 0 || end > source.length) {
484 throw new Error('sourceEnd out of bounds');
488 if (end > this.length) {
492 if (target.length - target_start < end - start) {
493 end = target.length - target_start + start;
496 return this.parent.copy(target.parent,
497 target_start + target.offset,
504 Buffer.prototype.slice = function(start, end) {
505 if (end === undefined) end = this.length;
506 if (end > this.length) throw new Error('oob');
507 if (start > end) throw new Error('oob');
509 return new Buffer(this.parent, end - start, +start + this.offset);
513 // Legacy methods for backwards compatibility.
515 Buffer.prototype.utf8Slice = function(start, end) {
516 return this.toString('utf8', start, end);
519 Buffer.prototype.binarySlice = function(start, end) {
520 return this.toString('binary', start, end);
523 Buffer.prototype.asciiSlice = function(start, end) {
524 return this.toString('ascii', start, end);
527 Buffer.prototype.utf8Write = function(string, offset) {
528 return this.write(string, offset, 'utf8');
531 Buffer.prototype.binaryWrite = function(string, offset) {
532 return this.write(string, offset, 'binary');
535 Buffer.prototype.asciiWrite = function(string, offset) {
536 return this.write(string, offset, 'ascii');
539 Buffer.prototype.readUInt8NoChk = function(offset, bigEndian) {
541 return buffer[offset];
544 Buffer.prototype.readUInt8 = function(offset, bigEndian) {
547 assert.ok(offset !== undefined && offset !== null,
550 assert.ok(offset < buffer.length,
551 'Trying to read beyond buffer length');
553 return buffer.readUInt8NoChk(offset, bigEndian);
556 Buffer.prototype.readUInt16NoChk = function(offset, bigEndian) {
561 val = buffer[offset] << 8;
562 val |= buffer[offset + 1];
564 val = buffer[offset];
565 val |= buffer[offset + 1] << 8;
571 Buffer.prototype.readUInt16 = function(offset, bigEndian) {
574 assert.ok(typeof (bigEndian) === 'boolean',
575 'missing or invalid endian');
577 assert.ok(offset !== undefined && offset !== null,
580 assert.ok(offset + 1 < buffer.length,
581 'Trying to read beyond buffer length');
583 return buffer.readUInt16NoChk(offset, bigEndian);
586 Buffer.prototype.readUInt32NoChk = function(offset, bigEndian) {
591 val = buffer[offset + 1] << 16;
592 val |= buffer[offset + 2] << 8;
593 val |= buffer[offset + 3];
594 val = val + (buffer[offset] << 24 >>> 0);
596 val = buffer[offset + 2] << 16;
597 val |= buffer[offset + 1] << 8;
598 val |= buffer[offset];
599 val = val + (buffer[offset + 3] << 24 >>> 0);
605 Buffer.prototype.readUInt32 = function(offset, bigEndian) {
609 assert.ok(typeof (bigEndian) === 'boolean',
610 'missing or invalid endian');
612 assert.ok(offset !== undefined && offset !== null,
615 assert.ok(offset + 3 < buffer.length,
616 'Trying to read beyond buffer length');
618 return buffer.readUInt32NoChk(offset, bigEndian);
623 * Signed integer types, yay team! A reminder on how two's complement actually
624 * works. The first bit is the signed bit, i.e. tells us whether or not the
625 * number should be positive or negative. If the two's complement value is
626 * positive, then we're done, as it's equivalent to the unsigned representation.
628 * Now if the number is positive, you're pretty much done, you can just leverage
629 * the unsigned translations and return those. Unfortunately, negative numbers
630 * aren't quite that straightforward.
632 * At first glance, one might be inclined to use the traditional formula to
633 * translate binary numbers between the positive and negative values in two's
634 * complement. (Though it doesn't quite work for the most negative value)
636 * - invert all the bits
637 * - add one to the result
639 * Of course, this doesn't quite work in Javascript. Take for example the value
640 * of -128. This could be represented in 16 bits (big-endian) as 0xff80. But of
641 * course, Javascript will do the following:
646 * Whoh there, Javascript, that's not quite right. But wait, according to
647 * Javascript that's perfectly correct. When Javascript ends up seeing the
648 * constant 0xff80, it has no notion that it is actually a signed number. It
649 * assumes that we've input the unsigned value 0xff80. Thus, when it does the
650 * binary negation, it casts it into a signed value, (positive 0xff80). Then
651 * when you perform binary negation on that, it turns it into a negative number.
653 * Instead, we're going to have to use the following general formula, that works
654 * in a rather Javascript friendly way. I'm glad we don't support this kind of
655 * weird numbering scheme in the kernel.
657 * (BIT-MAX - (unsigned)val + 1) * -1
659 * The astute observer, may think that this doesn't make sense for 8-bit numbers
660 * (really it isn't necessary for them). However, when you get 16-bit numbers,
661 * you do. Let's go back to our prior example and see how this will look:
663 * (0xffff - 0xff80 + 1) * -1
667 Buffer.prototype.readInt8 = function(offset, bigEndian) {
671 assert.ok(offset !== undefined && offset !== null,
674 assert.ok(offset < buffer.length,
675 'Trying to read beyond buffer length');
677 neg = buffer[offset] & 0x80;
679 return (buffer[offset]);
682 return ((0xff - buffer[offset] + 1) * -1);
686 Buffer.prototype.readInt16 = function(offset, bigEndian) {
690 assert.ok(typeof (bigEndian) === 'boolean',
691 'missing or invalid endian');
693 assert.ok(offset !== undefined && offset !== null,
696 assert.ok(offset + 1 < buffer.length,
697 'Trying to read beyond buffer length');
699 val = buffer.readUInt16NoChk(offset, bigEndian);
705 return (0xffff - val + 1) * -1;
709 Buffer.prototype.readInt32 = function(offset, bigEndian) {
713 assert.ok(typeof (bigEndian) === 'boolean',
714 'missing or invalid endian');
716 assert.ok(offset !== undefined && offset !== null,
719 assert.ok(offset + 3 < buffer.length,
720 'Trying to read beyond buffer length');
722 val = buffer.readUInt32NoChk(offset, bigEndian);
723 neg = val & 0x80000000;
728 return (0xffffffff - val + 1) * -1;
732 Buffer.prototype.readFloat = function(offset, bigEndian) {
735 assert.ok(typeof (bigEndian) === 'boolean',
736 'missing or invalid endian');
738 assert.ok(offset + 3 < buffer.length,
739 'Trying to read beyond buffer length');
741 return require('buffer_ieee754').readIEEE754(buffer, offset, bigEndian,
745 Buffer.prototype.readDouble = function(offset, bigEndian) {
748 assert.ok(typeof (bigEndian) === 'boolean',
749 'missing or invalid endian');
751 assert.ok(offset + 7 < buffer.length,
752 'Trying to read beyond buffer length');
754 return require('buffer_ieee754').readIEEE754(buffer, offset, bigEndian,
760 * We have to make sure that the value is a valid integer. This means that it is
761 * non-negative. It has no fractional component and that it does not exceed the
762 * maximum allowed value.
764 * value The number to check for validity
766 * max The maximum value
768 function verifuint(value, max) {
769 assert.ok(typeof (value) == 'number',
770 'cannot write a non-number as a number');
772 assert.ok(value >= 0,
773 'specified a negative value for writing an unsigned value');
775 assert.ok(value <= max, 'value is larger than maximum value for type');
777 assert.ok(Math.floor(value) === value, 'value has a fractional component');
780 Buffer.prototype.writeUInt8NoChk = function(value, offset, bigEndian) {
782 buffer[offset] = value;
785 Buffer.prototype.writeUInt8 = function(value, offset, bigEndian) {
788 assert.ok(value !== undefined && value !== null,
791 assert.ok(typeof (bigEndian) === 'boolean',
792 'missing or invalid endian');
794 assert.ok(offset !== undefined && offset !== null,
797 assert.ok(offset < buffer.length,
798 'trying to write beyond buffer length');
800 verifuint(value, 0xff);
802 buffer.writeUInt8NoChk(value, offset, bigEndian);
805 Buffer.prototype.writeUInt16NoChk = function(value, offset, bigEndian) {
809 buffer[offset] = (value & 0xff00) >>> 8;
810 buffer[offset + 1] = value & 0x00ff;
812 buffer[offset + 1] = (value & 0xff00) >>> 8;
813 buffer[offset] = value & 0x00ff;
818 Buffer.prototype.writeUInt16 = function(value, offset, bigEndian) {
821 assert.ok(value !== undefined && value !== null,
824 assert.ok(typeof (bigEndian) === 'boolean',
825 'missing or invalid endian');
827 assert.ok(offset !== undefined && offset !== null,
830 assert.ok(offset + 1 < buffer.length,
831 'trying to write beyond buffer length');
833 verifuint(value, 0xffff);
835 buffer.writeUInt16NoChk(value, offset, bigEndian);
838 Buffer.prototype.writeUInt32NoChk = function(value, offset, bigEndian) {
842 buffer[offset] = (value >>> 24) & 0xff;
843 buffer[offset + 1] = (value >>> 16) & 0xff;
844 buffer[offset + 2] = (value >>> 8) & 0xff;
845 buffer[offset + 3] = value & 0xff;
847 buffer[offset + 3] = (value >>> 24) & 0xff;
848 buffer[offset + 2] = (value >>> 16) & 0xff;
849 buffer[offset + 1] = (value >>> 8) & 0xff;
850 buffer[offset] = value & 0xff;
854 Buffer.prototype.writeUInt32 = function(value, offset, bigEndian) {
857 assert.ok(value !== undefined && value !== null,
860 assert.ok(typeof (bigEndian) === 'boolean',
861 'missing or invalid endian');
863 assert.ok(offset !== undefined && offset !== null,
866 assert.ok(offset + 3 < buffer.length,
867 'trying to write beyond buffer length');
869 verifuint(value, 0xffffffff);
871 buffer.writeUInt32NoChk(value, offset, bigEndian);
876 * We now move onto our friends in the signed number category. Unlike unsigned
877 * numbers, we're going to have to worry a bit more about how we put values into
878 * arrays. Since we are only worrying about signed 32-bit values, we're in
879 * slightly better shape. Unfortunately, we really can't do our favorite binary
880 * & in this system. It really seems to do the wrong thing. For example:
885 * What's happening above is really: 0xe0 & 0xff = 0xe0. However, the results of
886 * this aren't treated as a signed number. Ultimately a bad thing.
888 * What we're going to want to do is basically create the unsigned equivalent of
889 * our representation and pass that off to the wuint* functions. To do that
890 * we're going to do the following:
892 * - if the value is positive
893 * we can pass it directly off to the equivalent wuint
894 * - if the value is negative
895 * we do the following computation:
896 * mb + val + 1, where
897 * mb is the maximum unsigned value in that byte size
898 * val is the Javascript negative integer
901 * As a concrete value, take -128. In signed 16 bits this would be 0xff80. If
902 * you do out the computations:
908 * You can then encode this value as the signed version. This is really rather
909 * hacky, but it should work and get the job done which is our goal here.
913 * A series of checks to make sure we actually have a signed 32-bit number
915 function verifsint(value, max, min) {
916 assert.ok(typeof (value) == 'number',
917 'cannot write a non-number as a number');
919 assert.ok(value <= max, 'value larger than maximum allowed value');
921 assert.ok(value >= min, 'value smaller than minimum allowed value');
923 assert.ok(Math.floor(value) === value, 'value has a fractional component');
927 function verifIEEE754(value, max, min) {
928 assert.ok(typeof (value) == 'number',
929 'cannot write a non-number as a number');
931 assert.ok(value <= max, 'value larger than maximum allowed value');
933 assert.ok(value >= min, 'value smaller than minimum allowed value');
937 Buffer.prototype.writeInt8 = function(value, offset, bigEndian) {
940 assert.ok(value !== undefined && value !== null,
943 assert.ok(typeof (bigEndian) === 'boolean',
944 'missing or invalid endian');
946 assert.ok(offset !== undefined && offset !== null,
949 assert.ok(offset < buffer.length,
950 'Trying to write beyond buffer length');
952 verifsint(value, 0x7f, -0xf0);
955 buffer.writeUInt8NoChk(value, offset, bigEndian);
957 buffer.writeUInt8NoChk(0xff + value + 1, offset, bigEndian);
962 Buffer.prototype.writeInt16 = function(value, offset, bigEndian) {
965 assert.ok(value !== undefined && value !== null,
968 assert.ok(typeof (bigEndian) === 'boolean',
969 'missing or invalid endian');
971 assert.ok(offset !== undefined && offset !== null,
974 assert.ok(offset + 1 < buffer.length,
975 'Trying to write beyond buffer length');
977 verifsint(value, 0x7fff, -0xf000);
980 buffer.writeUInt16NoChk(value, offset, bigEndian);
982 buffer.writeUInt16NoChk(0xffff + value + 1, offset, bigEndian);
987 Buffer.prototype.writeInt32 = function(value, offset, bigEndian) {
990 assert.ok(value !== undefined && value !== null,
993 assert.ok(typeof (bigEndian) === 'boolean',
994 'missing or invalid endian');
996 assert.ok(offset !== undefined && offset !== null,
999 assert.ok(offset + 3 < buffer.length,
1000 'Trying to write beyond buffer length');
1002 verifsint(value, 0x7fffffff, -0xf0000000);
1004 buffer.writeUInt32NoChk(value, offset, bigEndian);
1006 buffer.writeUInt32NoChk(0xffffffff + value + 1, offset, bigEndian);
1011 Buffer.prototype.writeFloat = function(value, offset, bigEndian) {
1014 assert.ok(value !== undefined && value !== null,
1017 assert.ok(typeof (bigEndian) === 'boolean',
1018 'missing or invalid endian');
1020 assert.ok(offset !== undefined && offset !== null,
1023 assert.ok(offset + 3 < buffer.length,
1024 'Trying to write beyond buffer length');
1026 verifIEEE754(value, 3.4028234663852886e+38, -3.4028234663852886e+38);
1027 require('buffer_ieee754').writeIEEE754(buffer, value, offset, bigEndian,
1032 Buffer.prototype.writeDouble = function(value, offset, bigEndian) {
1035 assert.ok(value !== undefined && value !== null,
1038 assert.ok(typeof (bigEndian) === 'boolean',
1039 'missing or invalid endian');
1041 assert.ok(offset !== undefined && offset !== null,
1044 assert.ok(offset + 7 < buffer.length,
1045 'Trying to write beyond buffer length');
1047 verifIEEE754(value, 1.7976931348623157E+308, -1.7976931348623157E+308);
1048 require('buffer_ieee754').writeIEEE754(buffer, value, offset, bigEndian,