PageRenderTime 54ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/node_modules/mongous/bson/binary_parser.js

https://gitlab.com/bossmido/word-on-top
JavaScript | 392 lines | 294 code | 71 blank | 27 comment | 87 complexity | 34743310a759f3c9f2e795fec62bccf5 MD5 | raw file
  1. /**
  2. * Module dependencies.
  3. */
  4. //var sys = require('util');
  5. /**
  6. * Binary Parser.
  7. * Jonas Raoni Soares Silva
  8. * http://jsfromhell.com/classes/binary-parser [v1.0]
  9. */
  10. var chr = String.fromCharCode;
  11. var maxBits = [];
  12. for (var i = 0; i < 64; i++) {
  13. maxBits[i] = Math.pow(2, i);
  14. }
  15. function BinaryParser (bigEndian, allowExceptions) {
  16. this.bigEndian = bigEndian;
  17. this.allowExceptions = allowExceptions;
  18. };
  19. BinaryParser.warn = function warn (msg) {
  20. if (this.allowExceptions) {
  21. throw new Error(msg);
  22. }
  23. return 1;
  24. };
  25. BinaryParser.decodeFloat = function decodeFloat (data, precisionBits, exponentBits) {
  26. var b = new this.Buffer(this.bigEndian, data);
  27. b.checkBuffer(precisionBits + exponentBits + 1);
  28. var bias = maxBits[exponentBits - 1] - 1
  29. , signal = b.readBits(precisionBits + exponentBits, 1)
  30. , exponent = b.readBits(precisionBits, exponentBits)
  31. , significand = 0
  32. , divisor = 2
  33. , curByte = b.buffer.length + (-precisionBits >> 3) - 1;
  34. do {
  35. for (var byteValue = b.buffer[ ++curByte ], startBit = precisionBits % 8 || 8, mask = 1 << startBit; mask >>= 1; ( byteValue & mask ) && ( significand += 1 / divisor ), divisor *= 2 );
  36. } while (precisionBits -= startBit);
  37. 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 );
  38. };
  39. BinaryParser.decodeInt = function decodeInt (data, bits, signed, forceBigEndian) {
  40. var b = new this.Buffer(this.bigEndian || forceBigEndian, data)
  41. , x = b.readBits(0, bits)
  42. , max = maxBits[bits]; //max = Math.pow( 2, bits );
  43. return signed && x >= max / 2
  44. ? x - max
  45. : x;
  46. };
  47. BinaryParser.encodeFloat = function encodeFloat (data, precisionBits, exponentBits) {
  48. var bias = maxBits[exponentBits - 1] - 1
  49. , minExp = -bias + 1
  50. , maxExp = bias
  51. , minUnnormExp = minExp - precisionBits
  52. , n = parseFloat(data)
  53. , status = isNaN(n) || n == -Infinity || n == +Infinity ? n : 0
  54. , exp = 0
  55. , len = 2 * bias + 1 + precisionBits + 3
  56. , bin = new Array(len)
  57. , signal = (n = status !== 0 ? 0 : n) < 0
  58. , intPart = Math.floor(n = Math.abs(n))
  59. , floatPart = n - intPart
  60. , lastBit
  61. , rounded
  62. , result
  63. , i
  64. , j;
  65. for (i = len; i; bin[--i] = 0);
  66. for (i = bias + 2; intPart && i; bin[--i] = intPart % 2, intPart = Math.floor(intPart / 2));
  67. for (i = bias + 1; floatPart > 0 && i; (bin[++i] = ((floatPart *= 2) >= 1) - 0 ) && --floatPart);
  68. for (i = -1; ++i < len && !bin[i];);
  69. if (bin[(lastBit = precisionBits - 1 + (i = (exp = bias + 1 - i) >= minExp && exp <= maxExp ? i + 1 : bias + 1 - (exp = minExp - 1))) + 1]) {
  70. if (!(rounded = bin[lastBit])) {
  71. for (j = lastBit + 2; !rounded && j < len; rounded = bin[j++]);
  72. }
  73. for (j = lastBit + 1; rounded && --j >= 0; (bin[j] = !bin[j] - 0) && (rounded = 0));
  74. }
  75. for (i = i - 2 < 0 ? -1 : i - 3; ++i < len && !bin[i];);
  76. if ((exp = bias + 1 - i) >= minExp && exp <= maxExp) {
  77. ++i;
  78. } else if (exp < minExp) {
  79. exp != bias + 1 - len && exp < minUnnormExp && this.warn("encodeFloat::float underflow");
  80. i = bias + 1 - (exp = minExp - 1);
  81. }
  82. if (intPart || status !== 0) {
  83. this.warn(intPart ? "encodeFloat::float overflow" : "encodeFloat::" + status);
  84. exp = maxExp + 1;
  85. i = bias + 2;
  86. if (status == -Infinity) {
  87. signal = 1;
  88. } else if (isNaN(status)) {
  89. bin[i] = 1;
  90. }
  91. }
  92. for (n = Math.abs(exp + bias), j = exponentBits + 1, result = ""; --j; result = (n % 2) + result, n = n >>= 1);
  93. for (n = 0, j = 0, i = (result = (signal ? "1" : "0") + result + bin.slice(i, i + precisionBits).join("")).length, r = []; i; j = (j + 1) % 8) {
  94. n += (1 << j) * result.charAt(--i);
  95. if (j == 7) {
  96. r[r.length] = String.fromCharCode(n);
  97. n = 0;
  98. }
  99. }
  100. r[r.length] = n
  101. ? String.fromCharCode(n)
  102. : "";
  103. return (this.bigEndian ? r.reverse() : r).join("");
  104. };
  105. BinaryParser.encodeInt = function encodeInt (data, bits, signed, forceBigEndian) {
  106. var max = maxBits[bits];
  107. if (data >= max || data < -(max / 2)) {
  108. this.warn("encodeInt::overflow");
  109. data = 0;
  110. }
  111. if (data < 0) {
  112. data += max;
  113. }
  114. for (var r = []; data; r[r.length] = String.fromCharCode(data % 256), data = Math.floor(data / 256));
  115. for (bits = -(-bits >> 3) - r.length; bits--; r[r.length] = "\0");
  116. return ((this.bigEndian || forceBigEndian) ? r.reverse() : r).join("");
  117. };
  118. BinaryParser.toSmall = function( data ){ return this.decodeInt( data, 8, true ); };
  119. BinaryParser.fromSmall = function( data ){ return this.encodeInt( data, 8, true ); };
  120. BinaryParser.toByte = function( data ){ return this.decodeInt( data, 8, false ); };
  121. BinaryParser.fromByte = function( data ){ return this.encodeInt( data, 8, false ); };
  122. BinaryParser.toShort = function( data ){ return this.decodeInt( data, 16, true ); };
  123. BinaryParser.fromShort = function( data ){ return this.encodeInt( data, 16, true ); };
  124. BinaryParser.toWord = function( data ){ return this.decodeInt( data, 16, false ); };
  125. BinaryParser.fromWord = function( data ){ return this.encodeInt( data, 16, false ); };
  126. BinaryParser.toInt = function( data ){ return this.decodeInt( data, 32, true ); };
  127. BinaryParser.fromInt = function( data ){ return this.encodeInt( data, 32, true ); };
  128. BinaryParser.toLong = function( data ){ return this.decodeInt( data, 64, true ); };
  129. BinaryParser.fromLong = function( data ){ return this.encodeInt( data, 64, true ); };
  130. BinaryParser.toDWord = function( data ){ return this.decodeInt( data, 32, false ); };
  131. BinaryParser.fromDWord = function( data ){ return this.encodeInt( data, 32, false ); };
  132. BinaryParser.toQWord = function( data ){ return this.decodeInt( data, 64, true ); };
  133. BinaryParser.fromQWord = function( data ){ return this.encodeInt( data, 64, true ); };
  134. BinaryParser.toFloat = function( data ){ return this.decodeFloat( data, 23, 8 ); };
  135. BinaryParser.fromFloat = function( data ){ return this.encodeFloat( data, 23, 8 ); };
  136. BinaryParser.toDouble = function( data ){ return this.decodeFloat( data, 52, 11 ); };
  137. BinaryParser.fromDouble = function( data ){ return this.encodeFloat( data, 52, 11 ); };
  138. // Factor out the encode so it can be shared by add_header and push_int32
  139. BinaryParser.encode_int32 = function encode_int32 (number) {
  140. var a, b, c, d, unsigned;
  141. unsigned = (number < 0) ? (number + 0x100000000) : number;
  142. a = Math.floor(unsigned / 0xffffff);
  143. unsigned &= 0xffffff;
  144. b = Math.floor(unsigned / 0xffff);
  145. unsigned &= 0xffff;
  146. c = Math.floor(unsigned / 0xff);
  147. unsigned &= 0xff;
  148. d = Math.floor(unsigned);
  149. return chr(a) + chr(b) + chr(c) + chr(d);
  150. };
  151. BinaryParser.encode_int64 = function encode_int64 (number) {
  152. var a, b, c, d, e, f, g, h, unsigned;
  153. unsigned = (number < 0) ? (number + 0x10000000000000000) : number;
  154. a = Math.floor(unsigned / 0xffffffffffffff);
  155. unsigned &= 0xffffffffffffff;
  156. b = Math.floor(unsigned / 0xffffffffffff);
  157. unsigned &= 0xffffffffffff;
  158. c = Math.floor(unsigned / 0xffffffffff);
  159. unsigned &= 0xffffffffff;
  160. d = Math.floor(unsigned / 0xffffffff);
  161. unsigned &= 0xffffffff;
  162. e = Math.floor(unsigned / 0xffffff);
  163. unsigned &= 0xffffff;
  164. f = Math.floor(unsigned / 0xffff);
  165. unsigned &= 0xffff;
  166. g = Math.floor(unsigned / 0xff);
  167. unsigned &= 0xff;
  168. h = Math.floor(unsigned);
  169. return chr(a) + chr(b) + chr(c) + chr(d) + chr(e) + chr(f) + chr(g) + chr(h);
  170. };
  171. /**
  172. * UTF8 methods
  173. */
  174. // Take a raw binary string and return a utf8 string
  175. BinaryParser.decode_utf8 = function decode_utf8 (binaryStr) {
  176. var len = binaryStr.length
  177. , decoded = ''
  178. , i = 0
  179. , c = 0
  180. , c1 = 0
  181. , c2 = 0
  182. , c3;
  183. while (i < len) {
  184. c = binaryStr.charCodeAt(i);
  185. if (c < 128) {
  186. decoded += String.fromCharCode(c);
  187. i++;
  188. } else if ((c > 191) && (c < 224)) {
  189. c2 = binaryStr.charCodeAt(i+1);
  190. decoded += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
  191. i += 2;
  192. } else {
  193. c2 = binaryStr.charCodeAt(i+1);
  194. c3 = binaryStr.charCodeAt(i+2);
  195. decoded += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
  196. i += 3;
  197. }
  198. }
  199. return decoded;
  200. };
  201. // Encode a cstring
  202. BinaryParser.encode_cstring = function encode_cstring (s) {
  203. return unescape(encodeURIComponent(s)) + BinaryParser.fromByte(0);
  204. };
  205. // Take a utf8 string and return a binary string
  206. BinaryParser.encode_utf8 = function encode_utf8 (s) {
  207. var a = ""
  208. , c;
  209. for (var n = 0, len = s.length; n < len; n++) {
  210. c = s.charCodeAt(n);
  211. if (c < 128) {
  212. a += String.fromCharCode(c);
  213. } else if ((c > 127) && (c < 2048)) {
  214. a += String.fromCharCode((c>>6) | 192) ;
  215. a += String.fromCharCode((c&63) | 128);
  216. } else {
  217. a += String.fromCharCode((c>>12) | 224);
  218. a += String.fromCharCode(((c>>6) & 63) | 128);
  219. a += String.fromCharCode((c&63) | 128);
  220. }
  221. }
  222. return a;
  223. };
  224. BinaryParser.hprint = function hprint (s) {
  225. var number;
  226. for (var i = 0, len = s.length; i < len; i++) {
  227. if (s.charCodeAt(i) < 32) {
  228. number = s.charCodeAt(i) <= 15
  229. ? "0" + s.charCodeAt(i).toString(16)
  230. : s.charCodeAt(i).toString(16);
  231. process.stdout.write(number + " ")
  232. } else {
  233. number = s.charCodeAt(i) <= 15
  234. ? "0" + s.charCodeAt(i).toString(16)
  235. : s.charCodeAt(i).toString(16);
  236. process.stdout.write(number + " ")
  237. }
  238. }
  239. process.stdout.write("\n\n");
  240. };
  241. BinaryParser.ilprint = function hprint (s) {
  242. var number;
  243. for (var i = 0, len = s.length; i < len; i++) {
  244. if (s.charCodeAt(i) < 32) {
  245. number = s.charCodeAt(i) <= 15
  246. ? "0" + s.charCodeAt(i).toString(10)
  247. : s.charCodeAt(i).toString(10);
  248. //sys.debug(number+' : ');
  249. } else {
  250. number = s.charCodeAt(i) <= 15
  251. ? "0" + s.charCodeAt(i).toString(10)
  252. : s.charCodeAt(i).toString(10);
  253. //sys.debug(number+' : '+ s.charAt(i));
  254. }
  255. }
  256. };
  257. BinaryParser.hlprint = function hprint (s) {
  258. var number;
  259. for (var i = 0, len = s.length; i < len; i++) {
  260. if (s.charCodeAt(i) < 32) {
  261. number = s.charCodeAt(i) <= 15
  262. ? "0" + s.charCodeAt(i).toString(16)
  263. : s.charCodeAt(i).toString(16);
  264. //sys.debug(number+' : ');
  265. } else {
  266. number = s.charCodeAt(i) <= 15
  267. ? "0" + s.charCodeAt(i).toString(16)
  268. : s.charCodeAt(i).toString(16);
  269. //sys.debug(number+' : '+ s.charAt(i));
  270. }
  271. }
  272. };
  273. /**
  274. * BinaryParser buffer constructor.
  275. */
  276. function BinaryParserBuffer (bigEndian, buffer) {
  277. this.bigEndian = bigEndian || 0;
  278. this.buffer = [];
  279. this.setBuffer(buffer);
  280. };
  281. BinaryParserBuffer.prototype.setBuffer = function setBuffer (data) {
  282. var l, i, b;
  283. if (data) {
  284. i = l = data.length;
  285. b = this.buffer = new Array(l);
  286. for (; i; b[l - i] = data.charCodeAt(--i));
  287. this.bigEndian && b.reverse();
  288. }
  289. };
  290. BinaryParserBuffer.prototype.hasNeededBits = function hasNeededBits (neededBits) {
  291. return this.buffer.length >= -(-neededBits >> 3);
  292. };
  293. BinaryParserBuffer.prototype.checkBuffer = function checkBuffer (neededBits) {
  294. if (!this.hasNeededBits(neededBits)) {
  295. throw new Error("checkBuffer::missing bytes");
  296. }
  297. };
  298. BinaryParserBuffer.prototype.readBits = function readBits (start, length) {
  299. //shl fix: Henri Torgemane ~1996 (compressed by Jonas Raoni)
  300. function shl (a, b) {
  301. for (; b--; a = ((a %= 0x7fffffff + 1) & 0x40000000) == 0x40000000 ? a * 2 : (a - 0x40000000) * 2 + 0x7fffffff + 1);
  302. return a;
  303. }
  304. if (start < 0 || length <= 0) {
  305. return 0;
  306. }
  307. this.checkBuffer(start + length);
  308. var offsetLeft
  309. , offsetRight = start % 8
  310. , curByte = this.buffer.length - ( start >> 3 ) - 1
  311. , lastByte = this.buffer.length + ( -( start + length ) >> 3 )
  312. , diff = curByte - lastByte
  313. , 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);
  314. for(; diff; sum += shl(this.buffer[lastByte++], (diff-- << 3) - offsetRight));
  315. return sum;
  316. };
  317. /**
  318. * Expose.
  319. */
  320. exports.BinaryParser = BinaryParser;
  321. BinaryParser.Buffer = BinaryParserBuffer;