Coverage Report

Created: 2025-08-24 06:53

/src/jsoncons/include/jsoncons/json_object.hpp
Line
Count
Source (jump to first uncovered line)
1
// Copyright 2013-2025 Daniel Parker
2
// Distributed under the Boost license, Version 1.0.
3
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
4
5
// See https://github.com/danielaparker/jsoncons for latest version
6
7
#ifndef JSONCONS_JSON_OBJECT_HPP
8
#define JSONCONS_JSON_OBJECT_HPP
9
10
#include <algorithm> // std::sort, std::stable_sort, std::lower_bound, std::unique
11
#include <cassert> // assert
12
#include <cstring>
13
#include <initializer_list>
14
#include <iterator> // std::iterator_traits
15
#include <memory> // std::allocator
16
#include <string>
17
#include <tuple>
18
#include <type_traits> // std::enable_if
19
#include <unordered_set>
20
#include <utility>
21
#include <utility> // std::move
22
#include <vector>
23
24
#include <jsoncons/config/compiler_support.hpp>
25
#include <jsoncons/allocator_holder.hpp>
26
#include <jsoncons/json_array.hpp>
27
#include <jsoncons/json_exception.hpp>
28
29
namespace jsoncons {
30
31
    template <typename Json>
32
    struct index_key_value
33
    {
34
        using key_type = typename Json::key_type;
35
        using allocator_type = typename Json::allocator_type;
36
37
        key_type name;
38
        int64_t index;
39
        Json value;
40
41
        template <typename... Args>
42
        index_key_value(key_type&& Name, int64_t Index, Args&& ... args) 
43
23.2M
            : name(std::move(Name)), index(Index), value(std::forward<Args>(args)...)
44
23.2M
        {
45
23.2M
        }
jsoncons::index_key_value<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > >::index_key_value<jsoncons::json_object_arg_t const&, jsoncons::semantic_tag&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&, long, jsoncons::json_object_arg_t const&, jsoncons::semantic_tag&)
Line
Count
Source
43
61.1k
            : name(std::move(Name)), index(Index), value(std::forward<Args>(args)...)
44
61.1k
        {
45
61.1k
        }
jsoncons::index_key_value<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > >::index_key_value<jsoncons::json_array_arg_t const&, jsoncons::semantic_tag&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&, long, jsoncons::json_array_arg_t const&, jsoncons::semantic_tag&)
Line
Count
Source
43
48.3k
            : name(std::move(Name)), index(Index), value(std::forward<Args>(args)...)
44
48.3k
        {
45
48.3k
        }
jsoncons::index_key_value<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > >::index_key_value<jsoncons::null_type, jsoncons::semantic_tag&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&, long, jsoncons::null_type&&, jsoncons::semantic_tag&)
Line
Count
Source
43
22.3M
            : name(std::move(Name)), index(Index), value(std::forward<Args>(args)...)
44
22.3M
        {
45
22.3M
        }
jsoncons::index_key_value<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > >::index_key_value<bool&, jsoncons::semantic_tag&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&, long, bool&, jsoncons::semantic_tag&)
Line
Count
Source
43
151k
            : name(std::move(Name)), index(Index), value(std::forward<Args>(args)...)
44
151k
        {
45
151k
        }
jsoncons::index_key_value<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > >::index_key_value<std::__1::basic_string_view<char, std::__1::char_traits<char> > const&, jsoncons::semantic_tag&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&, long, std::__1::basic_string_view<char, std::__1::char_traits<char> > const&, jsoncons::semantic_tag&)
Line
Count
Source
43
232k
            : name(std::move(Name)), index(Index), value(std::forward<Args>(args)...)
44
232k
        {
45
232k
        }
Unexecuted instantiation: jsoncons::index_key_value<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > >::index_key_value<jsoncons::byte_string_arg_t const&, jsoncons::byte_string_view const&, jsoncons::semantic_tag&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&, long, jsoncons::byte_string_arg_t const&, jsoncons::byte_string_view const&, jsoncons::semantic_tag&)
jsoncons::index_key_value<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > >::index_key_value<jsoncons::byte_string_arg_t const&, jsoncons::byte_string_view const&, unsigned long&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&, long, jsoncons::byte_string_arg_t const&, jsoncons::byte_string_view const&, unsigned long&)
Line
Count
Source
43
23.6k
            : name(std::move(Name)), index(Index), value(std::forward<Args>(args)...)
44
23.6k
        {
45
23.6k
        }
jsoncons::index_key_value<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > >::index_key_value<unsigned long&, jsoncons::semantic_tag&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&, long, unsigned long&, jsoncons::semantic_tag&)
Line
Count
Source
43
30.1k
            : name(std::move(Name)), index(Index), value(std::forward<Args>(args)...)
44
30.1k
        {
45
30.1k
        }
jsoncons::index_key_value<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > >::index_key_value<long&, jsoncons::semantic_tag&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&, long, long&, jsoncons::semantic_tag&)
Line
Count
Source
43
282k
            : name(std::move(Name)), index(Index), value(std::forward<Args>(args)...)
44
282k
        {
45
282k
        }
Unexecuted instantiation: jsoncons::index_key_value<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > >::index_key_value<jsoncons::half_arg_t const&, unsigned short&, jsoncons::semantic_tag&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&, long, jsoncons::half_arg_t const&, unsigned short&, jsoncons::semantic_tag&)
jsoncons::index_key_value<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > >::index_key_value<double&, jsoncons::semantic_tag&>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&, long, double&, jsoncons::semantic_tag&)
Line
Count
Source
43
47.7k
            : name(std::move(Name)), index(Index), value(std::forward<Args>(args)...)
44
47.7k
        {
45
47.7k
        }
46
47
        index_key_value() = default;
48
        index_key_value(const index_key_value&) = default;
49
55.0M
        index_key_value(index_key_value&&) = default;
50
        index_key_value(const index_key_value& other, const allocator_type& alloc) 
51
            : name(other.name, alloc), index(0), value(other.value, alloc) 
52
        {
53
        }
54
        index_key_value(index_key_value&& other, const allocator_type& alloc)
55
            : name(std::move(other.name), alloc), index(0), value(std::move(other.value), alloc) 
56
        {
57
58
        }
59
        index_key_value& operator=(const index_key_value&) = default;
60
33.5M
        index_key_value& operator=(index_key_value&&) = default;
61
    };
62
63
    struct sorted_unique_range_tag
64
    {
65
        explicit sorted_unique_range_tag() = default; 
66
    };
67
68
    // key_value
69
70
    template <typename KeyT,typename ValueT>
71
    class key_value
72
    {
73
    public:
74
        using key_type = KeyT;
75
        using value_type = ValueT;
76
        using string_view_type = typename value_type::string_view_type;
77
        using allocator_type = typename ValueT::allocator_type;
78
    private:
79
80
        key_type key_;
81
        value_type value_;
82
    public:
83
84
        key_value() noexcept
85
        {
86
        }
87
88
        template <typename... Args>
89
        key_value(key_type&& name,  Args&& ... args) 
90
37.5k
            : key_(std::move(name)), value_(std::forward<Args>(args)...)
91
37.5k
        {
92
37.5k
        }
93
        key_value(const key_value& member)
94
            : key_(member.key_), value_(member.value_)
95
        {
96
        }
97
98
        key_value(const key_value& member, const allocator_type& alloc)
99
            : key_(member.key_, alloc), value_(member.value_, alloc)
100
        {
101
        }
102
103
        key_value(key_value&& member) noexcept
104
0
            : key_(std::move(member.key_)), value_(std::move(member.value_))
105
0
        {
106
0
        }
107
108
        key_value(key_value&& member, const allocator_type& alloc) noexcept
109
            : key_(std::move(member.key_), alloc), value_(std::move(member.value_), alloc)
110
        {
111
        }
112
113
        const key_type& key() const
114
        {
115
            return key_;
116
        }
117
118
        value_type& value()
119
54.5k
        {
120
54.5k
            return value_;
121
54.5k
        }
jsoncons::key_value<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > >::value()
Line
Count
Source
119
54.5k
        {
120
54.5k
            return value_;
121
54.5k
        }
Unexecuted instantiation: jsoncons::key_value<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >, jsoncons::basic_json<wchar_t, jsoncons::sorted_policy, std::__1::allocator<char> > >::value()
Unexecuted instantiation: jsoncons::key_value<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, jsoncons::basic_json<char, jsoncons::order_preserving_policy, std::__1::allocator<char> > >::value()
Unexecuted instantiation: jsoncons::key_value<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >, jsoncons::basic_json<wchar_t, jsoncons::order_preserving_policy, std::__1::allocator<char> > >::value()
122
123
        const value_type& value() const
124
        {
125
            return value_;
126
        }
127
128
        template <typename T>
129
        void value(T&& newValue)
130
        {
131
            value_ = std::forward<T>(newValue);
132
        }
133
134
        void swap(key_value& member) noexcept
135
        {
136
            key_.swap(member.key_);
137
            value_.swap(member.value_);
138
        }
139
140
        key_value& operator=(const key_value& member)
141
        {
142
            if (this != & member)
143
            {
144
                key_ = member.key_;
145
                value_ = member.value_;
146
            }
147
            return *this;
148
        }
149
150
        key_value& operator=(key_value&& member) noexcept
151
        {
152
            if (this != &member)
153
            {
154
                key_.swap(member.key_);
155
                value_.swap(member.value_);
156
            }
157
            return *this;
158
        }
159
160
        void shrink_to_fit() 
161
        {
162
            key_.shrink_to_fit();
163
            value_.shrink_to_fit();
164
        }
165
166
        friend bool operator==(const key_value& lhs, const key_value& rhs) noexcept
167
        {
168
            return lhs.key_ == rhs.key_ && lhs.value_ == rhs.value_;
169
        }
170
171
        friend bool operator!=(const key_value& lhs, const key_value& rhs) noexcept
172
        {
173
            return !(lhs == rhs);
174
        }
175
176
        friend bool operator<(const key_value& lhs, const key_value& rhs) noexcept
177
        {
178
            if (lhs.key_ < rhs.key_)
179
            {
180
                return true;
181
            }
182
            if (lhs.key_ == rhs.key_ && lhs.value_ < rhs.value_)
183
            {
184
                return true;
185
            }
186
            return false;
187
        }
188
189
        friend bool operator<=(const key_value& lhs, const key_value& rhs) noexcept
190
        {
191
            return !(rhs < lhs);
192
        }
193
194
        friend bool operator>(const key_value& lhs, const key_value& rhs) noexcept
195
        {
196
            return !(lhs <= rhs);
197
        }
198
199
        friend bool operator>=(const key_value& lhs, const key_value& rhs) noexcept
200
        {
201
            return !(lhs < rhs);
202
        }
203
204
        friend void swap(key_value& a, key_value& b) noexcept(
205
            noexcept(std::declval<key_value&>().swap(std::declval<key_value&>()))) 
206
        {
207
            a.swap(b);
208
        }
209
    };
210
211
    // Structured Bindings Support
212
    // See https://blog.tartanllama.xyz/structured-bindings/
213
    template<std::size_t N,typename Key,typename Value,typename std::enable_if<N == 0, int>::type = 0>
214
    auto get(const key_value<Key,Value>& i) -> decltype(i.key())
215
    {
216
        return i.key();
217
    }
218
    // Structured Bindings Support
219
    // See https://blog.tartanllama.xyz/structured-bindings/
220
    template<std::size_t N,typename Key,typename Value,typename std::enable_if<N == 1, int>::type = 0>
221
    auto get(const key_value<Key,Value>& i) -> decltype(i.value())
222
    {
223
        return i.value();
224
    }
225
226
} // namespace jsoncons
227
228
namespace std
229
{
230
#if defined(__clang__)
231
    // Fix: https://github.com/nlohmann/json/issues/1401
232
    #pragma clang diagnostic push
233
    #pragma clang diagnostic ignored "-Wmismatched-tags"
234
#endif
235
236
    template <typename Key,typename Value>
237
    struct tuple_size<jsoncons::key_value<Key,Value>>
238
        : public std::integral_constant<std::size_t, 2> {};
239
240
    template <typename Key,typename Value> struct tuple_element<0, jsoncons::key_value<Key,Value>> { using type = Key; };
241
    template <typename Key,typename Value> struct tuple_element<1, jsoncons::key_value<Key,Value>> { using type = Value; };
242
243
#if defined(__clang__)
244
    #pragma clang diagnostic pop
245
#endif
246
247
}  // namespace std
248
249
namespace jsoncons {
250
251
    template <typename KeyT,typename ValueT>
252
    struct get_key_value
253
    {
254
        using key_value_type = key_value<KeyT,ValueT>;
255
256
        template <typename T1,typename T2>
257
        key_value_type operator()(const std::pair<T1,T2>& p) // Remove
258
        {
259
            return key_value_type(p.first,p.second);
260
        }
261
        template <typename T1,typename T2>
262
        key_value_type operator()(std::pair<T1,T2>&& p)
263
        {
264
            return key_value_type(std::forward<T1>(p.first),std::forward<T2>(p.second));
265
        }
266
        template <typename T1,typename T2>
267
        const key_value_type& operator()(const key_value<T1,T2>& p)
268
        {
269
            return p;
270
        }
271
        template <typename T1,typename T2>
272
        key_value_type operator()(key_value<T1,T2>&& p)
273
        {
274
            return std::move(p);
275
        }
276
    };
277
278
    struct sort_key_order
279
    {
280
        explicit sort_key_order() = default; 
281
    };
282
283
    struct preserve_key_order
284
    {
285
        explicit preserve_key_order() = default; 
286
    };
287
288
289
    // Sort keys
290
    template <typename KeyT,typename Json,template <typename,typename> class SequenceContainer = std::vector>
291
    class sorted_json_object : public allocator_holder<typename Json::allocator_type>    
292
    {
293
    public:
294
        using allocator_type = typename Json::allocator_type;
295
        using key_type = KeyT;
296
        using key_value_type = key_value<KeyT,Json>;
297
        using char_type = typename Json::char_type;
298
        using string_view_type = typename Json::string_view_type;
299
    private:
300
        struct Comp
301
        {
302
            bool operator() (const key_value_type& kv, string_view_type k) const { return kv.key() < k; }
303
            bool operator() (string_view_type k, const key_value_type& kv) const { return k < kv.key(); }
304
        };
305
306
        using key_value_allocator_type = typename std::allocator_traits<allocator_type>:: template rebind_alloc<key_value_type>;
307
        using key_value_container_type = SequenceContainer<key_value_type,key_value_allocator_type>;
308
309
        key_value_container_type members_;
310
    public:
311
        using iterator = typename key_value_container_type::iterator;
312
        using const_iterator = typename key_value_container_type::const_iterator;
313
314
        using allocator_holder<allocator_type>::get_allocator;
315
316
        sorted_json_object()
317
61.1k
        {
318
61.1k
        }
319
320
        explicit sorted_json_object(const allocator_type& alloc)
321
            : allocator_holder<allocator_type>(alloc), 
322
              members_(key_value_allocator_type(alloc))
323
        {
324
        }
325
326
        sorted_json_object(const sorted_json_object& other)
327
            : allocator_holder<allocator_type>(other.get_allocator()),
328
              members_(other.members_)
329
        {
330
        }
331
332
        sorted_json_object(const sorted_json_object& other, const allocator_type& alloc) 
333
            : allocator_holder<allocator_type>(alloc), 
334
              members_(other.members_,key_value_allocator_type(alloc))
335
        {
336
        }
337
338
        sorted_json_object(sorted_json_object&& other) noexcept
339
            : allocator_holder<allocator_type>(other.get_allocator()), 
340
              members_(std::move(other.members_))
341
        {
342
        }
343
344
        sorted_json_object(sorted_json_object&& other,const allocator_type& alloc) 
345
            : allocator_holder<allocator_type>(alloc), members_(std::move(other.members_),key_value_allocator_type(alloc))
346
        {
347
        }
348
349
        sorted_json_object& operator=(const sorted_json_object& other)
350
        {
351
            members_ = other.members_;
352
            return *this;
353
        }
354
355
        sorted_json_object& operator=(sorted_json_object&& other) noexcept
356
        {
357
            other.swap(*this);
358
            return *this;
359
        }
360
361
        template <typename InputIt>
362
        sorted_json_object(InputIt first, InputIt last)
363
        {
364
            std::size_t count = std::distance(first,last);
365
            members_.reserve(count);
366
            for (auto it = first; it != last; ++it)
367
            {
368
                members_.emplace_back(key_type((*it).first,get_allocator()), (*it).second);
369
            }
370
            std::stable_sort(members_.begin(),members_.end(),
371
                             [](const key_value_type& a, const key_value_type& b) -> bool {return a.key().compare(b.key()) < 0;});
372
            auto last2 = std::unique(members_.begin(), members_.end(),
373
                                  [](const key_value_type& a, const key_value_type& b) -> bool { return !(a.key().compare(b.key()));});
374
            members_.erase(last2, members_.end());
375
        }
376
377
        template <typename InputIt>
378
        sorted_json_object(InputIt first, InputIt last, 
379
                    const allocator_type& alloc)
380
            : allocator_holder<allocator_type>(alloc), 
381
              members_(key_value_allocator_type(alloc))
382
        {
383
            std::size_t count = std::distance(first,last);
384
            members_.reserve(count);
385
            for (auto it = first; it != last; ++it)
386
            {
387
                members_.emplace_back(key_type((*it).first.c_str(), (*it).first.size(), get_allocator()), (*it).second);
388
            }
389
            std::stable_sort(members_.begin(), members_.end(),
390
                             [](const key_value_type& a, const key_value_type& b) -> bool {return a.key().compare(b.key()) < 0;});
391
            auto last2 = std::unique(members_.begin(), members_.end(),
392
                                  [](const key_value_type& a, const key_value_type& b) -> bool { return !(a.key().compare(b.key()));});
393
            members_.erase(last2, members_.end());
394
        }
395
396
        sorted_json_object(const std::initializer_list<std::pair<std::basic_string<char_type>,Json>>& init, 
397
                    const allocator_type& alloc = allocator_type())
398
            : allocator_holder<allocator_type>(alloc), 
399
              members_(key_value_allocator_type(alloc))
400
        {
401
            members_.reserve(init.size());
402
            for (auto& item : init)
403
            {
404
                insert_or_assign(item.first, item.second);
405
            }
406
        }
407
408
        ~sorted_json_object() noexcept
409
61.1k
        {
410
61.1k
            flatten_and_destroy();
411
61.1k
        }
412
413
        bool empty() const
414
3.61k
        {
415
3.61k
            return members_.empty();
416
3.61k
        }
jsoncons::sorted_json_object<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> >, std::__1::vector>::empty() const
Line
Count
Source
414
3.61k
        {
415
3.61k
            return members_.empty();
416
3.61k
        }
Unexecuted instantiation: jsoncons::sorted_json_object<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >, jsoncons::basic_json<wchar_t, jsoncons::sorted_policy, std::__1::allocator<char> >, std::__1::vector>::empty() const
417
418
        void swap(sorted_json_object& other) noexcept
419
        {
420
            members_.swap(other.members_);
421
        }
422
423
        iterator begin()
424
3.65k
        {
425
3.65k
            return members_.begin();
426
3.65k
        }
jsoncons::sorted_json_object<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> >, std::__1::vector>::begin()
Line
Count
Source
424
3.65k
        {
425
3.65k
            return members_.begin();
426
3.65k
        }
Unexecuted instantiation: jsoncons::sorted_json_object<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >, jsoncons::basic_json<wchar_t, jsoncons::sorted_policy, std::__1::allocator<char> >, std::__1::vector>::begin()
427
428
        iterator end()
429
3.65k
        {
430
3.65k
            return members_.end();
431
3.65k
        }
jsoncons::sorted_json_object<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> >, std::__1::vector>::end()
Line
Count
Source
429
3.65k
        {
430
3.65k
            return members_.end();
431
3.65k
        }
Unexecuted instantiation: jsoncons::sorted_json_object<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >, jsoncons::basic_json<wchar_t, jsoncons::sorted_policy, std::__1::allocator<char> >, std::__1::vector>::end()
432
433
        const_iterator begin() const
434
        {
435
            return members_.begin();
436
        }
437
438
        const_iterator end() const
439
        {
440
            return members_.end();
441
        }
442
443
        std::size_t size() const {return members_.size();}
444
445
        std::size_t capacity() const {return members_.capacity();}
446
447
3.65k
        void clear() {members_.clear();}
jsoncons::sorted_json_object<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> >, std::__1::vector>::clear()
Line
Count
Source
447
3.65k
        void clear() {members_.clear();}
Unexecuted instantiation: jsoncons::sorted_json_object<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >, jsoncons::basic_json<wchar_t, jsoncons::sorted_policy, std::__1::allocator<char> >, std::__1::vector>::clear()
448
449
        void shrink_to_fit() 
450
        {
451
            for (std::size_t i = 0; i < members_.size(); ++i)
452
            {
453
                members_[i].shrink_to_fit();
454
            }
455
            members_.shrink_to_fit();
456
        }
457
458
0
        void reserve(std::size_t n) {members_.reserve(n);}
Unexecuted instantiation: jsoncons::sorted_json_object<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> >, std::__1::vector>::reserve(unsigned long)
Unexecuted instantiation: jsoncons::sorted_json_object<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >, jsoncons::basic_json<wchar_t, jsoncons::sorted_policy, std::__1::allocator<char> >, std::__1::vector>::reserve(unsigned long)
459
460
        Json& at(std::size_t i) 
461
        {
462
            if (i >= members_.size())
463
            {
464
                JSONCONS_THROW(json_runtime_error<std::out_of_range>("Invalid array subscript"));
465
            }
466
            return members_[i].value();
467
        }
468
469
        const Json& at(std::size_t i) const 
470
        {
471
            if (i >= members_.size())
472
            {
473
                JSONCONS_THROW(json_runtime_error<std::out_of_range>("Invalid array subscript"));
474
            }
475
            return members_[i].value();
476
        }
477
478
        iterator find(const string_view_type& name) noexcept
479
        {
480
            auto p = std::equal_range(members_.begin(),members_.end(), name, 
481
                                       Comp());        
482
            return p.first == p.second ? members_.end() : p.first;
483
        }
484
485
        const_iterator find(const string_view_type& name) const noexcept
486
        {
487
            auto p = std::equal_range(members_.begin(),members_.end(), name, 
488
                                       Comp());        
489
            return p.first == p.second ? members_.end() : p.first;
490
        }
491
492
        iterator erase(const_iterator pos) 
493
        {
494
            return members_.erase(pos);
495
        }
496
497
        iterator erase(const_iterator first, const_iterator last) 
498
        {
499
            return members_.erase(first,last);
500
        }
501
502
        void erase(const string_view_type& name) 
503
        {
504
            auto it = find(name);
505
            if (it != members_.end())
506
            {
507
                members_.erase(it);
508
            }
509
        }
510
511
        static bool compare(const index_key_value<Json>& item1, const index_key_value<Json>& item2)
512
158M
        {
513
158M
            int comp = item1.name.compare(item2.name); 
514
158M
            if (comp < 0) return true;
515
157M
            if (comp == 0) return item1.index < item2.index;
516
517
209k
            return false;
518
157M
        }
jsoncons::sorted_json_object<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> >, std::__1::vector>::compare(jsoncons::index_key_value<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > > const&, jsoncons::index_key_value<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > > const&)
Line
Count
Source
512
158M
        {
513
158M
            int comp = item1.name.compare(item2.name); 
514
158M
            if (comp < 0) return true;
515
157M
            if (comp == 0) return item1.index < item2.index;
516
517
209k
            return false;
518
157M
        }
Unexecuted instantiation: jsoncons::sorted_json_object<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >, jsoncons::basic_json<wchar_t, jsoncons::sorted_policy, std::__1::allocator<char> >, std::__1::vector>::compare(jsoncons::index_key_value<jsoncons::basic_json<wchar_t, jsoncons::sorted_policy, std::__1::allocator<char> > > const&, jsoncons::index_key_value<jsoncons::basic_json<wchar_t, jsoncons::sorted_policy, std::__1::allocator<char> > > const&)
519
520
        void uninitialized_init(index_key_value<Json>* items, std::size_t count)
521
12.5k
        {
522
12.5k
            if (count > 0)
523
12.5k
            {
524
12.5k
                members_.reserve(count);
525
526
12.5k
                std::sort(items, items+count, compare);
527
12.5k
                members_.emplace_back(key_type(items[0].name.data(), items[0].name.size(), get_allocator()), std::move(items[0].value));
528
                
529
6.70M
                for (std::size_t i = 1; i < count; ++i)
530
6.68M
                {
531
6.68M
                    auto& item = items[i];
532
6.68M
                    if (item.name != items[i-1].name)
533
25.0k
                    {
534
25.0k
                        members_.emplace_back(key_type(item.name.data(), item.name.size(), get_allocator()), std::move(item.value));
535
25.0k
                    }
536
6.68M
                }
537
12.5k
            }
538
12.5k
        }
jsoncons::sorted_json_object<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> >, std::__1::vector>::uninitialized_init(jsoncons::index_key_value<jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> > >*, unsigned long)
Line
Count
Source
521
12.5k
        {
522
12.5k
            if (count > 0)
523
12.5k
            {
524
12.5k
                members_.reserve(count);
525
526
12.5k
                std::sort(items, items+count, compare);
527
12.5k
                members_.emplace_back(key_type(items[0].name.data(), items[0].name.size(), get_allocator()), std::move(items[0].value));
528
                
529
6.70M
                for (std::size_t i = 1; i < count; ++i)
530
6.68M
                {
531
6.68M
                    auto& item = items[i];
532
6.68M
                    if (item.name != items[i-1].name)
533
25.0k
                    {
534
25.0k
                        members_.emplace_back(key_type(item.name.data(), item.name.size(), get_allocator()), std::move(item.value));
535
25.0k
                    }
536
6.68M
                }
537
12.5k
            }
538
12.5k
        }
Unexecuted instantiation: jsoncons::sorted_json_object<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >, jsoncons::basic_json<wchar_t, jsoncons::sorted_policy, std::__1::allocator<char> >, std::__1::vector>::uninitialized_init(jsoncons::index_key_value<jsoncons::basic_json<wchar_t, jsoncons::sorted_policy, std::__1::allocator<char> > >*, unsigned long)
539
540
        template <typename InputIt>
541
        void insert(InputIt first, InputIt last)
542
        {
543
            for (auto it = first; it != last; ++it)
544
            {
545
                members_.emplace_back(key_type((*it).first.c_str(), (*it).first.size(), get_allocator()), (*it).second);
546
            }
547
            std::stable_sort(members_.begin(),members_.end(),
548
                             [](const key_value_type& a, const key_value_type& b) -> bool {return a.key().compare(b.key()) < 0;});
549
            auto last2 = std::unique(members_.begin(), members_.end(),
550
                                  [](const key_value_type& a, const key_value_type& b) -> bool { return !(a.key().compare(b.key()));});
551
            members_.erase(last2, members_.end());
552
        }
553
554
        template <typename InputIt>
555
        void insert(sorted_unique_range_tag, InputIt first, InputIt last)
556
        {
557
            if (first != last)
558
            {
559
                auto it = find(convert(*first).key());
560
                if (it != members_.end())
561
                {
562
                    for (auto s = first; s != last; ++s)
563
                    {
564
                        it = members_.emplace(it, key_type(s->first, get_allocator()), s->second);
565
                    }
566
                }
567
                else
568
                {
569
                    for (auto s = first; s != last; ++s)
570
                    {
571
                        members_.emplace_back(convert(*s));
572
                    }
573
                }
574
            }
575
        }
576
577
        // insert_or_assign
578
579
        template <typename T,typename A=allocator_type>
580
        typename std::enable_if<std::allocator_traits<A>::is_always_equal::value,std::pair<iterator,bool>>::type
581
        insert_or_assign(const string_view_type& name, T&& value)
582
        {
583
            bool inserted;
584
            auto it = std::lower_bound(members_.begin(),members_.end(), name, Comp());        
585
            if (it == members_.end())
586
            {
587
                members_.emplace_back(key_type(name.begin(),name.end()), std::forward<T>(value));
588
                inserted = true;
589
                it = members_.begin() + members_.size() - 1;
590
            }
591
            else if ((*it).key() == name)
592
            {
593
                (*it).value(Json(std::forward<T>(value)));
594
                inserted = false; // assigned
595
            }
596
            else
597
            {
598
                it = members_.emplace(it, key_type(name.begin(),name.end()), std::forward<T>(value));
599
                inserted = true;
600
            }
601
            return std::make_pair(it,inserted);
602
        }
603
604
        template <typename T,typename A=allocator_type>
605
        typename std::enable_if<!std::allocator_traits<A>::is_always_equal::value,std::pair<iterator,bool>>::type
606
        insert_or_assign(const string_view_type& name, T&& value)
607
        {
608
            bool inserted;
609
            auto it = std::lower_bound(members_.begin(),members_.end(), name, 
610
                                       Comp());        
611
            if (it == members_.end())
612
            {
613
                members_.emplace_back(key_type(name.begin(),name.end(), get_allocator()), std::forward<T>(value));
614
                inserted = true;
615
                it = members_.begin() + members_.size() - 1;
616
            }
617
            else if ((*it).key() == name)
618
            {
619
                (*it).value(Json(std::forward<T>(value), get_allocator()));
620
                inserted = false; // assigned
621
            }
622
            else
623
            {
624
                it = members_.emplace(it, key_type(name.begin(),name.end(), get_allocator()),
625
                    std::forward<T>(value));
626
                inserted = true;
627
            }
628
            return std::make_pair(it,inserted);
629
        }
630
631
        // try_emplace
632
633
        template <typename A=allocator_type,typename... Args>
634
        typename std::enable_if<std::allocator_traits<A>::is_always_equal::value,std::pair<iterator,bool>>::type
635
        try_emplace(const string_view_type& name, Args&&... args)
636
        {
637
            bool inserted;
638
            auto it = std::lower_bound(members_.begin(),members_.end(), name, 
639
                                       Comp());        
640
            if (it == members_.end())
641
            {
642
                members_.emplace_back(key_type(name.begin(),name.end()), std::forward<Args>(args)...);
643
                it = members_.begin() + members_.size() - 1;
644
                inserted = true;
645
            }
646
            else if ((*it).key() == name)
647
            {
648
                inserted = false;
649
            }
650
            else
651
            {
652
                it = members_.emplace(it, key_type(name.begin(),name.end()),
653
                                            std::forward<Args>(args)...);
654
                inserted = true;
655
            }
656
            return std::make_pair(it,inserted);
657
        }
658
659
        template <typename A=allocator_type,typename... Args>
660
        typename std::enable_if<!std::allocator_traits<A>::is_always_equal::value,std::pair<iterator,bool>>::type
661
        try_emplace(const string_view_type& name, Args&&... args)
662
        {
663
            bool inserted;
664
            auto it = std::lower_bound(members_.begin(),members_.end(), name, 
665
                                       Comp());        
666
            if (it == members_.end())
667
            {
668
                members_.emplace_back(key_type(name.begin(),name.end(), get_allocator()), std::forward<Args>(args)...);
669
                it = members_.begin() + members_.size() - 1;
670
                inserted = true;
671
            }
672
            else if ((*it).key() == name)
673
            {
674
                inserted = false;
675
            }
676
            else
677
            {
678
                it = members_.emplace(it,
679
                                            key_type(name.begin(),name.end(), get_allocator()),
680
                                            std::forward<Args>(args)...);
681
                inserted = true;
682
            }
683
            return std::make_pair(it,inserted);
684
        }
685
686
        template <typename A=allocator_type,typename ... Args>
687
        typename std::enable_if<std::allocator_traits<A>::is_always_equal::value,iterator>::type 
688
        try_emplace(iterator hint, const string_view_type& name, Args&&... args)
689
        {
690
            iterator it = hint;
691
692
            if (hint != members_.end() && hint->key() <= name)
693
            {
694
                it = std::lower_bound(hint,members_.end(), name, 
695
                                      Comp());        
696
            }
697
            else
698
            {
699
                it = std::lower_bound(members_.begin(),members_.end(), name, 
700
                                      Comp());        
701
            }
702
703
            if (it == members_.end())
704
            {
705
                members_.emplace_back(key_type(name.begin(),name.end()), 
706
                    std::forward<Args>(args)...);
707
                it = members_.begin() + (members_.size() - 1);
708
            }
709
            else if ((*it).key() == name)
710
            {
711
            }
712
            else
713
            {
714
                it = members_.emplace(it,
715
                                            key_type(name.begin(),name.end()),
716
                                            std::forward<Args>(args)...);
717
            }
718
719
            return it;
720
        }
721
722
        template <typename A=allocator_type,typename ... Args>
723
        typename std::enable_if<!std::allocator_traits<A>::is_always_equal::value,iterator>::type 
724
        try_emplace(iterator hint, const string_view_type& name, Args&&... args)
725
        {
726
            iterator it = hint;
727
            if (hint != members_.end() && hint->key() <= name)
728
            {
729
                it = std::lower_bound(hint,members_.end(), name, 
730
                                      Comp());        
731
            }
732
            else
733
            {
734
                it = std::lower_bound(members_.begin(),members_.end(), name, 
735
                                      Comp());        
736
            }
737
738
            if (it == members_.end())
739
            {
740
                members_.emplace_back(key_type(name.begin(),name.end(), get_allocator()), 
741
                    std::forward<Args>(args)...);
742
                it = members_.begin() + (members_.size() - 1);
743
            }
744
            else if ((*it).key() == name)
745
            {
746
            }
747
            else
748
            {
749
                it = members_.emplace(it,
750
                                            key_type(name.begin(),name.end(), get_allocator()),
751
                                            std::forward<Args>(args)...);
752
            }
753
            return it;
754
        }
755
756
        // insert_or_assign
757
758
        template <typename T,typename A=allocator_type>
759
        typename std::enable_if<std::allocator_traits<A>::is_always_equal::value,iterator>::type 
760
        insert_or_assign(iterator hint, const string_view_type& name, T&& value)
761
        {
762
            iterator it;
763
            if (hint != members_.end() && hint->key() <= name)
764
            {
765
                it = std::lower_bound(hint,members_.end(), name, 
766
                                      [](const key_value_type& a, const string_view_type& k) -> bool {return string_view_type(a.key()).compare(k) < 0;});        
767
            }
768
            else
769
            {
770
                it = std::lower_bound(members_.begin(),members_.end(), name, 
771
                                      [](const key_value_type& a, const string_view_type& k) -> bool {return string_view_type(a.key()).compare(k) < 0;});        
772
            }
773
774
            if (it == members_.end())
775
            {
776
                members_.emplace_back(key_type(name.begin(),name.end()), std::forward<T>(value));
777
                it = members_.begin() + (members_.size() - 1);
778
            }
779
            else if ((*it).key() == name)
780
            {
781
                (*it).value(Json(std::forward<T>(value)));
782
            }
783
            else
784
            {
785
                it = members_.emplace(it, key_type(name.begin(),name.end()), std::forward<T>(value));
786
            }
787
            return it;
788
        }
789
790
        template <typename T,typename A=allocator_type>
791
        typename std::enable_if<!std::allocator_traits<A>::is_always_equal::value,iterator>::type 
792
        insert_or_assign(iterator hint, const string_view_type& name, T&& value)
793
        {
794
            iterator it;
795
            if (hint != members_.end() && hint->key() <= name)
796
            {
797
                it = std::lower_bound(hint,members_.end(), name, 
798
                                      Comp());        
799
            }
800
            else
801
            {
802
                it = std::lower_bound(members_.begin(),members_.end(), name, 
803
                                      Comp());        
804
            }
805
806
            if (it == members_.end())
807
            {
808
                members_.emplace_back(key_type(name.begin(),name.end(), get_allocator()), std::forward<T>(value));
809
                it = members_.begin() + (members_.size() - 1);
810
            }
811
            else if ((*it).key() == name)
812
            {
813
                (*it).value(Json(std::forward<T>(value),get_allocator()));
814
            }
815
            else
816
            {
817
                it = members_.emplace(it, key_type(name.begin(),name.end(), get_allocator()),
818
                    std::forward<T>(value));
819
            }
820
            return it;
821
        }
822
823
        // merge
824
825
        void merge(const sorted_json_object& source)
826
        {
827
            for (auto it = source.begin(); it != source.end(); ++it)
828
            {
829
                try_emplace((*it).key(),(*it).value());
830
            }
831
        }
832
833
        void merge(sorted_json_object&& source)
834
        {
835
            auto it = std::make_move_iterator(source.begin());
836
            auto end = std::make_move_iterator(source.end());
837
            for (; it != end; ++it)
838
            {
839
                auto pos = std::lower_bound(members_.begin(),members_.end(), (*it).key(), 
840
                                            Comp());   
841
                if (pos == members_.end())
842
                {
843
                    members_.emplace_back(*it);
844
                }
845
                else if ((*it).key() != pos->key())
846
                {
847
                    members_.emplace(pos,*it);
848
                }
849
            }
850
        }
851
852
        void merge(iterator hint, const sorted_json_object& source)
853
        {
854
            for (auto it = source.begin(); it != source.end(); ++it)
855
            {
856
                hint = try_emplace(hint, (*it).key(),(*it).value());
857
            }
858
        }
859
860
        void merge(iterator hint, sorted_json_object&& source)
861
        {
862
            auto it = std::make_move_iterator(source.begin());
863
            auto end = std::make_move_iterator(source.end());
864
            for (; it != end; ++it)
865
            {
866
                iterator pos;
867
                if (hint != members_.end() && hint->key() <= (*it).key())
868
                {
869
                    pos = std::lower_bound(hint,members_.end(), (*it).key(), 
870
                                          Comp());        
871
                }
872
                else
873
                {
874
                    pos = std::lower_bound(members_.begin(),members_.end(), (*it).key(), 
875
                                          Comp());        
876
                }
877
                if (pos == members_.end())
878
                {
879
                    members_.emplace_back(*it);
880
                    hint = members_.begin() + (members_.size() - 1);
881
                }
882
                else if ((*it).key() != pos->key())
883
                {
884
                    hint = members_.emplace(pos,*it);
885
                }
886
            }
887
        }
888
889
        // merge_or_update
890
891
        void merge_or_update(const sorted_json_object& source)
892
        {
893
            for (auto it = source.begin(); it != source.end(); ++it)
894
            {
895
                insert_or_assign((*it).key(),(*it).value());
896
            }
897
        }
898
899
        void merge_or_update(sorted_json_object&& source)
900
        {
901
            auto it = std::make_move_iterator(source.begin());
902
            auto end = std::make_move_iterator(source.end());
903
            for (; it != end; ++it)
904
            {
905
                auto pos = std::lower_bound(members_.begin(),members_.end(), (*it).key(), 
906
                                            Comp());   
907
                if (pos == members_.end())
908
                {
909
                    members_.emplace_back(*it);
910
                }
911
                else 
912
                {
913
                    pos->value((*it).value());
914
                }
915
            }
916
        }
917
918
        void merge_or_update(iterator hint, const sorted_json_object& source)
919
        {
920
            for (auto it = source.begin(); it != source.end(); ++it)
921
            {
922
                hint = insert_or_assign(hint, (*it).key(),(*it).value());
923
            }
924
        }
925
926
        void merge_or_update(iterator hint, sorted_json_object&& source)
927
        {
928
            auto it = std::make_move_iterator(source.begin());
929
            auto end = std::make_move_iterator(source.end());
930
            for (; it != end; ++it)
931
            {
932
                iterator pos;
933
                if (hint != members_.end() && hint->key() <= (*it).key())
934
                {
935
                    pos = std::lower_bound(hint,members_.end(), (*it).key(), 
936
                                          Comp());        
937
                }
938
                else
939
                {
940
                    pos = std::lower_bound(members_.begin(),members_.end(), (*it).key(), 
941
                                          Comp());        
942
                }
943
                if (pos == members_.end())
944
                {
945
                    members_.emplace_back(*it);
946
                    hint = members_.begin() + (members_.size() - 1);
947
                }
948
                else 
949
                {
950
                    pos->value((*it).value());
951
                    hint = pos;
952
                }
953
            }
954
        }
955
956
        bool operator==(const sorted_json_object& rhs) const
957
        {
958
            return members_ == rhs.members_;
959
        }
960
961
        bool operator<(const sorted_json_object& rhs) const
962
        {
963
            return members_ < rhs.members_;
964
        }
965
    private:
966
967
        void flatten_and_destroy() noexcept
968
61.1k
        {
969
61.1k
            if (!members_.empty())
970
9.27k
            {
971
9.27k
                json_array<Json> temp(get_allocator());
972
973
9.27k
                for (auto& kv : members_)
974
32.7k
                {
975
32.7k
                    switch (kv.value().storage_kind())
976
32.7k
                    {
977
4.09k
                        case json_storage_kind::array:
978
6.01k
                        case json_storage_kind::object:
979
6.01k
                            if (!kv.value().empty())
980
4.08k
                            {
981
4.08k
                                temp.emplace_back(std::move(kv.value()));
982
4.08k
                            }
983
6.01k
                            break;
984
26.6k
                        default:
985
26.6k
                            break;
986
32.7k
                    }
987
32.7k
                }
988
9.27k
            }
989
61.1k
        }
jsoncons::sorted_json_object<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, jsoncons::basic_json<char, jsoncons::sorted_policy, std::__1::allocator<char> >, std::__1::vector>::flatten_and_destroy()
Line
Count
Source
968
61.1k
        {
969
61.1k
            if (!members_.empty())
970
9.27k
            {
971
9.27k
                json_array<Json> temp(get_allocator());
972
973
9.27k
                for (auto& kv : members_)
974
32.7k
                {
975
32.7k
                    switch (kv.value().storage_kind())
976
32.7k
                    {
977
4.09k
                        case json_storage_kind::array:
978
6.01k
                        case json_storage_kind::object:
979
6.01k
                            if (!kv.value().empty())
980
4.08k
                            {
981
4.08k
                                temp.emplace_back(std::move(kv.value()));
982
4.08k
                            }
983
6.01k
                            break;
984
26.6k
                        default:
985
26.6k
                            break;
986
32.7k
                    }
987
32.7k
                }
988
9.27k
            }
989
61.1k
        }
Unexecuted instantiation: jsoncons::sorted_json_object<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >, jsoncons::basic_json<wchar_t, jsoncons::sorted_policy, std::__1::allocator<char> >, std::__1::vector>::flatten_and_destroy()
990
    };
991
992
    // Preserve order
993
    template <typename KeyT,typename Json,template <typename,typename> class SequenceContainer = std::vector>
994
    class order_preserving_json_object : public allocator_holder<typename Json::allocator_type>
995
    {
996
    public:
997
        using allocator_type = typename Json::allocator_type;
998
        using char_type = typename Json::char_type;
999
        using key_type = KeyT;
1000
        using string_view_type = typename Json::string_view_type;
1001
        using key_value_type = key_value<KeyT,Json>;
1002
    private:
1003
        struct MyHash
1004
        {
1005
            std::uintmax_t operator()(const key_type& s) const noexcept
1006
            {
1007
                const int p = 31;
1008
                const int m = static_cast<int>(1e9) + 9;
1009
                std::uintmax_t hash_value = 0;
1010
                std::uintmax_t p_pow = 1;
1011
                for (char_type c : s) {
1012
                    hash_value = (hash_value + (c - 'a' + 1) * p_pow) % m;
1013
                    p_pow = (p_pow * p) % m;
1014
                }
1015
                return hash_value;   
1016
            }
1017
        };
1018
1019
        using key_value_allocator_type = typename std::allocator_traits<allocator_type>:: template rebind_alloc<key_value_type>;
1020
        using key_value_container_type = SequenceContainer<key_value_type,key_value_allocator_type>;
1021
1022
        key_value_container_type members_;
1023
1024
        struct Comp
1025
        {
1026
            const key_value_container_type& members_;
1027
1028
            Comp(const key_value_container_type& members_)
1029
                : members_(members_)
1030
            {
1031
            }
1032
1033
            bool operator() (std::size_t i, string_view_type k) const { return members_.at(i).key() < k; }
1034
            bool operator() (string_view_type k, std::size_t i) const { return k < members_.at(i).key(); }
1035
        };
1036
    public:
1037
        using iterator = typename key_value_container_type::iterator;
1038
        using const_iterator = typename key_value_container_type::const_iterator;
1039
1040
        using allocator_holder<allocator_type>::get_allocator;
1041
1042
        order_preserving_json_object()
1043
        {
1044
        }
1045
        order_preserving_json_object(const allocator_type& alloc)
1046
            : allocator_holder<allocator_type>(alloc), 
1047
              members_(key_value_allocator_type(alloc))
1048
        {
1049
        }
1050
1051
        order_preserving_json_object(const order_preserving_json_object& val)
1052
            : allocator_holder<allocator_type>(val.get_allocator()), 
1053
              members_(val.members_)
1054
        {
1055
        }
1056
1057
        order_preserving_json_object(order_preserving_json_object&& val,const allocator_type& alloc) 
1058
            : allocator_holder<allocator_type>(alloc), 
1059
              members_(std::move(val.members_),key_value_allocator_type(alloc))
1060
        {
1061
        }
1062
1063
        order_preserving_json_object(order_preserving_json_object&& val) noexcept
1064
            : allocator_holder<allocator_type>(val.get_allocator()), 
1065
              members_(std::move(val.members_))
1066
        {
1067
        }
1068
1069
        order_preserving_json_object(const order_preserving_json_object& val, const allocator_type& alloc) 
1070
            : allocator_holder<allocator_type>(alloc), 
1071
              members_(val.members_,key_value_allocator_type(alloc))
1072
        {
1073
        }
1074
1075
        template <typename InputIt>
1076
        order_preserving_json_object(InputIt first, InputIt last)
1077
        {
1078
            std::unordered_set<key_type,MyHash> keys;
1079
            for (auto it = first; it != last; ++it)
1080
            {
1081
                auto kv = get_key_value<KeyT,Json>()(*it);
1082
                if (keys.find(kv.key()) == keys.end())
1083
                {
1084
                    keys.emplace(kv.key());
1085
                    members_.emplace_back(std::move(kv));
1086
                }
1087
            }
1088
        }
1089
1090
        template <typename InputIt>
1091
        order_preserving_json_object(InputIt first, InputIt last, 
1092
                    const allocator_type& alloc)
1093
            : allocator_holder<allocator_type>(alloc), 
1094
              members_(key_value_allocator_type(alloc))
1095
        {
1096
            std::unordered_set<key_type,MyHash> keys;
1097
            for (auto it = first; it != last; ++it)
1098
            {
1099
                auto kv = get_key_value<KeyT,Json>()(*it);
1100
                if (keys.find(kv.key()) == keys.end())
1101
                {
1102
                    keys.emplace(kv.key());
1103
                    members_.emplace_back(std::move(kv));
1104
                }
1105
            }
1106
        }
1107
1108
        order_preserving_json_object(std::initializer_list<std::pair<std::basic_string<char_type>,Json>> init, 
1109
                    const allocator_type& alloc = allocator_type())
1110
            : allocator_holder<allocator_type>(alloc), 
1111
              members_(key_value_allocator_type(alloc))
1112
        {
1113
            members_.reserve(init.size());
1114
            for (auto& item : init)
1115
            {
1116
                insert_or_assign(item.first, item.second);
1117
            }
1118
        }
1119
1120
        ~order_preserving_json_object() noexcept
1121
        {
1122
            flatten_and_destroy();
1123
        }
1124
1125
        order_preserving_json_object& operator=(order_preserving_json_object&& val)
1126
        {
1127
            val.swap(*this);
1128
            return *this;
1129
        }
1130
1131
        order_preserving_json_object& operator=(const order_preserving_json_object& val)
1132
        {
1133
            members_ = val.members_;
1134
            return *this;
1135
        }
1136
1137
        void swap(order_preserving_json_object& other) noexcept
1138
        {
1139
            members_.swap(other.members_);
1140
        }
1141
1142
        bool empty() const
1143
0
        {
1144
0
            return members_.empty();
1145
0
        }
Unexecuted instantiation: jsoncons::order_preserving_json_object<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, jsoncons::basic_json<char, jsoncons::order_preserving_policy, std::__1::allocator<char> >, std::__1::vector>::empty() const
Unexecuted instantiation: jsoncons::order_preserving_json_object<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >, jsoncons::basic_json<wchar_t, jsoncons::order_preserving_policy, std::__1::allocator<char> >, std::__1::vector>::empty() const
1146
1147
        iterator begin()
1148
0
        {
1149
0
            return members_.begin();
1150
0
        }
Unexecuted instantiation: jsoncons::order_preserving_json_object<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, jsoncons::basic_json<char, jsoncons::order_preserving_policy, std::__1::allocator<char> >, std::__1::vector>::begin()
Unexecuted instantiation: jsoncons::order_preserving_json_object<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >, jsoncons::basic_json<wchar_t, jsoncons::order_preserving_policy, std::__1::allocator<char> >, std::__1::vector>::begin()
1151
1152
        iterator end()
1153
0
        {
1154
0
            return members_.end();
1155
0
        }
Unexecuted instantiation: jsoncons::order_preserving_json_object<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, jsoncons::basic_json<char, jsoncons::order_preserving_policy, std::__1::allocator<char> >, std::__1::vector>::end()
Unexecuted instantiation: jsoncons::order_preserving_json_object<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >, jsoncons::basic_json<wchar_t, jsoncons::order_preserving_policy, std::__1::allocator<char> >, std::__1::vector>::end()
1156
1157
        const_iterator begin() const
1158
        {
1159
            return members_.begin();
1160
        }
1161
1162
        const_iterator end() const
1163
        {
1164
            return members_.end();
1165
        }
1166
1167
        std::size_t size() const {return members_.size();}
1168
1169
        std::size_t capacity() const {return members_.capacity();}
1170
1171
        void clear() 
1172
0
        {
1173
0
            members_.clear();
1174
0
        }
Unexecuted instantiation: jsoncons::order_preserving_json_object<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, jsoncons::basic_json<char, jsoncons::order_preserving_policy, std::__1::allocator<char> >, std::__1::vector>::clear()
Unexecuted instantiation: jsoncons::order_preserving_json_object<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >, jsoncons::basic_json<wchar_t, jsoncons::order_preserving_policy, std::__1::allocator<char> >, std::__1::vector>::clear()
1175
1176
        void shrink_to_fit() 
1177
        {
1178
            for (std::size_t i = 0; i < members_.size(); ++i)
1179
            {
1180
                members_[i].shrink_to_fit();
1181
            }
1182
            members_.shrink_to_fit();
1183
        }
1184
1185
0
        void reserve(std::size_t n) {members_.reserve(n);}
Unexecuted instantiation: jsoncons::order_preserving_json_object<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, jsoncons::basic_json<char, jsoncons::order_preserving_policy, std::__1::allocator<char> >, std::__1::vector>::reserve(unsigned long)
Unexecuted instantiation: jsoncons::order_preserving_json_object<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >, jsoncons::basic_json<wchar_t, jsoncons::order_preserving_policy, std::__1::allocator<char> >, std::__1::vector>::reserve(unsigned long)
1186
1187
        Json& at(std::size_t i) 
1188
        {
1189
            if (i >= members_.size())
1190
            {
1191
                JSONCONS_THROW(json_runtime_error<std::out_of_range>("Invalid array subscript"));
1192
            }
1193
            return members_[i].value();
1194
        }
1195
1196
        const Json& at(std::size_t i) const 
1197
        {
1198
            if (i >= members_.size())
1199
            {
1200
                JSONCONS_THROW(json_runtime_error<std::out_of_range>("Invalid array subscript"));
1201
            }
1202
            return members_[i].value();
1203
        }
1204
1205
        iterator find(const string_view_type& name) noexcept
1206
        {
1207
            bool found = false;
1208
            auto it = members_.begin();
1209
            while (!found && it != members_.end())
1210
            {
1211
                if ((*it).key() == name)
1212
                {
1213
                    found = true;
1214
                }
1215
                else
1216
                {
1217
                    ++it;
1218
                }
1219
            }
1220
            return it;
1221
        }
1222
1223
        const_iterator find(const string_view_type& name) const noexcept
1224
        {
1225
            bool found = false;
1226
            auto it = members_.begin();
1227
            while (!found && it != members_.end())
1228
            {
1229
                if ((*it).key() == name)
1230
                {
1231
                    found = true;
1232
                }
1233
                else
1234
                {
1235
                    ++it;
1236
                }
1237
            }
1238
            return it;
1239
        }
1240
1241
        iterator erase(const_iterator pos) 
1242
        {
1243
            if (pos != members_.end())
1244
            {
1245
                return members_.erase(pos);
1246
            }
1247
            else
1248
            {
1249
                return members_.end();
1250
            }
1251
        }
1252
1253
        iterator erase(const_iterator first, const_iterator last) 
1254
        {
1255
            std::size_t pos1 = first == members_.end() ? members_.size() : first - members_.begin();
1256
            std::size_t pos2 = last == members_.end() ? members_.size() : last - members_.begin();
1257
1258
            if (pos1 < members_.size() && pos2 <= members_.size())
1259
            {
1260
1261
                return members_.erase(first,last);
1262
            }
1263
            else
1264
            {
1265
                return members_.end();
1266
            }
1267
        }
1268
1269
        void erase(const string_view_type& name) 
1270
        {
1271
            auto pos = find(name);
1272
            if (pos != members_.end())
1273
            {
1274
                members_.erase(pos);
1275
            }
1276
        }
1277
1278
        static bool compare1(const index_key_value<Json>& item1, const index_key_value<Json>& item2)
1279
0
        {
1280
0
            int comp = item1.name.compare(item2.name); 
1281
0
            if (comp < 0) return true;
1282
0
            if (comp == 0) return item1.index < item2.index;
1283
0
1284
0
            return false;
1285
0
        }
Unexecuted instantiation: jsoncons::order_preserving_json_object<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, jsoncons::basic_json<char, jsoncons::order_preserving_policy, std::__1::allocator<char> >, std::__1::vector>::compare1(jsoncons::index_key_value<jsoncons::basic_json<char, jsoncons::order_preserving_policy, std::__1::allocator<char> > > const&, jsoncons::index_key_value<jsoncons::basic_json<char, jsoncons::order_preserving_policy, std::__1::allocator<char> > > const&)
Unexecuted instantiation: jsoncons::order_preserving_json_object<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >, jsoncons::basic_json<wchar_t, jsoncons::order_preserving_policy, std::__1::allocator<char> >, std::__1::vector>::compare1(jsoncons::index_key_value<jsoncons::basic_json<wchar_t, jsoncons::order_preserving_policy, std::__1::allocator<char> > > const&, jsoncons::index_key_value<jsoncons::basic_json<wchar_t, jsoncons::order_preserving_policy, std::__1::allocator<char> > > const&)
1286
1287
        static bool compare2(const index_key_value<Json>& item1, const index_key_value<Json>& item2)
1288
0
        {
1289
0
            return item1.index < item2.index;
1290
0
        }
Unexecuted instantiation: jsoncons::order_preserving_json_object<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, jsoncons::basic_json<char, jsoncons::order_preserving_policy, std::__1::allocator<char> >, std::__1::vector>::compare2(jsoncons::index_key_value<jsoncons::basic_json<char, jsoncons::order_preserving_policy, std::__1::allocator<char> > > const&, jsoncons::index_key_value<jsoncons::basic_json<char, jsoncons::order_preserving_policy, std::__1::allocator<char> > > const&)
Unexecuted instantiation: jsoncons::order_preserving_json_object<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >, jsoncons::basic_json<wchar_t, jsoncons::order_preserving_policy, std::__1::allocator<char> >, std::__1::vector>::compare2(jsoncons::index_key_value<jsoncons::basic_json<wchar_t, jsoncons::order_preserving_policy, std::__1::allocator<char> > > const&, jsoncons::index_key_value<jsoncons::basic_json<wchar_t, jsoncons::order_preserving_policy, std::__1::allocator<char> > > const&)
1291
1292
        void uninitialized_init(index_key_value<Json>* items, std::size_t length)
1293
0
        {
1294
0
            if (length > 0)
1295
0
            {
1296
0
                std::sort(items, items+length, compare1);
1297
0
1298
0
                std::size_t count = 1;
1299
0
                for (std::size_t i = 1; i < length; ++i)
1300
0
                {
1301
0
                    while (i < length && items[i-1].name == items[i].name)
1302
0
                    {
1303
0
                        ++i;
1304
0
                    }
1305
0
                    if (i < length)
1306
0
                    {
1307
0
                        if (i != count)
1308
0
                        {
1309
0
                            items[count] = std::move(items[i]);
1310
0
                        }
1311
0
                        ++count;
1312
0
                    }
1313
0
                }
1314
0
1315
0
                std::sort(items, items+count, compare2);
1316
0
1317
0
                members_.reserve(count);
1318
0
1319
0
                for (std::size_t i = 0; i < count; ++i)
1320
0
                {
1321
0
                    members_.emplace_back(std::move(items[i].name), std::move(items[i].value));
1322
0
                }
1323
0
            }
1324
0
        }
Unexecuted instantiation: jsoncons::order_preserving_json_object<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, jsoncons::basic_json<char, jsoncons::order_preserving_policy, std::__1::allocator<char> >, std::__1::vector>::uninitialized_init(jsoncons::index_key_value<jsoncons::basic_json<char, jsoncons::order_preserving_policy, std::__1::allocator<char> > >*, unsigned long)
Unexecuted instantiation: jsoncons::order_preserving_json_object<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >, jsoncons::basic_json<wchar_t, jsoncons::order_preserving_policy, std::__1::allocator<char> >, std::__1::vector>::uninitialized_init(jsoncons::index_key_value<jsoncons::basic_json<wchar_t, jsoncons::order_preserving_policy, std::__1::allocator<char> > >*, unsigned long)
1325
1326
        template <typename InputIt>
1327
        void insert(InputIt first, InputIt last)
1328
        {
1329
            std::unordered_set<key_type,MyHash> keys;
1330
            for (auto it = first; it != last; ++it)
1331
            {
1332
                key_type key{(*it).first.c_str(), (*it).first.size(), get_allocator()};
1333
                if (keys.find(key) == keys.end())
1334
                {
1335
                    keys.emplace(key.c_str(), key.size(), get_allocator());
1336
                    members_.emplace_back(std::move(key), (*it).second);
1337
                }
1338
            }
1339
        }
1340
1341
        template <typename InputIt>
1342
        void insert(sorted_unique_range_tag, InputIt first, InputIt last)
1343
        {
1344
            for (auto it = first; it != last; ++it)
1345
            {
1346
                members_.emplace_back(get_key_value<KeyT,Json>()(*it));
1347
            }
1348
        }
1349
   
1350
        template <typename T,typename A=allocator_type>
1351
        typename std::enable_if<std::allocator_traits<A>::is_always_equal::value,std::pair<iterator,bool>>::type
1352
        insert_or_assign(const string_view_type& name, T&& value)
1353
        {
1354
            auto it = find(name);
1355
            if (it == members_.end())
1356
            {
1357
                members_.emplace_back(key_type(name.begin(), name.end()), std::forward<T>(value));
1358
                auto pos = members_.begin() + (members_.size() - 1);
1359
                return std::make_pair(pos, true);
1360
            }
1361
            else
1362
            {
1363
                (*it).value(Json(std::forward<T>(value)));
1364
                return std::make_pair(it,false);
1365
            }
1366
        }
1367
1368
        template <typename T,typename A=allocator_type>
1369
        typename std::enable_if<!std::allocator_traits<A>::is_always_equal::value,std::pair<iterator,bool>>::type
1370
        insert_or_assign(const string_view_type& name, T&& value)
1371
        {
1372
            auto it = find(name);
1373
            if (it == members_.end())
1374
            {
1375
                members_.emplace_back(key_type(name.begin(),name.end(),get_allocator()), std::forward<T>(value));
1376
                auto pos = members_.begin() + (members_.size()-1);
1377
                return std::make_pair(pos,true);
1378
            }
1379
            else
1380
            {
1381
                (*it).value(Json(std::forward<T>(value),get_allocator()));
1382
                return std::make_pair(it,false);
1383
            }
1384
        }
1385
1386
        template <typename A=allocator_type,typename T>
1387
        typename std::enable_if<std::allocator_traits<A>::is_always_equal::value,iterator>::type 
1388
        insert_or_assign(iterator hint, const string_view_type& key, T&& value)
1389
        {
1390
            if (hint == members_.end())
1391
            {
1392
                auto result = insert_or_assign(key, std::forward<T>(value));
1393
                return result.first;
1394
            }
1395
            else
1396
            {
1397
                auto it = find(hint, key);
1398
                if (it == members_.end())
1399
                {
1400
                    members_.emplace_back(key_type(key.begin(), key.end()), std::forward<T>(value));
1401
                    auto pos = members_.begin() + (members_.size() - 1);
1402
                    return pos;
1403
                }
1404
                else
1405
                {
1406
                    (*it).value(Json(std::forward<T>(value)));
1407
                    return it;
1408
                }
1409
            }
1410
        }
1411
1412
        template <typename A=allocator_type,typename T>
1413
        typename std::enable_if<!std::allocator_traits<A>::is_always_equal::value,iterator>::type 
1414
        insert_or_assign(iterator hint, const string_view_type& key, T&& value)
1415
        {
1416
            if (hint == members_.end())
1417
            {
1418
                auto result = insert_or_assign(key, std::forward<T>(value));
1419
                return result.first;
1420
            }
1421
            else
1422
            {
1423
                auto it = find(hint, key);
1424
                if (it == members_.end())
1425
                {
1426
                    members_.emplace_back(key_type(key.begin(),key.end(),get_allocator()), std::forward<T>(value));
1427
                    auto pos = members_.begin() + (members_.size()-1);
1428
                    return pos;
1429
                }
1430
                else
1431
                {
1432
                    (*it).value(Json(std::forward<T>(value),get_allocator()));
1433
                    return it;
1434
                }
1435
            }
1436
        }
1437
1438
        // merge
1439
1440
        void merge(const order_preserving_json_object& source)
1441
        {
1442
            for (auto it = source.begin(); it != source.end(); ++it)
1443
            {
1444
                try_emplace((*it).key(),(*it).value());
1445
            }
1446
        }
1447
1448
        void merge(order_preserving_json_object&& source)
1449
        {
1450
            auto it = std::make_move_iterator(source.begin());
1451
            auto end = std::make_move_iterator(source.end());
1452
            for (; it != end; ++it)
1453
            {
1454
                auto pos = find((*it).key());
1455
                if (pos == members_.end())
1456
                {
1457
                    try_emplace((*it).key(),std::move((*it).value()));
1458
                }
1459
            }
1460
        }
1461
1462
        void merge(iterator hint, const order_preserving_json_object& source)
1463
        {
1464
            std::size_t pos = hint - members_.begin();
1465
            for (auto it = source.begin(); it != source.end(); ++it)
1466
            {
1467
                hint = try_emplace(hint, (*it).key(),(*it).value());
1468
                std::size_t newpos = hint - members_.begin();
1469
                if (newpos == pos)
1470
                {
1471
                    ++hint;
1472
                    pos = hint - members_.begin();
1473
                }
1474
                else
1475
                {
1476
                    hint = members_.begin() + pos;
1477
                }
1478
            }
1479
        }
1480
1481
        void merge(iterator hint, order_preserving_json_object&& source)
1482
        {
1483
            std::size_t pos = hint - members_.begin();
1484
1485
            auto it = std::make_move_iterator(source.begin());
1486
            auto end = std::make_move_iterator(source.end());
1487
            for (; it != end; ++it)
1488
            {
1489
                hint = try_emplace(hint, (*it).key(), std::move((*it).value()));
1490
                std::size_t newpos = hint - members_.begin();
1491
                if (newpos == pos)
1492
                {
1493
                    ++hint;
1494
                    pos = hint - members_.begin();
1495
                }
1496
                else
1497
                {
1498
                    hint = members_.begin() + pos;
1499
                }
1500
            }
1501
        }
1502
1503
        // merge_or_update
1504
1505
        void merge_or_update(const order_preserving_json_object& source)
1506
        {
1507
            for (auto it = source.begin(); it != source.end(); ++it)
1508
            {
1509
                insert_or_assign((*it).key(),(*it).value());
1510
            }
1511
        }
1512
1513
        void merge_or_update(order_preserving_json_object&& source)
1514
        {
1515
            auto it = std::make_move_iterator(source.begin());
1516
            auto end = std::make_move_iterator(source.end());
1517
            for (; it != end; ++it)
1518
            {
1519
                auto pos = find((*it).key());
1520
                if (pos == members_.end())
1521
                {
1522
                    insert_or_assign((*it).key(),std::move((*it).value()));
1523
                }
1524
                else
1525
                {
1526
                    pos->value(std::move((*it).value()));
1527
                }
1528
            }
1529
        }
1530
1531
        void merge_or_update(iterator hint, const order_preserving_json_object& source)
1532
        {
1533
            std::size_t pos = hint - members_.begin();
1534
            for (auto it = source.begin(); it != source.end(); ++it)
1535
            {
1536
                hint = insert_or_assign(hint, (*it).key(),(*it).value());
1537
                std::size_t newpos = hint - members_.begin();
1538
                if (newpos == pos)
1539
                {
1540
                    ++hint;
1541
                    pos = hint - members_.begin();
1542
                }
1543
                else
1544
                {
1545
                    hint = members_.begin() + pos;
1546
                }
1547
            }
1548
        }
1549
1550
        void merge_or_update(iterator hint, order_preserving_json_object&& source)
1551
        {
1552
            std::size_t pos = hint - members_.begin();
1553
            auto it = std::make_move_iterator(source.begin());
1554
            auto end = std::make_move_iterator(source.end());
1555
            for (; it != end; ++it)
1556
            {
1557
                hint = insert_or_assign(hint, (*it).key(), std::move((*it).value()));
1558
                std::size_t newpos = hint - members_.begin();
1559
                if (newpos == pos)
1560
                {
1561
                    ++hint;
1562
                    pos = hint - members_.begin();
1563
                }
1564
                else
1565
                {
1566
                    hint = members_.begin() + pos;
1567
                }
1568
            }
1569
        }
1570
1571
        // try_emplace
1572
1573
        template <typename A=allocator_type,typename... Args>
1574
        typename std::enable_if<std::allocator_traits<A>::is_always_equal::value,std::pair<iterator,bool>>::type
1575
        try_emplace(const string_view_type& name, Args&&... args)
1576
        {
1577
            auto it = find(name);
1578
            if (it == members_.end())
1579
            {
1580
                members_.emplace_back(key_type(name.begin(), name.end()), std::forward<Args>(args)...);
1581
                auto pos = members_.begin() + (members_.size()-1);
1582
                return std::make_pair(pos,true);
1583
            }
1584
            else
1585
            {
1586
                return std::make_pair(it,false);
1587
            }
1588
        }
1589
1590
        template <typename A=allocator_type,typename... Args>
1591
        typename std::enable_if<!std::allocator_traits<A>::is_always_equal::value,std::pair<iterator,bool>>::type
1592
        try_emplace(const string_view_type& key, Args&&... args)
1593
        {
1594
            auto it = find(key);
1595
            if (it == members_.end())
1596
            {
1597
                members_.emplace_back(key_type(key.begin(),key.end(), get_allocator()), 
1598
                    std::forward<Args>(args)...);
1599
                auto pos = members_.begin() + members_.size();
1600
                return std::make_pair(pos,true);
1601
            }
1602
            else
1603
            {
1604
                return std::make_pair(it,false);
1605
            }
1606
        }
1607
     
1608
        template <typename A=allocator_type,typename ... Args>
1609
        typename std::enable_if<std::allocator_traits<A>::is_always_equal::value,iterator>::type
1610
        try_emplace(iterator hint, const string_view_type& key, Args&&... args)
1611
        {
1612
            if (hint == members_.end())
1613
            {
1614
                auto result = try_emplace(key, std::forward<Args>(args)...);
1615
                return result.first;
1616
            }
1617
            else
1618
            {
1619
                auto it = find(hint, key);
1620
                if (it == members_.end())
1621
                {
1622
                    members_.emplace_back(key_type(key.begin(),key.end(), get_allocator()), 
1623
                        std::forward<Args>(args)...);
1624
                    auto pos = members_.begin() + members_.size();
1625
                    return pos;
1626
                }
1627
                else
1628
                {
1629
                    return it;
1630
                }
1631
            }
1632
        }
1633
1634
        template <typename A=allocator_type,typename ... Args>
1635
        typename std::enable_if<!std::allocator_traits<A>::is_always_equal::value,iterator>::type
1636
        try_emplace(iterator hint, const string_view_type& key, Args&&... args)
1637
        {
1638
            if (hint == members_.end())
1639
            {
1640
                auto result = try_emplace(key, std::forward<Args>(args)...);
1641
                return result.first;
1642
            }
1643
            else
1644
            {
1645
                auto it = find(hint, key);
1646
                if (it == members_.end())
1647
                {
1648
                    members_.emplace_back(key_type(key.begin(),key.end(), get_allocator()), 
1649
                        std::forward<Args>(args)...);
1650
                    auto pos = members_.begin() + members_.size();
1651
                    return pos;
1652
                }
1653
                else
1654
                {
1655
                    return it;
1656
                }
1657
            }
1658
        }
1659
1660
        bool operator==(const order_preserving_json_object& rhs) const
1661
        {
1662
            return members_ == rhs.members_;
1663
        }
1664
     
1665
        bool operator<(const order_preserving_json_object& rhs) const
1666
        {
1667
            return members_ < rhs.members_;
1668
        }
1669
    private:
1670
1671
        iterator find(iterator hint, const string_view_type& name) noexcept
1672
        {
1673
            bool found = false;
1674
            auto it = hint;
1675
            while (!found && it != members_.end())
1676
            {
1677
                if ((*it).key() == name)
1678
                {
1679
                    found = true;
1680
                }
1681
                else
1682
                {
1683
                    ++it;
1684
                }
1685
            }
1686
            return found ? it : find(name);
1687
        }
1688
1689
        void flatten_and_destroy() noexcept
1690
0
        {
1691
0
            if (!members_.empty())
1692
0
            {
1693
0
                json_array<Json> temp(get_allocator());
1694
0
1695
0
                for (auto& kv : members_)
1696
0
                {
1697
0
                    switch (kv.value().storage_kind())
1698
0
                    {
1699
0
                        case json_storage_kind::array:
1700
0
                        case json_storage_kind::object:
1701
0
                            if (!kv.value().empty())
1702
0
                            {
1703
0
                                temp.emplace_back(std::move(kv.value()));
1704
0
                            }
1705
0
                            break;
1706
0
                        default:
1707
0
                            break;
1708
0
                    }
1709
0
                }
1710
0
            }
1711
0
        }
Unexecuted instantiation: jsoncons::order_preserving_json_object<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, jsoncons::basic_json<char, jsoncons::order_preserving_policy, std::__1::allocator<char> >, std::__1::vector>::flatten_and_destroy()
Unexecuted instantiation: jsoncons::order_preserving_json_object<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >, jsoncons::basic_json<wchar_t, jsoncons::order_preserving_policy, std::__1::allocator<char> >, std::__1::vector>::flatten_and_destroy()
1712
    };
1713
1714
} // namespace jsoncons
1715
1716
#endif // JSONCONS_JSON_OBJECT_HPP