int64.js 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. var util = require('../core').util;
  2. var toBuffer = util.buffer.toBuffer;
  3. /**
  4. * A lossless representation of a signed, 64-bit integer. Instances of this
  5. * class may be used in arithmetic expressions as if they were numeric
  6. * primitives, but the binary representation will be preserved unchanged as the
  7. * `bytes` property of the object. The bytes should be encoded as big-endian,
  8. * two's complement integers.
  9. * @param {Buffer} bytes
  10. *
  11. * @api private
  12. */
  13. function Int64(bytes) {
  14. if (bytes.length !== 8) {
  15. throw new Error('Int64 buffers must be exactly 8 bytes');
  16. }
  17. if (!util.Buffer.isBuffer(bytes)) bytes = toBuffer(bytes);
  18. this.bytes = bytes;
  19. }
  20. /**
  21. * @param {number} number
  22. * @returns {Int64}
  23. *
  24. * @api private
  25. */
  26. Int64.fromNumber = function(number) {
  27. if (number > 9223372036854775807 || number < -9223372036854775808) {
  28. throw new Error(
  29. number + ' is too large (or, if negative, too small) to represent as an Int64'
  30. );
  31. }
  32. var bytes = new Uint8Array(8);
  33. for (
  34. var i = 7, remaining = Math.abs(Math.round(number));
  35. i > -1 && remaining > 0;
  36. i--, remaining /= 256
  37. ) {
  38. bytes[i] = remaining;
  39. }
  40. if (number < 0) {
  41. negate(bytes);
  42. }
  43. return new Int64(bytes);
  44. };
  45. /**
  46. * @returns {number}
  47. *
  48. * @api private
  49. */
  50. Int64.prototype.valueOf = function() {
  51. var bytes = this.bytes.slice(0);
  52. var negative = bytes[0] & 128;
  53. if (negative) {
  54. negate(bytes);
  55. }
  56. return parseInt(bytes.toString('hex'), 16) * (negative ? -1 : 1);
  57. };
  58. Int64.prototype.toString = function() {
  59. return String(this.valueOf());
  60. };
  61. /**
  62. * @param {Buffer} bytes
  63. *
  64. * @api private
  65. */
  66. function negate(bytes) {
  67. for (var i = 0; i < 8; i++) {
  68. bytes[i] ^= 0xFF;
  69. }
  70. for (var i = 7; i > -1; i--) {
  71. bytes[i]++;
  72. if (bytes[i] !== 0) {
  73. break;
  74. }
  75. }
  76. }
  77. /**
  78. * @api private
  79. */
  80. module.exports = {
  81. Int64: Int64
  82. };