rj_schema 0.1.4 → 0.2.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 +4 -4
- data/ext/rj_schema/extconf.rb +1 -1
- data/ext/rj_schema/rapidjson/include/rapidjson/allocators.h +14 -1
- data/ext/rj_schema/rapidjson/include/rapidjson/document.h +8 -20
- data/ext/rj_schema/rapidjson/include/rapidjson/encodings.h +29 -29
- data/ext/rj_schema/rapidjson/include/rapidjson/internal/biginteger.h +1 -1
- data/ext/rj_schema/rapidjson/include/rapidjson/internal/diyfp.h +24 -11
- data/ext/rj_schema/rapidjson/include/rapidjson/internal/itoa.h +1 -2
- data/ext/rj_schema/rapidjson/include/rapidjson/internal/meta.h +7 -2
- data/ext/rj_schema/rapidjson/include/rapidjson/internal/regex.h +5 -7
- data/ext/rj_schema/rapidjson/include/rapidjson/internal/strtod.h +59 -38
- data/ext/rj_schema/rapidjson/include/rapidjson/istreamwrapper.h +1 -3
- data/ext/rj_schema/rapidjson/include/rapidjson/pointer.h +2 -8
- data/ext/rj_schema/rapidjson/include/rapidjson/prettywriter.h +12 -12
- data/ext/rj_schema/rapidjson/include/rapidjson/rapidjson.h +15 -13
- data/ext/rj_schema/rapidjson/include/rapidjson/reader.h +27 -19
- data/ext/rj_schema/rapidjson/include/rapidjson/schema.h +15 -6
- data/ext/rj_schema/rapidjson/include/rapidjson/writer.h +4 -10
- data/ext/rj_schema/rapidjson/test/perftest/schematest.cpp +7 -0
- data/ext/rj_schema/rapidjson/test/unittest/allocatorstest.cpp +12 -14
- data/ext/rj_schema/rapidjson/test/unittest/bigintegertest.cpp +5 -0
- data/ext/rj_schema/rapidjson/test/unittest/istreamwrappertest.cpp +2 -2
- data/ext/rj_schema/rapidjson/test/unittest/prettywritertest.cpp +29 -0
- data/ext/rj_schema/rapidjson/test/unittest/readertest.cpp +303 -8
- data/ext/rj_schema/rapidjson/test/unittest/schematest.cpp +36 -2
- data/ext/rj_schema/rapidjson/test/unittest/simdtest.cpp +2 -2
- data/ext/rj_schema/rj_schema.cpp +46 -26
- data/lib/rj_schema.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 15a16238549524a1c7a9216107cd2125b0c4522c4df9a9fd7b32c94dcd9e776c
|
4
|
+
data.tar.gz: 688384742d09e5b50c171a91b20dd79a89ac04f0401a45a1de8bca0ed5547f07
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7263af5b39b00efddf0b6374cfabe5fb7c685dee7284cab5ef9ac49984e2844eed76a5d45b5d78740bd02ee984726058e7783ad31d49e4292b78d03eab46c56c
|
7
|
+
data.tar.gz: e46e876e00373491a8e817bb291029aae672427fa7b5a87ebc5a4a1d84f527acca6e28b589d569e8294d362e770b6113c289fe03aee081f60c61991a4cca0fa8
|
data/ext/rj_schema/extconf.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'mkmf'
|
2
2
|
$INCFLAGS << " -I$(srcdir)/rapidjson/include"
|
3
|
-
$CXXFLAGS << " -std=c++
|
3
|
+
$CXXFLAGS << " -std=c++14 "
|
4
4
|
CONFIG['CXX'] = ENV['CXX'] unless ENV['CXX'].nil?
|
5
5
|
CONFIG['CC'] = ENV['CC'] unless ENV['CC'].nil?
|
6
6
|
puts "compiler ENV: CC #{ENV['CC']}, CXX #{ENV['CXX']}"
|
@@ -52,6 +52,19 @@ concept Allocator {
|
|
52
52
|
\endcode
|
53
53
|
*/
|
54
54
|
|
55
|
+
|
56
|
+
/*! \def RAPIDJSON_ALLOCATOR_DEFUALT_CHUNK_CAPACITY
|
57
|
+
\ingroup RAPIDJSON_CONFIG
|
58
|
+
\brief User-defined kDefaultChunkCapacity definition.
|
59
|
+
|
60
|
+
User can define this as any \c size that is a power of 2.
|
61
|
+
*/
|
62
|
+
|
63
|
+
#ifndef RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY
|
64
|
+
#define RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY (64 * 1024)
|
65
|
+
#endif
|
66
|
+
|
67
|
+
|
55
68
|
///////////////////////////////////////////////////////////////////////////////
|
56
69
|
// CrtAllocator
|
57
70
|
|
@@ -248,7 +261,7 @@ private:
|
|
248
261
|
return false;
|
249
262
|
}
|
250
263
|
|
251
|
-
static const int kDefaultChunkCapacity =
|
264
|
+
static const int kDefaultChunkCapacity = RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY; //!< Default chunk capacity.
|
252
265
|
|
253
266
|
//! Chunk header for perpending to each chunk.
|
254
267
|
/*! Chunks are stored as a singly linked list.
|
@@ -26,15 +26,13 @@
|
|
26
26
|
#include <limits>
|
27
27
|
|
28
28
|
RAPIDJSON_DIAG_PUSH
|
29
|
-
#ifdef _MSC_VER
|
30
|
-
RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
|
31
|
-
RAPIDJSON_DIAG_OFF(4244) // conversion from kXxxFlags to 'uint16_t', possible loss of data
|
32
|
-
#endif
|
33
|
-
|
34
29
|
#ifdef __clang__
|
35
30
|
RAPIDJSON_DIAG_OFF(padded)
|
36
31
|
RAPIDJSON_DIAG_OFF(switch-enum)
|
37
32
|
RAPIDJSON_DIAG_OFF(c++98-compat)
|
33
|
+
#elif defined(_MSC_VER)
|
34
|
+
RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
|
35
|
+
RAPIDJSON_DIAG_OFF(4244) // conversion from kXxxFlags to 'uint16_t', possible loss of data
|
38
36
|
#endif
|
39
37
|
|
40
38
|
#ifdef __GNUC__
|
@@ -1515,7 +1513,7 @@ public:
|
|
1515
1513
|
MemberIterator pos = MemberBegin() + (first - MemberBegin());
|
1516
1514
|
for (MemberIterator itr = pos; itr != last; ++itr)
|
1517
1515
|
itr->~Member();
|
1518
|
-
std::memmove(&*pos, &*last, static_cast<size_t>(MemberEnd() - last) * sizeof(Member));
|
1516
|
+
std::memmove(static_cast<void*>(&*pos), &*last, static_cast<size_t>(MemberEnd() - last) * sizeof(Member));
|
1519
1517
|
data_.o.size -= static_cast<SizeType>(last - first);
|
1520
1518
|
return pos;
|
1521
1519
|
}
|
@@ -1718,8 +1716,8 @@ public:
|
|
1718
1716
|
RAPIDJSON_ASSERT(last <= End());
|
1719
1717
|
ValueIterator pos = Begin() + (first - Begin());
|
1720
1718
|
for (ValueIterator itr = pos; itr != last; ++itr)
|
1721
|
-
itr->~GenericValue();
|
1722
|
-
std::memmove(pos, last, static_cast<size_t>(End() - last) * sizeof(GenericValue));
|
1719
|
+
itr->~GenericValue();
|
1720
|
+
std::memmove(static_cast<void*>(pos), last, static_cast<size_t>(End() - last) * sizeof(GenericValue));
|
1723
1721
|
data_.a.size -= static_cast<SizeType>(last - first);
|
1724
1722
|
return pos;
|
1725
1723
|
}
|
@@ -2034,12 +2032,7 @@ private:
|
|
2034
2032
|
if (count) {
|
2035
2033
|
GenericValue* e = static_cast<GenericValue*>(allocator.Malloc(count * sizeof(GenericValue)));
|
2036
2034
|
SetElementsPointer(e);
|
2037
|
-
|
2038
|
-
#if defined(__GNUC__) && __GNUC__ >= 8
|
2039
|
-
RAPIDJSON_DIAG_OFF(class-memaccess) // ignore complains from gcc that no trivial copy constructor exists.
|
2040
|
-
#endif
|
2041
|
-
std::memcpy(e, values, count * sizeof(GenericValue));
|
2042
|
-
RAPIDJSON_DIAG_POP
|
2035
|
+
std::memcpy(static_cast<void*>(e), values, count * sizeof(GenericValue));
|
2043
2036
|
}
|
2044
2037
|
else
|
2045
2038
|
SetElementsPointer(0);
|
@@ -2052,12 +2045,7 @@ RAPIDJSON_DIAG_POP
|
|
2052
2045
|
if (count) {
|
2053
2046
|
Member* m = static_cast<Member*>(allocator.Malloc(count * sizeof(Member)));
|
2054
2047
|
SetMembersPointer(m);
|
2055
|
-
|
2056
|
-
#if defined(__GNUC__) && __GNUC__ >= 8
|
2057
|
-
RAPIDJSON_DIAG_OFF(class-memaccess) // ignore complains from gcc that no trivial copy constructor exists.
|
2058
|
-
#endif
|
2059
|
-
std::memcpy(m, members, count * sizeof(Member));
|
2060
|
-
RAPIDJSON_DIAG_POP
|
2048
|
+
std::memcpy(static_cast<void*>(m), members, count * sizeof(Member));
|
2061
2049
|
}
|
2062
2050
|
else
|
2063
2051
|
SetMembersPointer(0);
|
@@ -17,7 +17,7 @@
|
|
17
17
|
|
18
18
|
#include "rapidjson.h"
|
19
19
|
|
20
|
-
#
|
20
|
+
#if defined(_MSC_VER) && !defined(__clang__)
|
21
21
|
RAPIDJSON_DIAG_PUSH
|
22
22
|
RAPIDJSON_DIAG_OFF(4244) // conversion from 'type1' to 'type2', possible loss of data
|
23
23
|
RAPIDJSON_DIAG_OFF(4702) // unreachable code
|
@@ -144,9 +144,9 @@ struct UTF8 {
|
|
144
144
|
|
145
145
|
template <typename InputStream>
|
146
146
|
static bool Decode(InputStream& is, unsigned* codepoint) {
|
147
|
-
#define
|
148
|
-
#define
|
149
|
-
#define
|
147
|
+
#define RAPIDJSON_COPY() c = is.Take(); *codepoint = (*codepoint << 6) | (static_cast<unsigned char>(c) & 0x3Fu)
|
148
|
+
#define RAPIDJSON_TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0)
|
149
|
+
#define RAPIDJSON_TAIL() RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x70)
|
150
150
|
typename InputStream::Ch c = is.Take();
|
151
151
|
if (!(c & 0x80)) {
|
152
152
|
*codepoint = static_cast<unsigned char>(c);
|
@@ -161,44 +161,44 @@ struct UTF8 {
|
|
161
161
|
}
|
162
162
|
bool result = true;
|
163
163
|
switch (type) {
|
164
|
-
case 2:
|
165
|
-
case 3:
|
166
|
-
case 4:
|
167
|
-
case 5:
|
168
|
-
case 6:
|
169
|
-
case 10:
|
170
|
-
case 11:
|
164
|
+
case 2: RAPIDJSON_TAIL(); return result;
|
165
|
+
case 3: RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
|
166
|
+
case 4: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x50); RAPIDJSON_TAIL(); return result;
|
167
|
+
case 5: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x10); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
|
168
|
+
case 6: RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
|
169
|
+
case 10: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x20); RAPIDJSON_TAIL(); return result;
|
170
|
+
case 11: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x60); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
|
171
171
|
default: return false;
|
172
172
|
}
|
173
|
-
#undef
|
174
|
-
#undef
|
175
|
-
#undef
|
173
|
+
#undef RAPIDJSON_COPY
|
174
|
+
#undef RAPIDJSON_TRANS
|
175
|
+
#undef RAPIDJSON_TAIL
|
176
176
|
}
|
177
177
|
|
178
178
|
template <typename InputStream, typename OutputStream>
|
179
179
|
static bool Validate(InputStream& is, OutputStream& os) {
|
180
|
-
#define
|
181
|
-
#define
|
182
|
-
#define
|
180
|
+
#define RAPIDJSON_COPY() os.Put(c = is.Take())
|
181
|
+
#define RAPIDJSON_TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0)
|
182
|
+
#define RAPIDJSON_TAIL() RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x70)
|
183
183
|
Ch c;
|
184
|
-
|
184
|
+
RAPIDJSON_COPY();
|
185
185
|
if (!(c & 0x80))
|
186
186
|
return true;
|
187
187
|
|
188
188
|
bool result = true;
|
189
189
|
switch (GetRange(static_cast<unsigned char>(c))) {
|
190
|
-
case 2:
|
191
|
-
case 3:
|
192
|
-
case 4:
|
193
|
-
case 5:
|
194
|
-
case 6:
|
195
|
-
case 10:
|
196
|
-
case 11:
|
190
|
+
case 2: RAPIDJSON_TAIL(); return result;
|
191
|
+
case 3: RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
|
192
|
+
case 4: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x50); RAPIDJSON_TAIL(); return result;
|
193
|
+
case 5: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x10); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
|
194
|
+
case 6: RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
|
195
|
+
case 10: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x20); RAPIDJSON_TAIL(); return result;
|
196
|
+
case 11: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x60); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
|
197
197
|
default: return false;
|
198
198
|
}
|
199
|
-
#undef
|
200
|
-
#undef
|
201
|
-
#undef
|
199
|
+
#undef RAPIDJSON_COPY
|
200
|
+
#undef RAPIDJSON_TRANS
|
201
|
+
#undef RAPIDJSON_TAIL
|
202
202
|
}
|
203
203
|
|
204
204
|
static unsigned char GetRange(unsigned char c) {
|
@@ -709,7 +709,7 @@ struct Transcoder<Encoding, Encoding> {
|
|
709
709
|
|
710
710
|
RAPIDJSON_NAMESPACE_END
|
711
711
|
|
712
|
-
#if defined(__GNUC__) || defined(_MSC_VER)
|
712
|
+
#if defined(__GNUC__) || (defined(_MSC_VER) && !defined(__clang__))
|
713
713
|
RAPIDJSON_DIAG_POP
|
714
714
|
#endif
|
715
715
|
|
@@ -133,7 +133,7 @@ public:
|
|
133
133
|
RAPIDJSON_ASSERT(count_ + offset <= kCapacity);
|
134
134
|
|
135
135
|
if (interShift == 0) {
|
136
|
-
std::memmove(
|
136
|
+
std::memmove(digits_ + offset, digits_, count_ * sizeof(Type));
|
137
137
|
count_ += offset;
|
138
138
|
}
|
139
139
|
else {
|
@@ -1,5 +1,5 @@
|
|
1
1
|
// Tencent is pleased to support the open source community by making RapidJSON available.
|
2
|
-
//
|
2
|
+
//
|
3
3
|
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
4
4
|
//
|
5
5
|
// Licensed under the MIT License (the "License"); you may not use this file except
|
@@ -7,9 +7,9 @@
|
|
7
7
|
//
|
8
8
|
// http://opensource.org/licenses/MIT
|
9
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
|
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
13
|
// specific language governing permissions and limitations under the License.
|
14
14
|
|
15
15
|
// This is a C++ header-only implementation of Grisu2 algorithm from the publication:
|
@@ -20,6 +20,7 @@
|
|
20
20
|
#define RAPIDJSON_DIYFP_H_
|
21
21
|
|
22
22
|
#include "../rapidjson.h"
|
23
|
+
#include <limits>
|
23
24
|
|
24
25
|
#if defined(_MSC_VER) && defined(_M_AMD64) && !defined(__INTEL_COMPILER)
|
25
26
|
#include <intrin.h>
|
@@ -56,7 +57,7 @@ struct DiyFp {
|
|
56
57
|
if (biased_e != 0) {
|
57
58
|
f = significand + kDpHiddenBit;
|
58
59
|
e = biased_e - kDpExponentBias;
|
59
|
-
}
|
60
|
+
}
|
60
61
|
else {
|
61
62
|
f = significand;
|
62
63
|
e = kDpMinExponent + 1;
|
@@ -99,6 +100,7 @@ struct DiyFp {
|
|
99
100
|
}
|
100
101
|
|
101
102
|
DiyFp Normalize() const {
|
103
|
+
RAPIDJSON_ASSERT(f != 0); // https://stackoverflow.com/a/26809183/291737
|
102
104
|
#if defined(_MSC_VER) && defined(_M_AMD64)
|
103
105
|
unsigned long index;
|
104
106
|
_BitScanReverse64(&index, f);
|
@@ -141,7 +143,16 @@ struct DiyFp {
|
|
141
143
|
double d;
|
142
144
|
uint64_t u64;
|
143
145
|
}u;
|
144
|
-
|
146
|
+
RAPIDJSON_ASSERT(f <= kDpHiddenBit + kDpSignificandMask);
|
147
|
+
if (e < kDpDenormalExponent) {
|
148
|
+
// Underflow.
|
149
|
+
return 0.0;
|
150
|
+
}
|
151
|
+
if (e >= kDpMaxExponent) {
|
152
|
+
// Overflow.
|
153
|
+
return std::numeric_limits<double>::infinity();
|
154
|
+
}
|
155
|
+
const uint64_t be = (e == kDpDenormalExponent && (f & kDpHiddenBit) == 0) ? 0 :
|
145
156
|
static_cast<uint64_t>(e + kDpExponentBias);
|
146
157
|
u.u64 = (f & kDpSignificandMask) | (be << kDpSignificandSize);
|
147
158
|
return u.d;
|
@@ -220,9 +231,10 @@ inline DiyFp GetCachedPowerByIndex(size_t index) {
|
|
220
231
|
641, 667, 694, 720, 747, 774, 800, 827, 853, 880,
|
221
232
|
907, 933, 960, 986, 1013, 1039, 1066
|
222
233
|
};
|
234
|
+
RAPIDJSON_ASSERT(index < 87);
|
223
235
|
return DiyFp(kCachedPowers_F[index], kCachedPowers_E[index]);
|
224
236
|
}
|
225
|
-
|
237
|
+
|
226
238
|
inline DiyFp GetCachedPower(int e, int* K) {
|
227
239
|
|
228
240
|
//int k = static_cast<int>(ceil((-61 - e) * 0.30102999566398114)) + 374;
|
@@ -238,10 +250,11 @@ inline DiyFp GetCachedPower(int e, int* K) {
|
|
238
250
|
}
|
239
251
|
|
240
252
|
inline DiyFp GetCachedPower10(int exp, int *outExp) {
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
253
|
+
RAPIDJSON_ASSERT(exp >= -348);
|
254
|
+
unsigned index = static_cast<unsigned>(exp + 348) / 8u;
|
255
|
+
*outExp = -348 + static_cast<int>(index) * 8;
|
256
|
+
return GetCachedPowerByIndex(index);
|
257
|
+
}
|
245
258
|
|
246
259
|
#ifdef __GNUC__
|
247
260
|
RAPIDJSON_DIAG_POP
|
@@ -211,9 +211,8 @@ inline char* u64toa(uint64_t value, char* buffer) {
|
|
211
211
|
*buffer++ = cDigitsLut[d3 + 1];
|
212
212
|
if (value >= kTen9)
|
213
213
|
*buffer++ = cDigitsLut[d4];
|
214
|
-
if (value >= kTen8)
|
215
|
-
*buffer++ = cDigitsLut[d4 + 1];
|
216
214
|
|
215
|
+
*buffer++ = cDigitsLut[d4 + 1];
|
217
216
|
*buffer++ = cDigitsLut[d5];
|
218
217
|
*buffer++ = cDigitsLut[d5 + 1];
|
219
218
|
*buffer++ = cDigitsLut[d6];
|
@@ -21,7 +21,8 @@
|
|
21
21
|
RAPIDJSON_DIAG_PUSH
|
22
22
|
RAPIDJSON_DIAG_OFF(effc++)
|
23
23
|
#endif
|
24
|
-
|
24
|
+
|
25
|
+
#if defined(_MSC_VER) && !defined(__clang__)
|
25
26
|
RAPIDJSON_DIAG_PUSH
|
26
27
|
RAPIDJSON_DIAG_OFF(6334)
|
27
28
|
#endif
|
@@ -174,7 +175,11 @@ template <typename T> struct RemoveSfinaeTag<SfinaeTag&(*)(T)> { typedef T Type;
|
|
174
175
|
RAPIDJSON_NAMESPACE_END
|
175
176
|
//@endcond
|
176
177
|
|
177
|
-
#if defined(
|
178
|
+
#if defined(_MSC_VER) && !defined(__clang__)
|
179
|
+
RAPIDJSON_DIAG_POP
|
180
|
+
#endif
|
181
|
+
|
182
|
+
#ifdef __GNUC__
|
178
183
|
RAPIDJSON_DIAG_POP
|
179
184
|
#endif
|
180
185
|
|
@@ -24,6 +24,9 @@ RAPIDJSON_DIAG_PUSH
|
|
24
24
|
RAPIDJSON_DIAG_OFF(padded)
|
25
25
|
RAPIDJSON_DIAG_OFF(switch-enum)
|
26
26
|
RAPIDJSON_DIAG_OFF(implicit-fallthrough)
|
27
|
+
#elif defined(_MSC_VER)
|
28
|
+
RAPIDJSON_DIAG_PUSH
|
29
|
+
RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
|
27
30
|
#endif
|
28
31
|
|
29
32
|
#ifdef __GNUC__
|
@@ -34,11 +37,6 @@ RAPIDJSON_DIAG_OFF(implicit-fallthrough)
|
|
34
37
|
#endif
|
35
38
|
#endif
|
36
39
|
|
37
|
-
#ifdef _MSC_VER
|
38
|
-
RAPIDJSON_DIAG_PUSH
|
39
|
-
RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
|
40
|
-
#endif
|
41
|
-
|
42
40
|
#ifndef RAPIDJSON_REGEX_VERBOSE
|
43
41
|
#define RAPIDJSON_REGEX_VERBOSE 0
|
44
42
|
#endif
|
@@ -723,11 +721,11 @@ typedef GenericRegexSearch<Regex> RegexSearch;
|
|
723
721
|
} // namespace internal
|
724
722
|
RAPIDJSON_NAMESPACE_END
|
725
723
|
|
726
|
-
#ifdef
|
724
|
+
#ifdef __GNUC__
|
727
725
|
RAPIDJSON_DIAG_POP
|
728
726
|
#endif
|
729
727
|
|
730
|
-
#
|
728
|
+
#if defined(__clang__) || defined(_MSC_VER)
|
731
729
|
RAPIDJSON_DIAG_POP
|
732
730
|
#endif
|
733
731
|
|
@@ -19,6 +19,8 @@
|
|
19
19
|
#include "biginteger.h"
|
20
20
|
#include "diyfp.h"
|
21
21
|
#include "pow10.h"
|
22
|
+
#include <climits>
|
23
|
+
#include <limits>
|
22
24
|
|
23
25
|
RAPIDJSON_NAMESPACE_BEGIN
|
24
26
|
namespace internal {
|
@@ -126,20 +128,20 @@ inline bool StrtodFast(double d, int p, double* result) {
|
|
126
128
|
}
|
127
129
|
|
128
130
|
// Compute an approximation and see if it is within 1/2 ULP
|
129
|
-
inline bool StrtodDiyFp(const char* decimals,
|
131
|
+
inline bool StrtodDiyFp(const char* decimals, int dLen, int dExp, double* result) {
|
130
132
|
uint64_t significand = 0;
|
131
|
-
|
132
|
-
for (; i <
|
133
|
+
int i = 0; // 2^64 - 1 = 18446744073709551615, 1844674407370955161 = 0x1999999999999999
|
134
|
+
for (; i < dLen; i++) {
|
133
135
|
if (significand > RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) ||
|
134
136
|
(significand == RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) && decimals[i] > '5'))
|
135
137
|
break;
|
136
138
|
significand = significand * 10u + static_cast<unsigned>(decimals[i] - '0');
|
137
139
|
}
|
138
140
|
|
139
|
-
if (i <
|
141
|
+
if (i < dLen && decimals[i] >= '5') // Rounding
|
140
142
|
significand++;
|
141
143
|
|
142
|
-
|
144
|
+
int remaining = dLen - i;
|
143
145
|
const int kUlpShift = 3;
|
144
146
|
const int kUlp = 1 << kUlpShift;
|
145
147
|
int64_t error = (remaining == 0) ? 0 : kUlp / 2;
|
@@ -148,24 +150,24 @@ inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosit
|
|
148
150
|
v = v.Normalize();
|
149
151
|
error <<= -v.e;
|
150
152
|
|
151
|
-
|
153
|
+
dExp += remaining;
|
152
154
|
|
153
155
|
int actualExp;
|
154
156
|
DiyFp cachedPower = GetCachedPower10(dExp, &actualExp);
|
155
157
|
if (actualExp != dExp) {
|
156
158
|
static const DiyFp kPow10[] = {
|
157
|
-
DiyFp(RAPIDJSON_UINT64_C2(0xa0000000,
|
158
|
-
DiyFp(RAPIDJSON_UINT64_C2(0xc8000000,
|
159
|
-
DiyFp(RAPIDJSON_UINT64_C2(0xfa000000,
|
160
|
-
DiyFp(RAPIDJSON_UINT64_C2(0x9c400000,
|
161
|
-
DiyFp(RAPIDJSON_UINT64_C2(0xc3500000,
|
162
|
-
DiyFp(RAPIDJSON_UINT64_C2(0xf4240000,
|
163
|
-
DiyFp(RAPIDJSON_UINT64_C2(0x98968000,
|
159
|
+
DiyFp(RAPIDJSON_UINT64_C2(0xa0000000, 0x00000000), -60), // 10^1
|
160
|
+
DiyFp(RAPIDJSON_UINT64_C2(0xc8000000, 0x00000000), -57), // 10^2
|
161
|
+
DiyFp(RAPIDJSON_UINT64_C2(0xfa000000, 0x00000000), -54), // 10^3
|
162
|
+
DiyFp(RAPIDJSON_UINT64_C2(0x9c400000, 0x00000000), -50), // 10^4
|
163
|
+
DiyFp(RAPIDJSON_UINT64_C2(0xc3500000, 0x00000000), -47), // 10^5
|
164
|
+
DiyFp(RAPIDJSON_UINT64_C2(0xf4240000, 0x00000000), -44), // 10^6
|
165
|
+
DiyFp(RAPIDJSON_UINT64_C2(0x98968000, 0x00000000), -40) // 10^7
|
164
166
|
};
|
165
|
-
int
|
166
|
-
RAPIDJSON_ASSERT(adjustment >=
|
167
|
-
v = v * kPow10[adjustment];
|
168
|
-
if (
|
167
|
+
int adjustment = dExp - actualExp;
|
168
|
+
RAPIDJSON_ASSERT(adjustment >= 1 && adjustment < 8);
|
169
|
+
v = v * kPow10[adjustment - 1];
|
170
|
+
if (dLen + adjustment > 19) // has more digits than decimal digits in 64-bit
|
169
171
|
error += kUlp / 2;
|
170
172
|
}
|
171
173
|
|
@@ -203,9 +205,9 @@ inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosit
|
|
203
205
|
return halfWay - static_cast<unsigned>(error) >= precisionBits || precisionBits >= halfWay + static_cast<unsigned>(error);
|
204
206
|
}
|
205
207
|
|
206
|
-
inline double StrtodBigInteger(double approx, const char* decimals,
|
207
|
-
|
208
|
-
const
|
208
|
+
inline double StrtodBigInteger(double approx, const char* decimals, int dLen, int dExp) {
|
209
|
+
RAPIDJSON_ASSERT(dLen >= 0);
|
210
|
+
const BigInteger dInt(decimals, static_cast<unsigned>(dLen));
|
209
211
|
Double a(approx);
|
210
212
|
int cmp = CheckWithinHalfULP(a.Value(), dInt, dExp);
|
211
213
|
if (cmp < 0)
|
@@ -225,42 +227,61 @@ inline double StrtodFullPrecision(double d, int p, const char* decimals, size_t
|
|
225
227
|
RAPIDJSON_ASSERT(d >= 0.0);
|
226
228
|
RAPIDJSON_ASSERT(length >= 1);
|
227
229
|
|
228
|
-
double result;
|
230
|
+
double result = 0.0;
|
229
231
|
if (StrtodFast(d, p, &result))
|
230
232
|
return result;
|
231
233
|
|
234
|
+
RAPIDJSON_ASSERT(length <= INT_MAX);
|
235
|
+
int dLen = static_cast<int>(length);
|
236
|
+
|
237
|
+
RAPIDJSON_ASSERT(length >= decimalPosition);
|
238
|
+
RAPIDJSON_ASSERT(length - decimalPosition <= INT_MAX);
|
239
|
+
int dExpAdjust = static_cast<int>(length - decimalPosition);
|
240
|
+
|
241
|
+
RAPIDJSON_ASSERT(exp >= INT_MIN + dExpAdjust);
|
242
|
+
int dExp = exp - dExpAdjust;
|
243
|
+
|
244
|
+
// Make sure length+dExp does not overflow
|
245
|
+
RAPIDJSON_ASSERT(dExp <= INT_MAX - dLen);
|
246
|
+
|
232
247
|
// Trim leading zeros
|
233
|
-
while (*decimals == '0'
|
234
|
-
|
248
|
+
while (dLen > 0 && *decimals == '0') {
|
249
|
+
dLen--;
|
235
250
|
decimals++;
|
236
|
-
decimalPosition--;
|
237
251
|
}
|
238
252
|
|
239
253
|
// Trim trailing zeros
|
240
|
-
while (decimals[
|
241
|
-
|
242
|
-
|
243
|
-
|
254
|
+
while (dLen > 0 && decimals[dLen - 1] == '0') {
|
255
|
+
dLen--;
|
256
|
+
dExp++;
|
257
|
+
}
|
258
|
+
|
259
|
+
if (dLen == 0) { // Buffer only contains zeros.
|
260
|
+
return 0.0;
|
244
261
|
}
|
245
262
|
|
246
263
|
// Trim right-most digits
|
247
|
-
const int kMaxDecimalDigit =
|
248
|
-
if (
|
249
|
-
|
250
|
-
|
251
|
-
decimalPosition -= static_cast<unsigned>(delta);
|
252
|
-
length = kMaxDecimalDigit;
|
264
|
+
const int kMaxDecimalDigit = 767 + 1;
|
265
|
+
if (dLen > kMaxDecimalDigit) {
|
266
|
+
dExp += dLen - kMaxDecimalDigit;
|
267
|
+
dLen = kMaxDecimalDigit;
|
253
268
|
}
|
254
269
|
|
255
|
-
// If too small, underflow to zero
|
256
|
-
|
270
|
+
// If too small, underflow to zero.
|
271
|
+
// Any x <= 10^-324 is interpreted as zero.
|
272
|
+
if (dLen + dExp <= -324)
|
257
273
|
return 0.0;
|
258
274
|
|
259
|
-
|
275
|
+
// If too large, overflow to infinity.
|
276
|
+
// Any x >= 10^309 is interpreted as +infinity.
|
277
|
+
if (dLen + dExp > 309)
|
278
|
+
return std::numeric_limits<double>::infinity();
|
279
|
+
|
280
|
+
if (StrtodDiyFp(decimals, dLen, dExp, &result))
|
260
281
|
return result;
|
261
282
|
|
262
283
|
// Use approximation from StrtodDiyFp and make adjustment with BigInteger comparison
|
263
|
-
return StrtodBigInteger(result, decimals,
|
284
|
+
return StrtodBigInteger(result, decimals, dLen, dExp);
|
264
285
|
}
|
265
286
|
|
266
287
|
} // namespace internal
|