/src/jsoncons/include/jsoncons/utility/write_number.hpp
Line | Count | Source |
1 | | // Copyright 2013-2026 Daniel Parker |
2 | | // Distributed under the Boost license, Version 1.0. |
3 | | // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
4 | | |
5 | | // See https://github.com/danielaparker/jsoncons for latest version |
6 | | |
7 | | #ifndef JSONCONS_UTILITY_WRITE_NUMBER_HPP |
8 | | #define JSONCONS_UTILITY_WRITE_NUMBER_HPP |
9 | | |
10 | | #include <clocale> |
11 | | #include <cmath> |
12 | | #include <cstddef> |
13 | | #include <cstdint> |
14 | | #include <limits> // std::numeric_limits |
15 | | #include <locale> |
16 | | #include <stdexcept> |
17 | | #include <stdio.h> // snprintf |
18 | | #include <string> |
19 | | #include <type_traits> |
20 | | |
21 | | #include <jsoncons/config/compiler_support.hpp> |
22 | | #include <jsoncons/config/jsoncons_config.hpp> |
23 | | #include <jsoncons/detail/grisu3.hpp> |
24 | | #include <jsoncons/utility/read_number.hpp> |
25 | | #include <jsoncons/json_exception.hpp> |
26 | | #include <jsoncons/json_options.hpp> |
27 | | #include <jsoncons/utility/more_type_traits.hpp> |
28 | | |
29 | | namespace jsoncons { |
30 | | |
31 | | inline |
32 | | char to_hex_character(uint8_t c) |
33 | 958k | { |
34 | 958k | return (char)((c < 10) ? ('0' + c) : ('A' - 10 + c)); |
35 | 958k | } |
36 | | |
37 | | // from_integer |
38 | | |
39 | | template <typename Integer,typename Result> |
40 | | typename std::enable_if<ext_traits::is_integer<Integer>::value,std::size_t>::type |
41 | | from_integer(Integer value, Result& result) |
42 | 97.4M | { |
43 | 97.4M | using char_type = typename Result::value_type; |
44 | | |
45 | 97.4M | char_type buf[255]; |
46 | 97.4M | char_type *p = buf; |
47 | 97.4M | const char_type* last = buf+255; |
48 | | |
49 | 97.4M | bool is_negative = value < 0; |
50 | | |
51 | 97.4M | if (value < 0) |
52 | 16.0M | { |
53 | 16.0M | do |
54 | 40.1M | { |
55 | 40.1M | *p++ = static_cast<char_type>(48 - (value % 10)); |
56 | 40.1M | } |
57 | 40.1M | while ((value /= 10) && (p < last)); |
58 | 16.0M | } |
59 | 81.4M | else |
60 | 81.4M | { |
61 | | |
62 | 81.4M | do |
63 | 178M | { |
64 | 178M | *p++ = static_cast<char_type>(48 + value % 10); |
65 | 178M | } |
66 | 178M | while ((value /= 10) && (p < last)); |
67 | 81.4M | } |
68 | 97.4M | JSONCONS_ASSERT(p != last); |
69 | | |
70 | 97.4M | std::size_t count = (p - buf); |
71 | 97.4M | if (is_negative) |
72 | 16.0M | { |
73 | 16.0M | result.push_back('-'); |
74 | 16.0M | ++count; |
75 | 16.0M | } |
76 | 316M | while (--p >= buf) |
77 | 218M | { |
78 | 218M | result.push_back(*p); |
79 | 218M | } |
80 | | |
81 | 97.4M | return count; |
82 | 97.4M | } _ZN8jsoncons12from_integerImNS_11string_sinkINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEEEEENS2_9enable_ifIXsr10ext_traits10is_integerIT_EE5valueEmE4typeESB_RT0_ Line | Count | Source | 42 | 4.28M | { | 43 | 4.28M | using char_type = typename Result::value_type; | 44 | | | 45 | 4.28M | char_type buf[255]; | 46 | 4.28M | char_type *p = buf; | 47 | 4.28M | const char_type* last = buf+255; | 48 | | | 49 | 4.28M | bool is_negative = value < 0; | 50 | | | 51 | 4.28M | if (value < 0) | 52 | 0 | { | 53 | 0 | do | 54 | 0 | { | 55 | 0 | *p++ = static_cast<char_type>(48 - (value % 10)); | 56 | 0 | } | 57 | 0 | while ((value /= 10) && (p < last)); | 58 | 0 | } | 59 | 4.28M | else | 60 | 4.28M | { | 61 | | | 62 | 4.28M | do | 63 | 4.56M | { | 64 | 4.56M | *p++ = static_cast<char_type>(48 + value % 10); | 65 | 4.56M | } | 66 | 4.56M | while ((value /= 10) && (p < last)); | 67 | 4.28M | } | 68 | 4.28M | JSONCONS_ASSERT(p != last); | 69 | | | 70 | 4.28M | std::size_t count = (p - buf); | 71 | 4.28M | if (is_negative) | 72 | 0 | { | 73 | 0 | result.push_back('-'); | 74 | 0 | ++count; | 75 | 0 | } | 76 | 8.84M | while (--p >= buf) | 77 | 4.56M | { | 78 | 4.56M | result.push_back(*p); | 79 | 4.56M | } | 80 | | | 81 | 4.28M | return count; | 82 | 4.28M | } |
_ZN8jsoncons12from_integerIlNS_11string_sinkINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEEEEENS2_9enable_ifIXsr10ext_traits10is_integerIT_EE5valueEmE4typeESB_RT0_ Line | Count | Source | 42 | 171k | { | 43 | 171k | using char_type = typename Result::value_type; | 44 | | | 45 | 171k | char_type buf[255]; | 46 | 171k | char_type *p = buf; | 47 | 171k | const char_type* last = buf+255; | 48 | | | 49 | 171k | bool is_negative = value < 0; | 50 | | | 51 | 171k | if (value < 0) | 52 | 169k | { | 53 | 169k | do | 54 | 432k | { | 55 | 432k | *p++ = static_cast<char_type>(48 - (value % 10)); | 56 | 432k | } | 57 | 432k | while ((value /= 10) && (p < last)); | 58 | 169k | } | 59 | 1.64k | else | 60 | 1.64k | { | 61 | | | 62 | 1.64k | do | 63 | 1.64k | { | 64 | 1.64k | *p++ = static_cast<char_type>(48 + value % 10); | 65 | 1.64k | } | 66 | 1.64k | while ((value /= 10) && (p < last)); | 67 | 1.64k | } | 68 | 171k | JSONCONS_ASSERT(p != last); | 69 | | | 70 | 171k | std::size_t count = (p - buf); | 71 | 171k | if (is_negative) | 72 | 169k | { | 73 | 169k | result.push_back('-'); | 74 | 169k | ++count; | 75 | 169k | } | 76 | 605k | while (--p >= buf) | 77 | 433k | { | 78 | 433k | result.push_back(*p); | 79 | 433k | } | 80 | | | 81 | 171k | return count; | 82 | 171k | } |
Unexecuted instantiation: _ZN8jsoncons12from_integerIiNS_11string_sinkINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEEEEENS2_9enable_ifIXsr10ext_traits10is_integerIT_EE5valueEmE4typeESB_RT0_ _ZN8jsoncons12from_integerIiNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEEENS1_9enable_ifIXsr10ext_traits10is_integerIT_EE5valueEmE4typeES9_RT0_ Line | Count | Source | 42 | 36.9k | { | 43 | 36.9k | using char_type = typename Result::value_type; | 44 | | | 45 | 36.9k | char_type buf[255]; | 46 | 36.9k | char_type *p = buf; | 47 | 36.9k | const char_type* last = buf+255; | 48 | | | 49 | 36.9k | bool is_negative = value < 0; | 50 | | | 51 | 36.9k | if (value < 0) | 52 | 29.5k | { | 53 | 29.5k | do | 54 | 117k | { | 55 | 117k | *p++ = static_cast<char_type>(48 - (value % 10)); | 56 | 117k | } | 57 | 117k | while ((value /= 10) && (p < last)); | 58 | 29.5k | } | 59 | 7.46k | else | 60 | 7.46k | { | 61 | | | 62 | 7.46k | do | 63 | 26.6k | { | 64 | 26.6k | *p++ = static_cast<char_type>(48 + value % 10); | 65 | 26.6k | } | 66 | 26.6k | while ((value /= 10) && (p < last)); | 67 | 7.46k | } | 68 | 36.9k | JSONCONS_ASSERT(p != last); | 69 | | | 70 | 36.9k | std::size_t count = (p - buf); | 71 | 36.9k | if (is_negative) | 72 | 29.5k | { | 73 | 29.5k | result.push_back('-'); | 74 | 29.5k | ++count; | 75 | 29.5k | } | 76 | 180k | while (--p >= buf) | 77 | 143k | { | 78 | 143k | result.push_back(*p); | 79 | 143k | } | 80 | | | 81 | 36.9k | return count; | 82 | 36.9k | } |
_ZN8jsoncons12from_integerImNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEEENS1_9enable_ifIXsr10ext_traits10is_integerIT_EE5valueEmE4typeES9_RT0_ Line | Count | Source | 42 | 69.8M | { | 43 | 69.8M | using char_type = typename Result::value_type; | 44 | | | 45 | 69.8M | char_type buf[255]; | 46 | 69.8M | char_type *p = buf; | 47 | 69.8M | const char_type* last = buf+255; | 48 | | | 49 | 69.8M | bool is_negative = value < 0; | 50 | | | 51 | 69.8M | if (value < 0) | 52 | 0 | { | 53 | 0 | do | 54 | 0 | { | 55 | 0 | *p++ = static_cast<char_type>(48 - (value % 10)); | 56 | 0 | } | 57 | 0 | while ((value /= 10) && (p < last)); | 58 | 0 | } | 59 | 69.8M | else | 60 | 69.8M | { | 61 | | | 62 | 69.8M | do | 63 | 144M | { | 64 | 144M | *p++ = static_cast<char_type>(48 + value % 10); | 65 | 144M | } | 66 | 144M | while ((value /= 10) && (p < last)); | 67 | 69.8M | } | 68 | 69.8M | JSONCONS_ASSERT(p != last); | 69 | | | 70 | 69.8M | std::size_t count = (p - buf); | 71 | 69.8M | if (is_negative) | 72 | 0 | { | 73 | 0 | result.push_back('-'); | 74 | 0 | ++count; | 75 | 0 | } | 76 | 214M | while (--p >= buf) | 77 | 144M | { | 78 | 144M | result.push_back(*p); | 79 | 144M | } | 80 | | | 81 | 69.8M | return count; | 82 | 69.8M | } |
_ZN8jsoncons12from_integerIlNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEEENS1_9enable_ifIXsr10ext_traits10is_integerIT_EE5valueEmE4typeES9_RT0_ Line | Count | Source | 42 | 23.0M | { | 43 | 23.0M | using char_type = typename Result::value_type; | 44 | | | 45 | 23.0M | char_type buf[255]; | 46 | 23.0M | char_type *p = buf; | 47 | 23.0M | const char_type* last = buf+255; | 48 | | | 49 | 23.0M | bool is_negative = value < 0; | 50 | | | 51 | 23.0M | if (value < 0) | 52 | 15.8M | { | 53 | 15.8M | do | 54 | 39.5M | { | 55 | 39.5M | *p++ = static_cast<char_type>(48 - (value % 10)); | 56 | 39.5M | } | 57 | 39.5M | while ((value /= 10) && (p < last)); | 58 | 15.8M | } | 59 | 7.29M | else | 60 | 7.29M | { | 61 | | | 62 | 7.29M | do | 63 | 28.9M | { | 64 | 28.9M | *p++ = static_cast<char_type>(48 + value % 10); | 65 | 28.9M | } | 66 | 28.9M | while ((value /= 10) && (p < last)); | 67 | 7.29M | } | 68 | 23.0M | JSONCONS_ASSERT(p != last); | 69 | | | 70 | 23.0M | std::size_t count = (p - buf); | 71 | 23.0M | if (is_negative) | 72 | 15.8M | { | 73 | 15.8M | result.push_back('-'); | 74 | 15.8M | ++count; | 75 | 15.8M | } | 76 | 91.5M | while (--p >= buf) | 77 | 68.4M | { | 78 | 68.4M | result.push_back(*p); | 79 | 68.4M | } | 80 | | | 81 | 23.0M | return count; | 82 | 23.0M | } |
|
83 | | |
84 | | // integer_to_hex |
85 | | |
86 | | template <typename Integer,typename Result> |
87 | | typename std::enable_if<ext_traits::is_integer<Integer>::value,std::size_t>::type |
88 | | integer_to_hex(Integer value, Result& result) |
89 | 431k | { |
90 | 431k | using char_type = typename Result::value_type; |
91 | | |
92 | 431k | char_type buf[255]; |
93 | 431k | char_type *p = buf; |
94 | 431k | const char_type* last = buf+255; |
95 | | |
96 | 431k | bool is_negative = value < 0; |
97 | | |
98 | 431k | if (value < 0) |
99 | 0 | { |
100 | 0 | do |
101 | 0 | { |
102 | 0 | *p++ = to_hex_character(0-(value % 16)); |
103 | 0 | } |
104 | 0 | while ((value /= 16) && (p < last)); |
105 | 0 | } |
106 | 431k | else |
107 | 431k | { |
108 | | |
109 | 431k | do |
110 | 594k | { |
111 | 594k | *p++ = to_hex_character(value % 16); |
112 | 594k | } |
113 | 594k | while ((value /= 16) && (p < last)); |
114 | 431k | } |
115 | 431k | JSONCONS_ASSERT(p != last); |
116 | | |
117 | 431k | std::size_t count = (p - buf); |
118 | 431k | if (is_negative) |
119 | 0 | { |
120 | 0 | result.push_back('-'); |
121 | 0 | ++count; |
122 | 0 | } |
123 | 1.02M | while (--p >= buf) |
124 | 594k | { |
125 | 594k | result.push_back(*p); |
126 | 594k | } |
127 | | |
128 | 431k | return count; |
129 | 431k | } |
130 | | |
131 | | // write_double |
132 | | |
133 | | // fast exponent |
134 | | template <typename Result> |
135 | | void fill_exponent(int K, Result& result) |
136 | 21.6M | { |
137 | 21.6M | if (K < 0) |
138 | 13.3M | { |
139 | 13.3M | result.push_back('-'); |
140 | 13.3M | K = -K; |
141 | 13.3M | } |
142 | 8.29M | else |
143 | 8.29M | { |
144 | 8.29M | result.push_back('+'); // compatibility with sprintf |
145 | 8.29M | } |
146 | | |
147 | 21.6M | if (K < 10) |
148 | 12.7M | { |
149 | 12.7M | result.push_back('0'); // compatibility with sprintf |
150 | 12.7M | result.push_back((char)('0' + K)); |
151 | 12.7M | } |
152 | 8.94M | else if (K < 100) |
153 | 565k | { |
154 | 565k | result.push_back((char)('0' + K / 10)); K %= 10; |
155 | 565k | result.push_back((char)('0' + K)); |
156 | 565k | } |
157 | 8.37M | else if (K < 1000) |
158 | 8.37M | { |
159 | 8.37M | result.push_back((char)('0' + K / 100)); K %= 100; |
160 | 8.37M | result.push_back((char)('0' + K / 10)); K %= 10; |
161 | 8.37M | result.push_back((char)('0' + K)); |
162 | 8.37M | } |
163 | 895 | else |
164 | 895 | { |
165 | 895 | jsoncons::from_integer(K, result); |
166 | 895 | } |
167 | 21.6M | } void jsoncons::fill_exponent<jsoncons::string_sink<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >(int, jsoncons::string_sink<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&) Line | Count | Source | 136 | 21.5M | { | 137 | 21.5M | if (K < 0) | 138 | 13.3M | { | 139 | 13.3M | result.push_back('-'); | 140 | 13.3M | K = -K; | 141 | 13.3M | } | 142 | 8.19M | else | 143 | 8.19M | { | 144 | 8.19M | result.push_back('+'); // compatibility with sprintf | 145 | 8.19M | } | 146 | | | 147 | 21.5M | if (K < 10) | 148 | 12.7M | { | 149 | 12.7M | result.push_back('0'); // compatibility with sprintf | 150 | 12.7M | result.push_back((char)('0' + K)); | 151 | 12.7M | } | 152 | 8.84M | else if (K < 100) | 153 | 466k | { | 154 | 466k | result.push_back((char)('0' + K / 10)); K %= 10; | 155 | 466k | result.push_back((char)('0' + K)); | 156 | 466k | } | 157 | 8.37M | else if (K < 1000) | 158 | 8.37M | { | 159 | 8.37M | result.push_back((char)('0' + K / 100)); K %= 100; | 160 | 8.37M | result.push_back((char)('0' + K / 10)); K %= 10; | 161 | 8.37M | result.push_back((char)('0' + K)); | 162 | 8.37M | } | 163 | 0 | else | 164 | 0 | { | 165 | 0 | jsoncons::from_integer(K, result); | 166 | 0 | } | 167 | 21.5M | } |
void jsoncons::fill_exponent<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(int, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&) Line | Count | Source | 136 | 102k | { | 137 | 102k | if (K < 0) | 138 | 2.50k | { | 139 | 2.50k | result.push_back('-'); | 140 | 2.50k | K = -K; | 141 | 2.50k | } | 142 | 99.9k | else | 143 | 99.9k | { | 144 | 99.9k | result.push_back('+'); // compatibility with sprintf | 145 | 99.9k | } | 146 | | | 147 | 102k | if (K < 10) | 148 | 715 | { | 149 | 715 | result.push_back('0'); // compatibility with sprintf | 150 | 715 | result.push_back((char)('0' + K)); | 151 | 715 | } | 152 | 101k | else if (K < 100) | 153 | 99.7k | { | 154 | 99.7k | result.push_back((char)('0' + K / 10)); K %= 10; | 155 | 99.7k | result.push_back((char)('0' + K)); | 156 | 99.7k | } | 157 | 2.01k | else if (K < 1000) | 158 | 1.12k | { | 159 | 1.12k | result.push_back((char)('0' + K / 100)); K %= 100; | 160 | 1.12k | result.push_back((char)('0' + K / 10)); K %= 10; | 161 | 1.12k | result.push_back((char)('0' + K)); | 162 | 1.12k | } | 163 | 895 | else | 164 | 895 | { | 165 | 895 | jsoncons::from_integer(K, result); | 166 | 895 | } | 167 | 102k | } |
|
168 | | |
169 | | template <typename Result> |
170 | | void prettify_string(const char *buffer, std::size_t length, int k, int min_exp, int max_exp, Result& result) |
171 | 107M | { |
172 | 107M | int nb_digits = (int)length; |
173 | 107M | int offset; |
174 | | /* v = buffer * 10^k |
175 | | kk is such that 10^(kk-1) <= v < 10^kk |
176 | | this way kk gives the position of the decimal point. |
177 | | */ |
178 | 107M | int kk = nb_digits + k; |
179 | | |
180 | 107M | if (nb_digits <= kk && kk <= max_exp) |
181 | 16.2M | { |
182 | | /* the first digits are already in. Add some 0s and call it a day. */ |
183 | | /* the max_exp is a personal choice. Only 16 digits could possibly be relevant. |
184 | | * Basically we want to print 12340000000 rather than 1234.0e7 or 1.234e10 */ |
185 | 69.0M | for (int i = 0; i < nb_digits; ++i) |
186 | 52.8M | { |
187 | 52.8M | result.push_back(buffer[i]); |
188 | 52.8M | } |
189 | 23.6M | for (int i = nb_digits; i < kk; ++i) |
190 | 7.44M | { |
191 | 7.44M | result.push_back('0'); |
192 | 7.44M | } |
193 | 16.2M | result.push_back('.'); |
194 | 16.2M | result.push_back('0'); |
195 | 16.2M | } |
196 | 90.9M | else if (0 < kk && kk <= max_exp) |
197 | 27.4M | { |
198 | | /* comma number. Just insert a '.' at the correct location. */ |
199 | 87.7M | for (int i = 0; i < kk; ++i) |
200 | 60.2M | { |
201 | 60.2M | result.push_back(buffer[i]); |
202 | 60.2M | } |
203 | 27.4M | result.push_back('.'); |
204 | 110M | for (int i = kk; i < nb_digits; ++i) |
205 | 83.0M | { |
206 | 83.0M | result.push_back(buffer[i]); |
207 | 83.0M | } |
208 | 27.4M | } |
209 | 63.4M | else if (min_exp < kk && kk <= 0) |
210 | 41.8M | { |
211 | 41.8M | offset = 2 - kk; |
212 | | |
213 | 41.8M | result.push_back('0'); |
214 | 41.8M | result.push_back('.'); |
215 | 134M | for (int i = 2; i < offset; ++i) |
216 | 92.4M | result.push_back('0'); |
217 | 657M | for (int i = 0; i < nb_digits; ++i) |
218 | 615M | { |
219 | 615M | result.push_back(buffer[i]); |
220 | 615M | } |
221 | 41.8M | } |
222 | 21.6M | else if (nb_digits == 1) |
223 | 215k | { |
224 | 215k | result.push_back(buffer[0]); |
225 | 215k | result.push_back('e'); |
226 | 215k | fill_exponent(kk - 1, result); |
227 | 215k | } |
228 | 21.4M | else |
229 | 21.4M | { |
230 | 21.4M | result.push_back(buffer[0]); |
231 | 21.4M | result.push_back('.'); |
232 | 339M | for (int i = 1; i < nb_digits; ++i) |
233 | 317M | { |
234 | 317M | result.push_back(buffer[i]); |
235 | 317M | } |
236 | 21.4M | result.push_back('e'); |
237 | 21.4M | fill_exponent(kk - 1, result); |
238 | 21.4M | } |
239 | 107M | } void jsoncons::prettify_string<jsoncons::string_sink<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >(char const*, unsigned long, int, int, int, jsoncons::string_sink<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&) Line | Count | Source | 171 | 105M | { | 172 | 105M | int nb_digits = (int)length; | 173 | 105M | int offset; | 174 | | /* v = buffer * 10^k | 175 | | kk is such that 10^(kk-1) <= v < 10^kk | 176 | | this way kk gives the position of the decimal point. | 177 | | */ | 178 | 105M | int kk = nb_digits + k; | 179 | | | 180 | 105M | if (nb_digits <= kk && kk <= max_exp) | 181 | 16.1M | { | 182 | | /* the first digits are already in. Add some 0s and call it a day. */ | 183 | | /* the max_exp is a personal choice. Only 16 digits could possibly be relevant. | 184 | | * Basically we want to print 12340000000 rather than 1234.0e7 or 1.234e10 */ | 185 | 68.9M | for (int i = 0; i < nb_digits; ++i) | 186 | 52.7M | { | 187 | 52.7M | result.push_back(buffer[i]); | 188 | 52.7M | } | 189 | 23.5M | for (int i = nb_digits; i < kk; ++i) | 190 | 7.33M | { | 191 | 7.33M | result.push_back('0'); | 192 | 7.33M | } | 193 | 16.1M | result.push_back('.'); | 194 | 16.1M | result.push_back('0'); | 195 | 16.1M | } | 196 | 89.7M | else if (0 < kk && kk <= max_exp) | 197 | 26.3M | { | 198 | | /* comma number. Just insert a '.' at the correct location. */ | 199 | 85.4M | for (int i = 0; i < kk; ++i) | 200 | 59.1M | { | 201 | 59.1M | result.push_back(buffer[i]); | 202 | 59.1M | } | 203 | 26.3M | result.push_back('.'); | 204 | 108M | for (int i = kk; i < nb_digits; ++i) | 205 | 81.9M | { | 206 | 81.9M | result.push_back(buffer[i]); | 207 | 81.9M | } | 208 | 26.3M | } | 209 | 63.3M | else if (min_exp < kk && kk <= 0) | 210 | 41.8M | { | 211 | 41.8M | offset = 2 - kk; | 212 | | | 213 | 41.8M | result.push_back('0'); | 214 | 41.8M | result.push_back('.'); | 215 | 134M | for (int i = 2; i < offset; ++i) | 216 | 92.4M | result.push_back('0'); | 217 | 657M | for (int i = 0; i < nb_digits; ++i) | 218 | 615M | { | 219 | 615M | result.push_back(buffer[i]); | 220 | 615M | } | 221 | 41.8M | } | 222 | 21.5M | else if (nb_digits == 1) | 223 | 212k | { | 224 | 212k | result.push_back(buffer[0]); | 225 | 212k | result.push_back('e'); | 226 | 212k | fill_exponent(kk - 1, result); | 227 | 212k | } | 228 | 21.3M | else | 229 | 21.3M | { | 230 | 21.3M | result.push_back(buffer[0]); | 231 | 21.3M | result.push_back('.'); | 232 | 337M | for (int i = 1; i < nb_digits; ++i) | 233 | 316M | { | 234 | 316M | result.push_back(buffer[i]); | 235 | 316M | } | 236 | 21.3M | result.push_back('e'); | 237 | 21.3M | fill_exponent(kk - 1, result); | 238 | 21.3M | } | 239 | 105M | } |
void jsoncons::prettify_string<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(char const*, unsigned long, int, int, int, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&) Line | Count | Source | 171 | 1.24M | { | 172 | 1.24M | int nb_digits = (int)length; | 173 | 1.24M | int offset; | 174 | | /* v = buffer * 10^k | 175 | | kk is such that 10^(kk-1) <= v < 10^kk | 176 | | this way kk gives the position of the decimal point. | 177 | | */ | 178 | 1.24M | int kk = nb_digits + k; | 179 | | | 180 | 1.24M | if (nb_digits <= kk && kk <= max_exp) | 181 | 14.3k | { | 182 | | /* the first digits are already in. Add some 0s and call it a day. */ | 183 | | /* the max_exp is a personal choice. Only 16 digits could possibly be relevant. | 184 | | * Basically we want to print 12340000000 rather than 1234.0e7 or 1.234e10 */ | 185 | 101k | for (int i = 0; i < nb_digits; ++i) | 186 | 86.8k | { | 187 | 86.8k | result.push_back(buffer[i]); | 188 | 86.8k | } | 189 | 125k | for (int i = nb_digits; i < kk; ++i) | 190 | 111k | { | 191 | 111k | result.push_back('0'); | 192 | 111k | } | 193 | 14.3k | result.push_back('.'); | 194 | 14.3k | result.push_back('0'); | 195 | 14.3k | } | 196 | 1.23M | else if (0 < kk && kk <= max_exp) | 197 | 1.12M | { | 198 | | /* comma number. Just insert a '.' at the correct location. */ | 199 | 2.26M | for (int i = 0; i < kk; ++i) | 200 | 1.13M | { | 201 | 1.13M | result.push_back(buffer[i]); | 202 | 1.13M | } | 203 | 1.12M | result.push_back('.'); | 204 | 2.25M | for (int i = kk; i < nb_digits; ++i) | 205 | 1.13M | { | 206 | 1.13M | result.push_back(buffer[i]); | 207 | 1.13M | } | 208 | 1.12M | } | 209 | 104k | else if (min_exp < kk && kk <= 0) | 210 | 1.76k | { | 211 | 1.76k | offset = 2 - kk; | 212 | | | 213 | 1.76k | result.push_back('0'); | 214 | 1.76k | result.push_back('.'); | 215 | 4.26k | for (int i = 2; i < offset; ++i) | 216 | 2.50k | result.push_back('0'); | 217 | 4.99k | for (int i = 0; i < nb_digits; ++i) | 218 | 3.23k | { | 219 | 3.23k | result.push_back(buffer[i]); | 220 | 3.23k | } | 221 | 1.76k | } | 222 | 102k | else if (nb_digits == 1) | 223 | 2.46k | { | 224 | 2.46k | result.push_back(buffer[0]); | 225 | 2.46k | result.push_back('e'); | 226 | 2.46k | fill_exponent(kk - 1, result); | 227 | 2.46k | } | 228 | 100k | else | 229 | 100k | { | 230 | 100k | result.push_back(buffer[0]); | 231 | 100k | result.push_back('.'); | 232 | 1.16M | for (int i = 1; i < nb_digits; ++i) | 233 | 1.06M | { | 234 | 1.06M | result.push_back(buffer[i]); | 235 | 1.06M | } | 236 | 100k | result.push_back('e'); | 237 | 100k | fill_exponent(kk - 1, result); | 238 | 100k | } | 239 | 1.24M | } |
|
240 | | |
241 | | template <typename Result> |
242 | | void dump_buffer(const char *buffer, std::size_t length, char decimal_point, Result& result) |
243 | 636k | { |
244 | 636k | const char *sbeg = buffer; |
245 | 636k | const char *send = sbeg + length; |
246 | | |
247 | 636k | if (sbeg != send) |
248 | 636k | { |
249 | 636k | bool needs_dot = true; |
250 | 14.4M | for (const char* q = sbeg; q < send; ++q) |
251 | 13.7M | { |
252 | 13.7M | switch (*q) |
253 | 13.7M | { |
254 | 403k | case '-': |
255 | 3.15M | case '0': |
256 | 4.50M | case '1': |
257 | 5.36M | case '2': |
258 | 6.65M | case '3': |
259 | 7.61M | case '4': |
260 | 8.44M | case '5': |
261 | 9.68M | case '6': |
262 | 10.9M | case '7': |
263 | 12.3M | case '8': |
264 | 12.9M | case '9': |
265 | 12.9M | case '+': |
266 | 12.9M | result.push_back(*q); |
267 | 12.9M | break; |
268 | 154k | case 'e': |
269 | 154k | case 'E': |
270 | 154k | result.push_back('e'); |
271 | 154k | needs_dot = false; |
272 | 154k | break; |
273 | 640k | default: |
274 | 640k | if (*q == decimal_point) |
275 | 630k | { |
276 | 630k | needs_dot = false; |
277 | 630k | result.push_back('.'); |
278 | 630k | } |
279 | 640k | break; |
280 | 13.7M | } |
281 | 13.7M | } |
282 | 636k | if (needs_dot) |
283 | 5.80k | { |
284 | 5.80k | result.push_back('.'); |
285 | 5.80k | result.push_back('0'); |
286 | 5.80k | } |
287 | 636k | } |
288 | 636k | } void jsoncons::dump_buffer<jsoncons::string_sink<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >(char const*, unsigned long, char, jsoncons::string_sink<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&) Line | Count | Source | 243 | 636k | { | 244 | 636k | const char *sbeg = buffer; | 245 | 636k | const char *send = sbeg + length; | 246 | | | 247 | 636k | if (sbeg != send) | 248 | 636k | { | 249 | 636k | bool needs_dot = true; | 250 | 14.4M | for (const char* q = sbeg; q < send; ++q) | 251 | 13.7M | { | 252 | 13.7M | switch (*q) | 253 | 13.7M | { | 254 | 403k | case '-': | 255 | 3.15M | case '0': | 256 | 4.50M | case '1': | 257 | 5.36M | case '2': | 258 | 6.65M | case '3': | 259 | 7.61M | case '4': | 260 | 8.44M | case '5': | 261 | 9.67M | case '6': | 262 | 10.9M | case '7': | 263 | 12.3M | case '8': | 264 | 12.9M | case '9': | 265 | 12.9M | case '+': | 266 | 12.9M | result.push_back(*q); | 267 | 12.9M | break; | 268 | 154k | case 'e': | 269 | 154k | case 'E': | 270 | 154k | result.push_back('e'); | 271 | 154k | needs_dot = false; | 272 | 154k | break; | 273 | 640k | default: | 274 | 640k | if (*q == decimal_point) | 275 | 630k | { | 276 | 630k | needs_dot = false; | 277 | 630k | result.push_back('.'); | 278 | 630k | } | 279 | 640k | break; | 280 | 13.7M | } | 281 | 13.7M | } | 282 | 636k | if (needs_dot) | 283 | 5.80k | { | 284 | 5.80k | result.push_back('.'); | 285 | 5.80k | result.push_back('0'); | 286 | 5.80k | } | 287 | 636k | } | 288 | 636k | } |
void jsoncons::dump_buffer<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(char const*, unsigned long, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&) Line | Count | Source | 243 | 184 | { | 244 | 184 | const char *sbeg = buffer; | 245 | 184 | const char *send = sbeg + length; | 246 | | | 247 | 184 | if (sbeg != send) | 248 | 184 | { | 249 | 184 | bool needs_dot = true; | 250 | 2.43k | for (const char* q = sbeg; q < send; ++q) | 251 | 2.25k | { | 252 | 2.25k | switch (*q) | 253 | 2.25k | { | 254 | 9 | case '-': | 255 | 288 | case '0': | 256 | 474 | case '1': | 257 | 664 | case '2': | 258 | 846 | case '3': | 259 | 1.04k | case '4': | 260 | 1.22k | case '5': | 261 | 1.41k | case '6': | 262 | 1.56k | case '7': | 263 | 1.75k | case '8': | 264 | 1.98k | case '9': | 265 | 2.03k | case '+': | 266 | 2.03k | result.push_back(*q); | 267 | 2.03k | break; | 268 | 51 | case 'e': | 269 | 51 | case 'E': | 270 | 51 | result.push_back('e'); | 271 | 51 | needs_dot = false; | 272 | 51 | break; | 273 | 172 | default: | 274 | 172 | if (*q == decimal_point) | 275 | 172 | { | 276 | 172 | needs_dot = false; | 277 | 172 | result.push_back('.'); | 278 | 172 | } | 279 | 172 | break; | 280 | 2.25k | } | 281 | 2.25k | } | 282 | 184 | if (needs_dot) | 283 | 2 | { | 284 | 2 | result.push_back('.'); | 285 | 2 | result.push_back('0'); | 286 | 2 | } | 287 | 184 | } | 288 | 184 | } |
|
289 | | |
290 | | template <typename Result> |
291 | | bool dtoa_scientific(double val, char decimal_point, Result& result) |
292 | 0 | { |
293 | 0 | if (val == 0) |
294 | 0 | { |
295 | 0 | result.push_back('0'); |
296 | 0 | result.push_back('.'); |
297 | 0 | result.push_back('0'); |
298 | 0 | return true; |
299 | 0 | } |
300 | | |
301 | 0 | char buffer[100]; |
302 | 0 | int precision = std::numeric_limits<double>::digits10; |
303 | 0 | int length = snprintf(buffer, sizeof(buffer), "%1.*e", precision, val); |
304 | 0 | if (length < 0) |
305 | 0 | { |
306 | 0 | return false; |
307 | 0 | } |
308 | 0 | double x{0}; |
309 | 0 | auto res = decstr_to_double(buffer, length, x); |
310 | 0 | if (res.ec == std::errc::invalid_argument) |
311 | 0 | { |
312 | 0 | return false; |
313 | 0 | } |
314 | 0 | if (x != val) |
315 | 0 | { |
316 | 0 | const int precision2 = std::numeric_limits<double>::max_digits10; |
317 | 0 | length = snprintf(buffer, sizeof(buffer), "%1.*e", precision2, val); |
318 | 0 | if (length < 0) |
319 | 0 | { |
320 | 0 | return false; |
321 | 0 | } |
322 | 0 | } |
323 | 0 | dump_buffer(buffer, static_cast<std::size_t>(length), decimal_point, result); |
324 | 0 | return true; |
325 | 0 | } Unexecuted instantiation: bool jsoncons::dtoa_scientific<jsoncons::string_sink<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >(double, char, jsoncons::string_sink<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&) Unexecuted instantiation: bool jsoncons::dtoa_scientific<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(double, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&) |
326 | | |
327 | | template <typename Result> |
328 | | bool dtoa_general(double val, char decimal_point, Result& result, std::false_type) |
329 | 636k | { |
330 | 636k | if (val == 0) |
331 | 0 | { |
332 | 0 | result.push_back('0'); |
333 | 0 | result.push_back('.'); |
334 | 0 | result.push_back('0'); |
335 | 0 | return true; |
336 | 0 | } |
337 | | |
338 | 636k | char buffer[100]; |
339 | 636k | int precision = std::numeric_limits<double>::digits10; |
340 | 636k | int length = snprintf(buffer, sizeof(buffer), "%1.*g", precision, val); |
341 | 636k | if (length < 0) |
342 | 0 | { |
343 | 0 | return false; |
344 | 0 | } |
345 | 636k | double x{0}; |
346 | 636k | auto res = decstr_to_double(buffer, length, x); |
347 | 636k | if (res.ec == std::errc::invalid_argument) |
348 | 0 | { |
349 | 0 | return false; |
350 | 0 | } |
351 | 636k | if (x != val) |
352 | 629k | { |
353 | 629k | const int precision2 = std::numeric_limits<double>::max_digits10; |
354 | 629k | length = snprintf(buffer, sizeof(buffer), "%1.*g", precision2, val); |
355 | 629k | if (length < 0) |
356 | 0 | { |
357 | 0 | return false; |
358 | 0 | } |
359 | 629k | } |
360 | 636k | dump_buffer(buffer, length, decimal_point, result); |
361 | 636k | return true; |
362 | 636k | } bool jsoncons::dtoa_general<jsoncons::string_sink<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >(double, char, jsoncons::string_sink<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&, std::__1::integral_constant<bool, false>) Line | Count | Source | 329 | 636k | { | 330 | 636k | if (val == 0) | 331 | 0 | { | 332 | 0 | result.push_back('0'); | 333 | 0 | result.push_back('.'); | 334 | 0 | result.push_back('0'); | 335 | 0 | return true; | 336 | 0 | } | 337 | | | 338 | 636k | char buffer[100]; | 339 | 636k | int precision = std::numeric_limits<double>::digits10; | 340 | 636k | int length = snprintf(buffer, sizeof(buffer), "%1.*g", precision, val); | 341 | 636k | if (length < 0) | 342 | 0 | { | 343 | 0 | return false; | 344 | 0 | } | 345 | 636k | double x{0}; | 346 | 636k | auto res = decstr_to_double(buffer, length, x); | 347 | 636k | if (res.ec == std::errc::invalid_argument) | 348 | 0 | { | 349 | 0 | return false; | 350 | 0 | } | 351 | 636k | if (x != val) | 352 | 629k | { | 353 | 629k | const int precision2 = std::numeric_limits<double>::max_digits10; | 354 | 629k | length = snprintf(buffer, sizeof(buffer), "%1.*g", precision2, val); | 355 | 629k | if (length < 0) | 356 | 0 | { | 357 | 0 | return false; | 358 | 0 | } | 359 | 629k | } | 360 | 636k | dump_buffer(buffer, length, decimal_point, result); | 361 | 636k | return true; | 362 | 636k | } |
bool jsoncons::dtoa_general<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(double, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&, std::__1::integral_constant<bool, false>) Line | Count | Source | 329 | 184 | { | 330 | 184 | if (val == 0) | 331 | 0 | { | 332 | 0 | result.push_back('0'); | 333 | 0 | result.push_back('.'); | 334 | 0 | result.push_back('0'); | 335 | 0 | return true; | 336 | 0 | } | 337 | | | 338 | 184 | char buffer[100]; | 339 | 184 | int precision = std::numeric_limits<double>::digits10; | 340 | 184 | int length = snprintf(buffer, sizeof(buffer), "%1.*g", precision, val); | 341 | 184 | if (length < 0) | 342 | 0 | { | 343 | 0 | return false; | 344 | 0 | } | 345 | 184 | double x{0}; | 346 | 184 | auto res = decstr_to_double(buffer, length, x); | 347 | 184 | if (res.ec == std::errc::invalid_argument) | 348 | 0 | { | 349 | 0 | return false; | 350 | 0 | } | 351 | 184 | if (x != val) | 352 | 47 | { | 353 | 47 | const int precision2 = std::numeric_limits<double>::max_digits10; | 354 | 47 | length = snprintf(buffer, sizeof(buffer), "%1.*g", precision2, val); | 355 | 47 | if (length < 0) | 356 | 0 | { | 357 | 0 | return false; | 358 | 0 | } | 359 | 47 | } | 360 | 184 | dump_buffer(buffer, length, decimal_point, result); | 361 | 184 | return true; | 362 | 184 | } |
|
363 | | |
364 | | template <typename Result> |
365 | | bool dtoa_general(double v, char decimal_point, Result& result, std::true_type) |
366 | 112M | { |
367 | 112M | if (v == 0) |
368 | 6.18M | { |
369 | 6.18M | result.push_back('0'); |
370 | 6.18M | result.push_back('.'); |
371 | 6.18M | result.push_back('0'); |
372 | 6.18M | return true; |
373 | 6.18M | } |
374 | | |
375 | 106M | int length = 0; |
376 | 106M | int k; |
377 | | |
378 | 106M | char buffer[100]; |
379 | | |
380 | 106M | double u = std::signbit(v) ? -v : v; |
381 | 106M | if (jsoncons::detail::grisu3(u, buffer, &length, &k)) |
382 | 105M | { |
383 | 105M | if (std::signbit(v)) |
384 | 58.8M | { |
385 | 58.8M | result.push_back('-'); |
386 | 58.8M | } |
387 | | // min exp: -4 is consistent with sprintf |
388 | | // max exp: std::numeric_limits<double>::max_digits10 |
389 | 105M | jsoncons::prettify_string(buffer, length, k, -4, std::numeric_limits<double>::max_digits10, result); |
390 | 105M | return true; |
391 | 105M | } |
392 | 636k | else |
393 | 636k | { |
394 | 636k | return dtoa_general(v, decimal_point, result, std::false_type()); |
395 | 636k | } |
396 | 106M | } bool jsoncons::dtoa_general<jsoncons::string_sink<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >(double, char, jsoncons::string_sink<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&, std::__1::integral_constant<bool, true>) Line | Count | Source | 366 | 112M | { | 367 | 112M | if (v == 0) | 368 | 6.18M | { | 369 | 6.18M | result.push_back('0'); | 370 | 6.18M | result.push_back('.'); | 371 | 6.18M | result.push_back('0'); | 372 | 6.18M | return true; | 373 | 6.18M | } | 374 | | | 375 | 106M | int length = 0; | 376 | 106M | int k; | 377 | | | 378 | 106M | char buffer[100]; | 379 | | | 380 | 106M | double u = std::signbit(v) ? -v : v; | 381 | 106M | if (jsoncons::detail::grisu3(u, buffer, &length, &k)) | 382 | 105M | { | 383 | 105M | if (std::signbit(v)) | 384 | 58.8M | { | 385 | 58.8M | result.push_back('-'); | 386 | 58.8M | } | 387 | | // min exp: -4 is consistent with sprintf | 388 | | // max exp: std::numeric_limits<double>::max_digits10 | 389 | 105M | jsoncons::prettify_string(buffer, length, k, -4, std::numeric_limits<double>::max_digits10, result); | 390 | 105M | return true; | 391 | 105M | } | 392 | 636k | else | 393 | 636k | { | 394 | 636k | return dtoa_general(v, decimal_point, result, std::false_type()); | 395 | 636k | } | 396 | 106M | } |
bool jsoncons::dtoa_general<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(double, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&, std::__1::integral_constant<bool, true>) Line | Count | Source | 366 | 948 | { | 367 | 948 | if (v == 0) | 368 | 11 | { | 369 | 11 | result.push_back('0'); | 370 | 11 | result.push_back('.'); | 371 | 11 | result.push_back('0'); | 372 | 11 | return true; | 373 | 11 | } | 374 | | | 375 | 937 | int length = 0; | 376 | 937 | int k; | 377 | | | 378 | 937 | char buffer[100]; | 379 | | | 380 | 937 | double u = std::signbit(v) ? -v : v; | 381 | 937 | if (jsoncons::detail::grisu3(u, buffer, &length, &k)) | 382 | 753 | { | 383 | 753 | if (std::signbit(v)) | 384 | 16 | { | 385 | 16 | result.push_back('-'); | 386 | 16 | } | 387 | | // min exp: -4 is consistent with sprintf | 388 | | // max exp: std::numeric_limits<double>::max_digits10 | 389 | 753 | jsoncons::prettify_string(buffer, length, k, -4, std::numeric_limits<double>::max_digits10, result); | 390 | 753 | return true; | 391 | 753 | } | 392 | 184 | else | 393 | 184 | { | 394 | 184 | return dtoa_general(v, decimal_point, result, std::false_type()); | 395 | 184 | } | 396 | 937 | } |
|
397 | | |
398 | | template <typename Result> |
399 | | bool dtoa_fixed(double val, char decimal_point, Result& result, std::false_type) |
400 | 0 | { |
401 | 0 | if (val == 0) |
402 | 0 | { |
403 | 0 | result.push_back('0'); |
404 | 0 | result.push_back('.'); |
405 | 0 | result.push_back('0'); |
406 | 0 | return true; |
407 | 0 | } |
408 | | |
409 | 0 | char buffer[100]; |
410 | 0 | int precision = std::numeric_limits<double>::digits10; |
411 | 0 | int length = snprintf(buffer, sizeof(buffer), "%1.*f", precision, val); |
412 | 0 | if (length < 0) |
413 | 0 | { |
414 | 0 | return false; |
415 | 0 | } |
416 | 0 | double x{0}; |
417 | 0 | auto res = decstr_to_double(buffer, length, x); |
418 | 0 | if (res.ec == std::errc::invalid_argument) |
419 | 0 | { |
420 | 0 | return false; |
421 | 0 | } |
422 | 0 | if (x != val) |
423 | 0 | { |
424 | 0 | const int precision2 = std::numeric_limits<double>::max_digits10; |
425 | 0 | length = snprintf(buffer, sizeof(buffer), "%1.*f", precision2, val); |
426 | 0 | if (length < 0) |
427 | 0 | { |
428 | 0 | return false; |
429 | 0 | } |
430 | 0 | } |
431 | 0 | dump_buffer(buffer, length, decimal_point, result); |
432 | 0 | return true; |
433 | 0 | } Unexecuted instantiation: bool jsoncons::dtoa_fixed<jsoncons::string_sink<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >(double, char, jsoncons::string_sink<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&, std::__1::integral_constant<bool, false>) Unexecuted instantiation: bool jsoncons::dtoa_fixed<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(double, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&, std::__1::integral_constant<bool, false>) |
434 | | |
435 | | template <typename Result> |
436 | | bool dtoa_fixed(double v, char decimal_point, Result& result, std::true_type) |
437 | 0 | { |
438 | 0 | if (v == 0) |
439 | 0 | { |
440 | 0 | result.push_back('0'); |
441 | 0 | result.push_back('.'); |
442 | 0 | result.push_back('0'); |
443 | 0 | return true; |
444 | 0 | } |
445 | | |
446 | 0 | int length = 0; |
447 | 0 | int k; |
448 | |
|
449 | 0 | char buffer[100]; |
450 | |
|
451 | 0 | double u = std::signbit(v) ? -v : v; |
452 | 0 | if (jsoncons::detail::grisu3(u, buffer, &length, &k)) |
453 | 0 | { |
454 | 0 | if (std::signbit(v)) |
455 | 0 | { |
456 | 0 | result.push_back('-'); |
457 | 0 | } |
458 | 0 | jsoncons::prettify_string(buffer, length, k, std::numeric_limits<int>::lowest(), (std::numeric_limits<int>::max)(), result); |
459 | 0 | return true; |
460 | 0 | } |
461 | 0 | else |
462 | 0 | { |
463 | 0 | return dtoa_fixed(v, decimal_point, result, std::false_type()); |
464 | 0 | } |
465 | 0 | } Unexecuted instantiation: bool jsoncons::dtoa_fixed<jsoncons::string_sink<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >(double, char, jsoncons::string_sink<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&, std::__1::integral_constant<bool, true>) Unexecuted instantiation: bool jsoncons::dtoa_fixed<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(double, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&, std::__1::integral_constant<bool, true>) |
466 | | |
467 | | template <typename Result> |
468 | | bool dtoa_fixed(double v, char decimal_point, Result& result) |
469 | 0 | { |
470 | 0 | return dtoa_fixed(v, decimal_point, result, std::integral_constant<bool, std::numeric_limits<double>::is_iec559>()); |
471 | 0 | } Unexecuted instantiation: bool jsoncons::dtoa_fixed<jsoncons::string_sink<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >(double, char, jsoncons::string_sink<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&) Unexecuted instantiation: bool jsoncons::dtoa_fixed<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(double, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&) |
472 | | |
473 | | template <typename Result> |
474 | | bool dtoa_general(double v, char decimal_point, Result& result) |
475 | 112M | { |
476 | 112M | return dtoa_general(v, decimal_point, result, std::integral_constant<bool, std::numeric_limits<double>::is_iec559>()); |
477 | 112M | } bool jsoncons::dtoa_general<jsoncons::string_sink<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >(double, char, jsoncons::string_sink<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&) Line | Count | Source | 475 | 112M | { | 476 | 112M | return dtoa_general(v, decimal_point, result, std::integral_constant<bool, std::numeric_limits<double>::is_iec559>()); | 477 | 112M | } |
bool jsoncons::dtoa_general<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(double, char, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&) Line | Count | Source | 475 | 948 | { | 476 | 948 | return dtoa_general(v, decimal_point, result, std::integral_constant<bool, std::numeric_limits<double>::is_iec559>()); | 477 | 948 | } |
|
478 | | |
479 | | class write_double |
480 | | { |
481 | | private: |
482 | | float_chars_format float_format_; |
483 | | int precision_; |
484 | | char decimal_point_; |
485 | | public: |
486 | | write_double(float_chars_format float_format, int precision) |
487 | 111M | : float_format_(float_format), precision_(precision), decimal_point_('.') |
488 | 111M | { |
489 | 111M | #if !defined(JSONCONS_NO_LOCALECONV) |
490 | 111M | struct lconv *lc = localeconv(); |
491 | 111M | if (lc != nullptr && lc->decimal_point[0] != 0) |
492 | 111M | { |
493 | 111M | decimal_point_ = lc->decimal_point[0]; |
494 | 111M | } |
495 | 111M | #endif |
496 | 111M | } |
497 | | write_double(const write_double&) = default; |
498 | | |
499 | | write_double& operator=(const write_double&) = default; |
500 | | |
501 | | template <typename Result> |
502 | | std::size_t operator()(double val, Result& result) |
503 | 112M | { |
504 | 112M | std::size_t count = 0; |
505 | | |
506 | 112M | char number_buffer[200]; |
507 | 112M | int length = 0; |
508 | | |
509 | 112M | switch (float_format_) |
510 | 112M | { |
511 | 0 | case float_chars_format::fixed: |
512 | 0 | { |
513 | 0 | if (precision_ > 0) |
514 | 0 | { |
515 | 0 | length = snprintf(number_buffer, sizeof(number_buffer), "%1.*f", precision_, val); |
516 | 0 | if (length < 0) |
517 | 0 | { |
518 | 0 | JSONCONS_THROW(json_runtime_error<std::invalid_argument>("write_double failed.")); |
519 | 0 | } |
520 | 0 | dump_buffer(number_buffer, length, decimal_point_, result); |
521 | 0 | } |
522 | 0 | else |
523 | 0 | { |
524 | 0 | if (!dtoa_fixed(val, decimal_point_, result)) |
525 | 0 | { |
526 | 0 | JSONCONS_THROW(json_runtime_error<std::invalid_argument>("write_double failed.")); |
527 | 0 | } |
528 | 0 | } |
529 | 0 | } |
530 | 0 | break; |
531 | 0 | case float_chars_format::scientific: |
532 | 0 | { |
533 | 0 | if (precision_ > 0) |
534 | 0 | { |
535 | 0 | length = snprintf(number_buffer, sizeof(number_buffer), "%1.*e", precision_, val); |
536 | 0 | if (length < 0) |
537 | 0 | { |
538 | 0 | JSONCONS_THROW(json_runtime_error<std::invalid_argument>("write_double failed.")); |
539 | 0 | } |
540 | 0 | dump_buffer(number_buffer, length, decimal_point_, result); |
541 | 0 | } |
542 | 0 | else |
543 | 0 | { |
544 | 0 | if (!dtoa_scientific(val, decimal_point_, result)) |
545 | 0 | { |
546 | 0 | JSONCONS_THROW(json_runtime_error<std::invalid_argument>("write_double failed.")); |
547 | 0 | } |
548 | 0 | } |
549 | 0 | } |
550 | 0 | break; |
551 | 112M | case float_chars_format::general: |
552 | 112M | { |
553 | 112M | if (precision_ > 0) |
554 | 0 | { |
555 | 0 | length = snprintf(number_buffer, sizeof(number_buffer), "%1.*g", precision_, val); |
556 | 0 | if (length < 0) |
557 | 0 | { |
558 | 0 | JSONCONS_THROW(json_runtime_error<std::invalid_argument>("write_double failed.")); |
559 | 0 | } |
560 | 0 | dump_buffer(number_buffer, length, decimal_point_, result); |
561 | 0 | } |
562 | 112M | else |
563 | 112M | { |
564 | 112M | if (!dtoa_general(val, decimal_point_, result)) |
565 | 0 | { |
566 | 0 | JSONCONS_THROW(json_runtime_error<std::invalid_argument>("write_double failed.")); |
567 | 0 | } |
568 | 112M | } |
569 | 112M | break; |
570 | 112M | } |
571 | 112M | default: |
572 | 0 | JSONCONS_THROW(json_runtime_error<std::invalid_argument>("write_double failed.")); |
573 | 0 | break; |
574 | 112M | } |
575 | 112M | return count; |
576 | 112M | } unsigned long jsoncons::write_double::operator()<jsoncons::string_sink<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >(double, jsoncons::string_sink<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&) Line | Count | Source | 503 | 112M | { | 504 | 112M | std::size_t count = 0; | 505 | | | 506 | 112M | char number_buffer[200]; | 507 | 112M | int length = 0; | 508 | | | 509 | 112M | switch (float_format_) | 510 | 112M | { | 511 | 0 | case float_chars_format::fixed: | 512 | 0 | { | 513 | 0 | if (precision_ > 0) | 514 | 0 | { | 515 | 0 | length = snprintf(number_buffer, sizeof(number_buffer), "%1.*f", precision_, val); | 516 | 0 | if (length < 0) | 517 | 0 | { | 518 | 0 | JSONCONS_THROW(json_runtime_error<std::invalid_argument>("write_double failed.")); | 519 | 0 | } | 520 | 0 | dump_buffer(number_buffer, length, decimal_point_, result); | 521 | 0 | } | 522 | 0 | else | 523 | 0 | { | 524 | 0 | if (!dtoa_fixed(val, decimal_point_, result)) | 525 | 0 | { | 526 | 0 | JSONCONS_THROW(json_runtime_error<std::invalid_argument>("write_double failed.")); | 527 | 0 | } | 528 | 0 | } | 529 | 0 | } | 530 | 0 | break; | 531 | 0 | case float_chars_format::scientific: | 532 | 0 | { | 533 | 0 | if (precision_ > 0) | 534 | 0 | { | 535 | 0 | length = snprintf(number_buffer, sizeof(number_buffer), "%1.*e", precision_, val); | 536 | 0 | if (length < 0) | 537 | 0 | { | 538 | 0 | JSONCONS_THROW(json_runtime_error<std::invalid_argument>("write_double failed.")); | 539 | 0 | } | 540 | 0 | dump_buffer(number_buffer, length, decimal_point_, result); | 541 | 0 | } | 542 | 0 | else | 543 | 0 | { | 544 | 0 | if (!dtoa_scientific(val, decimal_point_, result)) | 545 | 0 | { | 546 | 0 | JSONCONS_THROW(json_runtime_error<std::invalid_argument>("write_double failed.")); | 547 | 0 | } | 548 | 0 | } | 549 | 0 | } | 550 | 0 | break; | 551 | 112M | case float_chars_format::general: | 552 | 112M | { | 553 | 112M | if (precision_ > 0) | 554 | 0 | { | 555 | 0 | length = snprintf(number_buffer, sizeof(number_buffer), "%1.*g", precision_, val); | 556 | 0 | if (length < 0) | 557 | 0 | { | 558 | 0 | JSONCONS_THROW(json_runtime_error<std::invalid_argument>("write_double failed.")); | 559 | 0 | } | 560 | 0 | dump_buffer(number_buffer, length, decimal_point_, result); | 561 | 0 | } | 562 | 112M | else | 563 | 112M | { | 564 | 112M | if (!dtoa_general(val, decimal_point_, result)) | 565 | 0 | { | 566 | 0 | JSONCONS_THROW(json_runtime_error<std::invalid_argument>("write_double failed.")); | 567 | 0 | } | 568 | 112M | } | 569 | 112M | break; | 570 | 112M | } | 571 | 112M | default: | 572 | 0 | JSONCONS_THROW(json_runtime_error<std::invalid_argument>("write_double failed.")); | 573 | 0 | break; | 574 | 112M | } | 575 | 112M | return count; | 576 | 112M | } |
unsigned long jsoncons::write_double::operator()<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(double, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&) Line | Count | Source | 503 | 948 | { | 504 | 948 | std::size_t count = 0; | 505 | | | 506 | 948 | char number_buffer[200]; | 507 | 948 | int length = 0; | 508 | | | 509 | 948 | switch (float_format_) | 510 | 948 | { | 511 | 0 | case float_chars_format::fixed: | 512 | 0 | { | 513 | 0 | if (precision_ > 0) | 514 | 0 | { | 515 | 0 | length = snprintf(number_buffer, sizeof(number_buffer), "%1.*f", precision_, val); | 516 | 0 | if (length < 0) | 517 | 0 | { | 518 | 0 | JSONCONS_THROW(json_runtime_error<std::invalid_argument>("write_double failed.")); | 519 | 0 | } | 520 | 0 | dump_buffer(number_buffer, length, decimal_point_, result); | 521 | 0 | } | 522 | 0 | else | 523 | 0 | { | 524 | 0 | if (!dtoa_fixed(val, decimal_point_, result)) | 525 | 0 | { | 526 | 0 | JSONCONS_THROW(json_runtime_error<std::invalid_argument>("write_double failed.")); | 527 | 0 | } | 528 | 0 | } | 529 | 0 | } | 530 | 0 | break; | 531 | 0 | case float_chars_format::scientific: | 532 | 0 | { | 533 | 0 | if (precision_ > 0) | 534 | 0 | { | 535 | 0 | length = snprintf(number_buffer, sizeof(number_buffer), "%1.*e", precision_, val); | 536 | 0 | if (length < 0) | 537 | 0 | { | 538 | 0 | JSONCONS_THROW(json_runtime_error<std::invalid_argument>("write_double failed.")); | 539 | 0 | } | 540 | 0 | dump_buffer(number_buffer, length, decimal_point_, result); | 541 | 0 | } | 542 | 0 | else | 543 | 0 | { | 544 | 0 | if (!dtoa_scientific(val, decimal_point_, result)) | 545 | 0 | { | 546 | 0 | JSONCONS_THROW(json_runtime_error<std::invalid_argument>("write_double failed.")); | 547 | 0 | } | 548 | 0 | } | 549 | 0 | } | 550 | 0 | break; | 551 | 948 | case float_chars_format::general: | 552 | 948 | { | 553 | 948 | if (precision_ > 0) | 554 | 0 | { | 555 | 0 | length = snprintf(number_buffer, sizeof(number_buffer), "%1.*g", precision_, val); | 556 | 0 | if (length < 0) | 557 | 0 | { | 558 | 0 | JSONCONS_THROW(json_runtime_error<std::invalid_argument>("write_double failed.")); | 559 | 0 | } | 560 | 0 | dump_buffer(number_buffer, length, decimal_point_, result); | 561 | 0 | } | 562 | 948 | else | 563 | 948 | { | 564 | 948 | if (!dtoa_general(val, decimal_point_, result)) | 565 | 0 | { | 566 | 0 | JSONCONS_THROW(json_runtime_error<std::invalid_argument>("write_double failed.")); | 567 | 0 | } | 568 | 948 | } | 569 | 948 | break; | 570 | 948 | } | 571 | 948 | default: | 572 | 0 | JSONCONS_THROW(json_runtime_error<std::invalid_argument>("write_double failed.")); | 573 | 0 | break; | 574 | 948 | } | 575 | 948 | return count; | 576 | 948 | } |
|
577 | | }; |
578 | | |
579 | | } // namespace jsoncons |
580 | | |
581 | | #endif // JSONCONS_UTILITY_WRITE_NUMBER_HPP |