source: frontend/node_modules/node-int64/Int64.js

Last change on this file was 9af201e, checked in by MBK <marija.karapandzova@…>, 11 days ago

Fix frontend appearance

  • Property mode set to 100644
File size: 7.9 KB
Line 
1// Int64.js
2//
3// Copyright (c) 2012 Robert Kieffer
4// MIT License - http://opensource.org/licenses/mit-license.php
5
6/**
7 * Support for handling 64-bit int numbers in Javascript (node.js)
8 *
9 * JS Numbers are IEEE-754 binary double-precision floats, which limits the
10 * range of values that can be represented with integer precision to:
11 *
12 * 2^^53 <= N <= 2^53
13 *
14 * Int64 objects wrap a node Buffer that holds the 8-bytes of int64 data. These
15 * objects operate directly on the buffer which means that if they are created
16 * using an existing buffer then setting the value will modify the Buffer, and
17 * vice-versa.
18 *
19 * Internal Representation
20 *
21 * The internal buffer format is Big Endian. I.e. the most-significant byte is
22 * at buffer[0], the least-significant at buffer[7]. For the purposes of
23 * converting to/from JS native numbers, the value is assumed to be a signed
24 * integer stored in 2's complement form.
25 *
26 * For details about IEEE-754 see:
27 * http://en.wikipedia.org/wiki/Double_precision_floating-point_format
28 */
29
30// Useful masks and values for bit twiddling
31var MASK31 = 0x7fffffff, VAL31 = 0x80000000;
32var MASK32 = 0xffffffff, VAL32 = 0x100000000;
33
34// Map for converting hex octets to strings
35var _HEX = [];
36for (var i = 0; i < 256; i++) {
37 _HEX[i] = (i > 0xF ? '' : '0') + i.toString(16);
38}
39
40//
41// Int64
42//
43
44/**
45 * Constructor accepts any of the following argument types:
46 *
47 * new Int64(buffer[, offset=0]) - Existing Buffer with byte offset
48 * new Int64(Uint8Array[, offset=0]) - Existing Uint8Array with a byte offset
49 * new Int64(string) - Hex string (throws if n is outside int64 range)
50 * new Int64(number) - Number (throws if n is outside int64 range)
51 * new Int64(hi, lo) - Raw bits as two 32-bit values
52 */
53var Int64 = module.exports = function(a1, a2) {
54 if (a1 instanceof Buffer) {
55 this.buffer = a1;
56 this.offset = a2 || 0;
57 } else if (Object.prototype.toString.call(a1) == '[object Uint8Array]') {
58 // Under Browserify, Buffers can extend Uint8Arrays rather than an
59 // instance of Buffer. We could assume the passed in Uint8Array is actually
60 // a buffer but that won't handle the case where a raw Uint8Array is passed
61 // in. We construct a new Buffer just in case.
62 this.buffer = new Buffer(a1);
63 this.offset = a2 || 0;
64 } else {
65 this.buffer = this.buffer || new Buffer(8);
66 this.offset = 0;
67 this.setValue.apply(this, arguments);
68 }
69};
70
71
72// Max integer value that JS can accurately represent
73Int64.MAX_INT = Math.pow(2, 53);
74
75// Min integer value that JS can accurately represent
76Int64.MIN_INT = -Math.pow(2, 53);
77
78Int64.prototype = {
79
80 constructor: Int64,
81
82 /**
83 * Do in-place 2's compliment. See
84 * http://en.wikipedia.org/wiki/Two's_complement
85 */
86 _2scomp: function() {
87 var b = this.buffer, o = this.offset, carry = 1;
88 for (var i = o + 7; i >= o; i--) {
89 var v = (b[i] ^ 0xff) + carry;
90 b[i] = v & 0xff;
91 carry = v >> 8;
92 }
93 },
94
95 /**
96 * Set the value. Takes any of the following arguments:
97 *
98 * setValue(string) - A hexidecimal string
99 * setValue(number) - Number (throws if n is outside int64 range)
100 * setValue(hi, lo) - Raw bits as two 32-bit values
101 */
102 setValue: function(hi, lo) {
103 var negate = false;
104 if (arguments.length == 1) {
105 if (typeof(hi) == 'number') {
106 // Simplify bitfield retrieval by using abs() value. We restore sign
107 // later
108 negate = hi < 0;
109 hi = Math.abs(hi);
110 lo = hi % VAL32;
111 hi = hi / VAL32;
112 if (hi > VAL32) throw new RangeError(hi + ' is outside Int64 range');
113 hi = hi | 0;
114 } else if (typeof(hi) == 'string') {
115 hi = (hi + '').replace(/^0x/, '');
116 lo = hi.substr(-8);
117 hi = hi.length > 8 ? hi.substr(0, hi.length - 8) : '';
118 hi = parseInt(hi, 16);
119 lo = parseInt(lo, 16);
120 } else {
121 throw new Error(hi + ' must be a Number or String');
122 }
123 }
124
125 // Technically we should throw if hi or lo is outside int32 range here, but
126 // it's not worth the effort. Anything past the 32'nd bit is ignored.
127
128 // Copy bytes to buffer
129 var b = this.buffer, o = this.offset;
130 for (var i = 7; i >= 0; i--) {
131 b[o+i] = lo & 0xff;
132 lo = i == 4 ? hi : lo >>> 8;
133 }
134
135 // Restore sign of passed argument
136 if (negate) this._2scomp();
137 },
138
139 /**
140 * Convert to a native JS number.
141 *
142 * WARNING: Do not expect this value to be accurate to integer precision for
143 * large (positive or negative) numbers!
144 *
145 * @param allowImprecise If true, no check is performed to verify the
146 * returned value is accurate to integer precision. If false, imprecise
147 * numbers (very large positive or negative numbers) will be forced to +/-
148 * Infinity.
149 */
150 toNumber: function(allowImprecise) {
151 var b = this.buffer, o = this.offset;
152
153 // Running sum of octets, doing a 2's complement
154 var negate = b[o] & 0x80, x = 0, carry = 1;
155 for (var i = 7, m = 1; i >= 0; i--, m *= 256) {
156 var v = b[o+i];
157
158 // 2's complement for negative numbers
159 if (negate) {
160 v = (v ^ 0xff) + carry;
161 carry = v >> 8;
162 v = v & 0xff;
163 }
164
165 x += v * m;
166 }
167
168 // Return Infinity if we've lost integer precision
169 if (!allowImprecise && x >= Int64.MAX_INT) {
170 return negate ? -Infinity : Infinity;
171 }
172
173 return negate ? -x : x;
174 },
175
176 /**
177 * Convert to a JS Number. Returns +/-Infinity for values that can't be
178 * represented to integer precision.
179 */
180 valueOf: function() {
181 return this.toNumber(false);
182 },
183
184 /**
185 * Return string value
186 *
187 * @param radix Just like Number#toString()'s radix
188 */
189 toString: function(radix) {
190 return this.valueOf().toString(radix || 10);
191 },
192
193 /**
194 * Return a string showing the buffer octets, with MSB on the left.
195 *
196 * @param sep separator string. default is '' (empty string)
197 */
198 toOctetString: function(sep) {
199 var out = new Array(8);
200 var b = this.buffer, o = this.offset;
201 for (var i = 0; i < 8; i++) {
202 out[i] = _HEX[b[o+i]];
203 }
204 return out.join(sep || '');
205 },
206
207 /**
208 * Returns the int64's 8 bytes in a buffer.
209 *
210 * @param {bool} [rawBuffer=false] If no offset and this is true, return the internal buffer. Should only be used if
211 * you're discarding the Int64 afterwards, as it breaks encapsulation.
212 */
213 toBuffer: function(rawBuffer) {
214 if (rawBuffer && this.offset === 0) return this.buffer;
215
216 var out = new Buffer(8);
217 this.buffer.copy(out, 0, this.offset, this.offset + 8);
218 return out;
219 },
220
221 /**
222 * Copy 8 bytes of int64 into target buffer at target offset.
223 *
224 * @param {Buffer} targetBuffer Buffer to copy into.
225 * @param {number} [targetOffset=0] Offset into target buffer.
226 */
227 copy: function(targetBuffer, targetOffset) {
228 this.buffer.copy(targetBuffer, targetOffset || 0, this.offset, this.offset + 8);
229 },
230
231 /**
232 * Returns a number indicating whether this comes before or after or is the
233 * same as the other in sort order.
234 *
235 * @param {Int64} other Other Int64 to compare.
236 */
237 compare: function(other) {
238
239 // If sign bits differ ...
240 if ((this.buffer[this.offset] & 0x80) != (other.buffer[other.offset] & 0x80)) {
241 return other.buffer[other.offset] - this.buffer[this.offset];
242 }
243
244 // otherwise, compare bytes lexicographically
245 for (var i = 0; i < 8; i++) {
246 if (this.buffer[this.offset+i] !== other.buffer[other.offset+i]) {
247 return this.buffer[this.offset+i] - other.buffer[other.offset+i];
248 }
249 }
250 return 0;
251 },
252
253 /**
254 * Returns a boolean indicating if this integer is equal to other.
255 *
256 * @param {Int64} other Other Int64 to compare.
257 */
258 equals: function(other) {
259 return this.compare(other) === 0;
260 },
261
262 /**
263 * Pretty output in console.log
264 */
265 inspect: function() {
266 return '[Int64 value:' + this + ' octets:' + this.toOctetString(' ') + ']';
267 }
268};
Note: See TracBrowser for help on using the repository browser.