bson 4.0.4 → 4.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/HISTORY.md +56 -1
  2. package/README.md +7 -9
  3. package/bower.json +1 -1
  4. package/bson.d.ts +983 -0
  5. package/dist/bson.browser.esm.js +7261 -5004
  6. package/dist/bson.browser.esm.js.map +1 -0
  7. package/dist/bson.browser.umd.js +7319 -5099
  8. package/dist/bson.browser.umd.js.map +1 -0
  9. package/dist/bson.bundle.js +8168 -9216
  10. package/dist/bson.bundle.js.map +1 -0
  11. package/dist/bson.esm.js +5643 -5409
  12. package/dist/bson.esm.js.map +1 -0
  13. package/etc/prepare.js +19 -0
  14. package/lib/binary.js +194 -377
  15. package/lib/binary.js.map +1 -0
  16. package/lib/bson.js +200 -243
  17. package/lib/bson.js.map +1 -0
  18. package/lib/code.js +36 -39
  19. package/lib/code.js.map +1 -0
  20. package/lib/constants.js +78 -203
  21. package/lib/constants.js.map +1 -0
  22. package/lib/db_ref.js +79 -79
  23. package/lib/db_ref.js.map +1 -0
  24. package/lib/decimal128.js +647 -760
  25. package/lib/decimal128.js.map +1 -0
  26. package/lib/double.js +61 -58
  27. package/lib/double.js.map +1 -0
  28. package/lib/ensure_buffer.js +22 -18
  29. package/lib/ensure_buffer.js.map +1 -0
  30. package/lib/extended_json.js +305 -322
  31. package/lib/extended_json.js.map +1 -0
  32. package/lib/float_parser.js +98 -104
  33. package/lib/float_parser.js.map +1 -0
  34. package/lib/int_32.js +45 -47
  35. package/lib/int_32.js.map +1 -0
  36. package/lib/long.js +876 -16
  37. package/lib/long.js.map +1 -0
  38. package/lib/map.js +123 -124
  39. package/lib/map.js.map +1 -0
  40. package/lib/max_key.js +21 -23
  41. package/lib/max_key.js.map +1 -0
  42. package/lib/min_key.js +21 -23
  43. package/lib/min_key.js.map +1 -0
  44. package/lib/objectid.js +264 -382
  45. package/lib/objectid.js.map +1 -0
  46. package/lib/parser/calculate_size.js +185 -224
  47. package/lib/parser/calculate_size.js.map +1 -0
  48. package/lib/parser/deserializer.js +543 -620
  49. package/lib/parser/deserializer.js.map +1 -0
  50. package/lib/parser/serializer.js +774 -918
  51. package/lib/parser/serializer.js.map +1 -0
  52. package/lib/parser/utils.js +81 -30
  53. package/lib/parser/utils.js.map +1 -0
  54. package/lib/regexp.js +54 -70
  55. package/lib/regexp.js.map +1 -0
  56. package/lib/symbol.js +40 -56
  57. package/lib/symbol.js.map +1 -0
  58. package/lib/timestamp.js +70 -95
  59. package/lib/timestamp.js.map +1 -0
  60. package/lib/uuid.js +48 -0
  61. package/lib/uuid.js.map +1 -0
  62. package/lib/validate_utf8.js +32 -33
  63. package/lib/validate_utf8.js.map +1 -0
  64. package/package.json +53 -31
  65. package/src/binary.ts +270 -0
  66. package/src/bson.ts +326 -0
  67. package/src/code.ts +57 -0
  68. package/src/constants.ts +104 -0
  69. package/src/db_ref.ts +115 -0
  70. package/src/decimal128.ts +801 -0
  71. package/src/double.ts +85 -0
  72. package/src/ensure_buffer.ts +26 -0
  73. package/src/extended_json.ts +395 -0
  74. package/src/float_parser.ts +152 -0
  75. package/src/int_32.ts +64 -0
  76. package/src/long.ts +1000 -0
  77. package/src/map.ts +139 -0
  78. package/src/max_key.ts +33 -0
  79. package/src/min_key.ts +33 -0
  80. package/src/objectid.ts +377 -0
  81. package/src/parser/calculate_size.ts +230 -0
  82. package/src/parser/deserializer.ts +655 -0
  83. package/src/parser/serializer.ts +1069 -0
  84. package/src/parser/utils.ts +93 -0
  85. package/src/regexp.ts +92 -0
  86. package/src/symbol.ts +57 -0
  87. package/src/timestamp.ts +103 -0
  88. package/src/uuid.ts +57 -0
  89. package/src/validate_utf8.ts +47 -0
  90. package/lib/fnv1a.js +0 -48
package/lib/decimal128.js CHANGED
@@ -1,807 +1,694 @@
1
- 'use strict';
2
-
3
- let Long = require('./long');
4
- const Buffer = require('buffer').Buffer;
5
-
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Decimal128 = void 0;
4
+ const buffer_1 = require("buffer");
5
+ const long_1 = require("./long");
6
6
  const PARSE_STRING_REGEXP = /^(\+|-)?(\d+|(\d*\.\d*))?(E|e)?([-+])?(\d+)?$/;
7
7
  const PARSE_INF_REGEXP = /^(\+|-)?(Infinity|inf)$/i;
8
8
  const PARSE_NAN_REGEXP = /^(\+|-)?NaN$/i;
9
-
10
9
  const EXPONENT_MAX = 6111;
11
10
  const EXPONENT_MIN = -6176;
12
11
  const EXPONENT_BIAS = 6176;
13
12
  const MAX_DIGITS = 34;
14
-
15
13
  // Nan value bits as 32 bit values (due to lack of longs)
16
14
  const NAN_BUFFER = [
17
- 0x7c,
18
- 0x00,
19
- 0x00,
20
- 0x00,
21
- 0x00,
22
- 0x00,
23
- 0x00,
24
- 0x00,
25
- 0x00,
26
- 0x00,
27
- 0x00,
28
- 0x00,
29
- 0x00,
30
- 0x00,
31
- 0x00,
32
- 0x00
15
+ 0x7c,
16
+ 0x00,
17
+ 0x00,
18
+ 0x00,
19
+ 0x00,
20
+ 0x00,
21
+ 0x00,
22
+ 0x00,
23
+ 0x00,
24
+ 0x00,
25
+ 0x00,
26
+ 0x00,
27
+ 0x00,
28
+ 0x00,
29
+ 0x00,
30
+ 0x00
33
31
  ].reverse();
34
32
  // Infinity value bits 32 bit values (due to lack of longs)
35
33
  const INF_NEGATIVE_BUFFER = [
36
- 0xf8,
37
- 0x00,
38
- 0x00,
39
- 0x00,
40
- 0x00,
41
- 0x00,
42
- 0x00,
43
- 0x00,
44
- 0x00,
45
- 0x00,
46
- 0x00,
47
- 0x00,
48
- 0x00,
49
- 0x00,
50
- 0x00,
51
- 0x00
34
+ 0xf8,
35
+ 0x00,
36
+ 0x00,
37
+ 0x00,
38
+ 0x00,
39
+ 0x00,
40
+ 0x00,
41
+ 0x00,
42
+ 0x00,
43
+ 0x00,
44
+ 0x00,
45
+ 0x00,
46
+ 0x00,
47
+ 0x00,
48
+ 0x00,
49
+ 0x00
52
50
  ].reverse();
53
51
  const INF_POSITIVE_BUFFER = [
54
- 0x78,
55
- 0x00,
56
- 0x00,
57
- 0x00,
58
- 0x00,
59
- 0x00,
60
- 0x00,
61
- 0x00,
62
- 0x00,
63
- 0x00,
64
- 0x00,
65
- 0x00,
66
- 0x00,
67
- 0x00,
68
- 0x00,
69
- 0x00
52
+ 0x78,
53
+ 0x00,
54
+ 0x00,
55
+ 0x00,
56
+ 0x00,
57
+ 0x00,
58
+ 0x00,
59
+ 0x00,
60
+ 0x00,
61
+ 0x00,
62
+ 0x00,
63
+ 0x00,
64
+ 0x00,
65
+ 0x00,
66
+ 0x00,
67
+ 0x00
70
68
  ].reverse();
71
-
72
69
  const EXPONENT_REGEX = /^([-+])?(\d+)?$/;
73
-
70
+ // Extract least significant 5 bits
71
+ const COMBINATION_MASK = 0x1f;
72
+ // Extract least significant 14 bits
73
+ const EXPONENT_MASK = 0x3fff;
74
+ // Value of combination field for Inf
75
+ const COMBINATION_INFINITY = 30;
76
+ // Value of combination field for NaN
77
+ const COMBINATION_NAN = 31;
74
78
  // Detect if the value is a digit
75
79
  function isDigit(value) {
76
- return !isNaN(parseInt(value, 10));
80
+ return !isNaN(parseInt(value, 10));
77
81
  }
78
-
79
82
  // Divide two uint128 values
80
83
  function divideu128(value) {
81
- const DIVISOR = Long.fromNumber(1000 * 1000 * 1000);
82
- let _rem = Long.fromNumber(0);
83
-
84
- if (!value.parts[0] && !value.parts[1] && !value.parts[2] && !value.parts[3]) {
84
+ const DIVISOR = long_1.Long.fromNumber(1000 * 1000 * 1000);
85
+ let _rem = long_1.Long.fromNumber(0);
86
+ if (!value.parts[0] && !value.parts[1] && !value.parts[2] && !value.parts[3]) {
87
+ return { quotient: value, rem: _rem };
88
+ }
89
+ for (let i = 0; i <= 3; i++) {
90
+ // Adjust remainder to match value of next dividend
91
+ _rem = _rem.shiftLeft(32);
92
+ // Add the divided to _rem
93
+ _rem = _rem.add(new long_1.Long(value.parts[i], 0));
94
+ value.parts[i] = _rem.div(DIVISOR).low;
95
+ _rem = _rem.modulo(DIVISOR);
96
+ }
85
97
  return { quotient: value, rem: _rem };
86
- }
87
-
88
- for (let i = 0; i <= 3; i++) {
89
- // Adjust remainder to match value of next dividend
90
- _rem = _rem.shiftLeft(32);
91
- // Add the divided to _rem
92
- _rem = _rem.add(new Long(value.parts[i], 0));
93
- value.parts[i] = _rem.div(DIVISOR).low;
94
- _rem = _rem.modulo(DIVISOR);
95
- }
96
-
97
- return { quotient: value, rem: _rem };
98
98
  }
99
-
100
99
  // Multiply two Long values and return the 128 bit value
101
100
  function multiply64x2(left, right) {
102
- if (!left && !right) {
103
- return { high: Long.fromNumber(0), low: Long.fromNumber(0) };
104
- }
105
-
106
- const leftHigh = left.shiftRightUnsigned(32);
107
- const leftLow = new Long(left.getLowBits(), 0);
108
- const rightHigh = right.shiftRightUnsigned(32);
109
- const rightLow = new Long(right.getLowBits(), 0);
110
-
111
- let productHigh = leftHigh.multiply(rightHigh);
112
- let productMid = leftHigh.multiply(rightLow);
113
- let productMid2 = leftLow.multiply(rightHigh);
114
- let productLow = leftLow.multiply(rightLow);
115
-
116
- productHigh = productHigh.add(productMid.shiftRightUnsigned(32));
117
- productMid = new Long(productMid.getLowBits(), 0)
118
- .add(productMid2)
119
- .add(productLow.shiftRightUnsigned(32));
120
-
121
- productHigh = productHigh.add(productMid.shiftRightUnsigned(32));
122
- productLow = productMid.shiftLeft(32).add(new Long(productLow.getLowBits(), 0));
123
-
124
- // Return the 128 bit result
125
- return { high: productHigh, low: productLow };
101
+ if (!left && !right) {
102
+ return { high: long_1.Long.fromNumber(0), low: long_1.Long.fromNumber(0) };
103
+ }
104
+ const leftHigh = left.shiftRightUnsigned(32);
105
+ const leftLow = new long_1.Long(left.getLowBits(), 0);
106
+ const rightHigh = right.shiftRightUnsigned(32);
107
+ const rightLow = new long_1.Long(right.getLowBits(), 0);
108
+ let productHigh = leftHigh.multiply(rightHigh);
109
+ let productMid = leftHigh.multiply(rightLow);
110
+ const productMid2 = leftLow.multiply(rightHigh);
111
+ let productLow = leftLow.multiply(rightLow);
112
+ productHigh = productHigh.add(productMid.shiftRightUnsigned(32));
113
+ productMid = new long_1.Long(productMid.getLowBits(), 0)
114
+ .add(productMid2)
115
+ .add(productLow.shiftRightUnsigned(32));
116
+ productHigh = productHigh.add(productMid.shiftRightUnsigned(32));
117
+ productLow = productMid.shiftLeft(32).add(new long_1.Long(productLow.getLowBits(), 0));
118
+ // Return the 128 bit result
119
+ return { high: productHigh, low: productLow };
126
120
  }
127
-
128
121
  function lessThan(left, right) {
129
- // Make values unsigned
130
- const uhleft = left.high >>> 0;
131
- const uhright = right.high >>> 0;
132
-
133
- // Compare high bits first
134
- if (uhleft < uhright) {
135
- return true;
136
- } else if (uhleft === uhright) {
137
- const ulleft = left.low >>> 0;
138
- const ulright = right.low >>> 0;
139
- if (ulleft < ulright) return true;
140
- }
141
-
142
- return false;
122
+ // Make values unsigned
123
+ const uhleft = left.high >>> 0;
124
+ const uhright = right.high >>> 0;
125
+ // Compare high bits first
126
+ if (uhleft < uhright) {
127
+ return true;
128
+ }
129
+ else if (uhleft === uhright) {
130
+ const ulleft = left.low >>> 0;
131
+ const ulright = right.low >>> 0;
132
+ if (ulleft < ulright)
133
+ return true;
134
+ }
135
+ return false;
143
136
  }
144
-
145
137
  function invalidErr(string, message) {
146
- throw new TypeError(`"${string}" is not a valid Decimal128 string - ${message}`);
138
+ throw new TypeError(`"${string}" is not a valid Decimal128 string - ${message}`);
147
139
  }
148
-
149
140
  /**
150
141
  * A class representation of the BSON Decimal128 type.
151
- *
152
- * @class
153
- * @param {Buffer} bytes a buffer containing the raw Decimal128 bytes.
154
- * @return {Double}
142
+ * @public
155
143
  */
156
- function Decimal128(bytes) {
157
- this.bytes = bytes;
158
- }
159
-
160
- /**
161
- * Create a Decimal128 instance from a string representation
162
- *
163
- * @method
164
- * @param {string} string a numeric string representation.
165
- * @return {Decimal128} returns a Decimal128 instance.
166
- */
167
- Decimal128.fromString = function(string) {
168
- // Parse state tracking
169
- let isNegative = false;
170
- let sawRadix = false;
171
- let foundNonZero = false;
172
-
173
- // Total number of significant digits (no leading or trailing zero)
174
- let significantDigits = 0;
175
- // Total number of significand digits read
176
- let nDigitsRead = 0;
177
- // Total number of digits (no leading zeros)
178
- let nDigits = 0;
179
- // The number of the digits after radix
180
- let radixPosition = 0;
181
- // The index of the first non-zero in *str*
182
- let firstNonZero = 0;
183
-
184
- // Digits Array
185
- const digits = [0];
186
- // The number of digits in digits
187
- let nDigitsStored = 0;
188
- // Insertion pointer for digits
189
- let digitsInsert = 0;
190
- // The index of the first non-zero digit
191
- let firstDigit = 0;
192
- // The index of the last digit
193
- let lastDigit = 0;
194
-
195
- // Exponent
196
- let exponent = 0;
197
- // loop index over array
198
- let i = 0;
199
- // The high 17 digits of the significand
200
- let significandHigh = [0, 0];
201
- // The low 17 digits of the significand
202
- let significandLow = [0, 0];
203
- // The biased exponent
204
- let biasedExponent = 0;
205
-
206
- // Read index
207
- let index = 0;
208
-
209
- // Naively prevent against REDOS attacks.
210
- // TODO: implementing a custom parsing for this, or refactoring the regex would yield
211
- // further gains.
212
- if (string.length >= 7000) {
213
- throw new TypeError('' + string + ' not a valid Decimal128 string');
214
- }
215
-
216
- // Results
217
- const stringMatch = string.match(PARSE_STRING_REGEXP);
218
- const infMatch = string.match(PARSE_INF_REGEXP);
219
- const nanMatch = string.match(PARSE_NAN_REGEXP);
220
-
221
- // Validate the string
222
- if ((!stringMatch && !infMatch && !nanMatch) || string.length === 0) {
223
- throw new TypeError('' + string + ' not a valid Decimal128 string');
224
- }
225
-
226
- if (stringMatch) {
227
- // full_match = stringMatch[0]
228
- // sign = stringMatch[1]
229
-
230
- let unsignedNumber = stringMatch[2];
231
- // stringMatch[3] is undefined if a whole number (ex "1", 12")
232
- // but defined if a number w/ decimal in it (ex "1.0, 12.2")
233
-
234
- let e = stringMatch[4];
235
- let expSign = stringMatch[5];
236
- let expNumber = stringMatch[6];
237
-
238
- // they provided e, but didn't give an exponent number. for ex "1e"
239
- if (e && expNumber === undefined) invalidErr(string, 'missing exponent power');
240
-
241
- // they provided e, but didn't give a number before it. for ex "e1"
242
- if (e && unsignedNumber === undefined) invalidErr(string, 'missing exponent base');
243
-
244
- if (e === undefined && (expSign || expNumber)) {
245
- invalidErr(string, 'missing e before exponent');
246
- }
247
- }
248
-
249
- // Get the negative or positive sign
250
- if (string[index] === '+' || string[index] === '-') {
251
- isNegative = string[index++] === '-';
252
- }
253
-
254
- // Check if user passed Infinity or NaN
255
- if (!isDigit(string[index]) && string[index] !== '.') {
256
- if (string[index] === 'i' || string[index] === 'I') {
257
- return new Decimal128(Buffer.from(isNegative ? INF_NEGATIVE_BUFFER : INF_POSITIVE_BUFFER));
258
- } else if (string[index] === 'N') {
259
- return new Decimal128(Buffer.from(NAN_BUFFER));
260
- }
261
- }
262
-
263
- // Read all the digits
264
- while (isDigit(string[index]) || string[index] === '.') {
265
- if (string[index] === '.') {
266
- if (sawRadix) invalidErr(string, 'contains multiple periods');
267
-
268
- sawRadix = true;
269
- index = index + 1;
270
- continue;
144
+ class Decimal128 {
145
+ /** @param bytes - a buffer containing the raw Decimal128 bytes in little endian order */
146
+ constructor(bytes) {
147
+ this.bytes = bytes;
271
148
  }
272
-
273
- if (nDigitsStored < 34) {
274
- if (string[index] !== '0' || foundNonZero) {
275
- if (!foundNonZero) {
276
- firstNonZero = nDigitsRead;
149
+ /**
150
+ * Create a Decimal128 instance from a string representation
151
+ *
152
+ * @param representation - a numeric string representation.
153
+ */
154
+ static fromString(representation) {
155
+ // Parse state tracking
156
+ let isNegative = false;
157
+ let sawRadix = false;
158
+ let foundNonZero = false;
159
+ // Total number of significant digits (no leading or trailing zero)
160
+ let significantDigits = 0;
161
+ // Total number of significand digits read
162
+ let nDigitsRead = 0;
163
+ // Total number of digits (no leading zeros)
164
+ let nDigits = 0;
165
+ // The number of the digits after radix
166
+ let radixPosition = 0;
167
+ // The index of the first non-zero in *str*
168
+ let firstNonZero = 0;
169
+ // Digits Array
170
+ const digits = [0];
171
+ // The number of digits in digits
172
+ let nDigitsStored = 0;
173
+ // Insertion pointer for digits
174
+ let digitsInsert = 0;
175
+ // The index of the first non-zero digit
176
+ let firstDigit = 0;
177
+ // The index of the last digit
178
+ let lastDigit = 0;
179
+ // Exponent
180
+ let exponent = 0;
181
+ // loop index over array
182
+ let i = 0;
183
+ // The high 17 digits of the significand
184
+ let significandHigh = new long_1.Long(0, 0);
185
+ // The low 17 digits of the significand
186
+ let significandLow = new long_1.Long(0, 0);
187
+ // The biased exponent
188
+ let biasedExponent = 0;
189
+ // Read index
190
+ let index = 0;
191
+ // Naively prevent against REDOS attacks.
192
+ // TODO: implementing a custom parsing for this, or refactoring the regex would yield
193
+ // further gains.
194
+ if (representation.length >= 7000) {
195
+ throw new TypeError('' + representation + ' not a valid Decimal128 string');
277
196
  }
278
-
279
- foundNonZero = true;
280
-
281
- // Only store 34 digits
282
- digits[digitsInsert++] = parseInt(string[index], 10);
283
- nDigitsStored = nDigitsStored + 1;
284
- }
285
- }
286
-
287
- if (foundNonZero) nDigits = nDigits + 1;
288
- if (sawRadix) radixPosition = radixPosition + 1;
289
-
290
- nDigitsRead = nDigitsRead + 1;
291
- index = index + 1;
292
- }
293
-
294
- if (sawRadix && !nDigitsRead) throw new TypeError('' + string + ' not a valid Decimal128 string');
295
-
296
- // Read exponent if exists
297
- if (string[index] === 'e' || string[index] === 'E') {
298
- // Read exponent digits
299
- const match = string.substr(++index).match(EXPONENT_REGEX);
300
-
301
- // No digits read
302
- if (!match || !match[2]) return new Decimal128(Buffer.from(NAN_BUFFER));
303
-
304
- // Get exponent
305
- exponent = parseInt(match[0], 10);
306
-
307
- // Adjust the index
308
- index = index + match[0].length;
309
- }
310
-
311
- // Return not a number
312
- if (string[index]) return new Decimal128(Buffer.from(NAN_BUFFER));
313
-
314
- // Done reading input
315
- // Find first non-zero digit in digits
316
- firstDigit = 0;
317
-
318
- if (!nDigitsStored) {
319
- firstDigit = 0;
320
- lastDigit = 0;
321
- digits[0] = 0;
322
- nDigits = 1;
323
- nDigitsStored = 1;
324
- significantDigits = 0;
325
- } else {
326
- lastDigit = nDigitsStored - 1;
327
- significantDigits = nDigits;
328
- if (significantDigits !== 1) {
329
- while (string[firstNonZero + significantDigits - 1] === '0') {
330
- significantDigits = significantDigits - 1;
331
- }
332
- }
333
- }
334
-
335
- // Normalization of exponent
336
- // Correct exponent based on radix position, and shift significand as needed
337
- // to represent user input
338
-
339
- // Overflow prevention
340
- if (exponent <= radixPosition && radixPosition - exponent > 1 << 14) {
341
- exponent = EXPONENT_MIN;
342
- } else {
343
- exponent = exponent - radixPosition;
344
- }
345
-
346
- // Attempt to normalize the exponent
347
- while (exponent > EXPONENT_MAX) {
348
- // Shift exponent to significand and decrease
349
- lastDigit = lastDigit + 1;
350
-
351
- if (lastDigit - firstDigit > MAX_DIGITS) {
352
- // Check if we have a zero then just hard clamp, otherwise fail
353
- const digitsString = digits.join('');
354
- if (digitsString.match(/^0+$/)) {
355
- exponent = EXPONENT_MAX;
356
- break;
357
- }
358
-
359
- invalidErr(string, 'overflow');
360
- }
361
- exponent = exponent - 1;
362
- }
363
-
364
- while (exponent < EXPONENT_MIN || nDigitsStored < nDigits) {
365
- // Shift last digit. can only do this if < significant digits than # stored.
366
- if (lastDigit === 0 && significantDigits < nDigitsStored) {
367
- exponent = EXPONENT_MIN;
368
- significantDigits = 0;
369
- break;
370
- }
371
-
372
- if (nDigitsStored < nDigits) {
373
- // adjust to match digits not stored
374
- nDigits = nDigits - 1;
375
- } else {
376
- // adjust to round
377
- lastDigit = lastDigit - 1;
378
- }
379
-
380
- if (exponent < EXPONENT_MAX) {
381
- exponent = exponent + 1;
382
- } else {
383
- // Check if we have a zero then just hard clamp, otherwise fail
384
- const digitsString = digits.join('');
385
- if (digitsString.match(/^0+$/)) {
386
- exponent = EXPONENT_MAX;
387
- break;
388
- }
389
- invalidErr(string, 'overflow');
390
- }
391
- }
392
-
393
- // Round
394
- // We've normalized the exponent, but might still need to round.
395
- if (lastDigit - firstDigit + 1 < significantDigits) {
396
- let endOfString = nDigitsRead;
397
-
398
- // If we have seen a radix point, 'string' is 1 longer than we have
399
- // documented with ndigits_read, so inc the position of the first nonzero
400
- // digit and the position that digits are read to.
401
- if (sawRadix) {
402
- firstNonZero = firstNonZero + 1;
403
- endOfString = endOfString + 1;
404
- }
405
- // if negative, we need to increment again to account for - sign at start.
406
- if (isNegative) {
407
- firstNonZero = firstNonZero + 1;
408
- endOfString = endOfString + 1;
409
- }
410
-
411
- const roundDigit = parseInt(string[firstNonZero + lastDigit + 1], 10);
412
- let roundBit = 0;
413
-
414
- if (roundDigit >= 5) {
415
- roundBit = 1;
416
- if (roundDigit === 5) {
417
- roundBit = digits[lastDigit] % 2 === 1;
418
- for (i = firstNonZero + lastDigit + 2; i < endOfString; i++) {
419
- if (parseInt(string[i], 10)) {
420
- roundBit = 1;
421
- break;
422
- }
197
+ // Results
198
+ const stringMatch = representation.match(PARSE_STRING_REGEXP);
199
+ const infMatch = representation.match(PARSE_INF_REGEXP);
200
+ const nanMatch = representation.match(PARSE_NAN_REGEXP);
201
+ // Validate the string
202
+ if ((!stringMatch && !infMatch && !nanMatch) || representation.length === 0) {
203
+ throw new TypeError('' + representation + ' not a valid Decimal128 string');
423
204
  }
424
- }
425
- }
426
-
427
- if (roundBit) {
428
- let dIdx = lastDigit;
429
-
430
- for (; dIdx >= 0; dIdx--) {
431
- if (++digits[dIdx] > 9) {
432
- digits[dIdx] = 0;
433
-
434
- // overflowed most significant digit
435
- if (dIdx === 0) {
205
+ if (stringMatch) {
206
+ // full_match = stringMatch[0]
207
+ // sign = stringMatch[1]
208
+ const unsignedNumber = stringMatch[2];
209
+ // stringMatch[3] is undefined if a whole number (ex "1", 12")
210
+ // but defined if a number w/ decimal in it (ex "1.0, 12.2")
211
+ const e = stringMatch[4];
212
+ const expSign = stringMatch[5];
213
+ const expNumber = stringMatch[6];
214
+ // they provided e, but didn't give an exponent number. for ex "1e"
215
+ if (e && expNumber === undefined)
216
+ invalidErr(representation, 'missing exponent power');
217
+ // they provided e, but didn't give a number before it. for ex "e1"
218
+ if (e && unsignedNumber === undefined)
219
+ invalidErr(representation, 'missing exponent base');
220
+ if (e === undefined && (expSign || expNumber)) {
221
+ invalidErr(representation, 'missing e before exponent');
222
+ }
223
+ }
224
+ // Get the negative or positive sign
225
+ if (representation[index] === '+' || representation[index] === '-') {
226
+ isNegative = representation[index++] === '-';
227
+ }
228
+ // Check if user passed Infinity or NaN
229
+ if (!isDigit(representation[index]) && representation[index] !== '.') {
230
+ if (representation[index] === 'i' || representation[index] === 'I') {
231
+ return new Decimal128(buffer_1.Buffer.from(isNegative ? INF_NEGATIVE_BUFFER : INF_POSITIVE_BUFFER));
232
+ }
233
+ else if (representation[index] === 'N') {
234
+ return new Decimal128(buffer_1.Buffer.from(NAN_BUFFER));
235
+ }
236
+ }
237
+ // Read all the digits
238
+ while (isDigit(representation[index]) || representation[index] === '.') {
239
+ if (representation[index] === '.') {
240
+ if (sawRadix)
241
+ invalidErr(representation, 'contains multiple periods');
242
+ sawRadix = true;
243
+ index = index + 1;
244
+ continue;
245
+ }
246
+ if (nDigitsStored < 34) {
247
+ if (representation[index] !== '0' || foundNonZero) {
248
+ if (!foundNonZero) {
249
+ firstNonZero = nDigitsRead;
250
+ }
251
+ foundNonZero = true;
252
+ // Only store 34 digits
253
+ digits[digitsInsert++] = parseInt(representation[index], 10);
254
+ nDigitsStored = nDigitsStored + 1;
255
+ }
256
+ }
257
+ if (foundNonZero)
258
+ nDigits = nDigits + 1;
259
+ if (sawRadix)
260
+ radixPosition = radixPosition + 1;
261
+ nDigitsRead = nDigitsRead + 1;
262
+ index = index + 1;
263
+ }
264
+ if (sawRadix && !nDigitsRead)
265
+ throw new TypeError('' + representation + ' not a valid Decimal128 string');
266
+ // Read exponent if exists
267
+ if (representation[index] === 'e' || representation[index] === 'E') {
268
+ // Read exponent digits
269
+ const match = representation.substr(++index).match(EXPONENT_REGEX);
270
+ // No digits read
271
+ if (!match || !match[2])
272
+ return new Decimal128(buffer_1.Buffer.from(NAN_BUFFER));
273
+ // Get exponent
274
+ exponent = parseInt(match[0], 10);
275
+ // Adjust the index
276
+ index = index + match[0].length;
277
+ }
278
+ // Return not a number
279
+ if (representation[index])
280
+ return new Decimal128(buffer_1.Buffer.from(NAN_BUFFER));
281
+ // Done reading input
282
+ // Find first non-zero digit in digits
283
+ firstDigit = 0;
284
+ if (!nDigitsStored) {
285
+ firstDigit = 0;
286
+ lastDigit = 0;
287
+ digits[0] = 0;
288
+ nDigits = 1;
289
+ nDigitsStored = 1;
290
+ significantDigits = 0;
291
+ }
292
+ else {
293
+ lastDigit = nDigitsStored - 1;
294
+ significantDigits = nDigits;
295
+ if (significantDigits !== 1) {
296
+ while (representation[firstNonZero + significantDigits - 1] === '0') {
297
+ significantDigits = significantDigits - 1;
298
+ }
299
+ }
300
+ }
301
+ // Normalization of exponent
302
+ // Correct exponent based on radix position, and shift significand as needed
303
+ // to represent user input
304
+ // Overflow prevention
305
+ if (exponent <= radixPosition && radixPosition - exponent > 1 << 14) {
306
+ exponent = EXPONENT_MIN;
307
+ }
308
+ else {
309
+ exponent = exponent - radixPosition;
310
+ }
311
+ // Attempt to normalize the exponent
312
+ while (exponent > EXPONENT_MAX) {
313
+ // Shift exponent to significand and decrease
314
+ lastDigit = lastDigit + 1;
315
+ if (lastDigit - firstDigit > MAX_DIGITS) {
316
+ // Check if we have a zero then just hard clamp, otherwise fail
317
+ const digitsString = digits.join('');
318
+ if (digitsString.match(/^0+$/)) {
319
+ exponent = EXPONENT_MAX;
320
+ break;
321
+ }
322
+ invalidErr(representation, 'overflow');
323
+ }
324
+ exponent = exponent - 1;
325
+ }
326
+ while (exponent < EXPONENT_MIN || nDigitsStored < nDigits) {
327
+ // Shift last digit. can only do this if < significant digits than # stored.
328
+ if (lastDigit === 0 && significantDigits < nDigitsStored) {
329
+ exponent = EXPONENT_MIN;
330
+ significantDigits = 0;
331
+ break;
332
+ }
333
+ if (nDigitsStored < nDigits) {
334
+ // adjust to match digits not stored
335
+ nDigits = nDigits - 1;
336
+ }
337
+ else {
338
+ // adjust to round
339
+ lastDigit = lastDigit - 1;
340
+ }
436
341
  if (exponent < EXPONENT_MAX) {
437
- exponent = exponent + 1;
438
- digits[dIdx] = 1;
439
- } else {
440
- return new Decimal128(
441
- Buffer.from(isNegative ? INF_NEGATIVE_BUFFER : INF_POSITIVE_BUFFER)
442
- );
342
+ exponent = exponent + 1;
343
+ }
344
+ else {
345
+ // Check if we have a zero then just hard clamp, otherwise fail
346
+ const digitsString = digits.join('');
347
+ if (digitsString.match(/^0+$/)) {
348
+ exponent = EXPONENT_MAX;
349
+ break;
350
+ }
351
+ invalidErr(representation, 'overflow');
443
352
  }
444
- }
445
353
  }
446
- }
447
- }
448
- }
449
-
450
- // Encode significand
451
- // The high 17 digits of the significand
452
- significandHigh = Long.fromNumber(0);
453
- // The low 17 digits of the significand
454
- significandLow = Long.fromNumber(0);
455
-
456
- // read a zero
457
- if (significantDigits === 0) {
458
- significandHigh = Long.fromNumber(0);
459
- significandLow = Long.fromNumber(0);
460
- } else if (lastDigit - firstDigit < 17) {
461
- let dIdx = firstDigit;
462
- significandLow = Long.fromNumber(digits[dIdx++]);
463
- significandHigh = new Long(0, 0);
464
-
465
- for (; dIdx <= lastDigit; dIdx++) {
466
- significandLow = significandLow.multiply(Long.fromNumber(10));
467
- significandLow = significandLow.add(Long.fromNumber(digits[dIdx]));
468
- }
469
- } else {
470
- let dIdx = firstDigit;
471
- significandHigh = Long.fromNumber(digits[dIdx++]);
472
-
473
- for (; dIdx <= lastDigit - 17; dIdx++) {
474
- significandHigh = significandHigh.multiply(Long.fromNumber(10));
475
- significandHigh = significandHigh.add(Long.fromNumber(digits[dIdx]));
476
- }
477
-
478
- significandLow = Long.fromNumber(digits[dIdx++]);
479
-
480
- for (; dIdx <= lastDigit; dIdx++) {
481
- significandLow = significandLow.multiply(Long.fromNumber(10));
482
- significandLow = significandLow.add(Long.fromNumber(digits[dIdx]));
483
- }
484
- }
485
-
486
- const significand = multiply64x2(significandHigh, Long.fromString('100000000000000000'));
487
- significand.low = significand.low.add(significandLow);
488
-
489
- if (lessThan(significand.low, significandLow)) {
490
- significand.high = significand.high.add(Long.fromNumber(1));
491
- }
492
-
493
- // Biased exponent
494
- biasedExponent = exponent + EXPONENT_BIAS;
495
- const dec = { low: Long.fromNumber(0), high: Long.fromNumber(0) };
496
-
497
- // Encode combination, exponent, and significand.
498
- if (
499
- significand.high
500
- .shiftRightUnsigned(49)
501
- .and(Long.fromNumber(1))
502
- .equals(Long.fromNumber(1))
503
- ) {
504
- // Encode '11' into bits 1 to 3
505
- dec.high = dec.high.or(Long.fromNumber(0x3).shiftLeft(61));
506
- dec.high = dec.high.or(
507
- Long.fromNumber(biasedExponent).and(Long.fromNumber(0x3fff).shiftLeft(47))
508
- );
509
- dec.high = dec.high.or(significand.high.and(Long.fromNumber(0x7fffffffffff)));
510
- } else {
511
- dec.high = dec.high.or(Long.fromNumber(biasedExponent & 0x3fff).shiftLeft(49));
512
- dec.high = dec.high.or(significand.high.and(Long.fromNumber(0x1ffffffffffff)));
513
- }
514
-
515
- dec.low = significand.low;
516
-
517
- // Encode sign
518
- if (isNegative) {
519
- dec.high = dec.high.or(Long.fromString('9223372036854775808'));
520
- }
521
-
522
- // Encode into a buffer
523
- const buffer = Buffer.alloc(16);
524
- index = 0;
525
-
526
- // Encode the low 64 bits of the decimal
527
- // Encode low bits
528
- buffer[index++] = dec.low.low & 0xff;
529
- buffer[index++] = (dec.low.low >> 8) & 0xff;
530
- buffer[index++] = (dec.low.low >> 16) & 0xff;
531
- buffer[index++] = (dec.low.low >> 24) & 0xff;
532
- // Encode high bits
533
- buffer[index++] = dec.low.high & 0xff;
534
- buffer[index++] = (dec.low.high >> 8) & 0xff;
535
- buffer[index++] = (dec.low.high >> 16) & 0xff;
536
- buffer[index++] = (dec.low.high >> 24) & 0xff;
537
-
538
- // Encode the high 64 bits of the decimal
539
- // Encode low bits
540
- buffer[index++] = dec.high.low & 0xff;
541
- buffer[index++] = (dec.high.low >> 8) & 0xff;
542
- buffer[index++] = (dec.high.low >> 16) & 0xff;
543
- buffer[index++] = (dec.high.low >> 24) & 0xff;
544
- // Encode high bits
545
- buffer[index++] = dec.high.high & 0xff;
546
- buffer[index++] = (dec.high.high >> 8) & 0xff;
547
- buffer[index++] = (dec.high.high >> 16) & 0xff;
548
- buffer[index++] = (dec.high.high >> 24) & 0xff;
549
-
550
- // Return the new Decimal128
551
- return new Decimal128(buffer);
552
- };
553
-
554
- // Extract least significant 5 bits
555
- const COMBINATION_MASK = 0x1f;
556
- // Extract least significant 14 bits
557
- const EXPONENT_MASK = 0x3fff;
558
- // Value of combination field for Inf
559
- const COMBINATION_INFINITY = 30;
560
- // Value of combination field for NaN
561
- const COMBINATION_NAN = 31;
562
-
563
- /**
564
- * Create a string representation of the raw Decimal128 value
565
- *
566
- * @method
567
- * @return {string} returns a Decimal128 string representation.
568
- */
569
- Decimal128.prototype.toString = function() {
570
- // Note: bits in this routine are referred to starting at 0,
571
- // from the sign bit, towards the coefficient.
572
-
573
- // bits 0 - 31
574
- let high;
575
- // bits 32 - 63
576
- let midh;
577
- // bits 64 - 95
578
- let midl;
579
- // bits 96 - 127
580
- let low;
581
- // bits 1 - 5
582
- let combination;
583
- // decoded biased exponent (14 bits)
584
- let biased_exponent;
585
- // the number of significand digits
586
- let significand_digits = 0;
587
- // the base-10 digits in the significand
588
- const significand = new Array(36);
589
- for (let i = 0; i < significand.length; i++) significand[i] = 0;
590
- // read pointer into significand
591
- let index = 0;
592
-
593
- // unbiased exponent
594
- let exponent;
595
- // the exponent if scientific notation is used
596
- let scientific_exponent;
597
-
598
- // true if the number is zero
599
- let is_zero = false;
600
-
601
- // the most signifcant significand bits (50-46)
602
- let significand_msb;
603
- // temporary storage for significand decoding
604
- let significand128 = { parts: new Array(4) };
605
- // indexing variables
606
- let j, k;
607
-
608
- // Output string
609
- const string = [];
610
-
611
- // Unpack index
612
- index = 0;
613
-
614
- // Buffer reference
615
- const buffer = this.bytes;
616
-
617
- // Unpack the low 64bits into a long
618
- low =
619
- buffer[index++] | (buffer[index++] << 8) | (buffer[index++] << 16) | (buffer[index++] << 24);
620
- midl =
621
- buffer[index++] | (buffer[index++] << 8) | (buffer[index++] << 16) | (buffer[index++] << 24);
622
-
623
- // Unpack the high 64bits into a long
624
- midh =
625
- buffer[index++] | (buffer[index++] << 8) | (buffer[index++] << 16) | (buffer[index++] << 24);
626
- high =
627
- buffer[index++] | (buffer[index++] << 8) | (buffer[index++] << 16) | (buffer[index++] << 24);
628
-
629
- // Unpack index
630
- index = 0;
631
-
632
- // Create the state of the decimal
633
- const dec = {
634
- low: new Long(low, midl),
635
- high: new Long(midh, high)
636
- };
637
-
638
- if (dec.high.lessThan(Long.ZERO)) {
639
- string.push('-');
640
- }
641
-
642
- // Decode combination field and exponent
643
- combination = (high >> 26) & COMBINATION_MASK;
644
-
645
- if (combination >> 3 === 3) {
646
- // Check for 'special' values
647
- if (combination === COMBINATION_INFINITY) {
648
- return string.join('') + 'Infinity';
649
- } else if (combination === COMBINATION_NAN) {
650
- return 'NaN';
651
- } else {
652
- biased_exponent = (high >> 15) & EXPONENT_MASK;
653
- significand_msb = 0x08 + ((high >> 14) & 0x01);
654
- }
655
- } else {
656
- significand_msb = (high >> 14) & 0x07;
657
- biased_exponent = (high >> 17) & EXPONENT_MASK;
658
- }
659
-
660
- exponent = biased_exponent - EXPONENT_BIAS;
661
-
662
- // Create string of significand digits
663
-
664
- // Convert the 114-bit binary number represented by
665
- // (significand_high, significand_low) to at most 34 decimal
666
- // digits through modulo and division.
667
- significand128.parts[0] = (high & 0x3fff) + ((significand_msb & 0xf) << 14);
668
- significand128.parts[1] = midh;
669
- significand128.parts[2] = midl;
670
- significand128.parts[3] = low;
671
-
672
- if (
673
- significand128.parts[0] === 0 &&
674
- significand128.parts[1] === 0 &&
675
- significand128.parts[2] === 0 &&
676
- significand128.parts[3] === 0
677
- ) {
678
- is_zero = true;
679
- } else {
680
- for (k = 3; k >= 0; k--) {
681
- let least_digits = 0;
682
- // Peform the divide
683
- let result = divideu128(significand128);
684
- significand128 = result.quotient;
685
- least_digits = result.rem.low;
686
-
687
- // We now have the 9 least significant digits (in base 2).
688
- // Convert and output to string.
689
- if (!least_digits) continue;
690
-
691
- for (j = 8; j >= 0; j--) {
692
- // significand[k * 9 + j] = Math.round(least_digits % 10);
693
- significand[k * 9 + j] = least_digits % 10;
694
- // least_digits = Math.round(least_digits / 10);
695
- least_digits = Math.floor(least_digits / 10);
696
- }
354
+ // Round
355
+ // We've normalized the exponent, but might still need to round.
356
+ if (lastDigit - firstDigit + 1 < significantDigits) {
357
+ let endOfString = nDigitsRead;
358
+ // If we have seen a radix point, 'string' is 1 longer than we have
359
+ // documented with ndigits_read, so inc the position of the first nonzero
360
+ // digit and the position that digits are read to.
361
+ if (sawRadix) {
362
+ firstNonZero = firstNonZero + 1;
363
+ endOfString = endOfString + 1;
364
+ }
365
+ // if negative, we need to increment again to account for - sign at start.
366
+ if (isNegative) {
367
+ firstNonZero = firstNonZero + 1;
368
+ endOfString = endOfString + 1;
369
+ }
370
+ const roundDigit = parseInt(representation[firstNonZero + lastDigit + 1], 10);
371
+ let roundBit = 0;
372
+ if (roundDigit >= 5) {
373
+ roundBit = 1;
374
+ if (roundDigit === 5) {
375
+ roundBit = digits[lastDigit] % 2 === 1 ? 1 : 0;
376
+ for (i = firstNonZero + lastDigit + 2; i < endOfString; i++) {
377
+ if (parseInt(representation[i], 10)) {
378
+ roundBit = 1;
379
+ break;
380
+ }
381
+ }
382
+ }
383
+ }
384
+ if (roundBit) {
385
+ let dIdx = lastDigit;
386
+ for (; dIdx >= 0; dIdx--) {
387
+ if (++digits[dIdx] > 9) {
388
+ digits[dIdx] = 0;
389
+ // overflowed most significant digit
390
+ if (dIdx === 0) {
391
+ if (exponent < EXPONENT_MAX) {
392
+ exponent = exponent + 1;
393
+ digits[dIdx] = 1;
394
+ }
395
+ else {
396
+ return new Decimal128(buffer_1.Buffer.from(isNegative ? INF_NEGATIVE_BUFFER : INF_POSITIVE_BUFFER));
397
+ }
398
+ }
399
+ }
400
+ }
401
+ }
402
+ }
403
+ // Encode significand
404
+ // The high 17 digits of the significand
405
+ significandHigh = long_1.Long.fromNumber(0);
406
+ // The low 17 digits of the significand
407
+ significandLow = long_1.Long.fromNumber(0);
408
+ // read a zero
409
+ if (significantDigits === 0) {
410
+ significandHigh = long_1.Long.fromNumber(0);
411
+ significandLow = long_1.Long.fromNumber(0);
412
+ }
413
+ else if (lastDigit - firstDigit < 17) {
414
+ let dIdx = firstDigit;
415
+ significandLow = long_1.Long.fromNumber(digits[dIdx++]);
416
+ significandHigh = new long_1.Long(0, 0);
417
+ for (; dIdx <= lastDigit; dIdx++) {
418
+ significandLow = significandLow.multiply(long_1.Long.fromNumber(10));
419
+ significandLow = significandLow.add(long_1.Long.fromNumber(digits[dIdx]));
420
+ }
421
+ }
422
+ else {
423
+ let dIdx = firstDigit;
424
+ significandHigh = long_1.Long.fromNumber(digits[dIdx++]);
425
+ for (; dIdx <= lastDigit - 17; dIdx++) {
426
+ significandHigh = significandHigh.multiply(long_1.Long.fromNumber(10));
427
+ significandHigh = significandHigh.add(long_1.Long.fromNumber(digits[dIdx]));
428
+ }
429
+ significandLow = long_1.Long.fromNumber(digits[dIdx++]);
430
+ for (; dIdx <= lastDigit; dIdx++) {
431
+ significandLow = significandLow.multiply(long_1.Long.fromNumber(10));
432
+ significandLow = significandLow.add(long_1.Long.fromNumber(digits[dIdx]));
433
+ }
434
+ }
435
+ const significand = multiply64x2(significandHigh, long_1.Long.fromString('100000000000000000'));
436
+ significand.low = significand.low.add(significandLow);
437
+ if (lessThan(significand.low, significandLow)) {
438
+ significand.high = significand.high.add(long_1.Long.fromNumber(1));
439
+ }
440
+ // Biased exponent
441
+ biasedExponent = exponent + EXPONENT_BIAS;
442
+ const dec = { low: long_1.Long.fromNumber(0), high: long_1.Long.fromNumber(0) };
443
+ // Encode combination, exponent, and significand.
444
+ if (significand.high.shiftRightUnsigned(49).and(long_1.Long.fromNumber(1)).equals(long_1.Long.fromNumber(1))) {
445
+ // Encode '11' into bits 1 to 3
446
+ dec.high = dec.high.or(long_1.Long.fromNumber(0x3).shiftLeft(61));
447
+ dec.high = dec.high.or(long_1.Long.fromNumber(biasedExponent).and(long_1.Long.fromNumber(0x3fff).shiftLeft(47)));
448
+ dec.high = dec.high.or(significand.high.and(long_1.Long.fromNumber(0x7fffffffffff)));
449
+ }
450
+ else {
451
+ dec.high = dec.high.or(long_1.Long.fromNumber(biasedExponent & 0x3fff).shiftLeft(49));
452
+ dec.high = dec.high.or(significand.high.and(long_1.Long.fromNumber(0x1ffffffffffff)));
453
+ }
454
+ dec.low = significand.low;
455
+ // Encode sign
456
+ if (isNegative) {
457
+ dec.high = dec.high.or(long_1.Long.fromString('9223372036854775808'));
458
+ }
459
+ // Encode into a buffer
460
+ const buffer = buffer_1.Buffer.alloc(16);
461
+ index = 0;
462
+ // Encode the low 64 bits of the decimal
463
+ // Encode low bits
464
+ buffer[index++] = dec.low.low & 0xff;
465
+ buffer[index++] = (dec.low.low >> 8) & 0xff;
466
+ buffer[index++] = (dec.low.low >> 16) & 0xff;
467
+ buffer[index++] = (dec.low.low >> 24) & 0xff;
468
+ // Encode high bits
469
+ buffer[index++] = dec.low.high & 0xff;
470
+ buffer[index++] = (dec.low.high >> 8) & 0xff;
471
+ buffer[index++] = (dec.low.high >> 16) & 0xff;
472
+ buffer[index++] = (dec.low.high >> 24) & 0xff;
473
+ // Encode the high 64 bits of the decimal
474
+ // Encode low bits
475
+ buffer[index++] = dec.high.low & 0xff;
476
+ buffer[index++] = (dec.high.low >> 8) & 0xff;
477
+ buffer[index++] = (dec.high.low >> 16) & 0xff;
478
+ buffer[index++] = (dec.high.low >> 24) & 0xff;
479
+ // Encode high bits
480
+ buffer[index++] = dec.high.high & 0xff;
481
+ buffer[index++] = (dec.high.high >> 8) & 0xff;
482
+ buffer[index++] = (dec.high.high >> 16) & 0xff;
483
+ buffer[index++] = (dec.high.high >> 24) & 0xff;
484
+ // Return the new Decimal128
485
+ return new Decimal128(buffer);
697
486
  }
698
- }
699
-
700
- // Output format options:
701
- // Scientific - [-]d.dddE(+/-)dd or [-]dE(+/-)dd
702
- // Regular - ddd.ddd
703
-
704
- if (is_zero) {
705
- significand_digits = 1;
706
- significand[index] = 0;
707
- } else {
708
- significand_digits = 36;
709
- while (!significand[index]) {
710
- significand_digits = significand_digits - 1;
711
- index = index + 1;
487
+ /** Create a string representation of the raw Decimal128 value */
488
+ toString() {
489
+ // Note: bits in this routine are referred to starting at 0,
490
+ // from the sign bit, towards the coefficient.
491
+ // decoded biased exponent (14 bits)
492
+ let biased_exponent;
493
+ // the number of significand digits
494
+ let significand_digits = 0;
495
+ // the base-10 digits in the significand
496
+ const significand = new Array(36);
497
+ for (let i = 0; i < significand.length; i++)
498
+ significand[i] = 0;
499
+ // read pointer into significand
500
+ let index = 0;
501
+ // true if the number is zero
502
+ let is_zero = false;
503
+ // the most significant significand bits (50-46)
504
+ let significand_msb;
505
+ // temporary storage for significand decoding
506
+ let significand128 = { parts: [0, 0, 0, 0] };
507
+ // indexing variables
508
+ let j, k;
509
+ // Output string
510
+ const string = [];
511
+ // Unpack index
512
+ index = 0;
513
+ // Buffer reference
514
+ const buffer = this.bytes;
515
+ // Unpack the low 64bits into a long
516
+ // bits 96 - 127
517
+ const low = buffer[index++] | (buffer[index++] << 8) | (buffer[index++] << 16) | (buffer[index++] << 24);
518
+ // bits 64 - 95
519
+ const midl = buffer[index++] | (buffer[index++] << 8) | (buffer[index++] << 16) | (buffer[index++] << 24);
520
+ // Unpack the high 64bits into a long
521
+ // bits 32 - 63
522
+ const midh = buffer[index++] | (buffer[index++] << 8) | (buffer[index++] << 16) | (buffer[index++] << 24);
523
+ // bits 0 - 31
524
+ const high = buffer[index++] | (buffer[index++] << 8) | (buffer[index++] << 16) | (buffer[index++] << 24);
525
+ // Unpack index
526
+ index = 0;
527
+ // Create the state of the decimal
528
+ const dec = {
529
+ low: new long_1.Long(low, midl),
530
+ high: new long_1.Long(midh, high)
531
+ };
532
+ if (dec.high.lessThan(long_1.Long.ZERO)) {
533
+ string.push('-');
534
+ }
535
+ // Decode combination field and exponent
536
+ // bits 1 - 5
537
+ const combination = (high >> 26) & COMBINATION_MASK;
538
+ if (combination >> 3 === 3) {
539
+ // Check for 'special' values
540
+ if (combination === COMBINATION_INFINITY) {
541
+ return string.join('') + 'Infinity';
542
+ }
543
+ else if (combination === COMBINATION_NAN) {
544
+ return 'NaN';
545
+ }
546
+ else {
547
+ biased_exponent = (high >> 15) & EXPONENT_MASK;
548
+ significand_msb = 0x08 + ((high >> 14) & 0x01);
549
+ }
550
+ }
551
+ else {
552
+ significand_msb = (high >> 14) & 0x07;
553
+ biased_exponent = (high >> 17) & EXPONENT_MASK;
554
+ }
555
+ // unbiased exponent
556
+ const exponent = biased_exponent - EXPONENT_BIAS;
557
+ // Create string of significand digits
558
+ // Convert the 114-bit binary number represented by
559
+ // (significand_high, significand_low) to at most 34 decimal
560
+ // digits through modulo and division.
561
+ significand128.parts[0] = (high & 0x3fff) + ((significand_msb & 0xf) << 14);
562
+ significand128.parts[1] = midh;
563
+ significand128.parts[2] = midl;
564
+ significand128.parts[3] = low;
565
+ if (significand128.parts[0] === 0 &&
566
+ significand128.parts[1] === 0 &&
567
+ significand128.parts[2] === 0 &&
568
+ significand128.parts[3] === 0) {
569
+ is_zero = true;
570
+ }
571
+ else {
572
+ for (k = 3; k >= 0; k--) {
573
+ let least_digits = 0;
574
+ // Perform the divide
575
+ const result = divideu128(significand128);
576
+ significand128 = result.quotient;
577
+ least_digits = result.rem.low;
578
+ // We now have the 9 least significant digits (in base 2).
579
+ // Convert and output to string.
580
+ if (!least_digits)
581
+ continue;
582
+ for (j = 8; j >= 0; j--) {
583
+ // significand[k * 9 + j] = Math.round(least_digits % 10);
584
+ significand[k * 9 + j] = least_digits % 10;
585
+ // least_digits = Math.round(least_digits / 10);
586
+ least_digits = Math.floor(least_digits / 10);
587
+ }
588
+ }
589
+ }
590
+ // Output format options:
591
+ // Scientific - [-]d.dddE(+/-)dd or [-]dE(+/-)dd
592
+ // Regular - ddd.ddd
593
+ if (is_zero) {
594
+ significand_digits = 1;
595
+ significand[index] = 0;
596
+ }
597
+ else {
598
+ significand_digits = 36;
599
+ while (!significand[index]) {
600
+ significand_digits = significand_digits - 1;
601
+ index = index + 1;
602
+ }
603
+ }
604
+ // the exponent if scientific notation is used
605
+ const scientific_exponent = significand_digits - 1 + exponent;
606
+ // The scientific exponent checks are dictated by the string conversion
607
+ // specification and are somewhat arbitrary cutoffs.
608
+ //
609
+ // We must check exponent > 0, because if this is the case, the number
610
+ // has trailing zeros. However, we *cannot* output these trailing zeros,
611
+ // because doing so would change the precision of the value, and would
612
+ // change stored data if the string converted number is round tripped.
613
+ if (scientific_exponent >= 34 || scientific_exponent <= -7 || exponent > 0) {
614
+ // Scientific format
615
+ // if there are too many significant digits, we should just be treating numbers
616
+ // as + or - 0 and using the non-scientific exponent (this is for the "invalid
617
+ // representation should be treated as 0/-0" spec cases in decimal128-1.json)
618
+ if (significand_digits > 34) {
619
+ string.push(`${0}`);
620
+ if (exponent > 0)
621
+ string.push('E+' + exponent);
622
+ else if (exponent < 0)
623
+ string.push('E' + exponent);
624
+ return string.join('');
625
+ }
626
+ string.push(`${significand[index++]}`);
627
+ significand_digits = significand_digits - 1;
628
+ if (significand_digits) {
629
+ string.push('.');
630
+ }
631
+ for (let i = 0; i < significand_digits; i++) {
632
+ string.push(`${significand[index++]}`);
633
+ }
634
+ // Exponent
635
+ string.push('E');
636
+ if (scientific_exponent > 0) {
637
+ string.push('+' + scientific_exponent);
638
+ }
639
+ else {
640
+ string.push(`${scientific_exponent}`);
641
+ }
642
+ }
643
+ else {
644
+ // Regular format with no decimal place
645
+ if (exponent >= 0) {
646
+ for (let i = 0; i < significand_digits; i++) {
647
+ string.push(`${significand[index++]}`);
648
+ }
649
+ }
650
+ else {
651
+ let radix_position = significand_digits + exponent;
652
+ // non-zero digits before radix
653
+ if (radix_position > 0) {
654
+ for (let i = 0; i < radix_position; i++) {
655
+ string.push(`${significand[index++]}`);
656
+ }
657
+ }
658
+ else {
659
+ string.push('0');
660
+ }
661
+ string.push('.');
662
+ // add leading zeros after radix
663
+ while (radix_position++ < 0) {
664
+ string.push('0');
665
+ }
666
+ for (let i = 0; i < significand_digits - Math.max(radix_position - 1, 0); i++) {
667
+ string.push(`${significand[index++]}`);
668
+ }
669
+ }
670
+ }
671
+ return string.join('');
712
672
  }
713
- }
714
-
715
- scientific_exponent = significand_digits - 1 + exponent;
716
-
717
- // The scientific exponent checks are dictated by the string conversion
718
- // specification and are somewhat arbitrary cutoffs.
719
- //
720
- // We must check exponent > 0, because if this is the case, the number
721
- // has trailing zeros. However, we *cannot* output these trailing zeros,
722
- // because doing so would change the precision of the value, and would
723
- // change stored data if the string converted number is round tripped.
724
- if (scientific_exponent >= 34 || scientific_exponent <= -7 || exponent > 0) {
725
- // Scientific format
726
-
727
- // if there are too many significant digits, we should just be treating numbers
728
- // as + or - 0 and using the non-scientific exponent (this is for the "invalid
729
- // representation should be treated as 0/-0" spec cases in decimal128-1.json)
730
- if (significand_digits > 34) {
731
- string.push(0);
732
- if (exponent > 0) string.push('E+' + exponent);
733
- else if (exponent < 0) string.push('E' + exponent);
734
- return string.join('');
673
+ toJSON() {
674
+ return { $numberDecimal: this.toString() };
735
675
  }
736
-
737
- string.push(significand[index++]);
738
- significand_digits = significand_digits - 1;
739
-
740
- if (significand_digits) {
741
- string.push('.');
676
+ /** @internal */
677
+ toExtendedJSON() {
678
+ return { $numberDecimal: this.toString() };
742
679
  }
743
-
744
- for (let i = 0; i < significand_digits; i++) {
745
- string.push(significand[index++]);
680
+ /** @internal */
681
+ static fromExtendedJSON(doc) {
682
+ return Decimal128.fromString(doc.$numberDecimal);
746
683
  }
747
-
748
- // Exponent
749
- string.push('E');
750
- if (scientific_exponent > 0) {
751
- string.push('+' + scientific_exponent);
752
- } else {
753
- string.push(scientific_exponent);
684
+ /** @internal */
685
+ [Symbol.for('nodejs.util.inspect.custom')]() {
686
+ return this.inspect();
754
687
  }
755
- } else {
756
- // Regular format with no decimal place
757
- if (exponent >= 0) {
758
- for (let i = 0; i < significand_digits; i++) {
759
- string.push(significand[index++]);
760
- }
761
- } else {
762
- let radix_position = significand_digits + exponent;
763
-
764
- // non-zero digits before radix
765
- if (radix_position > 0) {
766
- for (let i = 0; i < radix_position; i++) {
767
- string.push(significand[index++]);
768
- }
769
- } else {
770
- string.push('0');
771
- }
772
-
773
- string.push('.');
774
- // add leading zeros after radix
775
- while (radix_position++ < 0) {
776
- string.push('0');
777
- }
778
-
779
- for (let i = 0; i < significand_digits - Math.max(radix_position - 1, 0); i++) {
780
- string.push(significand[index++]);
781
- }
688
+ inspect() {
689
+ return `Decimal128("${this.toString()}")`;
782
690
  }
783
- }
784
-
785
- return string.join('');
786
- };
787
-
788
- Decimal128.prototype.toJSON = function() {
789
- return { $numberDecimal: this.toString() };
790
- };
791
-
792
- /**
793
- * @ignore
794
- */
795
- Decimal128.prototype.toExtendedJSON = function() {
796
- return { $numberDecimal: this.toString() };
797
- };
798
-
799
- /**
800
- * @ignore
801
- */
802
- Decimal128.fromExtendedJSON = function(doc) {
803
- return Decimal128.fromString(doc.$numberDecimal);
804
- };
805
-
691
+ }
692
+ exports.Decimal128 = Decimal128;
806
693
  Object.defineProperty(Decimal128.prototype, '_bsontype', { value: 'Decimal128' });
807
- module.exports = Decimal128;
694
+ //# sourceMappingURL=decimal128.js.map