PageRenderTime 25ms CodeModel.GetById 29ms RepoModel.GetById 1ms app.codeStats 0ms

/node_modules/thrift/lib/thrift/binary_parser.js

https://github.com/zyklus/Vouchr
JavaScript | 261 lines | 228 code | 21 blank | 12 comment | 85 complexity | 183d4c80ed53dbb371c15ed479cfe488 MD5 | raw file
  1. // Adapted from: http://github.com/christkv/node-mongodb-native/raw/master/lib/mongodb/bson/binary_parser.js
  2. var sys = require('sys');
  3. //+ Jonas Raoni Soares Silva
  4. //@ http://jsfromhell.com/classes/binary-parser [v1.0]
  5. var chr = String.fromCharCode;
  6. var p = exports.BinaryParser = function( bigEndian, allowExceptions ){
  7. this.bigEndian = bigEndian || true;
  8. this.allowExceptions = allowExceptions;
  9. };
  10. p.bigEndian = true;
  11. var IBuffer = exports.BinaryParser.IBuffer = function( bigEndian, buffer ){
  12. this.bigEndian = bigEndian || 1;
  13. this.buffer = [];
  14. this.setBuffer( buffer );
  15. };
  16. IBuffer.prototype.setBuffer = function( data ){
  17. if( data ){
  18. for( var l, i = l = data.length, b = this.buffer = new Array( l ); i; b[l - i] = data[--i] );
  19. this.bigEndian && b.reverse();
  20. }
  21. };
  22. IBuffer.prototype.hasNeededBits = function( neededBits ){
  23. return this.buffer.length >= -( -neededBits >> 3 );
  24. };
  25. IBuffer.prototype.checkBuffer = function( neededBits ){
  26. if( !this.hasNeededBits( neededBits ) ) {
  27. console.log("missing: " + neededBits + " " + this.buffer.length);
  28. throw new Error( "checkBuffer::missing bytes" );
  29. }
  30. };
  31. IBuffer.prototype.readBits = function( start, length ){
  32. //shl fix: Henri Torgemane ~1996 (compressed by Jonas Raoni)
  33. function shl( a, b ){
  34. for( ; b--; a = ( ( a %= 0x7fffffff + 1 ) & 0x40000000 ) == 0x40000000 ? a * 2 : ( a - 0x40000000 ) * 2 + 0x7fffffff + 1 );
  35. return a;
  36. }
  37. if( start < 0 || length <= 0 )
  38. return 0;
  39. this.checkBuffer( start + length );
  40. 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 ) );
  41. return sum;
  42. };
  43. p.warn = function( msg ){
  44. if( this.allowExceptions )
  45. throw new Error( msg );
  46. return 1;
  47. };
  48. p.decodeFloat = function( data, precisionBits, exponentBits ){
  49. var b = new this.IBuffer( this.bigEndian, data );
  50. b.checkBuffer( precisionBits + exponentBits + 1 );
  51. var bias = Math.pow( 2, exponentBits - 1 ) - 1, signal = b.readBits( precisionBits + exponentBits, 1 ), exponent = b.readBits( precisionBits, exponentBits ), significand = 0,
  52. divisor = 2, curByte = b.buffer.length + ( -precisionBits >> 3 ) - 1;
  53. do{
  54. for( var byteValue = b.buffer[ ++curByte ], startBit = precisionBits % 8 || 8, mask = 1 << startBit; mask >>= 1; ( byteValue & mask ) && ( significand += 1 / divisor ), divisor *= 2 );
  55. }while( precisionBits -= startBit );
  56. 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 );
  57. };
  58. p.decodeInt = function( data, bits, signed, forceBigEndian ){
  59. //console.log("decodeInt: ", data, bits, signed);
  60. var b = new this.IBuffer( this.bigEndian||forceBigEndian, data ), x = b.readBits( 0, bits ), max = Math.pow( 2, bits );
  61. return signed && x >= max / 2 ? x - max : x;
  62. };
  63. p.encodeFloat = function( data, precisionBits, exponentBits ){
  64. var bias = Math.pow( 2, exponentBits - 1 ) - 1, minExp = -bias + 1, maxExp = bias, minUnnormExp = minExp - precisionBits,
  65. status = isNaN( n = parseFloat( data ) ) || n == -Infinity || n == +Infinity ? n : 0,
  66. exp = 0, len = 2 * bias + 1 + precisionBits + 3, bin = new Array( len ),
  67. signal = ( n = status !== 0 ? 0 : n ) < 0, n = Math.abs( n ), intPart = Math.floor( n ), floatPart = n - intPart,
  68. i, lastBit, rounded, j, result;
  69. for( i = len; i; bin[--i] = 0 );
  70. for( i = bias + 2; intPart && i; bin[--i] = intPart % 2, intPart = Math.floor( intPart / 2 ) );
  71. for( i = bias + 1; floatPart > 0 && i; ( bin[++i] = ( ( floatPart *= 2 ) >= 1 ) - 0 ) && --floatPart );
  72. for( i = -1; ++i < len && !bin[i]; );
  73. if( bin[( lastBit = precisionBits - 1 + ( i = ( exp = bias + 1 - i ) >= minExp && exp <= maxExp ? i + 1 : bias + 1 - ( exp = minExp - 1 ) ) ) + 1] ){
  74. if( !( rounded = bin[lastBit] ) ){
  75. for( j = lastBit + 2; !rounded && j < len; rounded = bin[j++] );
  76. }
  77. for( j = lastBit + 1; rounded && --j >= 0; ( bin[j] = !bin[j] - 0 ) && ( rounded = 0 ) );
  78. }
  79. for( i = i - 2 < 0 ? -1 : i - 3; ++i < len && !bin[i]; );
  80. if( ( exp = bias + 1 - i ) >= minExp && exp <= maxExp )
  81. ++i;
  82. else if( exp < minExp ){
  83. exp != bias + 1 - len && exp < minUnnormExp && this.warn( "encodeFloat::float underflow" );
  84. i = bias + 1 - ( exp = minExp - 1 );
  85. }
  86. if( intPart || status !== 0 ){
  87. this.warn( intPart ? "encodeFloat::float overflow" : "encodeFloat::" + status );
  88. exp = maxExp + 1;
  89. i = bias + 2;
  90. if( status == -Infinity )
  91. signal = 1;
  92. else if( isNaN( status ) )
  93. bin[i] = 1;
  94. }
  95. for( n = Math.abs( exp + bias ), j = exponentBits + 1, result = ""; --j; result = ( n % 2 ) + result, n = n >>= 1 );
  96. for( n = 0, j = 0, i = ( result = ( signal ? "1" : "0" ) + result + bin.slice( i, i + precisionBits ).join( "" ) ).length, r = []; i; j = ( j + 1 ) % 8 ){
  97. n += ( 1 << j ) * result.charAt( --i );
  98. if( j == 7 ){
  99. r[r.length] = n;
  100. n = 0;
  101. }
  102. }
  103. if (n) {
  104. r[r.length] = n;
  105. }
  106. return new Buffer( this.bigEndian ? r.reverse() : r );
  107. };
  108. p.encodeInt = function( data, bits, signed, forceBigEndian ){
  109. var max = Math.pow( 2, bits );
  110. ( data >= max || data < -( max / 2 ) ) && this.warn( "encodeInt::overflow" ) && ( data = 0 );
  111. data < 0 && ( data += max );
  112. for( var r = []; data; r[r.length] = data % 256, data = Math.floor( data / 256 ) );
  113. for( bits = -( -bits >> 3 ) - r.length; bits--; r[r.length] = 0 );
  114. return new Buffer((this.bigEndian||forceBigEndian) ? r.reverse() : r );
  115. };
  116. p.toSmall = function( data ){ return this.decodeInt( data, 8, true ); };
  117. p.fromSmall = function( data ){ return this.encodeInt( data, 8, true ); };
  118. p.toByte = function( data ){ return this.decodeInt( data, 8, false ); };
  119. p.fromByte = function( data ){ return this.encodeInt( data, 8, false ); };
  120. p.toShort = function( data ){ return this.decodeInt( data, 16, true ); };
  121. p.fromShort = function( data ){ return this.encodeInt( data, 16, true ); };
  122. p.toWord = function( data ){ return this.decodeInt( data, 16, false ); };
  123. p.fromWord = function( data ){ return this.encodeInt( data, 16, false ); };
  124. p.toInt = function( data ){ return this.decodeInt( data, 32, true ); };
  125. p.fromInt = function( data ){ return this.encodeInt( data, 32, true ); };
  126. p.toLong = function( data ){ return this.decodeInt( data, 64, true ); };
  127. p.fromLong = function( data ){ return this.encodeInt( data, 64, true ); };
  128. p.toDWord = function( data ){ return this.decodeInt( data, 32, false ); };
  129. p.fromDWord = function( data ){ return this.encodeInt( data, 32, false ); };
  130. p.toQWord = function( data ){ return this.decodeInt( data, 64, true ); };
  131. p.fromQWord = function( data ){ return this.encodeInt( data, 64, true ); };
  132. p.toFloat = function( data ){ return this.decodeFloat( data, 23, 8 ); };
  133. p.fromFloat = function( data ){ return this.encodeFloat( data, 23, 8 ); };
  134. p.toDouble = function( data ){ return this.decodeFloat( data, 52, 11 ); };
  135. p.fromDouble = function( data ){ return this.encodeFloat( data, 52, 11 ); };
  136. // Factor out the encode so it can be shared by add_header and push_int32
  137. p.encode_int32 = function(number) {
  138. var a, b, c, d, unsigned;
  139. unsigned = (number < 0) ? (number + 0x100000000) : number;
  140. a = Math.floor(unsigned / 0xffffff);
  141. unsigned &= 0xffffff;
  142. b = Math.floor(unsigned / 0xffff);
  143. unsigned &= 0xffff;
  144. c = Math.floor(unsigned / 0xff);
  145. unsigned &= 0xff;
  146. d = Math.floor(unsigned);
  147. return chr(a) + chr(b) + chr(c) + chr(d);
  148. };
  149. p.encode_int64 = function(number) {
  150. var a, b, c, d, e, f, g, h, unsigned;
  151. unsigned = (number < 0) ? (number + 0x10000000000000000) : number;
  152. a = Math.floor(unsigned / 0xffffffffffffff);
  153. unsigned &= 0xffffffffffffff;
  154. b = Math.floor(unsigned / 0xffffffffffff);
  155. unsigned &= 0xffffffffffff;
  156. c = Math.floor(unsigned / 0xffffffffff);
  157. unsigned &= 0xffffffffff;
  158. d = Math.floor(unsigned / 0xffffffff);
  159. unsigned &= 0xffffffff;
  160. e = Math.floor(unsigned / 0xffffff);
  161. unsigned &= 0xffffff;
  162. f = Math.floor(unsigned / 0xffff);
  163. unsigned &= 0xffff;
  164. g = Math.floor(unsigned / 0xff);
  165. unsigned &= 0xff;
  166. h = Math.floor(unsigned);
  167. return chr(a) + chr(b) + chr(c) + chr(d) + chr(e) + chr(f) + chr(g) + chr(h);
  168. };
  169. /**
  170. UTF8 methods
  171. **/
  172. // Take a raw binary string and return a utf8 string
  173. p.decode_utf8 = function(a) {
  174. var string = "";
  175. var i = 0;
  176. var c = c1 = c2 = 0;
  177. while ( i < a.length ) {
  178. c = a.charCodeAt(i);
  179. if (c < 128) {
  180. string += String.fromCharCode(c);
  181. i++;
  182. } else if((c > 191) && (c < 224)) {
  183. c2 = a.charCodeAt(i+1);
  184. string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
  185. i += 2;
  186. } else {
  187. c2 = a.charCodeAt(i+1);
  188. c3 = a.charCodeAt(i+2);
  189. string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
  190. i += 3;
  191. }
  192. }
  193. return string;
  194. };
  195. // Encode a cstring correctly
  196. p.encode_cstring = function(s) {
  197. return unescape(encodeURIComponent(s)) + p.fromByte(0);
  198. };
  199. // Take a utf8 string and return a binary string
  200. p.encode_utf8 = function(s) {
  201. var a="";
  202. for (var n=0; n< s.length; n++) {
  203. var c=s.charCodeAt(n);
  204. if (c<128) {
  205. a += String.fromCharCode(c);
  206. } else if ((c>127)&&(c<2048)) {
  207. a += String.fromCharCode( (c>>6) | 192) ;
  208. a += String.fromCharCode( (c&63) | 128);
  209. } else {
  210. a += String.fromCharCode( (c>>12) | 224);
  211. a += String.fromCharCode( ((c>>6) & 63) | 128);
  212. a += String.fromCharCode( (c&63) | 128);
  213. }
  214. }
  215. return a;
  216. };
  217. p.hprint = function(s) {
  218. for (var i=0; i<s.length; i++) {
  219. if (s.charCodeAt(i)<32) {
  220. var number = s.charCodeAt(i) <= 15 ? "0" + s.charCodeAt(i).toString(16) : s.charCodeAt(i).toString(16);
  221. sys.debug(number+' : ');}
  222. else {
  223. var number = s.charCodeAt(i) <= 15 ? "0" + s.charCodeAt(i).toString(16) : s.charCodeAt(i).toString(16);
  224. sys.debug(number+' : '+ s.charAt(i));}
  225. }
  226. };
  227. p.to_byte_array = function(s) {
  228. var array = [];
  229. for (var i=0; i<s.length; i++) {
  230. if (s.charCodeAt(i)<32) {array.push(s.charCodeAt(i));}
  231. else {array.push(s.charCodeAt(i))}
  232. }
  233. sys.puts(array);
  234. }
  235. p.pprint = function(s) {
  236. for (var i=0; i<s.length; i++) {
  237. if (s.charCodeAt(i)<32) {sys.puts(s.charCodeAt(i)+' : ');}
  238. else {sys.puts(s.charCodeAt(i)+' : '+ s.charAt(i));}
  239. }
  240. };