Coverage Report

Created: 2025-10-28 07:12

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/jsoncons/include/jsoncons_ext/bson/bson_decimal128.hpp
Line
Count
Source
1
#ifndef JSONCONS_EXT_BSON_BSON_DECIMAL128_HPP
2
#define JSONCONS_EXT_BSON_BSON_DECIMAL128_HPP
3
4
/*
5
 *  Implements decimal128_to_chars and decimal128_from_chars
6
 *  
7
 *  Based on the libjson functions bson_decimal128_to_string
8
 *  and bson_decimal128_from_string_w_len, available at
9
 *  https://github.com/mongodb/mongo-c-driver/blob/master/src/libbson/src/bson/bson-decimal128.h
10
 *  and https://github.com/mongodb/mongo-c-driver/blob/master/src/libbson/src/bson/bson-decimal128.c
11
 *  
12
*/
13
14
/*
15
 * Copyright 2015 MongoDB, Inc.
16
 *
17
 * Licensed under the Apache License, Version 2.0 (the "License");
18
 * you may not use this file except in compliance with the License.
19
 * You may obtain a copy of the License at
20
 *
21
 *   http://www.apache.org/licenses/LICENSE-2.0
22
 *
23
 * Unless required by applicable law or agreed to in writing, software
24
 * distributed under the License is distributed on an "AS IS" BASIS,
25
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
26
 * See the License for the specific language governing permissions and
27
 * limitations under the License.
28
 */
29
30
#include <algorithm>
31
#include <cstdint>
32
#include <cstring>
33
#include <ctype.h>
34
#include <stdlib.h>
35
#include <cstddef>
36
#include <string.h>
37
#include <string>
38
#include <system_error>
39
#include <type_traits>
40
41
#include <jsoncons/config/compiler_support.hpp>
42
#include <jsoncons/config/jsoncons_config.hpp>
43
#include <jsoncons/utility/read_number.hpp>
44
#include <jsoncons/utility/write_number.hpp>
45
46
namespace jsoncons { 
47
namespace bson {
48
49
    struct decimal128_to_chars_result 
50
    {
51
        char* ptr;
52
        std::errc ec;
53
    };
54
55
    struct decimal128_from_chars_result 
56
    {
57
        const char* ptr;
58
        std::errc ec;
59
    };
60
61
/**
62
 * BSON_DECIMAL128_STRING:
63
 *
64
 * The length of a decimal128 string (with null terminator).
65
 *
66
 * 1  for the sign
67
 * 35 for digits and radix
68
 * 2  for exponent indicator and sign
69
 * 4  for exponent digits
70
 */
71
#define BSON_DECIMAL128_STRING 43
72
73
    struct TP1 
74
    { 
75
        uint64_t low; 
76
        uint64_t high; 
77
78
46.5k
        constexpr TP1() : low(0), high(0) {}
79
3.81k
        constexpr TP1(uint64_t hi, uint64_t lo) : low(lo), high(hi) {}
80
    };
81
    struct TP2 
82
    { 
83
        uint64_t high; 
84
        uint64_t low; 
85
86
0
        constexpr TP2() : high(0), low(0) {}
87
0
        constexpr TP2(uint64_t hi, uint64_t lo) : high(hi), low(lo) {}
88
    };
89
90
    typedef std::conditional<
91
        jsoncons::endian::native == jsoncons::endian::little,
92
        TP1,
93
        TP2
94
    >::type decimal128_t;
95
96
    inline
97
    bool operator==(const decimal128_t& lhs, const decimal128_t& rhs)
98
0
    {
99
0
       return lhs.high == rhs.high && lhs.low == rhs.low;
100
0
    }   
101
102
    inline
103
    bool operator!=(const decimal128_t& lhs, const decimal128_t& rhs)
104
0
    {
105
0
       return !(lhs == rhs);
106
0
    }   
107
108
    struct decimal128_limits
109
    {
110
        // The length of a decimal128 string (without null terminator).
111
        //
112
        // 1  for the sign
113
        // 35 for digits and radix
114
        // 2  for exponent indicator and sign
115
        // 4  for exponent digits
116
        static constexpr int buf_size = 42;  
117
        static constexpr int exponent_max = 6111;
118
        static constexpr int exponent_min = -6176;
119
        static constexpr int exponent_bias = 6176;
120
        static constexpr int max_digits = 34;
121
122
1.80k
        static constexpr decimal128_t nan() {return decimal128_t(0x7c00000000000000ull, 0);}
123
204
        static constexpr decimal128_t infinity() {return decimal128_t(0x7800000000000000ull, 0);}
124
1.80k
        static constexpr decimal128_t neg_infinity() {return decimal128_t(0x7800000000000000ull + 0x8000000000000000ull, 0);}
125
    };
126
127
    inline
128
0
    bool is_nan(decimal128_t dec) { return dec == decimal128_limits::nan(); }
129
130
    inline
131
0
    bool is_inf(decimal128_t dec) { return dec == decimal128_limits::infinity(); }
132
133
    inline
134
0
    bool is_neg_inf(decimal128_t dec) { return dec == decimal128_limits::neg_infinity(); }
135
136
    /**
137
     * bson_uint128_t:
138
     *
139
     * This struct represents a 128 bit integer.
140
     */
141
    typedef struct {
142
       uint32_t parts[4]; /* 32-bit words stored high to low. */
143
    } bson_uint128_t;
144
145
    typedef struct {
146
       uint64_t high, low;
147
    } bson_uint128_6464_t;
148
149
    namespace detail {
150
    
151
        /**
152
         *------------------------------------------------------------------------------
153
         *
154
         * bson_uint128_divide1B --
155
         *
156
         *    This function divides a #bson_uint128_t by 1000000000 (1 billion) and
157
         *    computes the quotient and remainder.
158
         *
159
         *    The remainder will contain 9 decimal digits for conversion to string.
160
         *
161
         * @value     The #bson_uint128_t operand.
162
         * @quotient  A pointer to store the #bson_uint128_t quotient.
163
         * @rem       A pointer to store the #uint64_t remainder.
164
         *
165
         * Returns:
166
         *    The quotient at @quotient and the remainder at @rem.
167
         *
168
         * Side effects:
169
         *    None.
170
         *
171
         *------------------------------------------------------------------------------
172
         */
173
174
        inline
175
        void bson_uint128_divide1B (bson_uint128_t value,     /* IN */
176
                                     bson_uint128_t *quotient, /* OUT */
177
                                     uint32_t *rem)             /* OUT */
178
88.8k
        {
179
88.8k
            const uint32_t DIVISOR = 1000 * 1000 * 1000;
180
88.8k
            uint64_t _rem = 0;
181
88.8k
            int i = 0;
182
            
183
88.8k
            if (!value.parts[0] && !value.parts[1] && !value.parts[2] &&
184
32.0k
                !value.parts[3]) {
185
8.34k
               *quotient = value;
186
8.34k
               *rem = 0;
187
8.34k
               return;
188
8.34k
            }
189
            
190
402k
            for (i = 0; i <= 3; i++) {
191
322k
               _rem <<= 32; /* Adjust remainder to match value of next dividend */
192
322k
               _rem += value.parts[i]; /* Add the divided to _rem */
193
322k
               value.parts[i] = (uint32_t) (_rem / DIVISOR);
194
322k
               _rem %= DIVISOR; /* Store the remainder */
195
322k
            }
196
            
197
80.5k
            *quotient = value;
198
80.5k
            *rem = (uint32_t) _rem;
199
80.5k
        }
200
201
        /**
202
         *-------------------------------------------------------------------------
203
         *
204
         * mul64x64 --
205
         *
206
         *    This function multiplies two &uint64_t into a &bson_uint128_6464_t.
207
         *
208
         * Returns:
209
         *    The product of @left and @right.
210
         *
211
         * Side Effects:
212
         *    None.
213
         *
214
         *-------------------------------------------------------------------------
215
         */
216
217
        inline
218
        void mul_64x64 (uint64_t left,                 /* IN */
219
                        uint64_t right,                /* IN */
220
                        bson_uint128_6464_t *product) /* OUT */
221
11.6k
        {
222
11.6k
            uint64_t left_high, left_low, right_high, right_low, product_high,
223
11.6k
               product_mid, product_mid2, product_low;
224
11.6k
            bson_uint128_6464_t rt = {0,0};
225
 
226
11.6k
            if (!left && !right) {
227
0
               *product = rt;
228
0
               return;
229
0
            }
230
 
231
11.6k
            left_high = left >> 32;
232
11.6k
            left_low = (uint32_t) left;
233
11.6k
            right_high = right >> 32;
234
11.6k
            right_low = (uint32_t) right;
235
 
236
11.6k
            product_high = left_high * right_high;
237
11.6k
            product_mid = left_high * right_low;
238
11.6k
            product_mid2 = left_low * right_high;
239
11.6k
            product_low = left_low * right_low;
240
 
241
11.6k
            product_high += product_mid >> 32;
242
11.6k
            product_mid = (uint32_t) product_mid + product_mid2 + (product_low >> 32);
243
 
244
11.6k
            product_high = product_high + (product_mid >> 32);
245
11.6k
            product_low = (product_mid << 32) + (uint32_t) product_low;
246
 
247
11.6k
            rt.high = product_high;
248
11.6k
            rt.low = product_low;
249
11.6k
            *product = rt;
250
11.6k
        }
251
252
        /**
253
         *------------------------------------------------------------------------------
254
         *
255
         * dec128_tolower --
256
         *
257
         *    This function converts the ASCII character @c to lowercase.  It is locale
258
         *    insensitive (unlike the stdlib tolower).
259
         *
260
         * Returns:
261
         *    The lowercased character.
262
         */
263
264
        inline
265
        char dec128_tolower (char c)
266
54.4k
        {
267
54.4k
           if (isupper (c)) {
268
8.11k
              c += 32;
269
8.11k
           }
270
271
54.4k
           return c;
272
54.4k
        }
273
274
        /**
275
         *------------------------------------------------------------------------------
276
         *
277
         * dec128_istreq --
278
         *
279
         *    This function compares the null-terminated *ASCII* strings @a and @b
280
         *    for case-insensitive equality.
281
         *
282
         * Returns:
283
         *    true if the strings are equal, false otherwise.
284
         */
285
286
        inline
287
        bool dec128_istreq (const char* a, const char* lasta,
288
                            const char* b, const char* lastb)
289
7.08k
        {
290
32.2k
            while (!(a == lasta && b == lastb)) 
291
29.2k
            {
292
               // strings are different lengths
293
29.2k
               if (a == lasta || b == lastb) 
294
2.01k
               {
295
2.01k
                  return false;
296
2.01k
               }
297
         
298
27.2k
               if (dec128_tolower (*a) != dec128_tolower (*b)) {
299
2.04k
                  return false;
300
2.04k
               }
301
         
302
25.2k
               a++;
303
25.2k
               b++;
304
25.2k
            }
305
         
306
3.03k
            return true;
307
7.08k
        }
308
309
    } // namespace detail
310
311
312
    /**
313
     *------------------------------------------------------------------------------
314
     *
315
     * decimal128_to_chars --
316
     *
317
     *    This function converts a BID formatted decimal128 value to string,
318
     *    accepting a &decimal128_t as @dec.  The string is stored at @str.
319
     *
320
     * @dec : The BID formatted decimal to convert.
321
     * @str : The output decimal128 string. At least %BSON_DECIMAL128_STRING
322
     *characters.
323
     *
324
     * Returns:
325
     *    None.
326
     *
327
     * Side effects:
328
     *    None.
329
     *
330
     *------------------------------------------------------------------------------
331
     */
332
333
    inline
334
    decimal128_to_chars_result decimal128_to_chars(char* first, char* last, const decimal128_t& dec)
335
31.0k
    {
336
31.0k
        const std::string bson_decimal128_inf = "Infinity";
337
31.0k
        const std::string bson_decimal128_nan = "NaN";
338
339
31.0k
        const uint32_t combination_mask = 0x1f;   /* Extract least significant 5 bits */
340
31.0k
        const uint32_t exponent_mask = 0x3fff;    /* Extract least significant 14 bits */
341
31.0k
        const uint32_t combination_infinity = 30; /* Value of combination field for Inf */
342
31.0k
        const uint32_t combination_nan = 31;      /* Value of combination field for NaN */
343
31.0k
        const uint32_t exponent_bias = 6176;      /* decimal128 exponent bias */
344
345
31.0k
        char* str_out = first;      /* output pointer in string */
346
31.0k
        char significand_str[35]; /* decoded significand digits */
347
348
        /* Note: bits in this routine are referred to starting at 0, */
349
        /* from the sign bit, towards the coefficient. */
350
31.0k
        uint32_t high;                   /* bits 0 - 31 */
351
31.0k
        uint32_t midh;                   /* bits 32 - 63 */
352
31.0k
        uint32_t midl;                   /* bits 64 - 95 */
353
31.0k
        uint32_t low;                    /* bits 96 - 127 */
354
31.0k
        uint32_t combination;            /* bits 1 - 5 */
355
31.0k
        uint32_t biased_exponent;        /* decoded biased exponent (14 bits) */
356
31.0k
        uint32_t significand_digits = 0; /* the number of significand digits */
357
31.0k
        uint32_t significand[36] = {0};  /* the base-10 digits in the significand */
358
31.0k
        uint32_t *significand_read = significand; /* read pointer into significand */
359
31.0k
        int32_t exponent;                         /* unbiased exponent */
360
31.0k
        int32_t scientific_exponent; /* the exponent if scientific notation is
361
                                      * used */
362
31.0k
        bool is_zero = false;        /* true if the number is zero */
363
 
364
31.0k
        uint8_t significand_msb; /* the most signifcant significand bits (50-46) */
365
31.0k
        bson_uint128_t
366
31.0k
           significand128; /* temporary storage for significand decoding */
367
 
368
31.0k
        memset (significand_str, 0, sizeof (significand_str));
369
 
370
31.0k
        if ((int64_t) dec.high < 0) { /* negative */
371
7.97k
           *(str_out++) = '-';
372
7.97k
        }
373
 
374
31.0k
        low = (uint32_t) dec.low, midl = (uint32_t) (dec.low >> 32),
375
31.0k
        midh = (uint32_t) dec.high, high = (uint32_t) (dec.high >> 32);
376
 
377
        /* Decode combination field and exponent */
378
31.0k
        combination = (high >> 26) & combination_mask;
379
 
380
31.0k
        if (JSONCONS_UNLIKELY ((combination >> 3) == 3)) {
381
           /* Check for 'special' values */
382
7.77k
           if (combination == combination_infinity) { /* Infinity */
383
2.56k
               if (last-str_out >= static_cast<ptrdiff_t >(bson_decimal128_inf.size())) 
384
2.56k
               {
385
2.56k
                   std::memcpy(str_out, bson_decimal128_inf.data(), bson_decimal128_inf.size());
386
2.56k
                   str_out += bson_decimal128_inf.size();
387
2.56k
               }
388
2.56k
               *str_out = 0;
389
              //strcpy_s (str_out, last-str_out, bson_decimal128_inf.c_str());
390
2.56k
              return decimal128_to_chars_result{str_out, std::errc{}};
391
5.20k
           } else if (combination == combination_nan) { /* NaN */
392
               /* first, not str_out, to erase the sign */
393
2.43k
               str_out = first;
394
2.43k
               if (last-str_out >= static_cast<ptrdiff_t >(bson_decimal128_nan.size())) 
395
2.43k
               {
396
2.43k
                   std::memcpy(str_out, bson_decimal128_nan.data(), bson_decimal128_nan.size());
397
2.43k
                   str_out += bson_decimal128_nan.size();
398
2.43k
               }
399
2.43k
               *str_out = 0;
400
              //strcpy_s (first, last-first, bson_decimal128_nan.c_str());
401
              /* we don't care about the NaN payload. */
402
2.43k
               return decimal128_to_chars_result{str_out, std::errc{}};
403
2.77k
           } else {
404
2.77k
              biased_exponent = (high >> 15) & exponent_mask;
405
2.77k
              significand_msb = 0x8 + ((high >> 14) & 0x1);
406
2.77k
           }
407
23.3k
        } else {
408
23.3k
           significand_msb = (high >> 14) & 0x7;
409
23.3k
           biased_exponent = (high >> 17) & exponent_mask;
410
23.3k
        }
411
 
412
26.0k
        exponent = biased_exponent - exponent_bias;
413
        /* Create string of significand digits */
414
 
415
        /* Convert the 114-bit binary number represented by */
416
        /* (high, midh, midl, low) to at most 34 decimal */
417
        /* digits through modulo and division. */
418
26.0k
        significand128.parts[0] = (high & 0x3fff) + ((significand_msb & 0xf) << 14);
419
26.0k
        significand128.parts[1] = midh;
420
26.0k
        significand128.parts[2] = midl;
421
26.0k
        significand128.parts[3] = low;
422
 
423
26.0k
        if (significand128.parts[0] == 0 && significand128.parts[1] == 0 &&
424
4.76k
            significand128.parts[2] == 0 && significand128.parts[3] == 0) {
425
1.09k
           is_zero = true;
426
24.9k
        } else if (significand128.parts[0] >= (1 << 17)) {
427
           /* The significand is non-canonical or zero.
428
            * In order to preserve compatibility with the densely packed decimal
429
            * format, the maximum value for the significand of decimal128 is
430
            * 1e34 - 1.  If the value is greater than 1e34 - 1, the IEEE 754
431
            * standard dictates that the significand is interpreted as zero.
432
            */
433
2.77k
           is_zero = true;
434
22.2k
        } else {
435
111k
           for (int k = 3; k >= 0; k--) {
436
88.8k
              uint32_t least_digits = 0;
437
88.8k
              detail::bson_uint128_divide1B (
438
88.8k
                 significand128, &significand128, &least_digits);
439
 
440
              /* We now have the 9 least significant digits (in base 2). */
441
              /* Convert and output to string. */
442
88.8k
              if (!least_digits) {
443
8.35k
                 continue;
444
8.35k
              }
445
 
446
805k
              for (int j = 8; j >= 0; j--) {
447
724k
                 significand[k * 9 + j] = least_digits % 10;
448
724k
                 least_digits /= 10;
449
724k
              }
450
80.5k
           }
451
22.2k
        }
452
 
453
        /* Output format options: */
454
        /* Scientific - [-]d.dddE(+/-)dd or [-]dE(+/-)dd */
455
        /* Regular    - ddd.ddd */
456
 
457
26.0k
        if (is_zero) {
458
3.86k
           significand_digits = 1;
459
3.86k
           *significand_read = 0;
460
22.2k
        } else {
461
22.2k
           significand_digits = 36;
462
175k
           while (!(*significand_read)) {
463
153k
              significand_digits--;
464
153k
              significand_read++;
465
153k
           }
466
22.2k
        }
467
 
468
26.0k
        scientific_exponent = significand_digits - 1 + exponent;
469
 
470
        /* The scientific exponent checks are dictated by the string conversion
471
         * specification and are somewhat arbitrary cutoffs.
472
         *
473
         * We must check exponent > 0, because if this is the case, the number
474
         * has trailing zeros.  However, we *cannot* output these trailing zeros,
475
         * because doing so would change the precision of the value, and would
476
         * change stored data if the string converted number is round tripped.
477
         */
478
26.0k
        if (scientific_exponent < -6 || exponent > 0) {
479
           /* Scientific format */
480
21.2k
           *(str_out++) = char(*(significand_read++)) + '0';
481
21.2k
           significand_digits--;
482
 
483
21.2k
           if (significand_digits) {
484
18.3k
              *(str_out++) = '.';
485
18.3k
           }
486
 
487
544k
           for (std::size_t i = 0; i < significand_digits && (str_out - first) < 36; i++) {
488
523k
              *(str_out++) = char(*(significand_read++)) + '0';
489
523k
           }
490
           /* Exponent */
491
21.2k
           *(str_out++) = 'E';
492
493
21.2k
           std::string s;
494
21.2k
           if (scientific_exponent >= 0) {
495
5.61k
               s.push_back('+');
496
5.61k
           }
497
21.2k
           jsoncons::utility::from_integer(scientific_exponent, s);
498
21.2k
           if (str_out + s.size() < last) 
499
19.8k
           {
500
19.8k
               std::memcpy(str_out, s.data(), s.size());
501
19.8k
           }
502
1.39k
           else
503
1.39k
           {
504
1.39k
               return decimal128_to_chars_result{str_out, std::errc::value_too_large};
505
1.39k
           }
506
19.8k
           str_out += s.size();
507
19.8k
        } else {
508
           /* Regular format with no decimal place */
509
4.85k
           if (exponent >= 0) {
510
19.4k
              for (std::size_t i = 0; i < significand_digits && (str_out - first) < 36; i++) {
511
17.5k
                 *(str_out++) = char(*(significand_read++)) + '0';
512
17.5k
              }
513
2.95k
           } else {
514
2.95k
              int32_t radix_position = significand_digits + exponent;
515
 
516
2.95k
              if (radix_position > 0) { /* non-zero digits before radix */
517
959
                 for (int32_t i = 0;
518
7.30k
                      i < radix_position && (str_out < last);
519
6.34k
                      i++) {
520
6.34k
                    *(str_out++) = char(*(significand_read++)) + '0';
521
6.34k
                 }
522
1.99k
              } else { /* leading zero before radix point */
523
1.99k
                 *(str_out++) = '0';
524
1.99k
              }
525
 
526
2.95k
              *(str_out++) = '.';
527
8.26k
              while (radix_position++ < 0) { /* add leading zeros after radix */
528
5.31k
                 *(str_out++) = '0';
529
5.31k
              }
530
 
531
2.95k
              for (std::size_t i = 0;
532
84.4k
                   (i < significand_digits - (std::max) (radix_position - 1, 0)) &&
533
81.4k
                   (str_out < last);
534
81.4k
                   i++) {
535
81.4k
                 *(str_out++) = char(*(significand_read++)) + '0';
536
81.4k
              }
537
2.95k
           }
538
4.85k
        }
539
24.6k
        return decimal128_to_chars_result{str_out, std::errc{}};
540
26.0k
    }
541
542
543
544
    /**
545
     *------------------------------------------------------------------------------
546
     *
547
     * bson_decimal128_from_string_w_len --
548
     *
549
     *    This function converts @string in the format [+-]ddd[.]ddd[E][+-]dddd to
550
     *    decimal128.  Out of range values are converted to +/-Infinity.  Invalid
551
     *    strings are converted to NaN. @len is the length of the string, or -1
552
     *    meaning the string is null-terminated.
553
     *
554
     *    If more digits are provided than the available precision allows,
555
     *    round to the nearest expressable decimal128 with ties going to even will
556
     *    occur.
557
     *
558
     *    Note: @string must be ASCII only!
559
     *
560
     * Returns:
561
     *    true on success, or false on failure. @dec will be NaN if @str was invalid
562
     *    The &decimal128_t converted from @string at @dec.
563
     *
564
     * Side effects:
565
     *    None.
566
     *
567
     *------------------------------------------------------------------------------
568
     */
569
570
    inline
571
    decimal128_from_chars_result decimal128_from_chars(const char* first, const char* last, decimal128_t& dec) 
572
15.4k
    {
573
15.4k
        const string_view inf_str = "inf";
574
15.4k
        const string_view infinity_str = "infinity";
575
15.4k
        const string_view nan_str = "nan";
576
577
15.4k
        ptrdiff_t len = last - first;
578
579
15.4k
        bson_uint128_6464_t significand = {0,0};
580
 
581
15.4k
        const char* str_read = first; /* Read pointer for consuming str. */
582
 
583
        /* Parsing state tracking */
584
15.4k
        bool is_negative = false;
585
15.4k
        bool saw_radix = false;
586
15.4k
        bool includes_sign = false; /* True if the input first contains a sign. */
587
15.4k
        bool found_nonzero = false;
588
 
589
15.4k
        std::size_t significant_digits = 0; /* Total number of significant digits
590
                                        * (no leading or trailing zero) */
591
15.4k
        std::size_t ndigits_read = 0;       /* Total number of significand digits read */
592
15.4k
        std::size_t ndigits = 0;        /* Total number of digits (no leading zeros) */
593
15.4k
        std::size_t radix_position = 0; /* The number of the digits after radix */
594
15.4k
        std::size_t first_nonzero = 0;  /* The index of the first non-zero in *str* */
595
 
596
15.4k
        uint16_t digits[decimal128_limits::max_digits] = {0};
597
15.4k
        uint16_t ndigits_stored = 0;      /* The number of digits in digits */
598
15.4k
        uint16_t *digits_insert = digits; /* Insertion pointer for digits */
599
15.4k
        std::size_t first_digit = 0;           /* The index of the first non-zero digit */
600
15.4k
        std::size_t last_digit = 0;            /* The index of the last digit */
601
 
602
15.4k
        int32_t exponent = 0;
603
15.4k
        uint64_t significand_high = 0; /* The high 17 digits of the significand */
604
15.4k
        uint64_t significand_low = 0;  /* The low 17 digits of the significand */
605
15.4k
        uint16_t biased_exponent = 0;  /* The biased exponent */
606
 
607
15.4k
        dec.high = 0;
608
15.4k
        dec.low = 0;
609
 
610
15.4k
        if (*str_read == '+' || *str_read == '-') {
611
3.56k
           is_negative = *(str_read++) == '-';
612
3.56k
           includes_sign = true;
613
3.56k
        }
614
615
        /* Check for Infinity or NaN */
616
15.4k
        if (!isdigit(*str_read) && *str_read != '.') {
617
3.03k
           if (detail::dec128_istreq (str_read, last, inf_str.data(), inf_str.data()+inf_str.length()) ||
618
3.03k
               detail::dec128_istreq (str_read, last, infinity_str.data(), infinity_str.data()+infinity_str.length())) 
619
2.01k
           {
620
2.01k
               dec = is_negative ? decimal128_limits::neg_infinity() : decimal128_limits::infinity();
621
2.01k
              return decimal128_from_chars_result{str_read,std::errc{}};
622
2.01k
           } else if (detail::dec128_istreq (str_read, last, nan_str.data(), nan_str.data()+nan_str.length())) {
623
1.02k
              dec = decimal128_limits::nan();
624
1.02k
              return decimal128_from_chars_result{str_read,std::errc{}};
625
1.02k
           }
626
 
627
0
           dec = decimal128_limits::nan();
628
0
           return decimal128_from_chars_result{str_read,std::errc::invalid_argument};
629
3.03k
        }
630
 
631
        /* Read digits */
632
340k
        while (((isdigit (*str_read) || *str_read == '.')) &&
633
328k
               (len == -1 || str_read < first + len)) {
634
328k
           if (*str_read == '.') {
635
10.2k
              if (saw_radix) {
636
0
                 dec = decimal128_limits::nan();
637
0
                 return decimal128_from_chars_result{str_read,std::errc::invalid_argument};
638
0
              }
639
 
640
10.2k
              saw_radix = true;
641
10.2k
              str_read++;
642
10.2k
              continue;
643
10.2k
           }
644
 
645
317k
           if (ndigits_stored < 34) {
646
316k
              if (*str_read != '0' || found_nonzero) {
647
311k
                 if (!found_nonzero) {
648
10.7k
                    first_nonzero = ndigits_read;
649
10.7k
                 }
650
 
651
311k
                 found_nonzero = true;
652
311k
                 *(digits_insert++) = *(str_read) - '0'; /* Only store 34 digits */
653
311k
                 ndigits_stored++;
654
311k
              }
655
316k
           }
656
 
657
317k
           if (found_nonzero) {
658
313k
              ndigits++;
659
313k
           }
660
 
661
317k
           if (saw_radix) {
662
298k
              radix_position++;
663
298k
           }
664
 
665
317k
           ndigits_read++;
666
317k
           str_read++;
667
317k
        }
668
 
669
12.4k
        if (saw_radix && !ndigits_read) {
670
0
           dec = decimal128_limits::nan();
671
0
           return decimal128_from_chars_result{str_read,std::errc::invalid_argument};
672
0
        }
673
 
674
        /* Read exponent if exists */
675
12.4k
        if (*str_read == 'e' || *str_read == 'E') {
676
10.1k
           ++str_read;
677
10.1k
           if (*str_read == '+') {
678
3.09k
               ++str_read;
679
3.09k
           }
680
10.1k
           auto result = jsoncons::utility::to_integer(str_read, last - str_read, exponent);
681
10.1k
           if (result.ec != std::errc{}) 
682
260
           {
683
260
               dec = decimal128_limits::nan();
684
260
               return decimal128_from_chars_result{str_read,std::errc::invalid_argument};
685
260
           }
686
9.90k
           str_read = result.ptr;
687
9.90k
        }
688
689
12.1k
        if ((len == -1 || str_read < first + len) && *str_read) {
690
0
           dec = decimal128_limits::nan();
691
0
           return decimal128_from_chars_result{str_read,std::errc::invalid_argument};
692
0
        }
693
 
694
        /* Done reading input. */
695
        /* Find first non-zero digit in digits */
696
12.1k
        first_digit = 0;
697
 
698
12.1k
        if (!ndigits_stored) { /* value is zero */
699
1.71k
           first_digit = 0;
700
1.71k
           last_digit = 0;
701
1.71k
           digits[0] = 0;
702
1.71k
           ndigits = 1;
703
1.71k
           ndigits_stored = 1;
704
1.71k
           significant_digits = 0;
705
10.4k
        } else {
706
10.4k
           last_digit = ndigits_stored - 1;
707
10.4k
           significant_digits = ndigits;
708
           /* Mark trailing zeros as non-significant */
709
12.9k
           while (first[first_nonzero + significant_digits - 1 + includes_sign +
710
12.9k
                         saw_radix] == '0') {
711
2.44k
              significant_digits--;
712
2.44k
           }
713
10.4k
        }
714
 
715
 
716
        /* Normalization of exponent */
717
        /* Correct exponent based on radix position, and shift significand as needed
718
         */
719
        /* to represent user input */
720
 
721
        /* Overflow prevention */
722
12.1k
        if (exponent <= static_cast<int32_t>(radix_position) && static_cast<int32_t>(radix_position) - exponent > (1 << 14)) {
723
0
           exponent = decimal128_limits::exponent_min;
724
12.1k
        } else {
725
12.1k
           exponent -= static_cast<int32_t>(radix_position);
726
12.1k
        }
727
 
728
        /* Attempt to normalize the exponent */
729
12.1k
        while (exponent > decimal128_limits::exponent_max) {
730
           /* Shift exponent to significand and decrease */
731
0
           last_digit++;
732
 
733
0
           if (last_digit - first_digit > decimal128_limits::max_digits) {
734
              /* The exponent is too great to shift into the significand. */
735
0
              if (significant_digits == 0) {
736
                 /* Value is zero, we are allowed to clamp the exponent. */
737
0
                 exponent = decimal128_limits::exponent_max;
738
0
                 break;
739
0
              }
740
 
741
              /* Overflow is not permitted, error. */
742
0
              dec = decimal128_limits::nan();
743
0
              return decimal128_from_chars_result{str_read,std::errc::invalid_argument};
744
0
           }
745
 
746
0
           exponent--;
747
0
        }
748
 
749
13.0k
        while (exponent < decimal128_limits::exponent_min || ndigits_stored < ndigits) {
750
           /* Shift last digit */
751
1.13k
           if (last_digit == 0) {
752
              /* underflow is not allowed, but zero clamping is */
753
0
              if (significant_digits == 0) {
754
0
                 exponent = decimal128_limits::exponent_min;
755
0
                 break;
756
0
              }
757
 
758
0
              dec = decimal128_limits::nan();
759
0
              return decimal128_from_chars_result{str_read,std::errc::invalid_argument};
760
0
           }
761
 
762
1.13k
           if (ndigits_stored < ndigits) {
763
1.13k
              if (first[ndigits - 1 + includes_sign + saw_radix] - '0' != 0 &&
764
295
                  significant_digits != 0) {
765
295
                 dec = decimal128_limits::nan();
766
295
                 return decimal128_from_chars_result{str_read,std::errc::invalid_argument};
767
295
              }
768
 
769
839
              ndigits--; /* adjust to match digits not stored */
770
839
           } else {
771
0
              if (digits[last_digit] != 0) {
772
                 /* Inexact rounding is not allowed. */
773
0
                 dec = decimal128_limits::nan();
774
0
                 return decimal128_from_chars_result{str_read,std::errc::invalid_argument};
775
0
              }
776
 
777
 
778
0
              last_digit--; /* adjust to round */
779
0
           }
780
 
781
839
           if (exponent < decimal128_limits::exponent_max) {
782
839
              exponent++;
783
839
           } else {
784
0
              dec = decimal128_limits::nan();
785
0
              return decimal128_from_chars_result{str_read,std::errc::invalid_argument};
786
0
           }
787
839
        }
788
 
789
        /* Round */
790
        /* We've normalized the exponent, but might still need to round. */
791
11.8k
        if (last_digit - first_digit + 1 < significant_digits) {
792
230
           uint8_t round_digit;
793
 
794
           /* There are non-zero digits after last_digit that need rounding. */
795
           /* We round to nearest, ties to even */
796
230
           round_digit =
797
230
              first[first_nonzero + last_digit + includes_sign + saw_radix + 1] -
798
230
              '0';
799
 
800
230
           if (round_digit != 0) {
801
              /* Inexact (non-zero) rounding is not allowed */
802
230
              dec = decimal128_limits::nan();
803
230
              return decimal128_from_chars_result{str_read,std::errc::invalid_argument};
804
230
           }
805
230
        }
806
 
807
        /* Encode significand */
808
11.6k
        significand_high = 0,   /* The high 17 digits of the significand */
809
11.6k
           significand_low = 0; /* The low 17 digits of the significand */
810
 
811
11.6k
        if (significant_digits == 0) { /* read a zero */
812
1.71k
           significand_high = 0;
813
1.71k
           significand_low = 0;
814
9.95k
        } else if (last_digit - first_digit < 17) {
815
1.04k
           std::size_t d_idx = first_digit;
816
1.04k
           significand_low = digits[d_idx++];
817
 
818
7.72k
           for (; d_idx <= last_digit; d_idx++) {
819
6.68k
              significand_low *= 10;
820
6.68k
              significand_low += digits[d_idx];
821
6.68k
              significand_high = 0;
822
6.68k
           }
823
8.91k
        } else {
824
8.91k
           std::size_t d_idx = first_digit;
825
8.91k
           significand_high = digits[d_idx++];
826
 
827
126k
           for (; d_idx <= last_digit - 17; d_idx++) {
828
117k
              significand_high *= 10;
829
117k
              significand_high += digits[d_idx];
830
117k
           }
831
 
832
8.91k
           significand_low = digits[d_idx++];
833
 
834
151k
           for (; d_idx <= last_digit; d_idx++) {
835
142k
              significand_low *= 10;
836
142k
              significand_low += digits[d_idx];
837
142k
           }
838
8.91k
        }
839
 
840
11.6k
        detail::mul_64x64 (significand_high, 100000000000000000ull, &significand);
841
11.6k
        significand.low += significand_low;
842
 
843
11.6k
        if (significand.low < significand_low) {
844
1.97k
           significand.high += 1;
845
1.97k
        }
846
 
847
 
848
11.6k
        biased_exponent = static_cast<uint16_t>(exponent + static_cast<int32_t>(decimal128_limits::exponent_bias));
849
 
850
        /* Encode combination, exponent, and significand. */
851
11.6k
        if ((significand.high >> 49) & 1) {
852
           /* Encode '11' into bits 1 to 3 */
853
0
           dec.high |= (0x3ull << 61);
854
0
           dec.high |= (biased_exponent & 0x3fffull) << 47;
855
0
           dec.high |= significand.high & 0x7fffffffffffull;
856
11.6k
        } else {
857
11.6k
           dec.high |= (biased_exponent & 0x3fffull) << 49;
858
11.6k
           dec.high |= significand.high & 0x1ffffffffffffull;
859
11.6k
        }
860
 
861
11.6k
        dec.low = significand.low;
862
 
863
        /* Encode sign */
864
11.6k
        if (is_negative) {
865
1.45k
           dec.high |= 0x8000000000000000ull;
866
1.45k
        }
867
 
868
11.6k
        return decimal128_from_chars_result{str_read,std::errc{}};
869
11.8k
    }
870
871
} // namespace bson
872
} // namespace jsoncons
873
874
#endif // JSONCONS_EXT_BSON_BSON_DECIMAL128_HPP