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