rapidjson 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/CODE_OF_CONDUCT.md +84 -0
- data/LICENSE.txt +21 -0
- data/README.md +110 -0
- data/Rakefile +20 -0
- data/ext/rapidjson/buffer.hh +66 -0
- data/ext/rapidjson/cext.cc +77 -0
- data/ext/rapidjson/cext.hh +20 -0
- data/ext/rapidjson/encoder.hh +150 -0
- data/ext/rapidjson/extconf.rb +19 -0
- data/ext/rapidjson/parser.hh +149 -0
- data/ext/rapidjson/rapidjson/include/rapidjson/allocators.h +692 -0
- data/ext/rapidjson/rapidjson/include/rapidjson/cursorstreamwrapper.h +78 -0
- data/ext/rapidjson/rapidjson/include/rapidjson/document.h +3027 -0
- data/ext/rapidjson/rapidjson/include/rapidjson/encodedstream.h +299 -0
- data/ext/rapidjson/rapidjson/include/rapidjson/encodings.h +716 -0
- data/ext/rapidjson/rapidjson/include/rapidjson/error/en.h +122 -0
- data/ext/rapidjson/rapidjson/include/rapidjson/error/error.h +216 -0
- data/ext/rapidjson/rapidjson/include/rapidjson/filereadstream.h +99 -0
- data/ext/rapidjson/rapidjson/include/rapidjson/filewritestream.h +104 -0
- data/ext/rapidjson/rapidjson/include/rapidjson/fwd.h +151 -0
- data/ext/rapidjson/rapidjson/include/rapidjson/internal/biginteger.h +297 -0
- data/ext/rapidjson/rapidjson/include/rapidjson/internal/clzll.h +71 -0
- data/ext/rapidjson/rapidjson/include/rapidjson/internal/diyfp.h +261 -0
- data/ext/rapidjson/rapidjson/include/rapidjson/internal/dtoa.h +249 -0
- data/ext/rapidjson/rapidjson/include/rapidjson/internal/ieee754.h +78 -0
- data/ext/rapidjson/rapidjson/include/rapidjson/internal/itoa.h +308 -0
- data/ext/rapidjson/rapidjson/include/rapidjson/internal/meta.h +186 -0
- data/ext/rapidjson/rapidjson/include/rapidjson/internal/pow10.h +55 -0
- data/ext/rapidjson/rapidjson/include/rapidjson/internal/regex.h +739 -0
- data/ext/rapidjson/rapidjson/include/rapidjson/internal/stack.h +232 -0
- data/ext/rapidjson/rapidjson/include/rapidjson/internal/strfunc.h +83 -0
- data/ext/rapidjson/rapidjson/include/rapidjson/internal/strtod.h +293 -0
- data/ext/rapidjson/rapidjson/include/rapidjson/internal/swap.h +46 -0
- data/ext/rapidjson/rapidjson/include/rapidjson/istreamwrapper.h +128 -0
- data/ext/rapidjson/rapidjson/include/rapidjson/memorybuffer.h +70 -0
- data/ext/rapidjson/rapidjson/include/rapidjson/memorystream.h +71 -0
- data/ext/rapidjson/rapidjson/include/rapidjson/msinttypes/inttypes.h +316 -0
- data/ext/rapidjson/rapidjson/include/rapidjson/msinttypes/stdint.h +300 -0
- data/ext/rapidjson/rapidjson/include/rapidjson/ostreamwrapper.h +81 -0
- data/ext/rapidjson/rapidjson/include/rapidjson/pointer.h +1482 -0
- data/ext/rapidjson/rapidjson/include/rapidjson/prettywriter.h +277 -0
- data/ext/rapidjson/rapidjson/include/rapidjson/rapidjson.h +741 -0
- data/ext/rapidjson/rapidjson/include/rapidjson/reader.h +2246 -0
- data/ext/rapidjson/rapidjson/include/rapidjson/schema.h +2795 -0
- data/ext/rapidjson/rapidjson/include/rapidjson/stream.h +223 -0
- data/ext/rapidjson/rapidjson/include/rapidjson/stringbuffer.h +121 -0
- data/ext/rapidjson/rapidjson/include/rapidjson/uri.h +481 -0
- data/ext/rapidjson/rapidjson/include/rapidjson/writer.h +710 -0
- data/lib/rapidjson/json_gem.rb +36 -0
- data/lib/rapidjson/version.rb +5 -0
- data/lib/rapidjson.rb +9 -0
- metadata +98 -0
@@ -0,0 +1,261 @@
|
|
1
|
+
// Tencent is pleased to support the open source community by making RapidJSON available.
|
2
|
+
//
|
3
|
+
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
|
4
|
+
//
|
5
|
+
// Licensed under the MIT License (the "License"); you may not use this file except
|
6
|
+
// in compliance with the License. You may obtain a copy of the License at
|
7
|
+
//
|
8
|
+
// http://opensource.org/licenses/MIT
|
9
|
+
//
|
10
|
+
// Unless required by applicable law or agreed to in writing, software distributed
|
11
|
+
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
12
|
+
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
13
|
+
// specific language governing permissions and limitations under the License.
|
14
|
+
|
15
|
+
// This is a C++ header-only implementation of Grisu2 algorithm from the publication:
|
16
|
+
// Loitsch, Florian. "Printing floating-point numbers quickly and accurately with
|
17
|
+
// integers." ACM Sigplan Notices 45.6 (2010): 233-243.
|
18
|
+
|
19
|
+
#ifndef RAPIDJSON_DIYFP_H_
|
20
|
+
#define RAPIDJSON_DIYFP_H_
|
21
|
+
|
22
|
+
#include "../rapidjson.h"
|
23
|
+
#include "clzll.h"
|
24
|
+
#include <limits>
|
25
|
+
|
26
|
+
#if defined(_MSC_VER) && defined(_M_AMD64) && !defined(__INTEL_COMPILER)
|
27
|
+
#include <intrin.h>
|
28
|
+
#if !defined(_ARM64EC_)
|
29
|
+
#pragma intrinsic(_umul128)
|
30
|
+
#else
|
31
|
+
#pragma comment(lib,"softintrin")
|
32
|
+
#endif
|
33
|
+
#endif
|
34
|
+
|
35
|
+
RAPIDJSON_NAMESPACE_BEGIN
|
36
|
+
namespace internal {
|
37
|
+
|
38
|
+
#ifdef __GNUC__
|
39
|
+
RAPIDJSON_DIAG_PUSH
|
40
|
+
RAPIDJSON_DIAG_OFF(effc++)
|
41
|
+
#endif
|
42
|
+
|
43
|
+
#ifdef __clang__
|
44
|
+
RAPIDJSON_DIAG_PUSH
|
45
|
+
RAPIDJSON_DIAG_OFF(padded)
|
46
|
+
#endif
|
47
|
+
|
48
|
+
struct DiyFp {
|
49
|
+
DiyFp() : f(), e() {}
|
50
|
+
|
51
|
+
DiyFp(uint64_t fp, int exp) : f(fp), e(exp) {}
|
52
|
+
|
53
|
+
explicit DiyFp(double d) {
|
54
|
+
union {
|
55
|
+
double d;
|
56
|
+
uint64_t u64;
|
57
|
+
} u = { d };
|
58
|
+
|
59
|
+
int biased_e = static_cast<int>((u.u64 & kDpExponentMask) >> kDpSignificandSize);
|
60
|
+
uint64_t significand = (u.u64 & kDpSignificandMask);
|
61
|
+
if (biased_e != 0) {
|
62
|
+
f = significand + kDpHiddenBit;
|
63
|
+
e = biased_e - kDpExponentBias;
|
64
|
+
}
|
65
|
+
else {
|
66
|
+
f = significand;
|
67
|
+
e = kDpMinExponent + 1;
|
68
|
+
}
|
69
|
+
}
|
70
|
+
|
71
|
+
DiyFp operator-(const DiyFp& rhs) const {
|
72
|
+
return DiyFp(f - rhs.f, e);
|
73
|
+
}
|
74
|
+
|
75
|
+
DiyFp operator*(const DiyFp& rhs) const {
|
76
|
+
#if defined(_MSC_VER) && defined(_M_AMD64)
|
77
|
+
uint64_t h;
|
78
|
+
uint64_t l = _umul128(f, rhs.f, &h);
|
79
|
+
if (l & (uint64_t(1) << 63)) // rounding
|
80
|
+
h++;
|
81
|
+
return DiyFp(h, e + rhs.e + 64);
|
82
|
+
#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__)
|
83
|
+
__extension__ typedef unsigned __int128 uint128;
|
84
|
+
uint128 p = static_cast<uint128>(f) * static_cast<uint128>(rhs.f);
|
85
|
+
uint64_t h = static_cast<uint64_t>(p >> 64);
|
86
|
+
uint64_t l = static_cast<uint64_t>(p);
|
87
|
+
if (l & (uint64_t(1) << 63)) // rounding
|
88
|
+
h++;
|
89
|
+
return DiyFp(h, e + rhs.e + 64);
|
90
|
+
#else
|
91
|
+
const uint64_t M32 = 0xFFFFFFFF;
|
92
|
+
const uint64_t a = f >> 32;
|
93
|
+
const uint64_t b = f & M32;
|
94
|
+
const uint64_t c = rhs.f >> 32;
|
95
|
+
const uint64_t d = rhs.f & M32;
|
96
|
+
const uint64_t ac = a * c;
|
97
|
+
const uint64_t bc = b * c;
|
98
|
+
const uint64_t ad = a * d;
|
99
|
+
const uint64_t bd = b * d;
|
100
|
+
uint64_t tmp = (bd >> 32) + (ad & M32) + (bc & M32);
|
101
|
+
tmp += 1U << 31; /// mult_round
|
102
|
+
return DiyFp(ac + (ad >> 32) + (bc >> 32) + (tmp >> 32), e + rhs.e + 64);
|
103
|
+
#endif
|
104
|
+
}
|
105
|
+
|
106
|
+
DiyFp Normalize() const {
|
107
|
+
int s = static_cast<int>(clzll(f));
|
108
|
+
return DiyFp(f << s, e - s);
|
109
|
+
}
|
110
|
+
|
111
|
+
DiyFp NormalizeBoundary() const {
|
112
|
+
DiyFp res = *this;
|
113
|
+
while (!(res.f & (kDpHiddenBit << 1))) {
|
114
|
+
res.f <<= 1;
|
115
|
+
res.e--;
|
116
|
+
}
|
117
|
+
res.f <<= (kDiySignificandSize - kDpSignificandSize - 2);
|
118
|
+
res.e = res.e - (kDiySignificandSize - kDpSignificandSize - 2);
|
119
|
+
return res;
|
120
|
+
}
|
121
|
+
|
122
|
+
void NormalizedBoundaries(DiyFp* minus, DiyFp* plus) const {
|
123
|
+
DiyFp pl = DiyFp((f << 1) + 1, e - 1).NormalizeBoundary();
|
124
|
+
DiyFp mi = (f == kDpHiddenBit) ? DiyFp((f << 2) - 1, e - 2) : DiyFp((f << 1) - 1, e - 1);
|
125
|
+
mi.f <<= mi.e - pl.e;
|
126
|
+
mi.e = pl.e;
|
127
|
+
*plus = pl;
|
128
|
+
*minus = mi;
|
129
|
+
}
|
130
|
+
|
131
|
+
double ToDouble() const {
|
132
|
+
union {
|
133
|
+
double d;
|
134
|
+
uint64_t u64;
|
135
|
+
}u;
|
136
|
+
RAPIDJSON_ASSERT(f <= kDpHiddenBit + kDpSignificandMask);
|
137
|
+
if (e < kDpDenormalExponent) {
|
138
|
+
// Underflow.
|
139
|
+
return 0.0;
|
140
|
+
}
|
141
|
+
if (e >= kDpMaxExponent) {
|
142
|
+
// Overflow.
|
143
|
+
return std::numeric_limits<double>::infinity();
|
144
|
+
}
|
145
|
+
const uint64_t be = (e == kDpDenormalExponent && (f & kDpHiddenBit) == 0) ? 0 :
|
146
|
+
static_cast<uint64_t>(e + kDpExponentBias);
|
147
|
+
u.u64 = (f & kDpSignificandMask) | (be << kDpSignificandSize);
|
148
|
+
return u.d;
|
149
|
+
}
|
150
|
+
|
151
|
+
static const int kDiySignificandSize = 64;
|
152
|
+
static const int kDpSignificandSize = 52;
|
153
|
+
static const int kDpExponentBias = 0x3FF + kDpSignificandSize;
|
154
|
+
static const int kDpMaxExponent = 0x7FF - kDpExponentBias;
|
155
|
+
static const int kDpMinExponent = -kDpExponentBias;
|
156
|
+
static const int kDpDenormalExponent = -kDpExponentBias + 1;
|
157
|
+
static const uint64_t kDpExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000);
|
158
|
+
static const uint64_t kDpSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF);
|
159
|
+
static const uint64_t kDpHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000);
|
160
|
+
|
161
|
+
uint64_t f;
|
162
|
+
int e;
|
163
|
+
};
|
164
|
+
|
165
|
+
inline DiyFp GetCachedPowerByIndex(size_t index) {
|
166
|
+
// 10^-348, 10^-340, ..., 10^340
|
167
|
+
static const uint64_t kCachedPowers_F[] = {
|
168
|
+
RAPIDJSON_UINT64_C2(0xfa8fd5a0, 0x081c0288), RAPIDJSON_UINT64_C2(0xbaaee17f, 0xa23ebf76),
|
169
|
+
RAPIDJSON_UINT64_C2(0x8b16fb20, 0x3055ac76), RAPIDJSON_UINT64_C2(0xcf42894a, 0x5dce35ea),
|
170
|
+
RAPIDJSON_UINT64_C2(0x9a6bb0aa, 0x55653b2d), RAPIDJSON_UINT64_C2(0xe61acf03, 0x3d1a45df),
|
171
|
+
RAPIDJSON_UINT64_C2(0xab70fe17, 0xc79ac6ca), RAPIDJSON_UINT64_C2(0xff77b1fc, 0xbebcdc4f),
|
172
|
+
RAPIDJSON_UINT64_C2(0xbe5691ef, 0x416bd60c), RAPIDJSON_UINT64_C2(0x8dd01fad, 0x907ffc3c),
|
173
|
+
RAPIDJSON_UINT64_C2(0xd3515c28, 0x31559a83), RAPIDJSON_UINT64_C2(0x9d71ac8f, 0xada6c9b5),
|
174
|
+
RAPIDJSON_UINT64_C2(0xea9c2277, 0x23ee8bcb), RAPIDJSON_UINT64_C2(0xaecc4991, 0x4078536d),
|
175
|
+
RAPIDJSON_UINT64_C2(0x823c1279, 0x5db6ce57), RAPIDJSON_UINT64_C2(0xc2109436, 0x4dfb5637),
|
176
|
+
RAPIDJSON_UINT64_C2(0x9096ea6f, 0x3848984f), RAPIDJSON_UINT64_C2(0xd77485cb, 0x25823ac7),
|
177
|
+
RAPIDJSON_UINT64_C2(0xa086cfcd, 0x97bf97f4), RAPIDJSON_UINT64_C2(0xef340a98, 0x172aace5),
|
178
|
+
RAPIDJSON_UINT64_C2(0xb23867fb, 0x2a35b28e), RAPIDJSON_UINT64_C2(0x84c8d4df, 0xd2c63f3b),
|
179
|
+
RAPIDJSON_UINT64_C2(0xc5dd4427, 0x1ad3cdba), RAPIDJSON_UINT64_C2(0x936b9fce, 0xbb25c996),
|
180
|
+
RAPIDJSON_UINT64_C2(0xdbac6c24, 0x7d62a584), RAPIDJSON_UINT64_C2(0xa3ab6658, 0x0d5fdaf6),
|
181
|
+
RAPIDJSON_UINT64_C2(0xf3e2f893, 0xdec3f126), RAPIDJSON_UINT64_C2(0xb5b5ada8, 0xaaff80b8),
|
182
|
+
RAPIDJSON_UINT64_C2(0x87625f05, 0x6c7c4a8b), RAPIDJSON_UINT64_C2(0xc9bcff60, 0x34c13053),
|
183
|
+
RAPIDJSON_UINT64_C2(0x964e858c, 0x91ba2655), RAPIDJSON_UINT64_C2(0xdff97724, 0x70297ebd),
|
184
|
+
RAPIDJSON_UINT64_C2(0xa6dfbd9f, 0xb8e5b88f), RAPIDJSON_UINT64_C2(0xf8a95fcf, 0x88747d94),
|
185
|
+
RAPIDJSON_UINT64_C2(0xb9447093, 0x8fa89bcf), RAPIDJSON_UINT64_C2(0x8a08f0f8, 0xbf0f156b),
|
186
|
+
RAPIDJSON_UINT64_C2(0xcdb02555, 0x653131b6), RAPIDJSON_UINT64_C2(0x993fe2c6, 0xd07b7fac),
|
187
|
+
RAPIDJSON_UINT64_C2(0xe45c10c4, 0x2a2b3b06), RAPIDJSON_UINT64_C2(0xaa242499, 0x697392d3),
|
188
|
+
RAPIDJSON_UINT64_C2(0xfd87b5f2, 0x8300ca0e), RAPIDJSON_UINT64_C2(0xbce50864, 0x92111aeb),
|
189
|
+
RAPIDJSON_UINT64_C2(0x8cbccc09, 0x6f5088cc), RAPIDJSON_UINT64_C2(0xd1b71758, 0xe219652c),
|
190
|
+
RAPIDJSON_UINT64_C2(0x9c400000, 0x00000000), RAPIDJSON_UINT64_C2(0xe8d4a510, 0x00000000),
|
191
|
+
RAPIDJSON_UINT64_C2(0xad78ebc5, 0xac620000), RAPIDJSON_UINT64_C2(0x813f3978, 0xf8940984),
|
192
|
+
RAPIDJSON_UINT64_C2(0xc097ce7b, 0xc90715b3), RAPIDJSON_UINT64_C2(0x8f7e32ce, 0x7bea5c70),
|
193
|
+
RAPIDJSON_UINT64_C2(0xd5d238a4, 0xabe98068), RAPIDJSON_UINT64_C2(0x9f4f2726, 0x179a2245),
|
194
|
+
RAPIDJSON_UINT64_C2(0xed63a231, 0xd4c4fb27), RAPIDJSON_UINT64_C2(0xb0de6538, 0x8cc8ada8),
|
195
|
+
RAPIDJSON_UINT64_C2(0x83c7088e, 0x1aab65db), RAPIDJSON_UINT64_C2(0xc45d1df9, 0x42711d9a),
|
196
|
+
RAPIDJSON_UINT64_C2(0x924d692c, 0xa61be758), RAPIDJSON_UINT64_C2(0xda01ee64, 0x1a708dea),
|
197
|
+
RAPIDJSON_UINT64_C2(0xa26da399, 0x9aef774a), RAPIDJSON_UINT64_C2(0xf209787b, 0xb47d6b85),
|
198
|
+
RAPIDJSON_UINT64_C2(0xb454e4a1, 0x79dd1877), RAPIDJSON_UINT64_C2(0x865b8692, 0x5b9bc5c2),
|
199
|
+
RAPIDJSON_UINT64_C2(0xc83553c5, 0xc8965d3d), RAPIDJSON_UINT64_C2(0x952ab45c, 0xfa97a0b3),
|
200
|
+
RAPIDJSON_UINT64_C2(0xde469fbd, 0x99a05fe3), RAPIDJSON_UINT64_C2(0xa59bc234, 0xdb398c25),
|
201
|
+
RAPIDJSON_UINT64_C2(0xf6c69a72, 0xa3989f5c), RAPIDJSON_UINT64_C2(0xb7dcbf53, 0x54e9bece),
|
202
|
+
RAPIDJSON_UINT64_C2(0x88fcf317, 0xf22241e2), RAPIDJSON_UINT64_C2(0xcc20ce9b, 0xd35c78a5),
|
203
|
+
RAPIDJSON_UINT64_C2(0x98165af3, 0x7b2153df), RAPIDJSON_UINT64_C2(0xe2a0b5dc, 0x971f303a),
|
204
|
+
RAPIDJSON_UINT64_C2(0xa8d9d153, 0x5ce3b396), RAPIDJSON_UINT64_C2(0xfb9b7cd9, 0xa4a7443c),
|
205
|
+
RAPIDJSON_UINT64_C2(0xbb764c4c, 0xa7a44410), RAPIDJSON_UINT64_C2(0x8bab8eef, 0xb6409c1a),
|
206
|
+
RAPIDJSON_UINT64_C2(0xd01fef10, 0xa657842c), RAPIDJSON_UINT64_C2(0x9b10a4e5, 0xe9913129),
|
207
|
+
RAPIDJSON_UINT64_C2(0xe7109bfb, 0xa19c0c9d), RAPIDJSON_UINT64_C2(0xac2820d9, 0x623bf429),
|
208
|
+
RAPIDJSON_UINT64_C2(0x80444b5e, 0x7aa7cf85), RAPIDJSON_UINT64_C2(0xbf21e440, 0x03acdd2d),
|
209
|
+
RAPIDJSON_UINT64_C2(0x8e679c2f, 0x5e44ff8f), RAPIDJSON_UINT64_C2(0xd433179d, 0x9c8cb841),
|
210
|
+
RAPIDJSON_UINT64_C2(0x9e19db92, 0xb4e31ba9), RAPIDJSON_UINT64_C2(0xeb96bf6e, 0xbadf77d9),
|
211
|
+
RAPIDJSON_UINT64_C2(0xaf87023b, 0x9bf0ee6b)
|
212
|
+
};
|
213
|
+
static const int16_t kCachedPowers_E[] = {
|
214
|
+
-1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007, -980,
|
215
|
+
-954, -927, -901, -874, -847, -821, -794, -768, -741, -715,
|
216
|
+
-688, -661, -635, -608, -582, -555, -529, -502, -475, -449,
|
217
|
+
-422, -396, -369, -343, -316, -289, -263, -236, -210, -183,
|
218
|
+
-157, -130, -103, -77, -50, -24, 3, 30, 56, 83,
|
219
|
+
109, 136, 162, 189, 216, 242, 269, 295, 322, 348,
|
220
|
+
375, 402, 428, 455, 481, 508, 534, 561, 588, 614,
|
221
|
+
641, 667, 694, 720, 747, 774, 800, 827, 853, 880,
|
222
|
+
907, 933, 960, 986, 1013, 1039, 1066
|
223
|
+
};
|
224
|
+
RAPIDJSON_ASSERT(index < 87);
|
225
|
+
return DiyFp(kCachedPowers_F[index], kCachedPowers_E[index]);
|
226
|
+
}
|
227
|
+
|
228
|
+
inline DiyFp GetCachedPower(int e, int* K) {
|
229
|
+
|
230
|
+
//int k = static_cast<int>(ceil((-61 - e) * 0.30102999566398114)) + 374;
|
231
|
+
double dk = (-61 - e) * 0.30102999566398114 + 347; // dk must be positive, so can do ceiling in positive
|
232
|
+
int k = static_cast<int>(dk);
|
233
|
+
if (dk - k > 0.0)
|
234
|
+
k++;
|
235
|
+
|
236
|
+
unsigned index = static_cast<unsigned>((k >> 3) + 1);
|
237
|
+
*K = -(-348 + static_cast<int>(index << 3)); // decimal exponent no need lookup table
|
238
|
+
|
239
|
+
return GetCachedPowerByIndex(index);
|
240
|
+
}
|
241
|
+
|
242
|
+
inline DiyFp GetCachedPower10(int exp, int *outExp) {
|
243
|
+
RAPIDJSON_ASSERT(exp >= -348);
|
244
|
+
unsigned index = static_cast<unsigned>(exp + 348) / 8u;
|
245
|
+
*outExp = -348 + static_cast<int>(index) * 8;
|
246
|
+
return GetCachedPowerByIndex(index);
|
247
|
+
}
|
248
|
+
|
249
|
+
#ifdef __GNUC__
|
250
|
+
RAPIDJSON_DIAG_POP
|
251
|
+
#endif
|
252
|
+
|
253
|
+
#ifdef __clang__
|
254
|
+
RAPIDJSON_DIAG_POP
|
255
|
+
RAPIDJSON_DIAG_OFF(padded)
|
256
|
+
#endif
|
257
|
+
|
258
|
+
} // namespace internal
|
259
|
+
RAPIDJSON_NAMESPACE_END
|
260
|
+
|
261
|
+
#endif // RAPIDJSON_DIYFP_H_
|
@@ -0,0 +1,249 @@
|
|
1
|
+
// Tencent is pleased to support the open source community by making RapidJSON available.
|
2
|
+
//
|
3
|
+
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
|
4
|
+
//
|
5
|
+
// Licensed under the MIT License (the "License"); you may not use this file except
|
6
|
+
// in compliance with the License. You may obtain a copy of the License at
|
7
|
+
//
|
8
|
+
// http://opensource.org/licenses/MIT
|
9
|
+
//
|
10
|
+
// Unless required by applicable law or agreed to in writing, software distributed
|
11
|
+
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
12
|
+
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
13
|
+
// specific language governing permissions and limitations under the License.
|
14
|
+
|
15
|
+
// This is a C++ header-only implementation of Grisu2 algorithm from the publication:
|
16
|
+
// Loitsch, Florian. "Printing floating-point numbers quickly and accurately with
|
17
|
+
// integers." ACM Sigplan Notices 45.6 (2010): 233-243.
|
18
|
+
|
19
|
+
#ifndef RAPIDJSON_DTOA_
|
20
|
+
#define RAPIDJSON_DTOA_
|
21
|
+
|
22
|
+
#include "itoa.h" // GetDigitsLut()
|
23
|
+
#include "diyfp.h"
|
24
|
+
#include "ieee754.h"
|
25
|
+
|
26
|
+
RAPIDJSON_NAMESPACE_BEGIN
|
27
|
+
namespace internal {
|
28
|
+
|
29
|
+
#ifdef __GNUC__
|
30
|
+
RAPIDJSON_DIAG_PUSH
|
31
|
+
RAPIDJSON_DIAG_OFF(effc++)
|
32
|
+
RAPIDJSON_DIAG_OFF(array-bounds) // some gcc versions generate wrong warnings https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59124
|
33
|
+
#endif
|
34
|
+
|
35
|
+
inline void GrisuRound(char* buffer, int len, uint64_t delta, uint64_t rest, uint64_t ten_kappa, uint64_t wp_w) {
|
36
|
+
while (rest < wp_w && delta - rest >= ten_kappa &&
|
37
|
+
(rest + ten_kappa < wp_w || /// closer
|
38
|
+
wp_w - rest > rest + ten_kappa - wp_w)) {
|
39
|
+
buffer[len - 1]--;
|
40
|
+
rest += ten_kappa;
|
41
|
+
}
|
42
|
+
}
|
43
|
+
|
44
|
+
inline int CountDecimalDigit32(uint32_t n) {
|
45
|
+
// Simple pure C++ implementation was faster than __builtin_clz version in this situation.
|
46
|
+
if (n < 10) return 1;
|
47
|
+
if (n < 100) return 2;
|
48
|
+
if (n < 1000) return 3;
|
49
|
+
if (n < 10000) return 4;
|
50
|
+
if (n < 100000) return 5;
|
51
|
+
if (n < 1000000) return 6;
|
52
|
+
if (n < 10000000) return 7;
|
53
|
+
if (n < 100000000) return 8;
|
54
|
+
// Will not reach 10 digits in DigitGen()
|
55
|
+
//if (n < 1000000000) return 9;
|
56
|
+
//return 10;
|
57
|
+
return 9;
|
58
|
+
}
|
59
|
+
|
60
|
+
inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buffer, int* len, int* K) {
|
61
|
+
static const uint64_t kPow10[] = { 1U, 10U, 100U, 1000U, 10000U, 100000U, 1000000U, 10000000U, 100000000U,
|
62
|
+
1000000000U, 10000000000U, 100000000000U, 1000000000000U,
|
63
|
+
10000000000000U, 100000000000000U, 1000000000000000U,
|
64
|
+
10000000000000000U, 100000000000000000U, 1000000000000000000U,
|
65
|
+
10000000000000000000U };
|
66
|
+
const DiyFp one(uint64_t(1) << -Mp.e, Mp.e);
|
67
|
+
const DiyFp wp_w = Mp - W;
|
68
|
+
uint32_t p1 = static_cast<uint32_t>(Mp.f >> -one.e);
|
69
|
+
uint64_t p2 = Mp.f & (one.f - 1);
|
70
|
+
int kappa = CountDecimalDigit32(p1); // kappa in [0, 9]
|
71
|
+
*len = 0;
|
72
|
+
|
73
|
+
while (kappa > 0) {
|
74
|
+
uint32_t d = 0;
|
75
|
+
switch (kappa) {
|
76
|
+
case 9: d = p1 / 100000000; p1 %= 100000000; break;
|
77
|
+
case 8: d = p1 / 10000000; p1 %= 10000000; break;
|
78
|
+
case 7: d = p1 / 1000000; p1 %= 1000000; break;
|
79
|
+
case 6: d = p1 / 100000; p1 %= 100000; break;
|
80
|
+
case 5: d = p1 / 10000; p1 %= 10000; break;
|
81
|
+
case 4: d = p1 / 1000; p1 %= 1000; break;
|
82
|
+
case 3: d = p1 / 100; p1 %= 100; break;
|
83
|
+
case 2: d = p1 / 10; p1 %= 10; break;
|
84
|
+
case 1: d = p1; p1 = 0; break;
|
85
|
+
default:;
|
86
|
+
}
|
87
|
+
if (d || *len)
|
88
|
+
buffer[(*len)++] = static_cast<char>('0' + static_cast<char>(d));
|
89
|
+
kappa--;
|
90
|
+
uint64_t tmp = (static_cast<uint64_t>(p1) << -one.e) + p2;
|
91
|
+
if (tmp <= delta) {
|
92
|
+
*K += kappa;
|
93
|
+
GrisuRound(buffer, *len, delta, tmp, kPow10[kappa] << -one.e, wp_w.f);
|
94
|
+
return;
|
95
|
+
}
|
96
|
+
}
|
97
|
+
|
98
|
+
// kappa = 0
|
99
|
+
for (;;) {
|
100
|
+
p2 *= 10;
|
101
|
+
delta *= 10;
|
102
|
+
char d = static_cast<char>(p2 >> -one.e);
|
103
|
+
if (d || *len)
|
104
|
+
buffer[(*len)++] = static_cast<char>('0' + d);
|
105
|
+
p2 &= one.f - 1;
|
106
|
+
kappa--;
|
107
|
+
if (p2 < delta) {
|
108
|
+
*K += kappa;
|
109
|
+
int index = -kappa;
|
110
|
+
GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * (index < 20 ? kPow10[index] : 0));
|
111
|
+
return;
|
112
|
+
}
|
113
|
+
}
|
114
|
+
}
|
115
|
+
|
116
|
+
inline void Grisu2(double value, char* buffer, int* length, int* K) {
|
117
|
+
const DiyFp v(value);
|
118
|
+
DiyFp w_m, w_p;
|
119
|
+
v.NormalizedBoundaries(&w_m, &w_p);
|
120
|
+
|
121
|
+
const DiyFp c_mk = GetCachedPower(w_p.e, K);
|
122
|
+
const DiyFp W = v.Normalize() * c_mk;
|
123
|
+
DiyFp Wp = w_p * c_mk;
|
124
|
+
DiyFp Wm = w_m * c_mk;
|
125
|
+
Wm.f++;
|
126
|
+
Wp.f--;
|
127
|
+
DigitGen(W, Wp, Wp.f - Wm.f, buffer, length, K);
|
128
|
+
}
|
129
|
+
|
130
|
+
inline char* WriteExponent(int K, char* buffer) {
|
131
|
+
if (K < 0) {
|
132
|
+
*buffer++ = '-';
|
133
|
+
K = -K;
|
134
|
+
}
|
135
|
+
|
136
|
+
if (K >= 100) {
|
137
|
+
*buffer++ = static_cast<char>('0' + static_cast<char>(K / 100));
|
138
|
+
K %= 100;
|
139
|
+
const char* d = GetDigitsLut() + K * 2;
|
140
|
+
*buffer++ = d[0];
|
141
|
+
*buffer++ = d[1];
|
142
|
+
}
|
143
|
+
else if (K >= 10) {
|
144
|
+
const char* d = GetDigitsLut() + K * 2;
|
145
|
+
*buffer++ = d[0];
|
146
|
+
*buffer++ = d[1];
|
147
|
+
}
|
148
|
+
else
|
149
|
+
*buffer++ = static_cast<char>('0' + static_cast<char>(K));
|
150
|
+
|
151
|
+
return buffer;
|
152
|
+
}
|
153
|
+
|
154
|
+
inline char* Prettify(char* buffer, int length, int k, int maxDecimalPlaces) {
|
155
|
+
const int kk = length + k; // 10^(kk-1) <= v < 10^kk
|
156
|
+
|
157
|
+
if (0 <= k && kk <= 21) {
|
158
|
+
// 1234e7 -> 12340000000
|
159
|
+
for (int i = length; i < kk; i++)
|
160
|
+
buffer[i] = '0';
|
161
|
+
buffer[kk] = '.';
|
162
|
+
buffer[kk + 1] = '0';
|
163
|
+
return &buffer[kk + 2];
|
164
|
+
}
|
165
|
+
else if (0 < kk && kk <= 21) {
|
166
|
+
// 1234e-2 -> 12.34
|
167
|
+
std::memmove(&buffer[kk + 1], &buffer[kk], static_cast<size_t>(length - kk));
|
168
|
+
buffer[kk] = '.';
|
169
|
+
if (0 > k + maxDecimalPlaces) {
|
170
|
+
// When maxDecimalPlaces = 2, 1.2345 -> 1.23, 1.102 -> 1.1
|
171
|
+
// Remove extra trailing zeros (at least one) after truncation.
|
172
|
+
for (int i = kk + maxDecimalPlaces; i > kk + 1; i--)
|
173
|
+
if (buffer[i] != '0')
|
174
|
+
return &buffer[i + 1];
|
175
|
+
return &buffer[kk + 2]; // Reserve one zero
|
176
|
+
}
|
177
|
+
else
|
178
|
+
return &buffer[length + 1];
|
179
|
+
}
|
180
|
+
else if (-6 < kk && kk <= 0) {
|
181
|
+
// 1234e-6 -> 0.001234
|
182
|
+
const int offset = 2 - kk;
|
183
|
+
std::memmove(&buffer[offset], &buffer[0], static_cast<size_t>(length));
|
184
|
+
buffer[0] = '0';
|
185
|
+
buffer[1] = '.';
|
186
|
+
for (int i = 2; i < offset; i++)
|
187
|
+
buffer[i] = '0';
|
188
|
+
if (length - kk > maxDecimalPlaces) {
|
189
|
+
// When maxDecimalPlaces = 2, 0.123 -> 0.12, 0.102 -> 0.1
|
190
|
+
// Remove extra trailing zeros (at least one) after truncation.
|
191
|
+
for (int i = maxDecimalPlaces + 1; i > 2; i--)
|
192
|
+
if (buffer[i] != '0')
|
193
|
+
return &buffer[i + 1];
|
194
|
+
return &buffer[3]; // Reserve one zero
|
195
|
+
}
|
196
|
+
else
|
197
|
+
return &buffer[length + offset];
|
198
|
+
}
|
199
|
+
else if (kk < -maxDecimalPlaces) {
|
200
|
+
// Truncate to zero
|
201
|
+
buffer[0] = '0';
|
202
|
+
buffer[1] = '.';
|
203
|
+
buffer[2] = '0';
|
204
|
+
return &buffer[3];
|
205
|
+
}
|
206
|
+
else if (length == 1) {
|
207
|
+
// 1e30
|
208
|
+
buffer[1] = 'e';
|
209
|
+
return WriteExponent(kk - 1, &buffer[2]);
|
210
|
+
}
|
211
|
+
else {
|
212
|
+
// 1234e30 -> 1.234e33
|
213
|
+
std::memmove(&buffer[2], &buffer[1], static_cast<size_t>(length - 1));
|
214
|
+
buffer[1] = '.';
|
215
|
+
buffer[length + 1] = 'e';
|
216
|
+
return WriteExponent(kk - 1, &buffer[0 + length + 2]);
|
217
|
+
}
|
218
|
+
}
|
219
|
+
|
220
|
+
inline char* dtoa(double value, char* buffer, int maxDecimalPlaces = 324) {
|
221
|
+
RAPIDJSON_ASSERT(maxDecimalPlaces >= 1);
|
222
|
+
Double d(value);
|
223
|
+
if (d.IsZero()) {
|
224
|
+
if (d.Sign())
|
225
|
+
*buffer++ = '-'; // -0.0, Issue #289
|
226
|
+
buffer[0] = '0';
|
227
|
+
buffer[1] = '.';
|
228
|
+
buffer[2] = '0';
|
229
|
+
return &buffer[3];
|
230
|
+
}
|
231
|
+
else {
|
232
|
+
if (value < 0) {
|
233
|
+
*buffer++ = '-';
|
234
|
+
value = -value;
|
235
|
+
}
|
236
|
+
int length, K;
|
237
|
+
Grisu2(value, buffer, &length, &K);
|
238
|
+
return Prettify(buffer, length, K, maxDecimalPlaces);
|
239
|
+
}
|
240
|
+
}
|
241
|
+
|
242
|
+
#ifdef __GNUC__
|
243
|
+
RAPIDJSON_DIAG_POP
|
244
|
+
#endif
|
245
|
+
|
246
|
+
} // namespace internal
|
247
|
+
RAPIDJSON_NAMESPACE_END
|
248
|
+
|
249
|
+
#endif // RAPIDJSON_DTOA_
|
@@ -0,0 +1,78 @@
|
|
1
|
+
// Tencent is pleased to support the open source community by making RapidJSON available.
|
2
|
+
//
|
3
|
+
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
|
4
|
+
//
|
5
|
+
// Licensed under the MIT License (the "License"); you may not use this file except
|
6
|
+
// in compliance with the License. You may obtain a copy of the License at
|
7
|
+
//
|
8
|
+
// http://opensource.org/licenses/MIT
|
9
|
+
//
|
10
|
+
// Unless required by applicable law or agreed to in writing, software distributed
|
11
|
+
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
12
|
+
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
13
|
+
// specific language governing permissions and limitations under the License.
|
14
|
+
|
15
|
+
#ifndef RAPIDJSON_IEEE754_
|
16
|
+
#define RAPIDJSON_IEEE754_
|
17
|
+
|
18
|
+
#include "../rapidjson.h"
|
19
|
+
|
20
|
+
RAPIDJSON_NAMESPACE_BEGIN
|
21
|
+
namespace internal {
|
22
|
+
|
23
|
+
class Double {
|
24
|
+
public:
|
25
|
+
Double() {}
|
26
|
+
Double(double d) : d_(d) {}
|
27
|
+
Double(uint64_t u) : u_(u) {}
|
28
|
+
|
29
|
+
double Value() const { return d_; }
|
30
|
+
uint64_t Uint64Value() const { return u_; }
|
31
|
+
|
32
|
+
double NextPositiveDouble() const {
|
33
|
+
RAPIDJSON_ASSERT(!Sign());
|
34
|
+
return Double(u_ + 1).Value();
|
35
|
+
}
|
36
|
+
|
37
|
+
bool Sign() const { return (u_ & kSignMask) != 0; }
|
38
|
+
uint64_t Significand() const { return u_ & kSignificandMask; }
|
39
|
+
int Exponent() const { return static_cast<int>(((u_ & kExponentMask) >> kSignificandSize) - kExponentBias); }
|
40
|
+
|
41
|
+
bool IsNan() const { return (u_ & kExponentMask) == kExponentMask && Significand() != 0; }
|
42
|
+
bool IsInf() const { return (u_ & kExponentMask) == kExponentMask && Significand() == 0; }
|
43
|
+
bool IsNanOrInf() const { return (u_ & kExponentMask) == kExponentMask; }
|
44
|
+
bool IsNormal() const { return (u_ & kExponentMask) != 0 || Significand() == 0; }
|
45
|
+
bool IsZero() const { return (u_ & (kExponentMask | kSignificandMask)) == 0; }
|
46
|
+
|
47
|
+
uint64_t IntegerSignificand() const { return IsNormal() ? Significand() | kHiddenBit : Significand(); }
|
48
|
+
int IntegerExponent() const { return (IsNormal() ? Exponent() : kDenormalExponent) - kSignificandSize; }
|
49
|
+
uint64_t ToBias() const { return (u_ & kSignMask) ? ~u_ + 1 : u_ | kSignMask; }
|
50
|
+
|
51
|
+
static int EffectiveSignificandSize(int order) {
|
52
|
+
if (order >= -1021)
|
53
|
+
return 53;
|
54
|
+
else if (order <= -1074)
|
55
|
+
return 0;
|
56
|
+
else
|
57
|
+
return order + 1074;
|
58
|
+
}
|
59
|
+
|
60
|
+
private:
|
61
|
+
static const int kSignificandSize = 52;
|
62
|
+
static const int kExponentBias = 0x3FF;
|
63
|
+
static const int kDenormalExponent = 1 - kExponentBias;
|
64
|
+
static const uint64_t kSignMask = RAPIDJSON_UINT64_C2(0x80000000, 0x00000000);
|
65
|
+
static const uint64_t kExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000);
|
66
|
+
static const uint64_t kSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF);
|
67
|
+
static const uint64_t kHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000);
|
68
|
+
|
69
|
+
union {
|
70
|
+
double d_;
|
71
|
+
uint64_t u_;
|
72
|
+
};
|
73
|
+
};
|
74
|
+
|
75
|
+
} // namespace internal
|
76
|
+
RAPIDJSON_NAMESPACE_END
|
77
|
+
|
78
|
+
#endif // RAPIDJSON_IEEE754_
|