Coverage Report

Created: 2026-01-17 06:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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