rj_schema 0.1.4 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|