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.
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