diff --git a/lib/thrift/binary_parser.js b/lib/thrift/binary_parser.js index 6428a85..0ce8498 100644 --- a/lib/thrift/binary_parser.js +++ b/lib/thrift/binary_parser.js @@ -61,7 +61,7 @@ IBuffer.prototype.readBits = function( 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.warn = function( msg ){ if( this.allowExceptions ) throw new Error( msg ); @@ -145,8 +145,8 @@ p.toWord = function( data ){ return this.decodeInt( data, 16, false ); }; p.fromWord = function( data ){ return this.encodeInt( data, 16, false ); }; p.toInt = function( data ){ return this.decodeInt( data, 32, true ); }; p.fromInt = function( data ){ return this.encodeInt( data, 32, true ); }; -p.toLong = function( data ){ return this.decodeInt( data, 64, true ); }; -p.fromLong = function( data ){ return this.encodeInt( data, 64, true ); }; +p.toLong = function( data ){ return this.decodeLong( data, 64, true ); }; +p.fromLong = function( data ){ return this.encodeLong( data, 64, true ); }; p.toDWord = function( data ){ return this.decodeInt( data, 32, false ); }; p.fromDWord = function( data ){ return this.encodeInt( data, 32, false ); }; p.toQWord = function( data ){ return this.decodeInt( data, 64, true ); }; @@ -156,6 +156,46 @@ p.fromFloat = function( data ){ return this.encodeFloat( data, 23, 8 ); }; p.toDouble = function( data ){ return this.decodeFloat( data, 52, 11 ); }; p.fromDouble = function( data ){ return this.encodeFloat( data, 52, 11 ); }; +// Patch to have full support for longs. +p.encodeLong = function( data ){ + + var bits = 64, + signed = true, + origData = data; + + var max = Math.pow( 2, 53 ); + + ( data >= max || data < -( max / 2 ) ) && this.warn( "encodeInt::overflow" ) && ( data = 0 ); + data < 0 && ( data += max ); + for( var r = []; data; r[r.length] = data % 256, data = Math.floor( data / 256 ) ); + for( bits = -( -bits >> 3 ) - r.length; bits--; r[r.length] = 0 ); + + if (origData < 0) { + // Fill in last 11 bits. + r[r.length - 1] = 255; + r[r.length - 2] += 224; + } + + return new Buffer(this.bigEndian ? r.reverse() : r ); +}; + +p.decodeLong = function (data){ + + var bits = 64, + signed = true; + + var b = new this.IBuffer( this.bigEndian, data ), + x = b.readBits(48, 5); + + for (var i = 40; i >= 0; i-= 8) { + x *= 256; + x += b.readBits(i, 8); + } + + max = Math.pow( 2, 53); + return signed && b.readBits(63, 1) !== 0 ? x - max : x; +}; + // Factor out the encode so it can be shared by add_header and push_int32 p.encode_int32 = function(number) { var a, b, c, d, unsigned; @@ -221,7 +261,7 @@ p.decode_utf8 = function(a) { }; // Encode a cstring correctly -p.encode_cstring = function(s) { +p.encode_cstring = function(s) { return unescape(encodeURIComponent(s)) + p.fromByte(0); }; @@ -250,19 +290,19 @@ p.hprint = function(s) { var number = s.charCodeAt(i) <= 15 ? "0" + s.charCodeAt(i).toString(16) : s.charCodeAt(i).toString(16); sys.debug(number+' : ');} else { - var number = s.charCodeAt(i) <= 15 ? "0" + s.charCodeAt(i).toString(16) : s.charCodeAt(i).toString(16); + var number = s.charCodeAt(i) <= 15 ? "0" + s.charCodeAt(i).toString(16) : s.charCodeAt(i).toString(16); sys.debug(number+' : '+ s.charAt(i));} } }; p.to_byte_array = function(s) { var array = []; - + for (var i=0; i