forked from timwhitlock/node-amf
-
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.
Swapped to BinaryParser for packing/unpacking doubles
- Loading branch information
Tim Whitlock
committed
Jul 27, 2010
1 parent
e3e85b8
commit 9900fb3
Showing
3 changed files
with
149 additions
and
10 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
/** | ||
* Binary tools for node-amf | ||
*/ | ||
|
||
var BinaryParser; | ||
|
||
exports.parser = function( bigEndian, allowExceptions ){ | ||
return new BinaryParser( bigEndian, allowExceptions ); | ||
} | ||
|
||
|
||
|
||
|
||
|
||
|
||
// code below copied asis from http://jsfromhell.com/ | ||
|
||
|
||
//+ Jonas Raoni Soares Silva | ||
//@ http://jsfromhell.com/classes/binary-parser [rev. #1] | ||
|
||
BinaryParser = function(bigEndian, allowExceptions){ | ||
this.bigEndian = bigEndian, this.allowExceptions = allowExceptions; | ||
}; | ||
with({p: BinaryParser.prototype}){ | ||
p.encodeFloat = function(number, precisionBits, exponentBits){ | ||
var bias = Math.pow(2, exponentBits - 1) - 1, minExp = -bias + 1, maxExp = bias, minUnnormExp = minExp - precisionBits, | ||
status = isNaN(n = parseFloat(number)) || n == -Infinity || n == +Infinity ? n : 0, | ||
exp = 0, len = 2 * bias + 1 + precisionBits + 3, bin = new Array(len), | ||
signal = (n = status !== 0 ? 0 : n) < 0, n = Math.abs(n), intPart = Math.floor(n), floatPart = n - intPart, | ||
i, lastBit, rounded, j, result; | ||
for(i = len; i; bin[--i] = 0); | ||
for(i = bias + 2; intPart && i; bin[--i] = intPart % 2, intPart = Math.floor(intPart / 2)); | ||
for(i = bias + 1; floatPart > 0 && i; (bin[++i] = ((floatPart *= 2) >= 1) - 0) && --floatPart); | ||
for(i = -1; ++i < len && !bin[i];); | ||
if(bin[(lastBit = precisionBits - 1 + (i = (exp = bias + 1 - i) >= minExp && exp <= maxExp ? i + 1 : bias + 1 - (exp = minExp - 1))) + 1]){ | ||
if(!(rounded = bin[lastBit])) | ||
for(j = lastBit + 2; !rounded && j < len; rounded = bin[j++]); | ||
for(j = lastBit + 1; rounded && --j >= 0; (bin[j] = !bin[j] - 0) && (rounded = 0)); | ||
} | ||
for(i = i - 2 < 0 ? -1 : i - 3; ++i < len && !bin[i];); | ||
|
||
(exp = bias + 1 - i) >= minExp && exp <= maxExp ? ++i : exp < minExp && | ||
(exp != bias + 1 - len && exp < minUnnormExp && this.warn("encodeFloat::float underflow"), i = bias + 1 - (exp = minExp - 1)); | ||
(intPart || status !== 0) && (this.warn(intPart ? "encodeFloat::float overflow" : "encodeFloat::" + status), | ||
exp = maxExp + 1, i = bias + 2, status == -Infinity ? signal = 1 : isNaN(status) && (bin[i] = 1)); | ||
for(n = Math.abs(exp + bias), j = exponentBits + 1, result = ""; --j; result = (n % 2) + result, n = n >>= 1); | ||
for(n = 0, j = 0, i = (result = (signal ? "1" : "0") + result + bin.slice(i, i + precisionBits).join("")).length, r = []; | ||
i; n += (1 << j) * result.charAt(--i), j == 7 && (r[r.length] = String.fromCharCode(n), n = 0), j = (j + 1) % 8); | ||
r[r.length] = n ? String.fromCharCode(n) : ""; | ||
return (this.bigEndian ? r.reverse() : r).join(""); | ||
}; | ||
p.encodeInt = function(number, bits, signed){ | ||
var max = Math.pow(2, bits), r = []; | ||
(number >= max || number < -(max >> 1)) && this.warn("encodeInt::overflow") && (number = 0); | ||
number < 0 && (number += max); | ||
for(; number; r[r.length] = String.fromCharCode(number % 256), number = Math.floor(number / 256)); | ||
for(bits = -(-bits >> 3) - r.length; bits--; r[r.length] = "\0"); | ||
return (this.bigEndian ? r.reverse() : r).join(""); | ||
}; | ||
p.decodeFloat = function(data, precisionBits, exponentBits){ | ||
var b = ((b = new this.Buffer(this.bigEndian, data)).checkBuffer(precisionBits + exponentBits + 1), b), | ||
bias = Math.pow(2, exponentBits - 1) - 1, signal = b.readBits(precisionBits + exponentBits, 1), | ||
exponent = b.readBits(precisionBits, exponentBits), significand = 0, | ||
divisor = 2, curByte = b.buffer.length + (-precisionBits >> 3) - 1, | ||
byteValue, startBit, mask; | ||
do | ||
for(byteValue = b.buffer[ ++curByte ], startBit = precisionBits % 8 || 8, mask = 1 << startBit; | ||
mask >>= 1; (byteValue & mask) && (significand += 1 / divisor), divisor *= 2); | ||
while(precisionBits -= startBit); | ||
return exponent == (bias << 1) + 1 ? significand ? NaN : signal ? -Infinity : +Infinity | ||
: (1 + signal * -2) * (exponent || significand ? !exponent ? Math.pow(2, -bias + 1) * significand | ||
: Math.pow(2, exponent - bias) * (1 + significand) : 0); | ||
}; | ||
p.decodeInt = function(data, bits, signed){ | ||
var b = new this.Buffer(this.bigEndian, data), x = b.readBits(0, bits), max = Math.pow(2, bits); | ||
return signed && x >= max / 2 ? x - max : x; | ||
}; | ||
with({p: (p.Buffer = function(bigEndian, buffer){ | ||
this.bigEndian = bigEndian || 0, this.buffer = [], this.setBuffer(buffer); | ||
}).prototype}){ | ||
p.readBits = function(start, length){ | ||
//shl fix: Henri Torgemane ~1996 (compressed by Jonas Raoni) | ||
function shl(a, b){ | ||
for(++b; --b; a = ((a %= 0x7fffffff + 1) & 0x40000000) == 0x40000000 ? a * 2 : (a - 0x40000000) * 2 + 0x7fffffff + 1); | ||
return a; | ||
} | ||
if(start < 0 || length <= 0) | ||
return 0; | ||
this.checkBuffer(start + length); | ||
for(var offsetLeft, offsetRight = start % 8, curByte = this.buffer.length - (start >> 3) - 1, | ||
lastByte = this.buffer.length + (-(start + length) >> 3), diff = curByte - lastByte, | ||
sum = ((this.buffer[ curByte ] >> offsetRight) & ((1 << (diff ? 8 - offsetRight : length)) - 1)) | ||
+ (diff && (offsetLeft = (start + length) % 8) ? (this.buffer[ lastByte++ ] & ((1 << offsetLeft) - 1)) | ||
<< (diff-- << 3) - offsetRight : 0); diff; sum += shl(this.buffer[ lastByte++ ], (diff-- << 3) - offsetRight) | ||
); | ||
return sum; | ||
}; | ||
p.setBuffer = function(data){ | ||
if(data){ | ||
for(var l, i = l = data.length, b = this.buffer = new Array(l); i; b[l - i] = data.charCodeAt(--i)); | ||
this.bigEndian && b.reverse(); | ||
} | ||
}; | ||
p.hasNeededBits = function(neededBits){ | ||
return this.buffer.length >= -(-neededBits >> 3); | ||
}; | ||
p.checkBuffer = function(neededBits){ | ||
if(!this.hasNeededBits(neededBits)) | ||
throw new Error("checkBuffer::missing bytes"); | ||
}; | ||
} | ||
p.warn = function(msg){ | ||
if(this.allowExceptions) | ||
throw new Error(msg); | ||
return 1; | ||
}; | ||
p.toSmall = function(data){return this.decodeInt(data, 8, true);}; | ||
p.fromSmall = function(number){return this.encodeInt(number, 8, true);}; | ||
p.toByte = function(data){return this.decodeInt(data, 8, false);}; | ||
p.fromByte = function(number){return this.encodeInt(number, 8, false);}; | ||
p.toShort = function(data){return this.decodeInt(data, 16, true);}; | ||
p.fromShort = function(number){return this.encodeInt(number, 16, true);}; | ||
p.toWord = function(data){return this.decodeInt(data, 16, false);}; | ||
p.fromWord = function(number){return this.encodeInt(number, 16, false);}; | ||
p.toInt = function(data){return this.decodeInt(data, 32, true);}; | ||
p.fromInt = function(number){return this.encodeInt(number, 32, true);}; | ||
p.toDWord = function(data){return this.decodeInt(data, 32, false);}; | ||
p.fromDWord = function(number){return this.encodeInt(number, 32, false);}; | ||
p.toFloat = function(data){return this.decodeFloat(data, 23, 8);}; | ||
p.fromFloat = function(number){return this.encodeFloat(number, 23, 8);}; | ||
p.toDouble = function(data){return this.decodeFloat(data, 52, 11);}; | ||
p.fromDouble = function(number){return this.encodeFloat(number, 52, 11);}; | ||
} |
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