100.00% Lines (38/38) 100.00% Functions (6/6)
TLA Baseline Branch
Line Hits Code Line Hits Code
1   // Copyright 2018 Ulf Adams 1   // Copyright 2018 Ulf Adams
2   // 2   //
3   // The contents of this file may be used under the terms of the Apache License, 3   // The contents of this file may be used under the terms of the Apache License,
4   // Version 2.0. 4   // Version 2.0.
5   // 5   //
6   // (See accompanying file LICENSE-Apache or copy at 6   // (See accompanying file LICENSE-Apache or copy at
7   // http://www.apache.org/licenses/LICENSE-2.0) 7   // http://www.apache.org/licenses/LICENSE-2.0)
8   // 8   //
9   // Alternatively, the contents of this file may be used under the terms of 9   // Alternatively, the contents of this file may be used under the terms of
10   // the Boost Software License, Version 1.0. 10   // the Boost Software License, Version 1.0.
11   // (See accompanying file LICENSE-Boost or copy at 11   // (See accompanying file LICENSE-Boost or copy at
12   // https://www.boost.org/LICENSE_1_0.txt) 12   // https://www.boost.org/LICENSE_1_0.txt)
13   // 13   //
14   // Unless required by applicable law or agreed to in writing, this software 14   // Unless required by applicable law or agreed to in writing, this software
15   // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15   // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   // KIND, either express or implied. 16   // KIND, either express or implied.
17   17  
18   /* 18   /*
19   This is a derivative work 19   This is a derivative work
20   */ 20   */
21   21  
22   #ifndef BOOST_JSON_DETAIL_RYU_DETAIL_COMMON_HPP 22   #ifndef BOOST_JSON_DETAIL_RYU_DETAIL_COMMON_HPP
23   #define BOOST_JSON_DETAIL_RYU_DETAIL_COMMON_HPP 23   #define BOOST_JSON_DETAIL_RYU_DETAIL_COMMON_HPP
24   24  
25   #include <boost/json/detail/config.hpp> 25   #include <boost/json/detail/config.hpp>
26   #include <string.h> 26   #include <string.h>
27   27  
28   namespace boost { 28   namespace boost {
29   namespace json { 29   namespace json {
30   namespace detail { 30   namespace detail {
31   31  
32   namespace ryu { 32   namespace ryu {
33   namespace detail { 33   namespace detail {
34   34  
35   constexpr int DOUBLE_MANTISSA_BITS = 52; 35   constexpr int DOUBLE_MANTISSA_BITS = 52;
36   constexpr int DOUBLE_EXPONENT_BITS = 11; 36   constexpr int DOUBLE_EXPONENT_BITS = 11;
37   constexpr int DOUBLE_BIAS = 1023; 37   constexpr int DOUBLE_BIAS = 1023;
38   38  
39   #if defined(_M_IX86) || defined(_M_ARM) 39   #if defined(_M_IX86) || defined(_M_ARM)
40   #define BOOST_JSON_RYU_32_BIT_PLATFORM 40   #define BOOST_JSON_RYU_32_BIT_PLATFORM
41   #endif 41   #endif
42   42  
43   inline uint32_t decimalLength9(const uint32_t v) { 43   inline uint32_t decimalLength9(const uint32_t v) {
44   // Function precondition: v is not a 10-digit number. 44   // Function precondition: v is not a 10-digit number.
45   // (f2s: 9 digits are sufficient for round-tripping.) 45   // (f2s: 9 digits are sufficient for round-tripping.)
46   // (d2fixed: We print 9-digit blocks.) 46   // (d2fixed: We print 9-digit blocks.)
47   BOOST_ASSERT(v < 1000000000); 47   BOOST_ASSERT(v < 1000000000);
48   if (v >= 100000000) { return 9; } 48   if (v >= 100000000) { return 9; }
49   if (v >= 10000000) { return 8; } 49   if (v >= 10000000) { return 8; }
50   if (v >= 1000000) { return 7; } 50   if (v >= 1000000) { return 7; }
51   if (v >= 100000) { return 6; } 51   if (v >= 100000) { return 6; }
52   if (v >= 10000) { return 5; } 52   if (v >= 10000) { return 5; }
53   if (v >= 1000) { return 4; } 53   if (v >= 1000) { return 4; }
54   if (v >= 100) { return 3; } 54   if (v >= 100) { return 3; }
55   if (v >= 10) { return 2; } 55   if (v >= 10) { return 2; }
56   return 1; 56   return 1;
57   } 57   }
58   58  
59   // Returns e == 0 ? 1 : ceil(log_2(5^e)). 59   // Returns e == 0 ? 1 : ceil(log_2(5^e)).
HITCBC 60   2634 inline int32_t pow5bits(const int32_t e) { 60   2634 inline int32_t pow5bits(const int32_t e) {
61   // This approximation works up to the point that the multiplication overflows at e = 3529. 61   // This approximation works up to the point that the multiplication overflows at e = 3529.
62   // If the multiplication were done in 64 bits, it would fail at 5^4004 which is just greater 62   // If the multiplication were done in 64 bits, it would fail at 5^4004 which is just greater
63   // than 2^9297. 63   // than 2^9297.
HITCBC 64   2634 BOOST_ASSERT(e >= 0); 64   2634 BOOST_ASSERT(e >= 0);
HITCBC 65   2634 BOOST_ASSERT(e <= 3528); 65   2634 BOOST_ASSERT(e <= 3528);
HITCBC 66   2634 return (int32_t) (((((uint32_t) e) * 1217359) >> 19) + 1); 66   2634 return (int32_t) (((((uint32_t) e) * 1217359) >> 19) + 1);
67   } 67   }
68   68  
69   // Returns floor(log_10(2^e)). 69   // Returns floor(log_10(2^e)).
HITCBC 70   128 inline uint32_t log10Pow2(const int32_t e) { 70   128 inline uint32_t log10Pow2(const int32_t e) {
71   // The first value this approximation fails for is 2^1651 which is just greater than 10^297. 71   // The first value this approximation fails for is 2^1651 which is just greater than 10^297.
HITCBC 72   128 BOOST_ASSERT(e >= 0); 72   128 BOOST_ASSERT(e >= 0);
HITCBC 73   128 BOOST_ASSERT(e <= 1650); 73   128 BOOST_ASSERT(e <= 1650);
HITCBC 74   128 return (((uint32_t) e) * 78913) >> 18; 74   128 return (((uint32_t) e) * 78913) >> 18;
75   } 75   }
76   76  
77   // Returns floor(log_10(5^e)). 77   // Returns floor(log_10(5^e)).
HITCBC 78   134 inline uint32_t log10Pow5(const int32_t e) { 78   134 inline uint32_t log10Pow5(const int32_t e) {
79   // The first value this approximation fails for is 5^2621 which is just greater than 10^1832. 79   // The first value this approximation fails for is 5^2621 which is just greater than 10^1832.
HITCBC 80   134 BOOST_ASSERT(e >= 0); 80   134 BOOST_ASSERT(e >= 0);
HITCBC 81   134 BOOST_ASSERT(e <= 2620); 81   134 BOOST_ASSERT(e <= 2620);
HITCBC 82   134 return (((uint32_t) e) * 732923) >> 20; 82   134 return (((uint32_t) e) * 732923) >> 20;
83   } 83   }
84   84  
HITCBC 85   11 inline int copy_special_str(char * const result, const bool sign, const bool exponent, const bool mantissa) { 85   11 inline int copy_special_str(char * const result, const bool sign, const bool exponent, const bool mantissa) {
HITCBC 86   11 if (mantissa) { 86   11 if (mantissa) {
HITCBC 87   3 memcpy(result, "NaN", 3); 87   3 memcpy(result, "NaN", 3);
HITCBC 88   3 return 3; 88   3 return 3;
89   } 89   }
HITCBC 90   8 if (sign) { 90   8 if (sign) {
HITCBC 91   4 result[0] = '-'; 91   4 result[0] = '-';
92   } 92   }
HITCBC 93   8 if (exponent) { 93   8 if (exponent) {
HITCBC 94   6 memcpy(result + sign, "Infinity", 8); 94   6 memcpy(result + sign, "Infinity", 8);
HITCBC 95   6 return sign + 8; 95   6 return sign + 8;
96   } 96   }
HITCBC 97   2 memcpy(result + sign, "0E0", 3); 97   2 memcpy(result + sign, "0E0", 3);
HITCBC 98   2 return sign + 3; 98   2 return sign + 3;
99   } 99   }
100   100  
101   inline 101   inline
102   int 102   int
HITCBC 103   60 copy_special_str_conforming( 103   60 copy_special_str_conforming(
104   char* const result, bool sign, bool exponent, bool mantissa) 104   char* const result, bool sign, bool exponent, bool mantissa)
105   { 105   {
HITCBC 106   60 if (mantissa) 106   60 if (mantissa)
107   { 107   {
HITCBC 108   3 memcpy(result, "null", 4); 108   3 memcpy(result, "null", 4);
HITCBC 109   3 return 4; 109   3 return 4;
110   } 110   }
111   111  
HITCBC 112   57 if (sign) 112   57 if (sign)
HITCBC 113   20 result[0] = '-'; 113   20 result[0] = '-';
114   114  
HITCBC 115   57 if (exponent) 115   57 if (exponent)
116   { 116   {
HITCBC 117   6 memcpy(result + sign, "1e99999", 7); 117   6 memcpy(result + sign, "1e99999", 7);
HITCBC 118   6 return sign + 7; 118   6 return sign + 7;
119   } 119   }
120   120  
HITCBC 121   51 memcpy(result + sign, "0E0", 3); 121   51 memcpy(result + sign, "0E0", 3);
HITCBC 122   51 return sign + 3; 122   51 return sign + 3;
123   } 123   }
124   124  
125   inline uint32_t float_to_bits(const float f) { 125   inline uint32_t float_to_bits(const float f) {
126   uint32_t bits = 0; 126   uint32_t bits = 0;
127   memcpy(&bits, &f, sizeof(float)); 127   memcpy(&bits, &f, sizeof(float));
128   return bits; 128   return bits;
129   } 129   }
130   130  
HITCBC 131   609 inline uint64_t double_to_bits(const double d) { 131   609 inline uint64_t double_to_bits(const double d) {
HITCBC 132   609 uint64_t bits = 0; 132   609 uint64_t bits = 0;
HITCBC 133   609 memcpy(&bits, &d, sizeof(double)); 133   609 memcpy(&bits, &d, sizeof(double));
HITCBC 134   609 return bits; 134   609 return bits;
135   } 135   }
136   136  
137   } // detail 137   } // detail
138   } // ryu 138   } // ryu
139   139  
140   } // detail 140   } // detail
141   } // namespace json 141   } // namespace json
142   } // namespace boost 142   } // namespace boost
143   143  
144   #endif 144   #endif