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 IEEE754 = require('buffer_ieee754');
24 var assert = require('assert');
28 if (n < 16) return '0' + n.toString(16);
29 return n.toString(16);
33 SlowBuffer.prototype.inspect = function() {
36 for (var i = 0; i < len; i++) {
37 out[i] = toHex(this[i]);
39 return '<SlowBuffer ' + out.join(' ') + '>';
43 SlowBuffer.prototype.hexSlice = function(start, end) {
44 var len = this.length;
46 if (!start || start < 0) start = 0;
47 if (!end || end < 0 || end > len) end = len;
50 for (var i = start; i < end; i++) {
51 out += toHex(this[i]);
58 SlowBuffer.prototype.toString = function(encoding, start, end) {
59 encoding = String(encoding || 'utf8').toLowerCase();
61 if (typeof end == 'undefined') end = this.length;
63 // Fastpath empty strings
70 return this.hexSlice(start, end);
74 return this.utf8Slice(start, end);
77 return this.asciiSlice(start, end);
80 return this.binarySlice(start, end);
83 return this.base64Slice(start, end);
87 return this.ucs2Slice(start, end);
90 throw new Error('Unknown encoding');
95 SlowBuffer.prototype.hexWrite = function(string, offset) {
96 var len = string.length;
97 offset = +offset || 0;
99 // must be an even number of digits
101 throw new Error('Invalid hex string');
103 for (var i = 0; i < len / 2; i++) {
104 var byte = parseInt(string.substr(i * 2, 2), 16);
105 if (isNaN(byte)) throw new Error('Invalid hex string');
106 this[offset + i] = byte;
112 SlowBuffer.prototype.write = function(string, offset, encoding) {
113 // Support both (string, offset, encoding)
114 // and the legacy (string, encoding, offset)
115 if (!isFinite(offset)) {
121 offset = +offset || 0;
122 encoding = String(encoding || 'utf8').toLowerCase();
126 return this.hexWrite(string, offset);
130 return this.utf8Write(string, offset);
133 return this.asciiWrite(string, offset);
136 return this.binaryWrite(string, offset);
139 return this.base64Write(string, offset);
143 return this.ucs2Write(string, offset);
146 throw new Error('Unknown encoding');
152 SlowBuffer.prototype.slice = function(start, end) {
153 if (end === undefined) end = this.length;
155 if (end > this.length) {
156 throw new Error('oob');
159 throw new Error('oob');
162 return new Buffer(this, end - start, +start);
168 function Buffer(subject, encoding, offset) {
169 if (!(this instanceof Buffer)) {
170 return new Buffer(subject, encoding, offset);
176 if (typeof offset === 'number') {
177 this.length = encoding;
178 this.parent = subject;
179 this.offset = offset;
182 switch (type = typeof subject) {
184 this.length = subject;
188 this.length = Buffer.byteLength(subject, encoding);
191 case 'object': // Assume object is an array
192 this.length = subject.length;
196 throw new Error('First argument needs to be a number, ' +
200 if (this.length > Buffer.poolSize) {
201 // Big buffer, just alloc one.
202 this.parent = new SlowBuffer(this.length);
207 if (!pool || pool.length - pool.used < this.length) allocPool();
209 this.offset = pool.used;
210 pool.used += this.length;
213 // Treat array-ish objects as a byte array.
214 if (isArrayIsh(subject)) {
215 for (var i = 0; i < this.length; i++) {
216 this.parent[i + this.offset] = subject[i];
218 } else if (type == 'string') {
220 this.length = this.write(subject, 0, encoding);
224 SlowBuffer.makeFastBuffer(this.parent, this, this.offset, this.length);
227 function isArrayIsh(subject) {
228 return Array.isArray(subject) || Buffer.isBuffer(subject) ||
229 subject && typeof subject === 'object' &&
230 typeof subject.length === 'number';
233 exports.SlowBuffer = SlowBuffer;
234 exports.Buffer = Buffer;
236 Buffer.poolSize = 8 * 1024;
239 function allocPool() {
240 pool = new SlowBuffer(Buffer.poolSize);
246 Buffer.isBuffer = function isBuffer(b) {
247 return b instanceof Buffer || b instanceof SlowBuffer;
252 Buffer.prototype.inspect = function inspect() {
255 for (var i = 0; i < len; i++) {
256 out[i] = toHex(this.parent[i + this.offset]);
258 return '<Buffer ' + out.join(' ') + '>';
262 Buffer.prototype.get = function get(i) {
263 if (i < 0 || i >= this.length) throw new Error('oob');
264 return this.parent[this.offset + i];
268 Buffer.prototype.set = function set(i, v) {
269 if (i < 0 || i >= this.length) throw new Error('oob');
270 return this.parent[this.offset + i] = v;
274 // write(string, offset = 0, encoding = 'utf8')
275 Buffer.prototype.write = function(string, offset, encoding) {
276 if (!isFinite(offset)) {
282 offset = +offset || 0;
283 encoding = String(encoding || 'utf8').toLowerCase();
285 // Make sure we are not going to overflow
286 var maxLength = this.length - offset;
291 ret = this.parent.hexWrite(string, this.offset + offset, maxLength);
296 ret = this.parent.utf8Write(string, this.offset + offset, maxLength);
300 ret = this.parent.asciiWrite(string, this.offset + offset, maxLength);
304 ret = this.parent.binaryWrite(string, this.offset + offset, maxLength);
308 // Warning: maxLength not taken into account in base64Write
309 ret = this.parent.base64Write(string, this.offset + offset, maxLength);
314 ret = this.parent.ucs2Write(string, this.offset + offset, maxLength);
318 throw new Error('Unknown encoding');
321 Buffer._charsWritten = SlowBuffer._charsWritten;
327 // toString(encoding, start=0, end=buffer.length)
328 Buffer.prototype.toString = function(encoding, start, end) {
329 encoding = String(encoding || 'utf8').toLowerCase();
331 if (typeof start == 'undefined' || start < 0) {
333 } else if (start > this.length) {
337 if (typeof end == 'undefined' || end > this.length) {
339 } else if (end < 0) {
343 start = start + this.offset;
344 end = end + this.offset;
348 return this.parent.hexSlice(start, end);
352 return this.parent.utf8Slice(start, end);
355 return this.parent.asciiSlice(start, end);
358 return this.parent.binarySlice(start, end);
361 return this.parent.base64Slice(start, end);
365 return this.parent.ucs2Slice(start, end);
368 throw new Error('Unknown encoding');
374 Buffer.byteLength = SlowBuffer.byteLength;
377 // fill(value, start=0, end=buffer.length)
378 Buffer.prototype.fill = function fill (value, start, end) {
379 value || (value = 0);
380 start || (start = 0);
381 end || (end = this.length);
383 if (typeof value === "string") {
384 value = value.charCodeAt(0);
386 if (!(typeof value === "number") || isNaN(value)) {
387 throw new Error("value is not a number");
390 if (end < start) throw new Error("end < start");
392 // Fill 0 bytes; we're done
393 if (end === start) return 0;
394 if (this.length == 0) return 0;
396 if (start < 0 || start >= this.length) {
397 throw new Error("start out of bounds");
400 if (end < 0 || end > this.length) {
401 throw new Error("end out of bounds");
404 return this.parent.fill(value,
410 // copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)
411 Buffer.prototype.copy = function(target, target_start, start, end) {
413 start || (start = 0);
414 end || (end = this.length);
415 target_start || (target_start = 0);
417 if (end < start) throw new Error('sourceEnd < sourceStart');
419 // Copy 0 bytes; we're done
420 if (end === start) return 0;
421 if (target.length == 0 || source.length == 0) return 0;
423 if (target_start < 0 || target_start >= target.length) {
424 throw new Error('targetStart out of bounds');
427 if (start < 0 || start >= source.length) {
428 throw new Error('sourceStart out of bounds');
431 if (end < 0 || end > source.length) {
432 throw new Error('sourceEnd out of bounds');
436 if (end > this.length) {
440 if (target.length - target_start < end - start) {
441 end = target.length - target_start + start;
444 return this.parent.copy(target.parent,
445 target_start + target.offset,
452 Buffer.prototype.slice = function(start, end) {
453 if (end === undefined) end = this.length;
454 if (end > this.length) throw new Error('oob');
455 if (start > end) throw new Error('oob');
457 return new Buffer(this.parent, end - start, +start + this.offset);
461 // Legacy methods for backwards compatibility.
463 Buffer.prototype.utf8Slice = function(start, end) {
464 return this.toString('utf8', start, end);
467 Buffer.prototype.binarySlice = function(start, end) {
468 return this.toString('binary', start, end);
471 Buffer.prototype.asciiSlice = function(start, end) {
472 return this.toString('ascii', start, end);
475 Buffer.prototype.utf8Write = function(string, offset) {
476 return this.write(string, offset, 'utf8');
479 Buffer.prototype.binaryWrite = function(string, offset) {
480 return this.write(string, offset, 'binary');
483 Buffer.prototype.asciiWrite = function(string, offset) {
484 return this.write(string, offset, 'ascii');
487 Buffer.prototype.readUInt8 = function(offset, endian) {
490 assert.ok(endian !== undefined && endian !== null,
493 assert.ok(endian == 'big' || endian == 'little',
496 assert.ok(offset !== undefined && offset !== null,
499 assert.ok(offset < buffer.length,
500 'Trying to read beyond buffer length');
502 return buffer[offset];
506 Buffer.prototype.readUInt16 = function(offset, endian) {
510 assert.ok(endian !== undefined && endian !== null,
513 assert.ok(endian == 'big' || endian == 'little',
516 assert.ok(offset !== undefined && offset !== null,
519 assert.ok(offset + 1 < buffer.length,
520 'Trying to read beyond buffer length');
522 if (endian == 'big') {
523 val = buffer[offset] << 8;
524 val |= buffer[offset + 1];
526 val = buffer[offset];
527 val |= buffer[offset + 1] << 8;
534 Buffer.prototype.readUInt32 = function(offset, endian) {
538 assert.ok(endian !== undefined && endian !== null,
541 assert.ok(endian == 'big' || endian == 'little',
544 assert.ok(offset !== undefined && offset !== null,
547 assert.ok(offset + 3 < buffer.length,
548 'Trying to read beyond buffer length');
550 if (endian == 'big') {
551 val = buffer[offset + 1] << 16;
552 val |= buffer[offset + 2] << 8;
553 val |= buffer[offset + 3];
554 val = val + (buffer[offset] << 24 >>> 0);
556 val = buffer[offset + 2] << 16;
557 val |= buffer[offset + 1] << 8;
558 val |= buffer[offset];
559 val = val + (buffer[offset + 3] << 24 >>> 0);
567 * Signed integer types, yay team! A reminder on how two's complement actually
568 * works. The first bit is the signed bit, i.e. tells us whether or not the
569 * number should be positive or negative. If the two's complement value is
570 * positive, then we're done, as it's equivalent to the unsigned representation.
572 * Now if the number is positive, you're pretty much done, you can just leverage
573 * the unsigned translations and return those. Unfortunately, negative numbers
574 * aren't quite that straightforward.
576 * At first glance, one might be inclined to use the traditional formula to
577 * translate binary numbers between the positive and negative values in two's
578 * complement. (Though it doesn't quite work for the most negative value)
580 * - invert all the bits
581 * - add one to the result
583 * Of course, this doesn't quite work in Javascript. Take for example the value
584 * of -128. This could be represented in 16 bits (big-endian) as 0xff80. But of
585 * course, Javascript will do the following:
590 * Whoh there, Javascript, that's not quite right. But wait, according to
591 * Javascript that's perfectly correct. When Javascript ends up seeing the
592 * constant 0xff80, it has no notion that it is actually a signed number. It
593 * assumes that we've input the unsigned value 0xff80. Thus, when it does the
594 * binary negation, it casts it into a signed value, (positive 0xff80). Then
595 * when you perform binary negation on that, it turns it into a negative number.
597 * Instead, we're going to have to use the following general formula, that works
598 * in a rather Javascript friendly way. I'm glad we don't support this kind of
599 * weird numbering scheme in the kernel.
601 * (BIT-MAX - (unsigned)val + 1) * -1
603 * The astute observer, may think that this doesn't make sense for 8-bit numbers
604 * (really it isn't necessary for them). However, when you get 16-bit numbers,
605 * you do. Let's go back to our prior example and see how this will look:
607 * (0xffff - 0xff80 + 1) * -1
611 Buffer.prototype.readInt8 = function(offset, endian) {
615 assert.ok(endian !== undefined && endian !== null,
618 assert.ok(endian == 'big' || endian == 'little',
621 assert.ok(offset !== undefined && offset !== null,
624 assert.ok(offset < buffer.length,
625 'Trying to read beyond buffer length');
627 neg = buffer[offset] & 0x80;
629 return (buffer[offset]);
632 return ((0xff - buffer[offset] + 1) * -1);
636 Buffer.prototype.readInt16 = function(offset, endian) {
640 assert.ok(endian !== undefined && endian !== null,
643 assert.ok(endian == 'big' || endian == 'little',
646 assert.ok(offset !== undefined && offset !== null,
649 assert.ok(offset + 1 < buffer.length,
650 'Trying to read beyond buffer length');
652 val = buffer.readUInt16(offset, endian);
658 return (0xffff - val + 1) * -1;
662 Buffer.prototype.readInt32 = function(offset, endian) {
666 assert.ok(endian !== undefined && endian !== null,
669 assert.ok(endian == 'big' || endian == 'little',
672 assert.ok(offset !== undefined && offset !== null,
675 assert.ok(offset + 3 < buffer.length,
676 'Trying to read beyond buffer length');
678 val = buffer.readUInt32(offset, endian);
679 neg = val & 0x80000000;
684 return (0xffffffff - val + 1) * -1;
688 Buffer.prototype.readFloat = function(offset, endian) {
691 assert.ok(endian !== undefined && endian !== null,
694 assert.ok(endian == 'big' || endian == 'little',
697 assert.ok(offset !== undefined && offset !== null,
700 assert.ok(offset + 3 < buffer.length,
701 'Trying to read beyond buffer length');
703 return IEEE754.readIEEE754(buffer, offset, endian, 23, 4);
706 Buffer.prototype.readDouble = function(offset, endian) {
709 assert.ok(endian !== undefined && endian !== null,
712 assert.ok(endian == 'big' || endian == 'little',
715 assert.ok(offset !== undefined && offset !== null,
718 assert.ok(offset + 7 < buffer.length,
719 'Trying to read beyond buffer length');
721 return IEEE754.readIEEE754(buffer, offset, endian, 52, 8);
726 * We have to make sure that the value is a valid integer. This means that it is
727 * non-negative. It has no fractional component and that it does not exceed the
728 * maximum allowed value.
730 * value The number to check for validity
732 * max The maximum value
734 function verifuint(value, max) {
735 assert.ok(typeof (value) == 'number',
736 'cannot write a non-number as a number');
738 assert.ok(value >= 0,
739 'specified a negative value for writing an unsigned value');
741 assert.ok(value <= max, 'value is larger than maximum value for type');
743 assert.ok(Math.floor(value) === value, 'value has a fractional component');
747 Buffer.prototype.writeUInt8 = function(value, offset, endian) {
750 assert.ok(value !== undefined && value !== null,
753 assert.ok(endian !== undefined && endian !== null,
756 assert.ok(endian == 'big' || endian == 'little',
759 assert.ok(offset !== undefined && offset !== null,
762 assert.ok(offset < buffer.length,
763 'trying to read beyond buffer length');
765 verifuint(value, 0xff);
766 buffer[offset] = value;
770 Buffer.prototype.writeUInt16 = function(value, offset, endian) {
773 assert.ok(value !== undefined && value !== null,
776 assert.ok(endian !== undefined && endian !== null,
779 assert.ok(endian == 'big' || endian == 'little',
782 assert.ok(offset !== undefined && offset !== null,
785 assert.ok(offset + 1 < buffer.length,
786 'trying to read beyond buffer length');
788 verifuint(value, 0xffff);
790 if (endian == 'big') {
791 buffer[offset] = (value & 0xff00) >>> 8;
792 buffer[offset + 1] = value & 0x00ff;
794 buffer[offset + 1] = (value & 0xff00) >>> 8;
795 buffer[offset] = value & 0x00ff;
800 Buffer.prototype.writeUInt32 = function(value, offset, endian) {
803 assert.ok(value !== undefined && value !== null,
806 assert.ok(endian !== undefined && endian !== null,
809 assert.ok(endian == 'big' || endian == 'little',
812 assert.ok(offset !== undefined && offset !== null,
815 assert.ok(offset + 3 < buffer.length,
816 'trying to read beyond buffer length');
818 verifuint(value, 0xffffffff);
819 if (endian == 'big') {
820 buffer[offset] = (value >>> 24) & 0xff;
821 buffer[offset + 1] = (value >>> 16) & 0xff;
822 buffer[offset + 2] = (value >>> 8) & 0xff;
823 buffer[offset + 3] = value & 0xff;
825 buffer[offset + 3] = (value >>> 24) & 0xff;
826 buffer[offset + 2] = (value >>> 16) & 0xff;
827 buffer[offset + 1] = (value >>> 8) & 0xff;
828 buffer[offset] = value & 0xff;
834 * We now move onto our friends in the signed number category. Unlike unsigned
835 * numbers, we're going to have to worry a bit more about how we put values into
836 * arrays. Since we are only worrying about signed 32-bit values, we're in
837 * slightly better shape. Unfortunately, we really can't do our favorite binary
838 * & in this system. It really seems to do the wrong thing. For example:
843 * What's happening above is really: 0xe0 & 0xff = 0xe0. However, the results of
844 * this aren't treated as a signed number. Ultimately a bad thing.
846 * What we're going to want to do is basically create the unsigned equivalent of
847 * our representation and pass that off to the wuint* functions. To do that
848 * we're going to do the following:
850 * - if the value is positive
851 * we can pass it directly off to the equivalent wuint
852 * - if the value is negative
853 * we do the following computation:
854 * mb + val + 1, where
855 * mb is the maximum unsigned value in that byte size
856 * val is the Javascript negative integer
859 * As a concrete value, take -128. In signed 16 bits this would be 0xff80. If
860 * you do out the computations:
866 * You can then encode this value as the signed version. This is really rather
867 * hacky, but it should work and get the job done which is our goal here.
871 * A series of checks to make sure we actually have a signed 32-bit number
873 function verifsint(value, max, min) {
874 assert.ok(typeof (value) == 'number',
875 'cannot write a non-number as a number');
877 assert.ok(value <= max, 'value larger than maximum allowed value');
879 assert.ok(value >= min, 'value smaller than minimum allowed value');
881 assert.ok(Math.floor(value) === value, 'value has a fractional component');
885 function verifIEEE754(value, max, min) {
886 assert.ok(typeof (value) == 'number',
887 'cannot write a non-number as a number');
889 assert.ok(value <= max, 'value larger than maximum allowed value');
891 assert.ok(value >= min, 'value smaller than minimum allowed value');
895 Buffer.prototype.writeInt8 = function(value, offset, endian) {
898 assert.ok(value !== undefined && value !== null,
901 assert.ok(endian !== undefined && endian !== null,
904 assert.ok(endian == 'big' || endian == 'little',
907 assert.ok(offset !== undefined && offset !== null,
910 assert.ok(offset < buffer.length,
911 'Trying to read beyond buffer length');
913 verifsint(value, 0x7f, -0xf0);
916 buffer.writeUInt8(value, offset, endian);
918 buffer.writeUInt8(0xff + value + 1, offset, endian);
923 Buffer.prototype.writeInt16 = function(value, offset, endian) {
926 assert.ok(value !== undefined && value !== null,
929 assert.ok(endian !== undefined && endian !== null,
932 assert.ok(endian == 'big' || endian == 'little',
935 assert.ok(offset !== undefined && offset !== null,
938 assert.ok(offset + 1 < buffer.length,
939 'Trying to read beyond buffer length');
941 verifsint(value, 0x7fff, -0xf000);
944 buffer.writeUInt16(value, offset, endian);
946 buffer.writeUInt16(0xffff + value + 1, offset, endian);
951 Buffer.prototype.writeInt32 = function(value, offset, endian) {
954 assert.ok(value !== undefined && value !== null,
957 assert.ok(endian !== undefined && endian !== null,
960 assert.ok(endian == 'big' || endian == 'little',
963 assert.ok(offset !== undefined && offset !== null,
966 assert.ok(offset + 3 < buffer.length,
967 'Trying to read beyond buffer length');
969 verifsint(value, 0x7fffffff, -0xf0000000);
971 buffer.writeUInt32(value, offset, endian);
973 buffer.writeUInt32(0xffffffff + value + 1, offset, endian);
978 Buffer.prototype.writeFloat = function(value, offset, endian) {
981 assert.ok(value !== undefined && value !== null,
984 assert.ok(endian !== undefined && endian !== null,
987 assert.ok(endian == 'big' || endian == 'little',
990 assert.ok(offset !== undefined && offset !== null,
993 assert.ok(offset + 3 < buffer.length,
994 'Trying to read beyond buffer length');
996 verifIEEE754(value, 3.4028234663852886e+38, -3.4028234663852886e+38);
997 IEEE754.writeIEEE754(buffer, value, offset, endian, 23, 4);
1001 Buffer.prototype.writeDouble = function(value, offset, endian) {
1004 assert.ok(value !== undefined && value !== null,
1007 assert.ok(endian !== undefined && endian !== null,
1010 assert.ok(endian == 'big' || endian == 'little',
1011 'bad endian value');
1013 assert.ok(offset !== undefined && offset !== null,
1016 assert.ok(offset + 7 < buffer.length,
1017 'Trying to read beyond buffer length');
1019 verifIEEE754(value, 1.7976931348623157E+308, -1.7976931348623157E+308);
1020 IEEE754.writeIEEE754(buffer, value, offset, endian, 52, 8);