forked from browserify/browserify
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- 1.15.3
- 1.15.2
- 1.15.1
- 1.15.0
- 1.14.5
- 1.14.4
- 1.14.3
- 1.14.2
- 1.14.1
- 1.14.0
- 1.13.10
- 1.13.9
- 1.13.8
- 1.13.7
- 1.13.6
- 1.13.5
- 1.13.4
- 1.13.3
- 1.13.2
- 1.13.1
- 1.13.0
- 1.12.3
- 1.12.2
- 1.12.1
- 1.12.0
- 1.11.2
- 1.11.1
- 1.11.0
- 1.10.17
- 1.10.16
- 1.10.15
- 1.10.14
- 1.10.13
- 1.10.12
- 1.10.11
- 1.10.10
- 1.10.9
- 1.10.8
- 1.10.7
- 1.10.6
- 1.10.5
- 1.10.4
- 1.10.4.a
- 1.10.3
- 1.10.2
- 1.10.1
- 1.10.0
James Halliday
committed
Feb 27, 2012
1 parent
4015be2
commit 4b9c1db
Showing
3 changed files
with
1,076 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,951 @@ | ||
var assert = require('assert'); | ||
|
||
exports.INSPECT_MAX_BYTES = 50; | ||
|
||
|
||
function toHex(n) { | ||
if (n < 16) return '0' + n.toString(16); | ||
return n.toString(16); | ||
} | ||
|
||
// Buffer | ||
|
||
function Buffer(subject, encoding, offset) { | ||
if (!(this instanceof Buffer)) { | ||
return new Buffer(subject, encoding, offset); | ||
} | ||
|
||
var type; | ||
|
||
// Are we slicing? | ||
if (typeof offset === 'number') { | ||
this.length = coerce(encoding); | ||
this.parent = subject; | ||
this.offset = offset; | ||
} else { | ||
// Find the length | ||
switch (type = typeof subject) { | ||
case 'number': | ||
this.length = coerce(subject); | ||
break; | ||
|
||
case 'string': | ||
this.length = Buffer.byteLength(subject, encoding); | ||
break; | ||
|
||
case 'object': // Assume object is an array | ||
this.length = coerce(subject.length); | ||
break; | ||
|
||
default: | ||
throw new Error('First argument needs to be a number, ' + | ||
'array or string.'); | ||
} | ||
|
||
if (this.length > Buffer.poolSize) { | ||
// Big buffer, just alloc one. | ||
this.parent = new SlowBuffer(this.length); | ||
this.offset = 0; | ||
|
||
} else { | ||
// Small buffer. | ||
if (!pool || pool.length - pool.used < this.length) allocPool(); | ||
this.parent = pool; | ||
this.offset = pool.used; | ||
pool.used += this.length; | ||
} | ||
|
||
// Treat array-ish objects as a byte array. | ||
if (isArrayIsh(subject)) { | ||
for (var i = 0; i < this.length; i++) { | ||
this.parent[i + this.offset] = subject[i]; | ||
} | ||
} else if (type == 'string') { | ||
// We are a string | ||
this.length = this.write(subject, 0, encoding); | ||
} | ||
} | ||
} | ||
|
||
function isArrayIsh(subject) { | ||
return Array.isArray(subject) || Buffer.isBuffer(subject) || | ||
subject && typeof subject === 'object' && | ||
typeof subject.length === 'number'; | ||
} | ||
|
||
Buffer.Buffer = Buffer; | ||
module.exports = Buffer; | ||
|
||
Buffer.poolSize = 8 * 1024; | ||
var pool; | ||
|
||
function allocPool() { | ||
pool = new SlowBuffer(Buffer.poolSize); | ||
pool.used = 0; | ||
} | ||
|
||
|
||
// Static methods | ||
Buffer.isBuffer = function isBuffer(b) { | ||
return b instanceof Buffer || b instanceof SlowBuffer; | ||
}; | ||
|
||
|
||
// Inspect | ||
Buffer.prototype.inspect = function inspect() { | ||
var out = [], | ||
len = this.length; | ||
|
||
for (var i = 0; i < len; i++) { | ||
out[i] = toHex(this.parent[i + this.offset]); | ||
if (i == exports.INSPECT_MAX_BYTES) { | ||
out[i + 1] = '...'; | ||
break; | ||
} | ||
} | ||
|
||
return '<Buffer ' + out.join(' ') + '>'; | ||
}; | ||
|
||
|
||
Buffer.prototype.get = function get(i) { | ||
if (i < 0 || i >= this.length) throw new Error('oob'); | ||
return this.parent[this.offset + i]; | ||
}; | ||
|
||
|
||
Buffer.prototype.set = function set(i, v) { | ||
if (i < 0 || i >= this.length) throw new Error('oob'); | ||
return this.parent[this.offset + i] = v; | ||
}; | ||
|
||
|
||
// write(string, offset = 0, length = buffer.length-offset, encoding = 'utf8') | ||
Buffer.prototype.write = function(string, offset, length, encoding) { | ||
// Support both (string, offset, length, encoding) | ||
// and the legacy (string, encoding, offset, length) | ||
if (isFinite(offset)) { | ||
if (!isFinite(length)) { | ||
encoding = length; | ||
length = undefined; | ||
} | ||
} else { // legacy | ||
var swap = encoding; | ||
encoding = offset; | ||
offset = length; | ||
length = swap; | ||
} | ||
|
||
offset = +offset || 0; | ||
var remaining = this.length - offset; | ||
if (!length) { | ||
length = remaining; | ||
} else { | ||
length = +length; | ||
if (length > remaining) { | ||
length = remaining; | ||
} | ||
} | ||
encoding = String(encoding || 'utf8').toLowerCase(); | ||
|
||
var ret; | ||
switch (encoding) { | ||
case 'hex': | ||
ret = this.parent.hexWrite(string, this.offset + offset, length); | ||
break; | ||
|
||
case 'utf8': | ||
case 'utf-8': | ||
ret = this.parent.utf8Write(string, this.offset + offset, length); | ||
break; | ||
|
||
case 'ascii': | ||
ret = this.parent.asciiWrite(string, this.offset + offset, length); | ||
break; | ||
|
||
case 'binary': | ||
ret = this.parent.binaryWrite(string, this.offset + offset, length); | ||
break; | ||
|
||
case 'base64': | ||
// Warning: maxLength not taken into account in base64Write | ||
ret = this.parent.base64Write(string, this.offset + offset, length); | ||
break; | ||
|
||
case 'ucs2': | ||
case 'ucs-2': | ||
ret = this.parent.ucs2Write(string, this.offset + offset, length); | ||
break; | ||
|
||
default: | ||
throw new Error('Unknown encoding'); | ||
} | ||
|
||
Buffer._charsWritten = SlowBuffer._charsWritten; | ||
|
||
return ret; | ||
}; | ||
|
||
|
||
// toString(encoding, start=0, end=buffer.length) | ||
Buffer.prototype.toString = function(encoding, start, end) { | ||
encoding = String(encoding || 'utf8').toLowerCase(); | ||
|
||
if (typeof start == 'undefined' || start < 0) { | ||
start = 0; | ||
} else if (start > this.length) { | ||
start = this.length; | ||
} | ||
|
||
if (typeof end == 'undefined' || end > this.length) { | ||
end = this.length; | ||
} else if (end < 0) { | ||
end = 0; | ||
} | ||
|
||
start = start + this.offset; | ||
end = end + this.offset; | ||
|
||
switch (encoding) { | ||
case 'hex': | ||
return this.parent.hexSlice(start, end); | ||
|
||
case 'utf8': | ||
case 'utf-8': | ||
return this.parent.utf8Slice(start, end); | ||
|
||
case 'ascii': | ||
return this.parent.asciiSlice(start, end); | ||
|
||
case 'binary': | ||
return this.parent.binarySlice(start, end); | ||
|
||
case 'base64': | ||
return this.parent.base64Slice(start, end); | ||
|
||
case 'ucs2': | ||
case 'ucs-2': | ||
return this.parent.ucs2Slice(start, end); | ||
|
||
default: | ||
throw new Error('Unknown encoding'); | ||
} | ||
}; | ||
|
||
|
||
// byteLength | ||
Buffer.byteLength = SlowBuffer.byteLength; | ||
|
||
|
||
// fill(value, start=0, end=buffer.length) | ||
Buffer.prototype.fill = function fill(value, start, end) { | ||
value || (value = 0); | ||
start || (start = 0); | ||
end || (end = this.length); | ||
|
||
if (typeof value === 'string') { | ||
value = value.charCodeAt(0); | ||
} | ||
if (!(typeof value === 'number') || isNaN(value)) { | ||
throw new Error('value is not a number'); | ||
} | ||
|
||
if (end < start) throw new Error('end < start'); | ||
|
||
// Fill 0 bytes; we're done | ||
if (end === start) return 0; | ||
if (this.length == 0) return 0; | ||
|
||
if (start < 0 || start >= this.length) { | ||
throw new Error('start out of bounds'); | ||
} | ||
|
||
if (end < 0 || end > this.length) { | ||
throw new Error('end out of bounds'); | ||
} | ||
|
||
return this.parent.fill(value, | ||
start + this.offset, | ||
end + this.offset); | ||
}; | ||
|
||
|
||
// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length) | ||
Buffer.prototype.copy = function(target, target_start, start, end) { | ||
var source = this; | ||
start || (start = 0); | ||
end || (end = this.length); | ||
target_start || (target_start = 0); | ||
|
||
if (end < start) throw new Error('sourceEnd < sourceStart'); | ||
|
||
// Copy 0 bytes; we're done | ||
if (end === start) return 0; | ||
if (target.length == 0 || source.length == 0) return 0; | ||
|
||
if (target_start < 0 || target_start >= target.length) { | ||
throw new Error('targetStart out of bounds'); | ||
} | ||
|
||
if (start < 0 || start >= source.length) { | ||
throw new Error('sourceStart out of bounds'); | ||
} | ||
|
||
if (end < 0 || end > source.length) { | ||
throw new Error('sourceEnd out of bounds'); | ||
} | ||
|
||
// Are we oob? | ||
if (end > this.length) { | ||
end = this.length; | ||
} | ||
|
||
if (target.length - target_start < end - start) { | ||
end = target.length - target_start + start; | ||
} | ||
|
||
return this.parent.copy(target.parent, | ||
target_start + target.offset, | ||
start + this.offset, | ||
end + this.offset); | ||
}; | ||
|
||
|
||
// slice(start, end) | ||
Buffer.prototype.slice = function(start, end) { | ||
if (end === undefined) end = this.length; | ||
if (end > this.length) throw new Error('oob'); | ||
if (start > end) throw new Error('oob'); | ||
|
||
return new Buffer(this.parent, end - start, +start + this.offset); | ||
}; | ||
|
||
|
||
// Legacy methods for backwards compatibility. | ||
|
||
Buffer.prototype.utf8Slice = function(start, end) { | ||
return this.toString('utf8', start, end); | ||
}; | ||
|
||
Buffer.prototype.binarySlice = function(start, end) { | ||
return this.toString('binary', start, end); | ||
}; | ||
|
||
Buffer.prototype.asciiSlice = function(start, end) { | ||
return this.toString('ascii', start, end); | ||
}; | ||
|
||
Buffer.prototype.utf8Write = function(string, offset) { | ||
return this.write(string, offset, 'utf8'); | ||
}; | ||
|
||
Buffer.prototype.binaryWrite = function(string, offset) { | ||
return this.write(string, offset, 'binary'); | ||
}; | ||
|
||
Buffer.prototype.asciiWrite = function(string, offset) { | ||
return this.write(string, offset, 'ascii'); | ||
}; | ||
|
||
Buffer.prototype.readUInt8 = function(offset, noAssert) { | ||
var buffer = this; | ||
|
||
if (!noAssert) { | ||
assert.ok(offset !== undefined && offset !== null, | ||
'missing offset'); | ||
|
||
assert.ok(offset < buffer.length, | ||
'Trying to read beyond buffer length'); | ||
} | ||
|
||
return buffer[offset]; | ||
}; | ||
|
||
function readUInt16(buffer, offset, isBigEndian, noAssert) { | ||
var val = 0; | ||
|
||
|
||
if (!noAssert) { | ||
assert.ok(typeof (isBigEndian) === 'boolean', | ||
'missing or invalid endian'); | ||
|
||
assert.ok(offset !== undefined && offset !== null, | ||
'missing offset'); | ||
|
||
assert.ok(offset + 1 < buffer.length, | ||
'Trying to read beyond buffer length'); | ||
} | ||
|
||
if (isBigEndian) { | ||
val = buffer[offset] << 8; | ||
val |= buffer[offset + 1]; | ||
} else { | ||
val = buffer[offset]; | ||
val |= buffer[offset + 1] << 8; | ||
} | ||
|
||
return val; | ||
} | ||
|
||
Buffer.prototype.readUInt16LE = function(offset, noAssert) { | ||
return readUInt16(this, offset, false, noAssert); | ||
}; | ||
|
||
Buffer.prototype.readUInt16BE = function(offset, noAssert) { | ||
return readUInt16(this, offset, true, noAssert); | ||
}; | ||
|
||
function readUInt32(buffer, offset, isBigEndian, noAssert) { | ||
var val = 0; | ||
|
||
if (!noAssert) { | ||
assert.ok(typeof (isBigEndian) === 'boolean', | ||
'missing or invalid endian'); | ||
|
||
assert.ok(offset !== undefined && offset !== null, | ||
'missing offset'); | ||
|
||
assert.ok(offset + 3 < buffer.length, | ||
'Trying to read beyond buffer length'); | ||
} | ||
|
||
if (isBigEndian) { | ||
val = buffer[offset + 1] << 16; | ||
val |= buffer[offset + 2] << 8; | ||
val |= buffer[offset + 3]; | ||
val = val + (buffer[offset] << 24 >>> 0); | ||
} else { | ||
val = buffer[offset + 2] << 16; | ||
val |= buffer[offset + 1] << 8; | ||
val |= buffer[offset]; | ||
val = val + (buffer[offset + 3] << 24 >>> 0); | ||
} | ||
|
||
return val; | ||
} | ||
|
||
Buffer.prototype.readUInt32LE = function(offset, noAssert) { | ||
return readUInt32(this, offset, false, noAssert); | ||
}; | ||
|
||
Buffer.prototype.readUInt32BE = function(offset, noAssert) { | ||
return readUInt32(this, offset, true, noAssert); | ||
}; | ||
|
||
|
||
/* | ||
* Signed integer types, yay team! A reminder on how two's complement actually | ||
* works. The first bit is the signed bit, i.e. tells us whether or not the | ||
* number should be positive or negative. If the two's complement value is | ||
* positive, then we're done, as it's equivalent to the unsigned representation. | ||
* | ||
* Now if the number is positive, you're pretty much done, you can just leverage | ||
* the unsigned translations and return those. Unfortunately, negative numbers | ||
* aren't quite that straightforward. | ||
* | ||
* At first glance, one might be inclined to use the traditional formula to | ||
* translate binary numbers between the positive and negative values in two's | ||
* complement. (Though it doesn't quite work for the most negative value) | ||
* Mainly: | ||
* - invert all the bits | ||
* - add one to the result | ||
* | ||
* Of course, this doesn't quite work in Javascript. Take for example the value | ||
* of -128. This could be represented in 16 bits (big-endian) as 0xff80. But of | ||
* course, Javascript will do the following: | ||
* | ||
* > ~0xff80 | ||
* -65409 | ||
* | ||
* Whoh there, Javascript, that's not quite right. But wait, according to | ||
* Javascript that's perfectly correct. When Javascript ends up seeing the | ||
* constant 0xff80, it has no notion that it is actually a signed number. It | ||
* assumes that we've input the unsigned value 0xff80. Thus, when it does the | ||
* binary negation, it casts it into a signed value, (positive 0xff80). Then | ||
* when you perform binary negation on that, it turns it into a negative number. | ||
* | ||
* Instead, we're going to have to use the following general formula, that works | ||
* in a rather Javascript friendly way. I'm glad we don't support this kind of | ||
* weird numbering scheme in the kernel. | ||
* | ||
* (BIT-MAX - (unsigned)val + 1) * -1 | ||
* | ||
* The astute observer, may think that this doesn't make sense for 8-bit numbers | ||
* (really it isn't necessary for them). However, when you get 16-bit numbers, | ||
* you do. Let's go back to our prior example and see how this will look: | ||
* | ||
* (0xffff - 0xff80 + 1) * -1 | ||
* (0x007f + 1) * -1 | ||
* (0x0080) * -1 | ||
*/ | ||
Buffer.prototype.readInt8 = function(offset, noAssert) { | ||
var buffer = this; | ||
var neg; | ||
|
||
if (!noAssert) { | ||
assert.ok(offset !== undefined && offset !== null, | ||
'missing offset'); | ||
|
||
assert.ok(offset < buffer.length, | ||
'Trying to read beyond buffer length'); | ||
} | ||
|
||
neg = buffer[offset] & 0x80; | ||
if (!neg) { | ||
return (buffer[offset]); | ||
} | ||
|
||
return ((0xff - buffer[offset] + 1) * -1); | ||
}; | ||
|
||
function readInt16(buffer, offset, isBigEndian, noAssert) { | ||
var neg, val; | ||
|
||
if (!noAssert) { | ||
assert.ok(typeof (isBigEndian) === 'boolean', | ||
'missing or invalid endian'); | ||
|
||
assert.ok(offset !== undefined && offset !== null, | ||
'missing offset'); | ||
|
||
assert.ok(offset + 1 < buffer.length, | ||
'Trying to read beyond buffer length'); | ||
} | ||
|
||
val = readUInt16(buffer, offset, isBigEndian, noAssert); | ||
neg = val & 0x8000; | ||
if (!neg) { | ||
return val; | ||
} | ||
|
||
return (0xffff - val + 1) * -1; | ||
} | ||
|
||
Buffer.prototype.readInt16LE = function(offset, noAssert) { | ||
return readInt16(this, offset, false, noAssert); | ||
}; | ||
|
||
Buffer.prototype.readInt16BE = function(offset, noAssert) { | ||
return readInt16(this, offset, true, noAssert); | ||
}; | ||
|
||
function readInt32(buffer, offset, isBigEndian, noAssert) { | ||
var neg, val; | ||
|
||
if (!noAssert) { | ||
assert.ok(typeof (isBigEndian) === 'boolean', | ||
'missing or invalid endian'); | ||
|
||
assert.ok(offset !== undefined && offset !== null, | ||
'missing offset'); | ||
|
||
assert.ok(offset + 3 < buffer.length, | ||
'Trying to read beyond buffer length'); | ||
} | ||
|
||
val = readUInt32(buffer, offset, isBigEndian, noAssert); | ||
neg = val & 0x80000000; | ||
if (!neg) { | ||
return (val); | ||
} | ||
|
||
return (0xffffffff - val + 1) * -1; | ||
} | ||
|
||
Buffer.prototype.readInt32LE = function(offset, noAssert) { | ||
return readInt32(this, offset, false, noAssert); | ||
}; | ||
|
||
Buffer.prototype.readInt32BE = function(offset, noAssert) { | ||
return readInt32(this, offset, true, noAssert); | ||
}; | ||
|
||
function readFloat(buffer, offset, isBigEndian, noAssert) { | ||
if (!noAssert) { | ||
assert.ok(typeof (isBigEndian) === 'boolean', | ||
'missing or invalid endian'); | ||
|
||
assert.ok(offset + 3 < buffer.length, | ||
'Trying to read beyond buffer length'); | ||
} | ||
|
||
return require('buffer_ieee754').readIEEE754(buffer, offset, isBigEndian, | ||
23, 4); | ||
} | ||
|
||
Buffer.prototype.readFloatLE = function(offset, noAssert) { | ||
return readFloat(this, offset, false, noAssert); | ||
}; | ||
|
||
Buffer.prototype.readFloatBE = function(offset, noAssert) { | ||
return readFloat(this, offset, true, noAssert); | ||
}; | ||
|
||
function readDouble(buffer, offset, isBigEndian, noAssert) { | ||
if (!noAssert) { | ||
assert.ok(typeof (isBigEndian) === 'boolean', | ||
'missing or invalid endian'); | ||
|
||
assert.ok(offset + 7 < buffer.length, | ||
'Trying to read beyond buffer length'); | ||
} | ||
|
||
return require('buffer_ieee754').readIEEE754(buffer, offset, isBigEndian, | ||
52, 8); | ||
} | ||
|
||
Buffer.prototype.readDoubleLE = function(offset, noAssert) { | ||
return readDouble(this, offset, false, noAssert); | ||
}; | ||
|
||
Buffer.prototype.readDoubleBE = function(offset, noAssert) { | ||
return readDouble(this, offset, true, noAssert); | ||
}; | ||
|
||
|
||
/* | ||
* We have to make sure that the value is a valid integer. This means that it is | ||
* non-negative. It has no fractional component and that it does not exceed the | ||
* maximum allowed value. | ||
* | ||
* value The number to check for validity | ||
* | ||
* max The maximum value | ||
*/ | ||
function verifuint(value, max) { | ||
assert.ok(typeof (value) == 'number', | ||
'cannot write a non-number as a number'); | ||
|
||
assert.ok(value >= 0, | ||
'specified a negative value for writing an unsigned value'); | ||
|
||
assert.ok(value <= max, 'value is larger than maximum value for type'); | ||
|
||
assert.ok(Math.floor(value) === value, 'value has a fractional component'); | ||
} | ||
|
||
Buffer.prototype.writeUInt8 = function(value, offset, noAssert) { | ||
var buffer = this; | ||
|
||
if (!noAssert) { | ||
assert.ok(value !== undefined && value !== null, | ||
'missing value'); | ||
|
||
assert.ok(offset !== undefined && offset !== null, | ||
'missing offset'); | ||
|
||
assert.ok(offset < buffer.length, | ||
'trying to write beyond buffer length'); | ||
|
||
verifuint(value, 0xff); | ||
} | ||
|
||
buffer[offset] = value; | ||
}; | ||
|
||
function writeUInt16(buffer, value, offset, isBigEndian, noAssert) { | ||
if (!noAssert) { | ||
assert.ok(value !== undefined && value !== null, | ||
'missing value'); | ||
|
||
assert.ok(typeof (isBigEndian) === 'boolean', | ||
'missing or invalid endian'); | ||
|
||
assert.ok(offset !== undefined && offset !== null, | ||
'missing offset'); | ||
|
||
assert.ok(offset + 1 < buffer.length, | ||
'trying to write beyond buffer length'); | ||
|
||
verifuint(value, 0xffff); | ||
} | ||
|
||
if (isBigEndian) { | ||
buffer[offset] = (value & 0xff00) >>> 8; | ||
buffer[offset + 1] = value & 0x00ff; | ||
} else { | ||
buffer[offset + 1] = (value & 0xff00) >>> 8; | ||
buffer[offset] = value & 0x00ff; | ||
} | ||
} | ||
|
||
Buffer.prototype.writeUInt16LE = function(value, offset, noAssert) { | ||
writeUInt16(this, value, offset, false, noAssert); | ||
}; | ||
|
||
Buffer.prototype.writeUInt16BE = function(value, offset, noAssert) { | ||
writeUInt16(this, value, offset, true, noAssert); | ||
}; | ||
|
||
function writeUInt32(buffer, value, offset, isBigEndian, noAssert) { | ||
if (!noAssert) { | ||
assert.ok(value !== undefined && value !== null, | ||
'missing value'); | ||
|
||
assert.ok(typeof (isBigEndian) === 'boolean', | ||
'missing or invalid endian'); | ||
|
||
assert.ok(offset !== undefined && offset !== null, | ||
'missing offset'); | ||
|
||
assert.ok(offset + 3 < buffer.length, | ||
'trying to write beyond buffer length'); | ||
|
||
verifuint(value, 0xffffffff); | ||
} | ||
|
||
if (isBigEndian) { | ||
buffer[offset] = (value >>> 24) & 0xff; | ||
buffer[offset + 1] = (value >>> 16) & 0xff; | ||
buffer[offset + 2] = (value >>> 8) & 0xff; | ||
buffer[offset + 3] = value & 0xff; | ||
} else { | ||
buffer[offset + 3] = (value >>> 24) & 0xff; | ||
buffer[offset + 2] = (value >>> 16) & 0xff; | ||
buffer[offset + 1] = (value >>> 8) & 0xff; | ||
buffer[offset] = value & 0xff; | ||
} | ||
} | ||
|
||
Buffer.prototype.writeUInt32LE = function(value, offset, noAssert) { | ||
writeUInt32(this, value, offset, false, noAssert); | ||
}; | ||
|
||
Buffer.prototype.writeUInt32BE = function(value, offset, noAssert) { | ||
writeUInt32(this, value, offset, true, noAssert); | ||
}; | ||
|
||
|
||
/* | ||
* We now move onto our friends in the signed number category. Unlike unsigned | ||
* numbers, we're going to have to worry a bit more about how we put values into | ||
* arrays. Since we are only worrying about signed 32-bit values, we're in | ||
* slightly better shape. Unfortunately, we really can't do our favorite binary | ||
* & in this system. It really seems to do the wrong thing. For example: | ||
* | ||
* > -32 & 0xff | ||
* 224 | ||
* | ||
* What's happening above is really: 0xe0 & 0xff = 0xe0. However, the results of | ||
* this aren't treated as a signed number. Ultimately a bad thing. | ||
* | ||
* What we're going to want to do is basically create the unsigned equivalent of | ||
* our representation and pass that off to the wuint* functions. To do that | ||
* we're going to do the following: | ||
* | ||
* - if the value is positive | ||
* we can pass it directly off to the equivalent wuint | ||
* - if the value is negative | ||
* we do the following computation: | ||
* mb + val + 1, where | ||
* mb is the maximum unsigned value in that byte size | ||
* val is the Javascript negative integer | ||
* | ||
* | ||
* As a concrete value, take -128. In signed 16 bits this would be 0xff80. If | ||
* you do out the computations: | ||
* | ||
* 0xffff - 128 + 1 | ||
* 0xffff - 127 | ||
* 0xff80 | ||
* | ||
* You can then encode this value as the signed version. This is really rather | ||
* hacky, but it should work and get the job done which is our goal here. | ||
*/ | ||
|
||
/* | ||
* A series of checks to make sure we actually have a signed 32-bit number | ||
*/ | ||
function verifsint(value, max, min) { | ||
assert.ok(typeof (value) == 'number', | ||
'cannot write a non-number as a number'); | ||
|
||
assert.ok(value <= max, 'value larger than maximum allowed value'); | ||
|
||
assert.ok(value >= min, 'value smaller than minimum allowed value'); | ||
|
||
assert.ok(Math.floor(value) === value, 'value has a fractional component'); | ||
} | ||
|
||
function verifIEEE754(value, max, min) { | ||
assert.ok(typeof (value) == 'number', | ||
'cannot write a non-number as a number'); | ||
|
||
assert.ok(value <= max, 'value larger than maximum allowed value'); | ||
|
||
assert.ok(value >= min, 'value smaller than minimum allowed value'); | ||
} | ||
|
||
Buffer.prototype.writeInt8 = function(value, offset, noAssert) { | ||
var buffer = this; | ||
|
||
if (!noAssert) { | ||
assert.ok(value !== undefined && value !== null, | ||
'missing value'); | ||
|
||
assert.ok(offset !== undefined && offset !== null, | ||
'missing offset'); | ||
|
||
assert.ok(offset < buffer.length, | ||
'Trying to write beyond buffer length'); | ||
|
||
verifsint(value, 0x7f, -0x80); | ||
} | ||
|
||
if (value >= 0) { | ||
buffer.writeUInt8(value, offset, noAssert); | ||
} else { | ||
buffer.writeUInt8(0xff + value + 1, offset, noAssert); | ||
} | ||
}; | ||
|
||
function writeInt16(buffer, value, offset, isBigEndian, noAssert) { | ||
if (!noAssert) { | ||
assert.ok(value !== undefined && value !== null, | ||
'missing value'); | ||
|
||
assert.ok(typeof (isBigEndian) === 'boolean', | ||
'missing or invalid endian'); | ||
|
||
assert.ok(offset !== undefined && offset !== null, | ||
'missing offset'); | ||
|
||
assert.ok(offset + 1 < buffer.length, | ||
'Trying to write beyond buffer length'); | ||
|
||
verifsint(value, 0x7fff, -0x8000); | ||
} | ||
|
||
if (value >= 0) { | ||
writeUInt16(buffer, value, offset, isBigEndian, noAssert); | ||
} else { | ||
writeUInt16(buffer, 0xffff + value + 1, offset, isBigEndian, noAssert); | ||
} | ||
} | ||
|
||
Buffer.prototype.writeInt16LE = function(value, offset, noAssert) { | ||
writeInt16(this, value, offset, false, noAssert); | ||
}; | ||
|
||
Buffer.prototype.writeInt16BE = function(value, offset, noAssert) { | ||
writeInt16(this, value, offset, true, noAssert); | ||
}; | ||
|
||
function writeInt32(buffer, value, offset, isBigEndian, noAssert) { | ||
if (!noAssert) { | ||
assert.ok(value !== undefined && value !== null, | ||
'missing value'); | ||
|
||
assert.ok(typeof (isBigEndian) === 'boolean', | ||
'missing or invalid endian'); | ||
|
||
assert.ok(offset !== undefined && offset !== null, | ||
'missing offset'); | ||
|
||
assert.ok(offset + 3 < buffer.length, | ||
'Trying to write beyond buffer length'); | ||
|
||
verifsint(value, 0x7fffffff, -0x80000000); | ||
} | ||
|
||
if (value >= 0) { | ||
writeUInt32(buffer, value, offset, isBigEndian, noAssert); | ||
} else { | ||
writeUInt32(buffer, 0xffffffff + value + 1, offset, isBigEndian, noAssert); | ||
} | ||
} | ||
|
||
Buffer.prototype.writeInt32LE = function(value, offset, noAssert) { | ||
writeInt32(this, value, offset, false, noAssert); | ||
}; | ||
|
||
Buffer.prototype.writeInt32BE = function(value, offset, noAssert) { | ||
writeInt32(this, value, offset, true, noAssert); | ||
}; | ||
|
||
function writeFloat(buffer, value, offset, isBigEndian, noAssert) { | ||
if (!noAssert) { | ||
assert.ok(value !== undefined && value !== null, | ||
'missing value'); | ||
|
||
assert.ok(typeof (isBigEndian) === 'boolean', | ||
'missing or invalid endian'); | ||
|
||
assert.ok(offset !== undefined && offset !== null, | ||
'missing offset'); | ||
|
||
assert.ok(offset + 3 < buffer.length, | ||
'Trying to write beyond buffer length'); | ||
|
||
verifIEEE754(value, 3.4028234663852886e+38, -3.4028234663852886e+38); | ||
} | ||
|
||
require('buffer_ieee754').writeIEEE754(buffer, value, offset, isBigEndian, | ||
23, 4); | ||
} | ||
|
||
Buffer.prototype.writeFloatLE = function(value, offset, noAssert) { | ||
writeFloat(this, value, offset, false, noAssert); | ||
}; | ||
|
||
Buffer.prototype.writeFloatBE = function(value, offset, noAssert) { | ||
writeFloat(this, value, offset, true, noAssert); | ||
}; | ||
|
||
function writeDouble(buffer, value, offset, isBigEndian, noAssert) { | ||
if (!noAssert) { | ||
assert.ok(value !== undefined && value !== null, | ||
'missing value'); | ||
|
||
assert.ok(typeof (isBigEndian) === 'boolean', | ||
'missing or invalid endian'); | ||
|
||
assert.ok(offset !== undefined && offset !== null, | ||
'missing offset'); | ||
|
||
assert.ok(offset + 7 < buffer.length, | ||
'Trying to write beyond buffer length'); | ||
|
||
verifIEEE754(value, 1.7976931348623157E+308, -1.7976931348623157E+308); | ||
} | ||
|
||
require('buffer_ieee754').writeIEEE754(buffer, value, offset, isBigEndian, | ||
52, 8); | ||
} | ||
|
||
Buffer.prototype.writeDoubleLE = function(value, offset, noAssert) { | ||
writeDouble(this, value, offset, false, noAssert); | ||
}; | ||
|
||
Buffer.prototype.writeDoubleBE = function(value, offset, noAssert) { | ||
writeDouble(this, value, offset, true, noAssert); | ||
}; | ||
|
||
SlowBuffer.prototype.readUInt8 = Buffer.prototype.readUInt8; | ||
SlowBuffer.prototype.readUInt16LE = Buffer.prototype.readUInt16LE; | ||
SlowBuffer.prototype.readUInt16BE = Buffer.prototype.readUInt16BE; | ||
SlowBuffer.prototype.readUInt32LE = Buffer.prototype.readUInt32LE; | ||
SlowBuffer.prototype.readUInt32BE = Buffer.prototype.readUInt32BE; | ||
SlowBuffer.prototype.readInt8 = Buffer.prototype.readInt8; | ||
SlowBuffer.prototype.readInt16LE = Buffer.prototype.readInt16LE; | ||
SlowBuffer.prototype.readInt16BE = Buffer.prototype.readInt16BE; | ||
SlowBuffer.prototype.readInt32LE = Buffer.prototype.readInt32LE; | ||
SlowBuffer.prototype.readInt32BE = Buffer.prototype.readInt32BE; | ||
SlowBuffer.prototype.readFloatLE = Buffer.prototype.readFloatLE; | ||
SlowBuffer.prototype.readFloatBE = Buffer.prototype.readFloatBE; | ||
SlowBuffer.prototype.readDoubleLE = Buffer.prototype.readDoubleLE; | ||
SlowBuffer.prototype.readDoubleBE = Buffer.prototype.readDoubleBE; | ||
SlowBuffer.prototype.writeUInt8 = Buffer.prototype.writeUInt8; | ||
SlowBuffer.prototype.writeUInt16LE = Buffer.prototype.writeUInt16LE; | ||
SlowBuffer.prototype.writeUInt16BE = Buffer.prototype.writeUInt16BE; | ||
SlowBuffer.prototype.writeUInt32LE = Buffer.prototype.writeUInt32LE; | ||
SlowBuffer.prototype.writeUInt32BE = Buffer.prototype.writeUInt32BE; | ||
SlowBuffer.prototype.writeInt8 = Buffer.prototype.writeInt8; | ||
SlowBuffer.prototype.writeInt16LE = Buffer.prototype.writeInt16LE; | ||
SlowBuffer.prototype.writeInt16BE = Buffer.prototype.writeInt16BE; | ||
SlowBuffer.prototype.writeInt32LE = Buffer.prototype.writeInt32LE; | ||
SlowBuffer.prototype.writeInt32BE = Buffer.prototype.writeInt32BE; | ||
SlowBuffer.prototype.writeFloatLE = Buffer.prototype.writeFloatLE; | ||
SlowBuffer.prototype.writeFloatBE = Buffer.prototype.writeFloatBE; | ||
SlowBuffer.prototype.writeDoubleLE = Buffer.prototype.writeDoubleLE; | ||
SlowBuffer.prototype.writeDoubleBE = Buffer.prototype.writeDoubleBE; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
exports.readIEEE754 = function(buffer, offset, isBE, mLen, nBytes) { | ||
var e, m, | ||
eLen = nBytes * 8 - mLen - 1, | ||
eMax = (1 << eLen) - 1, | ||
eBias = eMax >> 1, | ||
nBits = -7, | ||
i = isBE ? 0 : (nBytes - 1), | ||
d = isBE ? 1 : -1, | ||
s = buffer[offset + i]; | ||
|
||
i += d; | ||
|
||
e = s & ((1 << (-nBits)) - 1); | ||
s >>= (-nBits); | ||
nBits += eLen; | ||
for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8); | ||
|
||
m = e & ((1 << (-nBits)) - 1); | ||
e >>= (-nBits); | ||
nBits += mLen; | ||
for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8); | ||
|
||
if (e === 0) { | ||
e = 1 - eBias; | ||
} else if (e === eMax) { | ||
return m ? NaN : ((s ? -1 : 1) * Infinity); | ||
} else { | ||
m = m + Math.pow(2, mLen); | ||
e = e - eBias; | ||
} | ||
return (s ? -1 : 1) * m * Math.pow(2, e - mLen); | ||
}; | ||
|
||
exports.writeIEEE754 = function(buffer, value, offset, isBE, mLen, nBytes) { | ||
var e, m, c, | ||
eLen = nBytes * 8 - mLen - 1, | ||
eMax = (1 << eLen) - 1, | ||
eBias = eMax >> 1, | ||
rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0), | ||
i = isBE ? (nBytes - 1) : 0, | ||
d = isBE ? -1 : 1, | ||
s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0; | ||
|
||
value = Math.abs(value); | ||
|
||
if (isNaN(value) || value === Infinity) { | ||
m = isNaN(value) ? 1 : 0; | ||
e = eMax; | ||
} else { | ||
e = Math.floor(Math.log(value) / Math.LN2); | ||
if (value * (c = Math.pow(2, -e)) < 1) { | ||
e--; | ||
c *= 2; | ||
} | ||
if (e + eBias >= 1) { | ||
value += rt / c; | ||
} else { | ||
value += rt * Math.pow(2, 1 - eBias); | ||
} | ||
if (value * c >= 2) { | ||
e++; | ||
c /= 2; | ||
} | ||
|
||
if (e + eBias >= eMax) { | ||
m = 0; | ||
e = eMax; | ||
} else if (e + eBias >= 1) { | ||
m = (value * c - 1) * Math.pow(2, mLen); | ||
e = e + eBias; | ||
} else { | ||
m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen); | ||
e = 0; | ||
} | ||
} | ||
|
||
for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8); | ||
|
||
e = (e << mLen) | m; | ||
eLen += mLen; | ||
for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8); | ||
|
||
buffer[offset + i - d] |= s * 128; | ||
}; |