jsoncons 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/ext/jsoncons/extconf.rb +43 -0
- data/ext/jsoncons/jsoncons.cpp +161 -0
- data/ext/jsoncons/jsoncons.h +10 -0
- data/jsoncons.gemspec +44 -0
- data/lib/jsoncons/jsoncons/examples/input/address-book.json +13 -0
- data/lib/jsoncons/jsoncons/examples/input/books.json +28 -0
- data/lib/jsoncons/jsoncons/examples/input/countries.json +7 -0
- data/lib/jsoncons/jsoncons/examples/input/employees.json +30 -0
- data/lib/jsoncons/jsoncons/examples/input/jsonschema/name.json +15 -0
- data/lib/jsoncons/jsoncons/examples/input/multiple-json-objects.json +3 -0
- data/lib/jsoncons/jsoncons/examples/input/sales.csv +6 -0
- data/lib/jsoncons/jsoncons/examples/input/store.json +28 -0
- data/lib/jsoncons/jsoncons/examples/input/tasks.csv +6 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/allocator_holder.hpp +38 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/basic_json.hpp +5905 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/bigint.hpp +1611 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/byte_string.hpp +820 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/config/binary_config.hpp +226 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/config/compiler_support.hpp +375 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/config/jsoncons_config.hpp +309 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/config/version.hpp +40 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/conv_error.hpp +218 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/decode_json.hpp +209 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/decode_traits.hpp +651 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/detail/endian.hpp +44 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/detail/grisu3.hpp +312 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/detail/optional.hpp +483 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/detail/parse_number.hpp +1133 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/detail/span.hpp +188 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/detail/string_view.hpp +537 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/detail/string_wrapper.hpp +370 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/detail/write_number.hpp +567 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/encode_json.hpp +315 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/encode_traits.hpp +378 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json.hpp +18 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_array.hpp +324 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_content_handler.hpp +12 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_cursor.hpp +448 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_decoder.hpp +420 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_encoder.hpp +1587 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_error.hpp +156 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_exception.hpp +241 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_filter.hpp +653 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_fwd.hpp +23 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_object.hpp +1772 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_options.hpp +862 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_parser.hpp +2900 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_reader.hpp +731 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_traits_macros.hpp +1072 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_traits_macros_deprecated.hpp +144 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_type.hpp +206 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_type_traits.hpp +1830 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_visitor.hpp +1560 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/json_visitor2.hpp +2079 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/pretty_print.hpp +89 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/ser_context.hpp +62 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/sink.hpp +289 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/source.hpp +777 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/source_adaptor.hpp +148 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/staj2_cursor.hpp +1189 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/staj_cursor.hpp +1254 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/staj_iterator.hpp +449 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/tag_type.hpp +245 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/text_source_adaptor.hpp +144 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/traits_extension.hpp +884 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/typed_array_view.hpp +250 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/unicode_traits.hpp +1330 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/uri.hpp +635 -0
- data/lib/jsoncons/jsoncons/include/jsoncons/value_converter.hpp +340 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson.hpp +23 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_cursor.hpp +320 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_decimal128.hpp +865 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_encoder.hpp +585 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_error.hpp +103 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_oid.hpp +245 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_options.hpp +75 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_parser.hpp +645 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_reader.hpp +92 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_type.hpp +44 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/decode_bson.hpp +201 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/encode_bson.hpp +144 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor.hpp +26 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_cursor.hpp +351 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_cursor2.hpp +265 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_detail.hpp +93 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_encoder.hpp +1766 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_error.hpp +105 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_options.hpp +113 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_parser.hpp +1942 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_reader.hpp +116 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/decode_cbor.hpp +203 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/encode_cbor.hpp +151 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv.hpp +17 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_cursor.hpp +358 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_encoder.hpp +954 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_error.hpp +85 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_options.hpp +973 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_parser.hpp +2099 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_reader.hpp +348 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_serializer.hpp +12 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/decode_csv.hpp +208 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/encode_csv.hpp +122 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jmespath/jmespath.hpp +5215 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jmespath/jmespath_error.hpp +215 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpatch/jsonpatch.hpp +579 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpatch/jsonpatch_error.hpp +121 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/expression.hpp +3329 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/flatten.hpp +432 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/json_location.hpp +445 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/json_query.hpp +115 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/jsonpath.hpp +13 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/jsonpath_error.hpp +240 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/jsonpath_expression.hpp +2612 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/jsonpath_selector.hpp +1322 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpointer/jsonpointer.hpp +1577 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpointer/jsonpointer_error.hpp +119 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/format_validator.hpp +968 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/json_validator.hpp +120 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/jsonschema.hpp +13 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/jsonschema_error.hpp +105 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/jsonschema_version.hpp +18 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/keyword_validator.hpp +1745 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/keyword_validator_factory.hpp +556 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/schema_draft7.hpp +198 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/schema_location.hpp +200 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/schema_version.hpp +35 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/subschema.hpp +144 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/mergepatch/mergepatch.hpp +103 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/decode_msgpack.hpp +202 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/encode_msgpack.hpp +142 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack.hpp +24 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_cursor.hpp +343 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_cursor2.hpp +259 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_encoder.hpp +753 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_error.hpp +94 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_options.hpp +74 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_parser.hpp +748 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_reader.hpp +116 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_type.hpp +63 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/decode_ubjson.hpp +201 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/encode_ubjson.hpp +142 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson.hpp +23 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_cursor.hpp +307 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_encoder.hpp +502 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_error.hpp +100 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_options.hpp +87 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_parser.hpp +880 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_reader.hpp +92 -0
- data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_type.hpp +43 -0
- data/lib/jsoncons/version.rb +5 -0
- data/lib/jsoncons.rb +33 -0
- data/test/jsoncons_test.rb +108 -0
- data/test/test_helper.rb +7 -0
- metadata +268 -0
|
@@ -0,0 +1,567 @@
|
|
|
1
|
+
// Copyright 2013 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_DETAIL_WRITE_NUMBER_HPP
|
|
8
|
+
#define JSONCONS_DETAIL_WRITE_NUMBER_HPP
|
|
9
|
+
|
|
10
|
+
#include <stdexcept>
|
|
11
|
+
#include <string>
|
|
12
|
+
#include <cmath>
|
|
13
|
+
#include <locale>
|
|
14
|
+
#include <limits> // std::numeric_limits
|
|
15
|
+
#include <exception>
|
|
16
|
+
#include <stdio.h> // snprintf
|
|
17
|
+
#include <jsoncons/config/jsoncons_config.hpp>
|
|
18
|
+
#include <jsoncons/json_options.hpp>
|
|
19
|
+
#include <jsoncons/detail/grisu3.hpp>
|
|
20
|
+
#include <jsoncons/detail/parse_number.hpp>
|
|
21
|
+
#include <jsoncons/traits_extension.hpp>
|
|
22
|
+
|
|
23
|
+
namespace jsoncons {
|
|
24
|
+
namespace detail {
|
|
25
|
+
|
|
26
|
+
inline
|
|
27
|
+
char to_hex_character(uint8_t c)
|
|
28
|
+
{
|
|
29
|
+
return (char)((c < 10) ? ('0' + c) : ('A' - 10 + c));
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// from_integer
|
|
33
|
+
|
|
34
|
+
template<class Integer,class Result>
|
|
35
|
+
typename std::enable_if<traits_extension::is_integer<Integer>::value,std::size_t>::type
|
|
36
|
+
from_integer(Integer value, Result& result)
|
|
37
|
+
{
|
|
38
|
+
using char_type = typename Result::value_type;
|
|
39
|
+
|
|
40
|
+
char_type buf[255];
|
|
41
|
+
char_type *p = buf;
|
|
42
|
+
const char_type* last = buf+255;
|
|
43
|
+
|
|
44
|
+
bool is_negative = value < 0;
|
|
45
|
+
|
|
46
|
+
if (value < 0)
|
|
47
|
+
{
|
|
48
|
+
do
|
|
49
|
+
{
|
|
50
|
+
*p++ = static_cast<char_type>(48 - (value % 10));
|
|
51
|
+
}
|
|
52
|
+
while ((value /= 10) && (p < last));
|
|
53
|
+
}
|
|
54
|
+
else
|
|
55
|
+
{
|
|
56
|
+
|
|
57
|
+
do
|
|
58
|
+
{
|
|
59
|
+
*p++ = static_cast<char_type>(48 + value % 10);
|
|
60
|
+
}
|
|
61
|
+
while ((value /= 10) && (p < last));
|
|
62
|
+
}
|
|
63
|
+
JSONCONS_ASSERT(p != last);
|
|
64
|
+
|
|
65
|
+
std::size_t count = (p - buf);
|
|
66
|
+
if (is_negative)
|
|
67
|
+
{
|
|
68
|
+
result.push_back('-');
|
|
69
|
+
++count;
|
|
70
|
+
}
|
|
71
|
+
while (--p >= buf)
|
|
72
|
+
{
|
|
73
|
+
result.push_back(*p);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return count;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// integer_to_string_hex
|
|
80
|
+
|
|
81
|
+
template<class Integer,class Result>
|
|
82
|
+
typename std::enable_if<traits_extension::is_integer<Integer>::value,std::size_t>::type
|
|
83
|
+
integer_to_string_hex(Integer value, Result& result)
|
|
84
|
+
{
|
|
85
|
+
using char_type = typename Result::value_type;
|
|
86
|
+
|
|
87
|
+
char_type buf[255];
|
|
88
|
+
char_type *p = buf;
|
|
89
|
+
const char_type* last = buf+255;
|
|
90
|
+
|
|
91
|
+
bool is_negative = value < 0;
|
|
92
|
+
|
|
93
|
+
if (value < 0)
|
|
94
|
+
{
|
|
95
|
+
do
|
|
96
|
+
{
|
|
97
|
+
*p++ = to_hex_character(0-(value % 16));
|
|
98
|
+
}
|
|
99
|
+
while ((value /= 16) && (p < last));
|
|
100
|
+
}
|
|
101
|
+
else
|
|
102
|
+
{
|
|
103
|
+
|
|
104
|
+
do
|
|
105
|
+
{
|
|
106
|
+
*p++ = to_hex_character(value % 16);
|
|
107
|
+
}
|
|
108
|
+
while ((value /= 16) && (p < last));
|
|
109
|
+
}
|
|
110
|
+
JSONCONS_ASSERT(p != last);
|
|
111
|
+
|
|
112
|
+
std::size_t count = (p - buf);
|
|
113
|
+
if (is_negative)
|
|
114
|
+
{
|
|
115
|
+
result.push_back('-');
|
|
116
|
+
++count;
|
|
117
|
+
}
|
|
118
|
+
while (--p >= buf)
|
|
119
|
+
{
|
|
120
|
+
result.push_back(*p);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return count;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// write_double
|
|
127
|
+
|
|
128
|
+
// fast exponent
|
|
129
|
+
template <class Result>
|
|
130
|
+
void fill_exponent(int K, Result& result)
|
|
131
|
+
{
|
|
132
|
+
if (K < 0)
|
|
133
|
+
{
|
|
134
|
+
result.push_back('-');
|
|
135
|
+
K = -K;
|
|
136
|
+
}
|
|
137
|
+
else
|
|
138
|
+
{
|
|
139
|
+
result.push_back('+'); // compatibility with sprintf
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if (K < 10)
|
|
143
|
+
{
|
|
144
|
+
result.push_back('0'); // compatibility with sprintf
|
|
145
|
+
result.push_back((char)('0' + K));
|
|
146
|
+
}
|
|
147
|
+
else if (K < 100)
|
|
148
|
+
{
|
|
149
|
+
result.push_back((char)('0' + K / 10)); K %= 10;
|
|
150
|
+
result.push_back((char)('0' + K));
|
|
151
|
+
}
|
|
152
|
+
else if (K < 1000)
|
|
153
|
+
{
|
|
154
|
+
result.push_back((char)('0' + K / 100)); K %= 100;
|
|
155
|
+
result.push_back((char)('0' + K / 10)); K %= 10;
|
|
156
|
+
result.push_back((char)('0' + K));
|
|
157
|
+
}
|
|
158
|
+
else
|
|
159
|
+
{
|
|
160
|
+
jsoncons::detail::from_integer(K, result);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
template <class Result>
|
|
165
|
+
void prettify_string(const char *buffer, std::size_t length, int k, int min_exp, int max_exp, Result& result)
|
|
166
|
+
{
|
|
167
|
+
int nb_digits = (int)length;
|
|
168
|
+
int offset;
|
|
169
|
+
/* v = buffer * 10^k
|
|
170
|
+
kk is such that 10^(kk-1) <= v < 10^kk
|
|
171
|
+
this way kk gives the position of the decimal point.
|
|
172
|
+
*/
|
|
173
|
+
int kk = nb_digits + k;
|
|
174
|
+
|
|
175
|
+
if (nb_digits <= kk && kk <= max_exp)
|
|
176
|
+
{
|
|
177
|
+
/* the first digits are already in. Add some 0s and call it a day. */
|
|
178
|
+
/* the max_exp is a personal choice. Only 16 digits could possibly be relevant.
|
|
179
|
+
* Basically we want to print 12340000000 rather than 1234.0e7 or 1.234e10 */
|
|
180
|
+
for (int i = 0; i < nb_digits; ++i)
|
|
181
|
+
{
|
|
182
|
+
result.push_back(buffer[i]);
|
|
183
|
+
}
|
|
184
|
+
for (int i = nb_digits; i < kk; ++i)
|
|
185
|
+
{
|
|
186
|
+
result.push_back('0');
|
|
187
|
+
}
|
|
188
|
+
result.push_back('.');
|
|
189
|
+
result.push_back('0');
|
|
190
|
+
}
|
|
191
|
+
else if (0 < kk && kk <= max_exp)
|
|
192
|
+
{
|
|
193
|
+
/* comma number. Just insert a '.' at the correct location. */
|
|
194
|
+
for (int i = 0; i < kk; ++i)
|
|
195
|
+
{
|
|
196
|
+
result.push_back(buffer[i]);
|
|
197
|
+
}
|
|
198
|
+
result.push_back('.');
|
|
199
|
+
for (int i = kk; i < nb_digits; ++i)
|
|
200
|
+
{
|
|
201
|
+
result.push_back(buffer[i]);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
else if (min_exp < kk && kk <= 0)
|
|
205
|
+
{
|
|
206
|
+
offset = 2 - kk;
|
|
207
|
+
|
|
208
|
+
result.push_back('0');
|
|
209
|
+
result.push_back('.');
|
|
210
|
+
for (int i = 2; i < offset; ++i)
|
|
211
|
+
result.push_back('0');
|
|
212
|
+
for (int i = 0; i < nb_digits; ++i)
|
|
213
|
+
{
|
|
214
|
+
result.push_back(buffer[i]);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
else if (nb_digits == 1)
|
|
218
|
+
{
|
|
219
|
+
result.push_back(buffer[0]);
|
|
220
|
+
result.push_back('e');
|
|
221
|
+
fill_exponent(kk - 1, result);
|
|
222
|
+
}
|
|
223
|
+
else
|
|
224
|
+
{
|
|
225
|
+
result.push_back(buffer[0]);
|
|
226
|
+
result.push_back('.');
|
|
227
|
+
for (int i = 1; i < nb_digits; ++i)
|
|
228
|
+
{
|
|
229
|
+
result.push_back(buffer[i]);
|
|
230
|
+
}
|
|
231
|
+
result.push_back('e');
|
|
232
|
+
fill_exponent(kk - 1, result);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
template<class Result>
|
|
237
|
+
void dump_buffer(const char *buffer, std::size_t length, char decimal_point, Result& result)
|
|
238
|
+
{
|
|
239
|
+
const char *sbeg = buffer;
|
|
240
|
+
const char *send = sbeg + length;
|
|
241
|
+
|
|
242
|
+
if (sbeg != send)
|
|
243
|
+
{
|
|
244
|
+
bool needs_dot = true;
|
|
245
|
+
for (const char* q = sbeg; q < send; ++q)
|
|
246
|
+
{
|
|
247
|
+
switch (*q)
|
|
248
|
+
{
|
|
249
|
+
case '-':
|
|
250
|
+
case '0':
|
|
251
|
+
case '1':
|
|
252
|
+
case '2':
|
|
253
|
+
case '3':
|
|
254
|
+
case '4':
|
|
255
|
+
case '5':
|
|
256
|
+
case '6':
|
|
257
|
+
case '7':
|
|
258
|
+
case '8':
|
|
259
|
+
case '9':
|
|
260
|
+
case '+':
|
|
261
|
+
result.push_back(*q);
|
|
262
|
+
break;
|
|
263
|
+
case 'e':
|
|
264
|
+
case 'E':
|
|
265
|
+
result.push_back('e');
|
|
266
|
+
needs_dot = false;
|
|
267
|
+
break;
|
|
268
|
+
default:
|
|
269
|
+
if (*q == decimal_point)
|
|
270
|
+
{
|
|
271
|
+
needs_dot = false;
|
|
272
|
+
result.push_back('.');
|
|
273
|
+
}
|
|
274
|
+
break;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
if (needs_dot)
|
|
278
|
+
{
|
|
279
|
+
result.push_back('.');
|
|
280
|
+
result.push_back('0');
|
|
281
|
+
needs_dot = true;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
template<class Result>
|
|
287
|
+
bool dtoa_scientific(double val, char decimal_point, Result& result)
|
|
288
|
+
{
|
|
289
|
+
if (val == 0)
|
|
290
|
+
{
|
|
291
|
+
result.push_back('0');
|
|
292
|
+
result.push_back('.');
|
|
293
|
+
result.push_back('0');
|
|
294
|
+
return true;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
jsoncons::detail::chars_to to_double_;
|
|
298
|
+
|
|
299
|
+
char buffer[100];
|
|
300
|
+
int precision = std::numeric_limits<double>::digits10;
|
|
301
|
+
int length = snprintf(buffer, sizeof(buffer), "%1.*e", precision, val);
|
|
302
|
+
if (length < 0)
|
|
303
|
+
{
|
|
304
|
+
return false;
|
|
305
|
+
}
|
|
306
|
+
if (to_double_(buffer, sizeof(buffer)) != val)
|
|
307
|
+
{
|
|
308
|
+
const int precision2 = std::numeric_limits<double>::max_digits10;
|
|
309
|
+
length = snprintf(buffer, sizeof(buffer), "%1.*e", precision2, val);
|
|
310
|
+
if (length < 0)
|
|
311
|
+
{
|
|
312
|
+
return false;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
dump_buffer(buffer, static_cast<std::size_t>(length), decimal_point, result);
|
|
316
|
+
return true;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
template<class Result>
|
|
320
|
+
bool dtoa_general(double val, char decimal_point, Result& result, std::false_type)
|
|
321
|
+
{
|
|
322
|
+
if (val == 0)
|
|
323
|
+
{
|
|
324
|
+
result.push_back('0');
|
|
325
|
+
result.push_back('.');
|
|
326
|
+
result.push_back('0');
|
|
327
|
+
return true;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
jsoncons::detail::chars_to to_double_;
|
|
331
|
+
|
|
332
|
+
char buffer[100];
|
|
333
|
+
int precision = std::numeric_limits<double>::digits10;
|
|
334
|
+
int length = snprintf(buffer, sizeof(buffer), "%1.*g", precision, val);
|
|
335
|
+
if (length < 0)
|
|
336
|
+
{
|
|
337
|
+
return false;
|
|
338
|
+
}
|
|
339
|
+
if (to_double_(buffer, sizeof(buffer)) != val)
|
|
340
|
+
{
|
|
341
|
+
const int precision2 = std::numeric_limits<double>::max_digits10;
|
|
342
|
+
length = snprintf(buffer, sizeof(buffer), "%1.*g", precision2, val);
|
|
343
|
+
if (length < 0)
|
|
344
|
+
{
|
|
345
|
+
return false;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
dump_buffer(buffer, length, decimal_point, result);
|
|
349
|
+
return true;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
template<class Result>
|
|
353
|
+
bool dtoa_general(double v, char decimal_point, Result& result, std::true_type)
|
|
354
|
+
{
|
|
355
|
+
if (v == 0)
|
|
356
|
+
{
|
|
357
|
+
result.push_back('0');
|
|
358
|
+
result.push_back('.');
|
|
359
|
+
result.push_back('0');
|
|
360
|
+
return true;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
int length = 0;
|
|
364
|
+
int k;
|
|
365
|
+
|
|
366
|
+
char buffer[100];
|
|
367
|
+
|
|
368
|
+
double u = std::signbit(v) ? -v : v;
|
|
369
|
+
if (jsoncons::detail::grisu3(u, buffer, &length, &k))
|
|
370
|
+
{
|
|
371
|
+
if (std::signbit(v))
|
|
372
|
+
{
|
|
373
|
+
result.push_back('-');
|
|
374
|
+
}
|
|
375
|
+
// min exp: -4 is consistent with sprintf
|
|
376
|
+
// max exp: std::numeric_limits<double>::max_digits10
|
|
377
|
+
jsoncons::detail::prettify_string(buffer, length, k, -4, std::numeric_limits<double>::max_digits10, result);
|
|
378
|
+
return true;
|
|
379
|
+
}
|
|
380
|
+
else
|
|
381
|
+
{
|
|
382
|
+
return dtoa_general(v, decimal_point, result, std::false_type());
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
template<class Result>
|
|
387
|
+
bool dtoa_fixed(double val, char decimal_point, Result& result, std::false_type)
|
|
388
|
+
{
|
|
389
|
+
if (val == 0)
|
|
390
|
+
{
|
|
391
|
+
result.push_back('0');
|
|
392
|
+
result.push_back('.');
|
|
393
|
+
result.push_back('0');
|
|
394
|
+
return true;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
jsoncons::detail::chars_to to_double_;
|
|
398
|
+
|
|
399
|
+
char buffer[100];
|
|
400
|
+
int precision = std::numeric_limits<double>::digits10;
|
|
401
|
+
int length = snprintf(buffer, sizeof(buffer), "%1.*f", precision, val);
|
|
402
|
+
if (length < 0)
|
|
403
|
+
{
|
|
404
|
+
return false;
|
|
405
|
+
}
|
|
406
|
+
if (to_double_(buffer, sizeof(buffer)) != val)
|
|
407
|
+
{
|
|
408
|
+
const int precision2 = std::numeric_limits<double>::max_digits10;
|
|
409
|
+
length = snprintf(buffer, sizeof(buffer), "%1.*f", precision2, val);
|
|
410
|
+
if (length < 0)
|
|
411
|
+
{
|
|
412
|
+
return false;
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
dump_buffer(buffer, length, decimal_point, result);
|
|
416
|
+
return true;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
template<class Result>
|
|
420
|
+
bool dtoa_fixed(double v, char decimal_point, Result& result, std::true_type)
|
|
421
|
+
{
|
|
422
|
+
if (v == 0)
|
|
423
|
+
{
|
|
424
|
+
result.push_back('0');
|
|
425
|
+
result.push_back('.');
|
|
426
|
+
result.push_back('0');
|
|
427
|
+
return true;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
int length = 0;
|
|
431
|
+
int k;
|
|
432
|
+
|
|
433
|
+
char buffer[100];
|
|
434
|
+
|
|
435
|
+
double u = std::signbit(v) ? -v : v;
|
|
436
|
+
if (jsoncons::detail::grisu3(u, buffer, &length, &k))
|
|
437
|
+
{
|
|
438
|
+
if (std::signbit(v))
|
|
439
|
+
{
|
|
440
|
+
result.push_back('-');
|
|
441
|
+
}
|
|
442
|
+
jsoncons::detail::prettify_string(buffer, length, k, std::numeric_limits<int>::lowest(), (std::numeric_limits<int>::max)(), result);
|
|
443
|
+
return true;
|
|
444
|
+
}
|
|
445
|
+
else
|
|
446
|
+
{
|
|
447
|
+
return dtoa_fixed(v, decimal_point, result, std::false_type());
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
template<class Result>
|
|
452
|
+
bool dtoa_fixed(double v, char decimal_point, Result& result)
|
|
453
|
+
{
|
|
454
|
+
return dtoa_fixed(v, decimal_point, result, std::integral_constant<bool, std::numeric_limits<double>::is_iec559>());
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
template<class Result>
|
|
458
|
+
bool dtoa_general(double v, char decimal_point, Result& result)
|
|
459
|
+
{
|
|
460
|
+
return dtoa_general(v, decimal_point, result, std::integral_constant<bool, std::numeric_limits<double>::is_iec559>());
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
class write_double
|
|
464
|
+
{
|
|
465
|
+
private:
|
|
466
|
+
chars_to to_double_;
|
|
467
|
+
float_chars_format float_format_;
|
|
468
|
+
int precision_;
|
|
469
|
+
char decimal_point_;
|
|
470
|
+
public:
|
|
471
|
+
write_double(float_chars_format float_format, int precision)
|
|
472
|
+
: float_format_(float_format), precision_(precision), decimal_point_('.')
|
|
473
|
+
{
|
|
474
|
+
#if !defined(JSONCONS_NO_LOCALECONV)
|
|
475
|
+
struct lconv *lc = localeconv();
|
|
476
|
+
if (lc != nullptr && lc->decimal_point[0] != 0)
|
|
477
|
+
{
|
|
478
|
+
decimal_point_ = lc->decimal_point[0];
|
|
479
|
+
}
|
|
480
|
+
#endif
|
|
481
|
+
}
|
|
482
|
+
write_double(const write_double&) = default;
|
|
483
|
+
|
|
484
|
+
write_double& operator=(const write_double&) = default;
|
|
485
|
+
|
|
486
|
+
template<class Result>
|
|
487
|
+
std::size_t operator()(double val, Result& result)
|
|
488
|
+
{
|
|
489
|
+
std::size_t count = 0;
|
|
490
|
+
|
|
491
|
+
char number_buffer[200];
|
|
492
|
+
int length = 0;
|
|
493
|
+
|
|
494
|
+
switch (float_format_)
|
|
495
|
+
{
|
|
496
|
+
case float_chars_format::fixed:
|
|
497
|
+
{
|
|
498
|
+
if (precision_ > 0)
|
|
499
|
+
{
|
|
500
|
+
length = snprintf(number_buffer, sizeof(number_buffer), "%1.*f", precision_, val);
|
|
501
|
+
if (length < 0)
|
|
502
|
+
{
|
|
503
|
+
JSONCONS_THROW(json_runtime_error<std::invalid_argument>("write_double failed."));
|
|
504
|
+
}
|
|
505
|
+
dump_buffer(number_buffer, length, decimal_point_, result);
|
|
506
|
+
}
|
|
507
|
+
else
|
|
508
|
+
{
|
|
509
|
+
if (!dtoa_fixed(val, decimal_point_, result))
|
|
510
|
+
{
|
|
511
|
+
JSONCONS_THROW(json_runtime_error<std::invalid_argument>("write_double failed."));
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
break;
|
|
516
|
+
case float_chars_format::scientific:
|
|
517
|
+
{
|
|
518
|
+
if (precision_ > 0)
|
|
519
|
+
{
|
|
520
|
+
length = snprintf(number_buffer, sizeof(number_buffer), "%1.*e", precision_, val);
|
|
521
|
+
if (length < 0)
|
|
522
|
+
{
|
|
523
|
+
JSONCONS_THROW(json_runtime_error<std::invalid_argument>("write_double failed."));
|
|
524
|
+
}
|
|
525
|
+
dump_buffer(number_buffer, length, decimal_point_, result);
|
|
526
|
+
}
|
|
527
|
+
else
|
|
528
|
+
{
|
|
529
|
+
if (!dtoa_scientific(val, decimal_point_, result))
|
|
530
|
+
{
|
|
531
|
+
JSONCONS_THROW(json_runtime_error<std::invalid_argument>("write_double failed."));
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
break;
|
|
536
|
+
case float_chars_format::general:
|
|
537
|
+
{
|
|
538
|
+
if (precision_ > 0)
|
|
539
|
+
{
|
|
540
|
+
length = snprintf(number_buffer, sizeof(number_buffer), "%1.*g", precision_, val);
|
|
541
|
+
if (length < 0)
|
|
542
|
+
{
|
|
543
|
+
JSONCONS_THROW(json_runtime_error<std::invalid_argument>("write_double failed."));
|
|
544
|
+
}
|
|
545
|
+
dump_buffer(number_buffer, length, decimal_point_, result);
|
|
546
|
+
}
|
|
547
|
+
else
|
|
548
|
+
{
|
|
549
|
+
if (!dtoa_general(val, decimal_point_, result))
|
|
550
|
+
{
|
|
551
|
+
JSONCONS_THROW(json_runtime_error<std::invalid_argument>("write_double failed."));
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
break;
|
|
555
|
+
}
|
|
556
|
+
default:
|
|
557
|
+
JSONCONS_THROW(json_runtime_error<std::invalid_argument>("write_double failed."));
|
|
558
|
+
break;
|
|
559
|
+
}
|
|
560
|
+
return count;
|
|
561
|
+
}
|
|
562
|
+
};
|
|
563
|
+
|
|
564
|
+
} // namespace detail
|
|
565
|
+
} // namespace jsoncons
|
|
566
|
+
|
|
567
|
+
#endif
|