rj_schema 1.0.0 → 1.0.1

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 (30) hide show
  1. checksums.yaml +4 -4
  2. data/ext/rj_schema/rapidjson/CMakeLists.txt +23 -1
  3. data/ext/rj_schema/rapidjson/appveyor.yml +49 -1
  4. data/ext/rj_schema/rapidjson/bin/types/alotofkeys.json +502 -0
  5. data/ext/rj_schema/rapidjson/bin/unittestschema/idandref.json +69 -0
  6. data/ext/rj_schema/rapidjson/doc/stream.md +7 -7
  7. data/ext/rj_schema/rapidjson/doc/stream.zh-cn.md +1 -1
  8. data/ext/rj_schema/rapidjson/doc/tutorial.md +15 -15
  9. data/ext/rj_schema/rapidjson/example/schemavalidator/schemavalidator.cpp +2 -0
  10. data/ext/rj_schema/rapidjson/example/traverseaspointer.cpp +39 -0
  11. data/ext/rj_schema/rapidjson/include/rapidjson/allocators.h +460 -52
  12. data/ext/rj_schema/rapidjson/include/rapidjson/document.h +350 -60
  13. data/ext/rj_schema/rapidjson/include/rapidjson/internal/strfunc.h +14 -0
  14. data/ext/rj_schema/rapidjson/include/rapidjson/pointer.h +68 -1
  15. data/ext/rj_schema/rapidjson/include/rapidjson/rapidjson.h +60 -11
  16. data/ext/rj_schema/rapidjson/include/rapidjson/schema.h +249 -102
  17. data/ext/rj_schema/rapidjson/include/rapidjson/uri.h +466 -0
  18. data/ext/rj_schema/rapidjson/test/perftest/perftest.h +5 -4
  19. data/ext/rj_schema/rapidjson/test/perftest/rapidjsontest.cpp +20 -2
  20. data/ext/rj_schema/rapidjson/test/unittest/CMakeLists.txt +2 -0
  21. data/ext/rj_schema/rapidjson/test/unittest/allocatorstest.cpp +193 -1
  22. data/ext/rj_schema/rapidjson/test/unittest/documenttest.cpp +2 -0
  23. data/ext/rj_schema/rapidjson/test/unittest/platformtest.cpp +40 -0
  24. data/ext/rj_schema/rapidjson/test/unittest/pointertest.cpp +62 -2
  25. data/ext/rj_schema/rapidjson/test/unittest/schematest.cpp +372 -7
  26. data/ext/rj_schema/rapidjson/test/unittest/uritest.cpp +718 -0
  27. data/ext/rj_schema/rapidjson/test/unittest/valuetest.cpp +12 -2
  28. data/ext/rj_schema/rj_schema.cpp +1 -1
  29. data/lib/rj_schema.rb +1 -1
  30. metadata +9 -3
@@ -42,12 +42,21 @@ RAPIDJSON_DIAG_OFF(4244) // conversion from kXxxFlags to 'uint16_t', possible lo
42
42
  RAPIDJSON_DIAG_OFF(effc++)
43
43
  #endif // __GNUC__
44
44
 
45
+ #ifdef GetObject
46
+ // see https://github.com/Tencent/rapidjson/issues/1448
47
+ // a former included windows.h might have defined a macro called GetObject, which affects
48
+ // GetObject defined here. This ensures the macro does not get applied
49
+ #pragma push_macro("GetObject")
50
+ #define RAPIDJSON_WINDOWS_GETOBJECT_WORKAROUND_APPLIED
51
+ #undef GetObject
52
+ #endif
53
+
45
54
  #ifndef RAPIDJSON_NOMEMBERITERATORCLASS
46
55
  #include <iterator> // std::random_access_iterator_tag
47
56
  #endif
48
57
 
49
- #if RAPIDJSON_HAS_CXX11_RVALUE_REFS
50
- #include <utility> // std::move
58
+ #if RAPIDJSON_USE_MEMBERSMAP
59
+ #include <map> // std::multimap
51
60
  #endif
52
61
 
53
62
  RAPIDJSON_NAMESPACE_BEGIN
@@ -732,18 +741,8 @@ public:
732
741
  template <typename SourceAllocator>
733
742
  GenericValue(const GenericValue<Encoding,SourceAllocator>& rhs, Allocator& allocator, bool copyConstStrings = false) {
734
743
  switch (rhs.GetType()) {
735
- case kObjectType: {
736
- SizeType count = rhs.data_.o.size;
737
- Member* lm = reinterpret_cast<Member*>(allocator.Malloc(count * sizeof(Member)));
738
- const typename GenericValue<Encoding,SourceAllocator>::Member* rm = rhs.GetMembersPointer();
739
- for (SizeType i = 0; i < count; i++) {
740
- new (&lm[i].name) GenericValue(rm[i].name, allocator, copyConstStrings);
741
- new (&lm[i].value) GenericValue(rm[i].value, allocator, copyConstStrings);
742
- }
743
- data_.f.flags = kObjectFlag;
744
- data_.o.size = data_.o.capacity = count;
745
- SetMembersPointer(lm);
746
- }
744
+ case kObjectType:
745
+ DoCopyMembers(rhs, allocator, copyConstStrings);
747
746
  break;
748
747
  case kArrayType: {
749
748
  SizeType count = rhs.data_.a.size;
@@ -879,25 +878,30 @@ public:
879
878
  /*! Need to destruct elements of array, members of object, or copy-string.
880
879
  */
881
880
  ~GenericValue() {
882
- if (Allocator::kNeedFree) { // Shortcut by Allocator's trait
881
+ // With RAPIDJSON_USE_MEMBERSMAP, the maps need to be destroyed to release
882
+ // their Allocator if it's refcounted (e.g. MemoryPoolAllocator).
883
+ if (Allocator::kNeedFree || (RAPIDJSON_USE_MEMBERSMAP+0 &&
884
+ internal::IsRefCounted<Allocator>::Value)) {
883
885
  switch(data_.f.flags) {
884
886
  case kArrayFlag:
885
887
  {
886
888
  GenericValue* e = GetElementsPointer();
887
889
  for (GenericValue* v = e; v != e + data_.a.size; ++v)
888
890
  v->~GenericValue();
889
- Allocator::Free(e);
891
+ if (Allocator::kNeedFree) { // Shortcut by Allocator's trait
892
+ Allocator::Free(e);
893
+ }
890
894
  }
891
895
  break;
892
896
 
893
897
  case kObjectFlag:
894
- for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m)
895
- m->~Member();
896
- Allocator::Free(GetMembersPointer());
898
+ DoFreeMembers();
897
899
  break;
898
900
 
899
901
  case kCopyStringFlag:
900
- Allocator::Free(const_cast<Ch*>(GetStringPointer()));
902
+ if (Allocator::kNeedFree) { // Shortcut by Allocator's trait
903
+ Allocator::Free(const_cast<Ch*>(GetStringPointer()));
904
+ }
901
905
  break;
902
906
 
903
907
  default:
@@ -916,8 +920,13 @@ public:
916
920
  */
917
921
  GenericValue& operator=(GenericValue& rhs) RAPIDJSON_NOEXCEPT {
918
922
  if (RAPIDJSON_LIKELY(this != &rhs)) {
923
+ // Can't destroy "this" before assigning "rhs", otherwise "rhs"
924
+ // could be used after free if it's an sub-Value of "this",
925
+ // hence the temporary danse.
926
+ GenericValue temp;
927
+ temp.RawAssign(rhs);
919
928
  this->~GenericValue();
920
- RawAssign(rhs);
929
+ RawAssign(temp);
921
930
  }
922
931
  return *this;
923
932
  }
@@ -1083,6 +1092,7 @@ public:
1083
1092
  */
1084
1093
  template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator!=(const T& rhs) const { return !(*this == rhs); }
1085
1094
 
1095
+ #ifndef __cpp_lib_three_way_comparison
1086
1096
  //! Equal-to operator with arbitrary types (symmetric version)
1087
1097
  /*! \return (rhs == lhs)
1088
1098
  */
@@ -1093,6 +1103,7 @@ public:
1093
1103
  */
1094
1104
  template <typename T> friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator!=(const T& lhs, const GenericValue& rhs) { return !(rhs == lhs); }
1095
1105
  //@}
1106
+ #endif
1096
1107
 
1097
1108
  //!@name Type
1098
1109
  //@{
@@ -1258,10 +1269,7 @@ public:
1258
1269
  */
1259
1270
  GenericValue& MemberReserve(SizeType newCapacity, Allocator &allocator) {
1260
1271
  RAPIDJSON_ASSERT(IsObject());
1261
- if (newCapacity > data_.o.capacity) {
1262
- SetMembersPointer(reinterpret_cast<Member*>(allocator.Realloc(GetMembersPointer(), data_.o.capacity * sizeof(Member), newCapacity * sizeof(Member))));
1263
- data_.o.capacity = newCapacity;
1264
- }
1272
+ DoReserveMembers(newCapacity, allocator);
1265
1273
  return *this;
1266
1274
  }
1267
1275
 
@@ -1335,11 +1343,7 @@ public:
1335
1343
  MemberIterator FindMember(const GenericValue<Encoding, SourceAllocator>& name) {
1336
1344
  RAPIDJSON_ASSERT(IsObject());
1337
1345
  RAPIDJSON_ASSERT(name.IsString());
1338
- MemberIterator member = MemberBegin();
1339
- for ( ; member != MemberEnd(); ++member)
1340
- if (name.StringEqual(member->name))
1341
- break;
1342
- return member;
1346
+ return DoFindMember(name);
1343
1347
  }
1344
1348
  template <typename SourceAllocator> ConstMemberIterator FindMember(const GenericValue<Encoding, SourceAllocator>& name) const { return const_cast<GenericValue&>(*this).FindMember(name); }
1345
1349
 
@@ -1368,14 +1372,7 @@ public:
1368
1372
  GenericValue& AddMember(GenericValue& name, GenericValue& value, Allocator& allocator) {
1369
1373
  RAPIDJSON_ASSERT(IsObject());
1370
1374
  RAPIDJSON_ASSERT(name.IsString());
1371
-
1372
- ObjectData& o = data_.o;
1373
- if (o.size >= o.capacity)
1374
- MemberReserve(o.capacity == 0 ? kDefaultObjectCapacity : (o.capacity + (o.capacity + 1) / 2), allocator);
1375
- Member* members = GetMembersPointer();
1376
- members[o.size].name.RawAssign(name);
1377
- members[o.size].value.RawAssign(value);
1378
- o.size++;
1375
+ DoAddMember(name, value, allocator);
1379
1376
  return *this;
1380
1377
  }
1381
1378
 
@@ -1509,9 +1506,7 @@ public:
1509
1506
  */
1510
1507
  void RemoveAllMembers() {
1511
1508
  RAPIDJSON_ASSERT(IsObject());
1512
- for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m)
1513
- m->~Member();
1514
- data_.o.size = 0;
1509
+ DoClearMembers();
1515
1510
  }
1516
1511
 
1517
1512
  //! Remove a member in object by its name.
@@ -1555,14 +1550,7 @@ public:
1555
1550
  RAPIDJSON_ASSERT(data_.o.size > 0);
1556
1551
  RAPIDJSON_ASSERT(GetMembersPointer() != 0);
1557
1552
  RAPIDJSON_ASSERT(m >= MemberBegin() && m < MemberEnd());
1558
-
1559
- MemberIterator last(GetMembersPointer() + (data_.o.size - 1));
1560
- if (data_.o.size > 1 && m != last)
1561
- *m = *last; // Move the last one to this place
1562
- else
1563
- m->~Member(); // Only one left, just destroy
1564
- --data_.o.size;
1565
- return m;
1553
+ return DoRemoveMember(m);
1566
1554
  }
1567
1555
 
1568
1556
  //! Remove a member from an object by iterator.
@@ -1594,13 +1582,7 @@ public:
1594
1582
  RAPIDJSON_ASSERT(first >= MemberBegin());
1595
1583
  RAPIDJSON_ASSERT(first <= last);
1596
1584
  RAPIDJSON_ASSERT(last <= MemberEnd());
1597
-
1598
- MemberIterator pos = MemberBegin() + (first - MemberBegin());
1599
- for (MemberIterator itr = pos; itr != last; ++itr)
1600
- itr->~Member();
1601
- std::memmove(static_cast<void*>(&*pos), &*last, static_cast<size_t>(MemberEnd() - last) * sizeof(Member));
1602
- data_.o.size -= static_cast<SizeType>(last - first);
1603
- return pos;
1585
+ return DoEraseMembers(first, last);
1604
1586
  }
1605
1587
 
1606
1588
  //! Erase a member in object by its name.
@@ -1629,7 +1611,9 @@ public:
1629
1611
  }
1630
1612
 
1631
1613
  Object GetObject() { RAPIDJSON_ASSERT(IsObject()); return Object(*this); }
1614
+ Object GetObj() { RAPIDJSON_ASSERT(IsObject()); return Object(*this); }
1632
1615
  ConstObject GetObject() const { RAPIDJSON_ASSERT(IsObject()); return ConstObject(*this); }
1616
+ ConstObject GetObj() const { RAPIDJSON_ASSERT(IsObject()); return ConstObject(*this); }
1633
1617
 
1634
1618
  //@}
1635
1619
 
@@ -1851,12 +1835,12 @@ public:
1851
1835
  //!@name String
1852
1836
  //@{
1853
1837
 
1854
- const Ch* GetString() const { RAPIDJSON_ASSERT(IsString()); return (data_.f.flags & kInlineStrFlag) ? data_.ss.str : GetStringPointer(); }
1838
+ const Ch* GetString() const { RAPIDJSON_ASSERT(IsString()); return DataString(data_); }
1855
1839
 
1856
1840
  //! Get the length of string.
1857
1841
  /*! Since rapidjson permits "\\u0000" in the json string, strlen(v.GetString()) may not equal to v.GetStringLength().
1858
1842
  */
1859
- SizeType GetStringLength() const { RAPIDJSON_ASSERT(IsString()); return ((data_.f.flags & kInlineStrFlag) ? (data_.ss.GetLength()) : data_.s.length); }
1843
+ SizeType GetStringLength() const { RAPIDJSON_ASSERT(IsString()); return DataStringLength(data_); }
1860
1844
 
1861
1845
  //! Set this value as a string without copying source string.
1862
1846
  /*! This version has better performance with supplied length, and also support string containing null character.
@@ -1967,7 +1951,7 @@ public:
1967
1951
  case kArrayType:
1968
1952
  if (RAPIDJSON_UNLIKELY(!handler.StartArray()))
1969
1953
  return false;
1970
- for (const GenericValue* v = Begin(); v != End(); ++v)
1954
+ for (ConstValueIterator v = Begin(); v != End(); ++v)
1971
1955
  if (RAPIDJSON_UNLIKELY(!v->Accept(handler)))
1972
1956
  return false;
1973
1957
  return handler.EndArray(data_.a.size);
@@ -2105,6 +2089,13 @@ private:
2105
2089
  Flag f;
2106
2090
  }; // 16 bytes in 32-bit mode, 24 bytes in 64-bit mode, 16 bytes in 64-bit with RAPIDJSON_48BITPOINTER_OPTIMIZATION
2107
2091
 
2092
+ static RAPIDJSON_FORCEINLINE const Ch* DataString(const Data& data) {
2093
+ return (data.f.flags & kInlineStrFlag) ? data.ss.str : RAPIDJSON_GETPOINTER(Ch, data.s.str);
2094
+ }
2095
+ static RAPIDJSON_FORCEINLINE SizeType DataStringLength(const Data& data) {
2096
+ return (data.f.flags & kInlineStrFlag) ? data.ss.GetLength() : data.s.length;
2097
+ }
2098
+
2108
2099
  RAPIDJSON_FORCEINLINE const Ch* GetStringPointer() const { return RAPIDJSON_GETPOINTER(Ch, data_.s.str); }
2109
2100
  RAPIDJSON_FORCEINLINE const Ch* SetStringPointer(const Ch* str) { return RAPIDJSON_SETPOINTER(Ch, data_.s.str, str); }
2110
2101
  RAPIDJSON_FORCEINLINE GenericValue* GetElementsPointer() const { return RAPIDJSON_GETPOINTER(GenericValue, data_.a.elements); }
@@ -2112,6 +2103,286 @@ private:
2112
2103
  RAPIDJSON_FORCEINLINE Member* GetMembersPointer() const { return RAPIDJSON_GETPOINTER(Member, data_.o.members); }
2113
2104
  RAPIDJSON_FORCEINLINE Member* SetMembersPointer(Member* members) { return RAPIDJSON_SETPOINTER(Member, data_.o.members, members); }
2114
2105
 
2106
+ #if RAPIDJSON_USE_MEMBERSMAP
2107
+
2108
+ struct MapTraits {
2109
+ struct Less {
2110
+ bool operator()(const Data& s1, const Data& s2) const {
2111
+ SizeType n1 = DataStringLength(s1), n2 = DataStringLength(s2);
2112
+ int cmp = std::memcmp(DataString(s1), DataString(s2), sizeof(Ch) * (n1 < n2 ? n1 : n2));
2113
+ return cmp < 0 || (cmp == 0 && n1 < n2);
2114
+ }
2115
+ };
2116
+ typedef std::pair<const Data, SizeType> Pair;
2117
+ typedef std::multimap<Data, SizeType, Less, StdAllocator<Pair, Allocator> > Map;
2118
+ typedef typename Map::iterator Iterator;
2119
+ };
2120
+ typedef typename MapTraits::Map Map;
2121
+ typedef typename MapTraits::Less MapLess;
2122
+ typedef typename MapTraits::Pair MapPair;
2123
+ typedef typename MapTraits::Iterator MapIterator;
2124
+
2125
+ //
2126
+ // Layout of the members' map/array, re(al)located according to the needed capacity:
2127
+ //
2128
+ // {Map*}<>{capacity}<>{Member[capacity]}<>{MapIterator[capacity]}
2129
+ //
2130
+ // (where <> stands for the RAPIDJSON_ALIGN-ment, if needed)
2131
+ //
2132
+
2133
+ static RAPIDJSON_FORCEINLINE size_t GetMapLayoutSize(SizeType capacity) {
2134
+ return RAPIDJSON_ALIGN(sizeof(Map*)) +
2135
+ RAPIDJSON_ALIGN(sizeof(SizeType)) +
2136
+ RAPIDJSON_ALIGN(capacity * sizeof(Member)) +
2137
+ capacity * sizeof(MapIterator);
2138
+ }
2139
+
2140
+ static RAPIDJSON_FORCEINLINE SizeType &GetMapCapacity(Map* &map) {
2141
+ return *reinterpret_cast<SizeType*>(reinterpret_cast<uintptr_t>(&map) +
2142
+ RAPIDJSON_ALIGN(sizeof(Map*)));
2143
+ }
2144
+
2145
+ static RAPIDJSON_FORCEINLINE Member* GetMapMembers(Map* &map) {
2146
+ return reinterpret_cast<Member*>(reinterpret_cast<uintptr_t>(&map) +
2147
+ RAPIDJSON_ALIGN(sizeof(Map*)) +
2148
+ RAPIDJSON_ALIGN(sizeof(SizeType)));
2149
+ }
2150
+
2151
+ static RAPIDJSON_FORCEINLINE MapIterator* GetMapIterators(Map* &map) {
2152
+ return reinterpret_cast<MapIterator*>(reinterpret_cast<uintptr_t>(&map) +
2153
+ RAPIDJSON_ALIGN(sizeof(Map*)) +
2154
+ RAPIDJSON_ALIGN(sizeof(SizeType)) +
2155
+ RAPIDJSON_ALIGN(GetMapCapacity(map) * sizeof(Member)));
2156
+ }
2157
+
2158
+ static RAPIDJSON_FORCEINLINE Map* &GetMap(Member* members) {
2159
+ RAPIDJSON_ASSERT(members != 0);
2160
+ return *reinterpret_cast<Map**>(reinterpret_cast<uintptr_t>(members) -
2161
+ RAPIDJSON_ALIGN(sizeof(SizeType)) -
2162
+ RAPIDJSON_ALIGN(sizeof(Map*)));
2163
+ }
2164
+
2165
+ // Some compilers' debug mechanisms want all iterators to be destroyed, for their accounting..
2166
+ RAPIDJSON_FORCEINLINE MapIterator DropMapIterator(MapIterator& rhs) {
2167
+ #if RAPIDJSON_HAS_CXX11
2168
+ MapIterator ret = std::move(rhs);
2169
+ #else
2170
+ MapIterator ret = rhs;
2171
+ #endif
2172
+ rhs.~MapIterator();
2173
+ return ret;
2174
+ }
2175
+
2176
+ Map* &DoReallocMap(Map** oldMap, SizeType newCapacity, Allocator& allocator) {
2177
+ Map **newMap = static_cast<Map**>(allocator.Malloc(GetMapLayoutSize(newCapacity)));
2178
+ GetMapCapacity(*newMap) = newCapacity;
2179
+ if (!oldMap) {
2180
+ *newMap = new (allocator.Malloc(sizeof(Map))) Map(MapLess(), allocator);
2181
+ }
2182
+ else {
2183
+ *newMap = *oldMap;
2184
+ size_t count = (*oldMap)->size();
2185
+ std::memcpy(static_cast<void*>(GetMapMembers(*newMap)),
2186
+ static_cast<void*>(GetMapMembers(*oldMap)),
2187
+ count * sizeof(Member));
2188
+ MapIterator *oldIt = GetMapIterators(*oldMap),
2189
+ *newIt = GetMapIterators(*newMap);
2190
+ while (count--) {
2191
+ new (&newIt[count]) MapIterator(DropMapIterator(oldIt[count]));
2192
+ }
2193
+ Allocator::Free(oldMap);
2194
+ }
2195
+ return *newMap;
2196
+ }
2197
+
2198
+ RAPIDJSON_FORCEINLINE Member* DoAllocMembers(SizeType capacity, Allocator& allocator) {
2199
+ return GetMapMembers(DoReallocMap(0, capacity, allocator));
2200
+ }
2201
+
2202
+ void DoReserveMembers(SizeType newCapacity, Allocator& allocator) {
2203
+ ObjectData& o = data_.o;
2204
+ if (newCapacity > o.capacity) {
2205
+ Member* oldMembers = GetMembersPointer();
2206
+ Map **oldMap = oldMembers ? &GetMap(oldMembers) : 0,
2207
+ *&newMap = DoReallocMap(oldMap, newCapacity, allocator);
2208
+ RAPIDJSON_SETPOINTER(Member, o.members, GetMapMembers(newMap));
2209
+ o.capacity = newCapacity;
2210
+ }
2211
+ }
2212
+
2213
+ template <typename SourceAllocator>
2214
+ MemberIterator DoFindMember(const GenericValue<Encoding, SourceAllocator>& name) {
2215
+ if (Member* members = GetMembersPointer()) {
2216
+ Map* &map = GetMap(members);
2217
+ MapIterator mit = map->find(reinterpret_cast<const Data&>(name.data_));
2218
+ if (mit != map->end()) {
2219
+ return MemberIterator(&members[mit->second]);
2220
+ }
2221
+ }
2222
+ return MemberEnd();
2223
+ }
2224
+
2225
+ void DoClearMembers() {
2226
+ if (Member* members = GetMembersPointer()) {
2227
+ Map* &map = GetMap(members);
2228
+ MapIterator* mit = GetMapIterators(map);
2229
+ for (SizeType i = 0; i < data_.o.size; i++) {
2230
+ map->erase(DropMapIterator(mit[i]));
2231
+ members[i].~Member();
2232
+ }
2233
+ data_.o.size = 0;
2234
+ }
2235
+ }
2236
+
2237
+ void DoFreeMembers() {
2238
+ if (Member* members = GetMembersPointer()) {
2239
+ GetMap(members)->~Map();
2240
+ for (SizeType i = 0; i < data_.o.size; i++) {
2241
+ members[i].~Member();
2242
+ }
2243
+ if (Allocator::kNeedFree) { // Shortcut by Allocator's trait
2244
+ Map** map = &GetMap(members);
2245
+ Allocator::Free(*map);
2246
+ Allocator::Free(map);
2247
+ }
2248
+ }
2249
+ }
2250
+
2251
+ #else // !RAPIDJSON_USE_MEMBERSMAP
2252
+
2253
+ RAPIDJSON_FORCEINLINE Member* DoAllocMembers(SizeType capacity, Allocator& allocator) {
2254
+ return Malloc<Member>(allocator, capacity);
2255
+ }
2256
+
2257
+ void DoReserveMembers(SizeType newCapacity, Allocator& allocator) {
2258
+ ObjectData& o = data_.o;
2259
+ if (newCapacity > o.capacity) {
2260
+ Member* newMembers = Realloc<Member>(allocator, GetMembersPointer(), o.capacity, newCapacity);
2261
+ RAPIDJSON_SETPOINTER(Member, o.members, newMembers);
2262
+ o.capacity = newCapacity;
2263
+ }
2264
+ }
2265
+
2266
+ template <typename SourceAllocator>
2267
+ MemberIterator DoFindMember(const GenericValue<Encoding, SourceAllocator>& name) {
2268
+ MemberIterator member = MemberBegin();
2269
+ for ( ; member != MemberEnd(); ++member)
2270
+ if (name.StringEqual(member->name))
2271
+ break;
2272
+ return member;
2273
+ }
2274
+
2275
+ void DoClearMembers() {
2276
+ for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m)
2277
+ m->~Member();
2278
+ data_.o.size = 0;
2279
+ }
2280
+
2281
+ void DoFreeMembers() {
2282
+ for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m)
2283
+ m->~Member();
2284
+ Allocator::Free(GetMembersPointer());
2285
+ }
2286
+
2287
+ #endif // !RAPIDJSON_USE_MEMBERSMAP
2288
+
2289
+ void DoAddMember(GenericValue& name, GenericValue& value, Allocator& allocator) {
2290
+ ObjectData& o = data_.o;
2291
+ if (o.size >= o.capacity)
2292
+ DoReserveMembers(o.capacity ? (o.capacity + (o.capacity + 1) / 2) : kDefaultObjectCapacity, allocator);
2293
+ Member* members = GetMembersPointer();
2294
+ Member* m = members + o.size;
2295
+ m->name.RawAssign(name);
2296
+ m->value.RawAssign(value);
2297
+ #if RAPIDJSON_USE_MEMBERSMAP
2298
+ Map* &map = GetMap(members);
2299
+ MapIterator* mit = GetMapIterators(map);
2300
+ new (&mit[o.size]) MapIterator(map->insert(MapPair(m->name.data_, o.size)));
2301
+ #endif
2302
+ ++o.size;
2303
+ }
2304
+
2305
+ MemberIterator DoRemoveMember(MemberIterator m) {
2306
+ ObjectData& o = data_.o;
2307
+ Member* members = GetMembersPointer();
2308
+ #if RAPIDJSON_USE_MEMBERSMAP
2309
+ Map* &map = GetMap(members);
2310
+ MapIterator* mit = GetMapIterators(map);
2311
+ SizeType mpos = static_cast<SizeType>(&*m - members);
2312
+ map->erase(DropMapIterator(mit[mpos]));
2313
+ #endif
2314
+ MemberIterator last(members + (o.size - 1));
2315
+ if (o.size > 1 && m != last) {
2316
+ #if RAPIDJSON_USE_MEMBERSMAP
2317
+ new (&mit[mpos]) MapIterator(DropMapIterator(mit[&*last - members]));
2318
+ mit[mpos]->second = mpos;
2319
+ #endif
2320
+ *m = *last; // Move the last one to this place
2321
+ }
2322
+ else {
2323
+ m->~Member(); // Only one left, just destroy
2324
+ }
2325
+ --o.size;
2326
+ return m;
2327
+ }
2328
+
2329
+ MemberIterator DoEraseMembers(ConstMemberIterator first, ConstMemberIterator last) {
2330
+ ObjectData& o = data_.o;
2331
+ MemberIterator beg = MemberBegin(),
2332
+ pos = beg + (first - beg),
2333
+ end = MemberEnd();
2334
+ #if RAPIDJSON_USE_MEMBERSMAP
2335
+ Map* &map = GetMap(GetMembersPointer());
2336
+ MapIterator* mit = GetMapIterators(map);
2337
+ #endif
2338
+ for (MemberIterator itr = pos; itr != last; ++itr) {
2339
+ #if RAPIDJSON_USE_MEMBERSMAP
2340
+ map->erase(DropMapIterator(mit[itr - beg]));
2341
+ #endif
2342
+ itr->~Member();
2343
+ }
2344
+ #if RAPIDJSON_USE_MEMBERSMAP
2345
+ if (first != last) {
2346
+ // Move remaining members/iterators
2347
+ MemberIterator next = pos + (last - first);
2348
+ for (MemberIterator itr = pos; next != end; ++itr, ++next) {
2349
+ std::memcpy(static_cast<void*>(&*itr), &*next, sizeof(Member));
2350
+ SizeType mpos = static_cast<SizeType>(itr - beg);
2351
+ new (&mit[mpos]) MapIterator(DropMapIterator(mit[next - beg]));
2352
+ mit[mpos]->second = mpos;
2353
+ }
2354
+ }
2355
+ #else
2356
+ std::memmove(static_cast<void*>(&*pos), &*last,
2357
+ static_cast<size_t>(end - last) * sizeof(Member));
2358
+ #endif
2359
+ o.size -= static_cast<SizeType>(last - first);
2360
+ return pos;
2361
+ }
2362
+
2363
+ template <typename SourceAllocator>
2364
+ void DoCopyMembers(const GenericValue<Encoding,SourceAllocator>& rhs, Allocator& allocator, bool copyConstStrings) {
2365
+ RAPIDJSON_ASSERT(rhs.GetType() == kObjectType);
2366
+
2367
+ data_.f.flags = kObjectFlag;
2368
+ SizeType count = rhs.data_.o.size;
2369
+ Member* lm = DoAllocMembers(count, allocator);
2370
+ const typename GenericValue<Encoding,SourceAllocator>::Member* rm = rhs.GetMembersPointer();
2371
+ #if RAPIDJSON_USE_MEMBERSMAP
2372
+ Map* &map = GetMap(lm);
2373
+ MapIterator* mit = GetMapIterators(map);
2374
+ #endif
2375
+ for (SizeType i = 0; i < count; i++) {
2376
+ new (&lm[i].name) GenericValue(rm[i].name, allocator, copyConstStrings);
2377
+ new (&lm[i].value) GenericValue(rm[i].value, allocator, copyConstStrings);
2378
+ #if RAPIDJSON_USE_MEMBERSMAP
2379
+ new (&mit[i]) MapIterator(map->insert(MapPair(lm[i].name.data_, i)));
2380
+ #endif
2381
+ }
2382
+ data_.o.size = data_.o.capacity = count;
2383
+ SetMembersPointer(lm);
2384
+ }
2385
+
2115
2386
  // Initialize this value as array with initial data, without calling destructor.
2116
2387
  void SetArrayRaw(GenericValue* values, SizeType count, Allocator& allocator) {
2117
2388
  data_.f.flags = kArrayFlag;
@@ -2129,9 +2400,16 @@ private:
2129
2400
  void SetObjectRaw(Member* members, SizeType count, Allocator& allocator) {
2130
2401
  data_.f.flags = kObjectFlag;
2131
2402
  if (count) {
2132
- Member* m = static_cast<Member*>(allocator.Malloc(count * sizeof(Member)));
2403
+ Member* m = DoAllocMembers(count, allocator);
2133
2404
  SetMembersPointer(m);
2134
2405
  std::memcpy(static_cast<void*>(m), members, count * sizeof(Member));
2406
+ #if RAPIDJSON_USE_MEMBERSMAP
2407
+ Map* &map = GetMap(m);
2408
+ MapIterator* mit = GetMapIterators(map);
2409
+ for (SizeType i = 0; i < count; i++) {
2410
+ new (&mit[i]) MapIterator(map->insert(MapPair(m[i].name.data_, i)));
2411
+ }
2412
+ #endif
2135
2413
  }
2136
2414
  else
2137
2415
  SetMembersPointer(0);
@@ -2252,6 +2530,13 @@ public:
2252
2530
  #endif
2253
2531
 
2254
2532
  ~GenericDocument() {
2533
+ // Clear the ::ValueType before ownAllocator is destroyed, ~ValueType()
2534
+ // runs last and may access its elements or members which would be freed
2535
+ // with an allocator like MemoryPoolAllocator (CrtAllocator does not
2536
+ // free its data when destroyed, but MemoryPoolAllocator does).
2537
+ if (ownAllocator_) {
2538
+ ValueType::SetNull();
2539
+ }
2255
2540
  Destroy();
2256
2541
  }
2257
2542
 
@@ -2734,4 +3019,9 @@ private:
2734
3019
  RAPIDJSON_NAMESPACE_END
2735
3020
  RAPIDJSON_DIAG_POP
2736
3021
 
3022
+ #ifdef RAPIDJSON_WINDOWS_GETOBJECT_WORKAROUND_APPLIED
3023
+ #pragma pop_macro("GetObject")
3024
+ #undef RAPIDJSON_WINDOWS_GETOBJECT_WORKAROUND_APPLIED
3025
+ #endif
3026
+
2737
3027
  #endif // RAPIDJSON_DOCUMENT_H_