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.
Files changed (29) hide show
  1. checksums.yaml +4 -4
  2. data/ext/rj_schema/extconf.rb +1 -1
  3. data/ext/rj_schema/rapidjson/include/rapidjson/allocators.h +14 -1
  4. data/ext/rj_schema/rapidjson/include/rapidjson/document.h +8 -20
  5. data/ext/rj_schema/rapidjson/include/rapidjson/encodings.h +29 -29
  6. data/ext/rj_schema/rapidjson/include/rapidjson/internal/biginteger.h +1 -1
  7. data/ext/rj_schema/rapidjson/include/rapidjson/internal/diyfp.h +24 -11
  8. data/ext/rj_schema/rapidjson/include/rapidjson/internal/itoa.h +1 -2
  9. data/ext/rj_schema/rapidjson/include/rapidjson/internal/meta.h +7 -2
  10. data/ext/rj_schema/rapidjson/include/rapidjson/internal/regex.h +5 -7
  11. data/ext/rj_schema/rapidjson/include/rapidjson/internal/strtod.h +59 -38
  12. data/ext/rj_schema/rapidjson/include/rapidjson/istreamwrapper.h +1 -3
  13. data/ext/rj_schema/rapidjson/include/rapidjson/pointer.h +2 -8
  14. data/ext/rj_schema/rapidjson/include/rapidjson/prettywriter.h +12 -12
  15. data/ext/rj_schema/rapidjson/include/rapidjson/rapidjson.h +15 -13
  16. data/ext/rj_schema/rapidjson/include/rapidjson/reader.h +27 -19
  17. data/ext/rj_schema/rapidjson/include/rapidjson/schema.h +15 -6
  18. data/ext/rj_schema/rapidjson/include/rapidjson/writer.h +4 -10
  19. data/ext/rj_schema/rapidjson/test/perftest/schematest.cpp +7 -0
  20. data/ext/rj_schema/rapidjson/test/unittest/allocatorstest.cpp +12 -14
  21. data/ext/rj_schema/rapidjson/test/unittest/bigintegertest.cpp +5 -0
  22. data/ext/rj_schema/rapidjson/test/unittest/istreamwrappertest.cpp +2 -2
  23. data/ext/rj_schema/rapidjson/test/unittest/prettywritertest.cpp +29 -0
  24. data/ext/rj_schema/rapidjson/test/unittest/readertest.cpp +303 -8
  25. data/ext/rj_schema/rapidjson/test/unittest/schematest.cpp +36 -2
  26. data/ext/rj_schema/rapidjson/test/unittest/simdtest.cpp +2 -2
  27. data/ext/rj_schema/rj_schema.cpp +46 -26
  28. data/lib/rj_schema.rb +1 -1
  29. metadata +3 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: db6d63465e54f3312ccd40d2c977010837c56752ff9f69cec195e16c2e649e84
4
- data.tar.gz: 26f7ecbf9a6db0a996e0ea957170ac61f167a56f26569efa449e93516093fdc8
3
+ metadata.gz: 15a16238549524a1c7a9216107cd2125b0c4522c4df9a9fd7b32c94dcd9e776c
4
+ data.tar.gz: 688384742d09e5b50c171a91b20dd79a89ac04f0401a45a1de8bca0ed5547f07
5
5
  SHA512:
6
- metadata.gz: 13950dad02f406b7ab9393b49b671da97f496857f8636a7117742eed6ca40bbb24eba7c23e51cce143e228814808abb3f9b98ba79140d5463217b3c61bc681a6
7
- data.tar.gz: a5f68291b62e4ff4c40ea9d099f556ebf1ca390ed1b1ed095330436debd7cf9a4d2bfdc75f3113287ec8eb78d5732d31593b30d08256b7afcc9989b33fe25230
6
+ metadata.gz: 7263af5b39b00efddf0b6374cfabe5fb7c685dee7284cab5ef9ac49984e2844eed76a5d45b5d78740bd02ee984726058e7783ad31d49e4292b78d03eab46c56c
7
+ data.tar.gz: e46e876e00373491a8e817bb291029aae672427fa7b5a87ebc5a4a1d84f527acca6e28b589d569e8294d362e770b6113c289fe03aee081f60c61991a4cca0fa8
@@ -1,6 +1,6 @@
1
1
  require 'mkmf'
2
2
  $INCFLAGS << " -I$(srcdir)/rapidjson/include"
3
- $CXXFLAGS << " -std=c++11 "
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 = 64 * 1024; //!< Default chunk capacity.
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
- RAPIDJSON_DIAG_PUSH
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
- RAPIDJSON_DIAG_PUSH
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
- #ifdef _MSC_VER
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 COPY() c = is.Take(); *codepoint = (*codepoint << 6) | (static_cast<unsigned char>(c) & 0x3Fu)
148
- #define TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0)
149
- #define TAIL() COPY(); TRANS(0x70)
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: TAIL(); return result;
165
- case 3: TAIL(); TAIL(); return result;
166
- case 4: COPY(); TRANS(0x50); TAIL(); return result;
167
- case 5: COPY(); TRANS(0x10); TAIL(); TAIL(); return result;
168
- case 6: TAIL(); TAIL(); TAIL(); return result;
169
- case 10: COPY(); TRANS(0x20); TAIL(); return result;
170
- case 11: COPY(); TRANS(0x60); TAIL(); TAIL(); return result;
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 COPY
174
- #undef TRANS
175
- #undef TAIL
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 COPY() os.Put(c = is.Take())
181
- #define TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0)
182
- #define TAIL() COPY(); TRANS(0x70)
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
- COPY();
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: TAIL(); return result;
191
- case 3: TAIL(); TAIL(); return result;
192
- case 4: COPY(); TRANS(0x50); TAIL(); return result;
193
- case 5: COPY(); TRANS(0x10); TAIL(); TAIL(); return result;
194
- case 6: TAIL(); TAIL(); TAIL(); return result;
195
- case 10: COPY(); TRANS(0x20); TAIL(); return result;
196
- case 11: COPY(); TRANS(0x60); TAIL(); TAIL(); return result;
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 COPY
200
- #undef TRANS
201
- #undef TAIL
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(&digits_[count_ - 1 + offset], &digits_[count_ - 1], count_ * sizeof(Type));
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
- const uint64_t be = (e == kDpDenormalExponent && (f & kDpHiddenBit) == 0) ? 0 :
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
- unsigned index = (static_cast<unsigned>(exp) + 348u) / 8u;
242
- *outExp = -348 + static_cast<int>(index) * 8;
243
- return GetCachedPowerByIndex(index);
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
- #if defined(_MSC_VER)
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(__GNUC__) || defined(_MSC_VER)
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 __clang__
724
+ #ifdef __GNUC__
727
725
  RAPIDJSON_DIAG_POP
728
726
  #endif
729
727
 
730
- #ifdef _MSC_VER
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, size_t length, size_t decimalPosition, int exp, double* result) {
131
+ inline bool StrtodDiyFp(const char* decimals, int dLen, int dExp, double* result) {
130
132
  uint64_t significand = 0;
131
- size_t i = 0; // 2^64 - 1 = 18446744073709551615, 1844674407370955161 = 0x1999999999999999
132
- for (; i < length; 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 < length && decimals[i] >= '5') // Rounding
141
+ if (i < dLen && decimals[i] >= '5') // Rounding
140
142
  significand++;
141
143
 
142
- size_t remaining = length - i;
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
- const int dExp = static_cast<int>(decimalPosition) - static_cast<int>(i) + exp;
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, 00000000), -60), // 10^1
158
- DiyFp(RAPIDJSON_UINT64_C2(0xc8000000, 00000000), -57), // 10^2
159
- DiyFp(RAPIDJSON_UINT64_C2(0xfa000000, 00000000), -54), // 10^3
160
- DiyFp(RAPIDJSON_UINT64_C2(0x9c400000, 00000000), -50), // 10^4
161
- DiyFp(RAPIDJSON_UINT64_C2(0xc3500000, 00000000), -47), // 10^5
162
- DiyFp(RAPIDJSON_UINT64_C2(0xf4240000, 00000000), -44), // 10^6
163
- DiyFp(RAPIDJSON_UINT64_C2(0x98968000, 00000000), -40) // 10^7
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 adjustment = dExp - actualExp - 1;
166
- RAPIDJSON_ASSERT(adjustment >= 0 && adjustment < 7);
167
- v = v * kPow10[adjustment];
168
- if (length + static_cast<unsigned>(adjustment)> 19u) // has more digits than decimal digits in 64-bit
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, size_t length, size_t decimalPosition, int exp) {
207
- const BigInteger dInt(decimals, length);
208
- const int dExp = static_cast<int>(decimalPosition) - static_cast<int>(length) + exp;
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' && length > 1) {
234
- length--;
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[length - 1] == '0' && length > 1) {
241
- length--;
242
- decimalPosition--;
243
- exp++;
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 = 780;
248
- if (static_cast<int>(length) > kMaxDecimalDigit) {
249
- int delta = (static_cast<int>(length) - kMaxDecimalDigit);
250
- exp += delta;
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
- if (int(length) + exp < -324)
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
- if (StrtodDiyFp(decimals, length, decimalPosition, exp, &result))
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, length, decimalPosition, exp);
284
+ return StrtodBigInteger(result, decimals, dLen, dExp);
264
285
  }
265
286
 
266
287
  } // namespace internal