1  
//
1  
//
2  
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
2  
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3  
//
3  
//
4  
// Distributed under the Boost Software License, Version 1.0. (See accompanying
4  
// Distributed under the Boost Software License, Version 1.0. (See accompanying
5  
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5  
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6  
//
6  
//
7  
// Official repository: https://github.com/boostorg/json
7  
// Official repository: https://github.com/boostorg/json
8  
//
8  
//
9  

9  

10  
#ifndef BOOST_JSON_IMPL_ARRAY_HPP
10  
#ifndef BOOST_JSON_IMPL_ARRAY_HPP
11  
#define BOOST_JSON_IMPL_ARRAY_HPP
11  
#define BOOST_JSON_IMPL_ARRAY_HPP
12  

12  

13  
#include <boost/core/detail/static_assert.hpp>
13  
#include <boost/core/detail/static_assert.hpp>
14  
#include <boost/json/value.hpp>
14  
#include <boost/json/value.hpp>
15  
#include <boost/json/detail/except.hpp>
15  
#include <boost/json/detail/except.hpp>
16  
#include <algorithm>
16  
#include <algorithm>
17  
#include <stdexcept>
17  
#include <stdexcept>
18  
#include <type_traits>
18  
#include <type_traits>
19  

19  

20  
namespace boost {
20  
namespace boost {
21  
namespace json {
21  
namespace json {
22  

22  

23  
//----------------------------------------------------------
23  
//----------------------------------------------------------
24  

24  

25  
struct alignas(value)
25  
struct alignas(value)
26  
    array::table
26  
    array::table
27  
{
27  
{
28  
    std::uint32_t size = 0;
28  
    std::uint32_t size = 0;
29  
    std::uint32_t capacity = 0;
29  
    std::uint32_t capacity = 0;
30  

30  

31  
    constexpr table();
31  
    constexpr table();
32  

32  

33  
    value&
33  
    value&
34  
    operator[](std::size_t pos) noexcept
34  
    operator[](std::size_t pos) noexcept
35  
    {
35  
    {
36  
        return (reinterpret_cast<
36  
        return (reinterpret_cast<
37  
            value*>(this + 1))[pos];
37  
            value*>(this + 1))[pos];
38  
    }
38  
    }
39  

39  

40  
    BOOST_JSON_DECL
40  
    BOOST_JSON_DECL
41  
    static
41  
    static
42  
    table*
42  
    table*
43  
    allocate(
43  
    allocate(
44  
        std::size_t capacity,
44  
        std::size_t capacity,
45  
        storage_ptr const& sp);
45  
        storage_ptr const& sp);
46  

46  

47  
    BOOST_JSON_DECL
47  
    BOOST_JSON_DECL
48  
    static
48  
    static
49  
    void
49  
    void
50  
    deallocate(
50  
    deallocate(
51  
        table* p,
51  
        table* p,
52  
        storage_ptr const& sp);
52  
        storage_ptr const& sp);
53  
};
53  
};
54  

54  

55  
//----------------------------------------------------------
55  
//----------------------------------------------------------
56  

56  

57  
class array::revert_construct
57  
class array::revert_construct
58  
{
58  
{
59  
    array* arr_;
59  
    array* arr_;
60  

60  

61  
public:
61  
public:
62  
    explicit
62  
    explicit
63  
    revert_construct(
63  
    revert_construct(
64  
        array& arr) noexcept
64  
        array& arr) noexcept
65  
        : arr_(&arr)
65  
        : arr_(&arr)
66  
    {
66  
    {
67  
    }
67  
    }
68  

68  

69  
    ~revert_construct()
69  
    ~revert_construct()
70  
    {
70  
    {
71  
        if(! arr_)
71  
        if(! arr_)
72  
            return;
72  
            return;
73  
        arr_->destroy();
73  
        arr_->destroy();
74  
    }
74  
    }
75  

75  

76  
    void
76  
    void
77  
    commit() noexcept
77  
    commit() noexcept
78  
    {
78  
    {
79  
        arr_ = nullptr;
79  
        arr_ = nullptr;
80  
    }
80  
    }
81  
};
81  
};
82  

82  

83  
//----------------------------------------------------------
83  
//----------------------------------------------------------
84  

84  

85  
class array::revert_insert
85  
class array::revert_insert
86  
{
86  
{
87  
    array* arr_;
87  
    array* arr_;
88  
    std::size_t const i_;
88  
    std::size_t const i_;
89  
    std::size_t const n_;
89  
    std::size_t const n_;
90  

90  

91  
public:
91  
public:
92  
    value* p;
92  
    value* p;
93  

93  

94  
    BOOST_JSON_DECL
94  
    BOOST_JSON_DECL
95  
    revert_insert(
95  
    revert_insert(
96  
        const_iterator pos,
96  
        const_iterator pos,
97  
        std::size_t n,
97  
        std::size_t n,
98  
        array& arr);
98  
        array& arr);
99  

99  

100  
    BOOST_JSON_DECL
100  
    BOOST_JSON_DECL
101  
    ~revert_insert();
101  
    ~revert_insert();
102  

102  

103  
    value*
103  
    value*
104  
    commit() noexcept
104  
    commit() noexcept
105  
    {
105  
    {
106  
        auto it =
106  
        auto it =
107  
            arr_->data() + i_;
107  
            arr_->data() + i_;
108  
        arr_ = nullptr;
108  
        arr_ = nullptr;
109  
        return it;
109  
        return it;
110  
    }
110  
    }
111  
};
111  
};
112  

112  

113  
//----------------------------------------------------------
113  
//----------------------------------------------------------
114  

114  

115  
void
115  
void
116  
array::
116  
array::
117  
relocate(
117  
relocate(
118  
    value* dest,
118  
    value* dest,
119  
    value* src,
119  
    value* src,
120  
    std::size_t n) noexcept
120  
    std::size_t n) noexcept
121  
{
121  
{
122  
    if(n == 0)
122  
    if(n == 0)
123  
        return;
123  
        return;
124  
    std::memmove(
124  
    std::memmove(
125  
        static_cast<void*>(dest),
125  
        static_cast<void*>(dest),
126  
        static_cast<void const*>(src),
126  
        static_cast<void const*>(src),
127  
        n * sizeof(value));
127  
        n * sizeof(value));
128  
}
128  
}
129  

129  

130  
//----------------------------------------------------------
130  
//----------------------------------------------------------
131  
//
131  
//
132  
// Construction
132  
// Construction
133  
//
133  
//
134  
//----------------------------------------------------------
134  
//----------------------------------------------------------
135  

135  

136  
template<class InputIt, class>
136  
template<class InputIt, class>
137  
array::
137  
array::
138  
array(
138  
array(
139  
    InputIt first, InputIt last,
139  
    InputIt first, InputIt last,
140  
    storage_ptr sp)
140  
    storage_ptr sp)
141  
    : array(
141  
    : array(
142  
        first, last,
142  
        first, last,
143  
        std::move(sp),
143  
        std::move(sp),
144  
        iter_cat<InputIt>{})
144  
        iter_cat<InputIt>{})
145  
{
145  
{
146  
    BOOST_CORE_STATIC_ASSERT((
146  
    BOOST_CORE_STATIC_ASSERT((
147  
        std::is_constructible<value, decltype(*first)>::value));
147  
        std::is_constructible<value, decltype(*first)>::value));
148  
}
148  
}
149  

149  

150  
//----------------------------------------------------------
150  
//----------------------------------------------------------
151  
//
151  
//
152  
// Modifiers
152  
// Modifiers
153  
//
153  
//
154  
//----------------------------------------------------------
154  
//----------------------------------------------------------
155  

155  

156  
template<class InputIt, class>
156  
template<class InputIt, class>
157  
auto
157  
auto
158  
array::
158  
array::
159  
insert(
159  
insert(
160  
    const_iterator pos,
160  
    const_iterator pos,
161  
    InputIt first, InputIt last) ->
161  
    InputIt first, InputIt last) ->
162  
        iterator
162  
        iterator
163  
{
163  
{
164  
    BOOST_CORE_STATIC_ASSERT((
164  
    BOOST_CORE_STATIC_ASSERT((
165  
        std::is_constructible<value, decltype(*first)>::value));
165  
        std::is_constructible<value, decltype(*first)>::value));
166  
    return insert(pos, first, last,
166  
    return insert(pos, first, last,
167  
        iter_cat<InputIt>{});
167  
        iter_cat<InputIt>{});
168  
}
168  
}
169  

169  

170  
template<class Arg>
170  
template<class Arg>
171  
auto
171  
auto
172  
array::
172  
array::
173  
emplace(
173  
emplace(
174  
    const_iterator pos,
174  
    const_iterator pos,
175  
    Arg&& arg) ->
175  
    Arg&& arg) ->
176  
        iterator
176  
        iterator
177  
{
177  
{
178  
    BOOST_ASSERT(
178  
    BOOST_ASSERT(
179  
        pos >= begin() &&
179  
        pos >= begin() &&
180  
        pos <= end());
180  
        pos <= end());
181  
    value jv(
181  
    value jv(
182  
        std::forward<Arg>(arg),
182  
        std::forward<Arg>(arg),
183  
        storage());
183  
        storage());
184  
    return insert(pos, pilfer(jv));
184  
    return insert(pos, pilfer(jv));
185  
}
185  
}
186  

186  

187  
template<class Arg>
187  
template<class Arg>
188  
value&
188  
value&
189  
array::
189  
array::
190  
emplace_back(Arg&& arg)
190  
emplace_back(Arg&& arg)
191  
{
191  
{
192  
    value jv(
192  
    value jv(
193  
        std::forward<Arg>(arg),
193  
        std::forward<Arg>(arg),
194  
        storage());
194  
        storage());
195  
    return push_back(pilfer(jv));
195  
    return push_back(pilfer(jv));
196  
}
196  
}
197  

197  

198  
//----------------------------------------------------------
198  
//----------------------------------------------------------
199  
//
199  
//
200  
// Element access
200  
// Element access
201  
//
201  
//
202  
//----------------------------------------------------------
202  
//----------------------------------------------------------
203  

203  

204  
value&
204  
value&
205  
array::
205  
array::
206  
at(std::size_t pos, source_location const& loc) &
206  
at(std::size_t pos, source_location const& loc) &
207  
{
207  
{
208  
    auto const& self = *this;
208  
    auto const& self = *this;
209  
    return const_cast< value& >( self.at(pos, loc) );
209  
    return const_cast< value& >( self.at(pos, loc) );
210  
}
210  
}
211  

211  

212  
value&&
212  
value&&
213  
array::
213  
array::
214  
at(std::size_t pos, source_location const& loc) &&
214  
at(std::size_t pos, source_location const& loc) &&
215  
{
215  
{
216  
    return std::move( at(pos, loc) );
216  
    return std::move( at(pos, loc) );
217  
}
217  
}
218  

218  

219  
value&
219  
value&
220  
array::
220  
array::
221  
operator[](std::size_t pos) & noexcept
221  
operator[](std::size_t pos) & noexcept
222  
{
222  
{
223  
    BOOST_ASSERT(pos < t_->size);
223  
    BOOST_ASSERT(pos < t_->size);
224  
    return (*t_)[pos];
224  
    return (*t_)[pos];
225  
}
225  
}
226  

226  

227  
value&&
227  
value&&
228  
array::
228  
array::
229  
operator[](std::size_t pos) && noexcept
229  
operator[](std::size_t pos) && noexcept
230  
{
230  
{
231  
    return std::move( (*this)[pos] );
231  
    return std::move( (*this)[pos] );
232  
}
232  
}
233  

233  

234  
value const&
234  
value const&
235  
array::
235  
array::
236  
operator[](std::size_t pos) const& noexcept
236  
operator[](std::size_t pos) const& noexcept
237  
{
237  
{
238  
    BOOST_ASSERT(pos < t_->size);
238  
    BOOST_ASSERT(pos < t_->size);
239  
    return (*t_)[pos];
239  
    return (*t_)[pos];
240  
}
240  
}
241  

241  

242  
value&
242  
value&
243  
array::
243  
array::
244  
front() & noexcept
244  
front() & noexcept
245  
{
245  
{
246  
    BOOST_ASSERT(t_->size > 0);
246  
    BOOST_ASSERT(t_->size > 0);
247  
    return (*t_)[0];
247  
    return (*t_)[0];
248  
}
248  
}
249  

249  

250  
value&&
250  
value&&
251  
array::
251  
array::
252  
front() && noexcept
252  
front() && noexcept
253  
{
253  
{
254  
    return std::move( front() );
254  
    return std::move( front() );
255  
}
255  
}
256  

256  

257  
value const&
257  
value const&
258  
array::
258  
array::
259  
front() const& noexcept
259  
front() const& noexcept
260  
{
260  
{
261  
    BOOST_ASSERT(t_->size > 0);
261  
    BOOST_ASSERT(t_->size > 0);
262  
    return (*t_)[0];
262  
    return (*t_)[0];
263  
}
263  
}
264  

264  

265  
value&
265  
value&
266  
array::
266  
array::
267  
back() & noexcept
267  
back() & noexcept
268  
{
268  
{
269  
    BOOST_ASSERT(
269  
    BOOST_ASSERT(
270  
        t_->size > 0);
270  
        t_->size > 0);
271  
    return (*t_)[t_->size - 1];
271  
    return (*t_)[t_->size - 1];
272  
}
272  
}
273  

273  

274  
value&&
274  
value&&
275  
array::
275  
array::
276  
back() && noexcept
276  
back() && noexcept
277  
{
277  
{
278  
    return std::move( back() );
278  
    return std::move( back() );
279  
}
279  
}
280  

280  

281  
value const&
281  
value const&
282  
array::
282  
array::
283  
back() const& noexcept
283  
back() const& noexcept
284  
{
284  
{
285  
    BOOST_ASSERT(
285  
    BOOST_ASSERT(
286  
        t_->size > 0);
286  
        t_->size > 0);
287  
    return (*t_)[t_->size - 1];
287  
    return (*t_)[t_->size - 1];
288  
}
288  
}
289  

289  

290  
value*
290  
value*
291  
array::
291  
array::
292  
data() noexcept
292  
data() noexcept
293  
{
293  
{
294  
    return &(*t_)[0];
294  
    return &(*t_)[0];
295  
}
295  
}
296  

296  

297  
value const*
297  
value const*
298  
array::
298  
array::
299  
data() const noexcept
299  
data() const noexcept
300  
{
300  
{
301  
    return &(*t_)[0];
301  
    return &(*t_)[0];
302  
}
302  
}
303  

303  

304  
value const*
304  
value const*
305  
array::
305  
array::
306  
if_contains(
306  
if_contains(
307  
    std::size_t pos) const noexcept
307  
    std::size_t pos) const noexcept
308  
{
308  
{
309  
    if( pos < t_->size )
309  
    if( pos < t_->size )
310  
        return &(*t_)[pos];
310  
        return &(*t_)[pos];
311  
    return nullptr;
311  
    return nullptr;
312  
}
312  
}
313  

313  

314  
value*
314  
value*
315  
array::
315  
array::
316  
if_contains(
316  
if_contains(
317  
    std::size_t pos) noexcept
317  
    std::size_t pos) noexcept
318  
{
318  
{
319  
    if( pos < t_->size )
319  
    if( pos < t_->size )
320  
        return &(*t_)[pos];
320  
        return &(*t_)[pos];
321  
    return nullptr;
321  
    return nullptr;
322  
}
322  
}
323  

323  

324  
//----------------------------------------------------------
324  
//----------------------------------------------------------
325  
//
325  
//
326  
// Iterators
326  
// Iterators
327  
//
327  
//
328  
//----------------------------------------------------------
328  
//----------------------------------------------------------
329  

329  

330  
auto
330  
auto
331  
array::
331  
array::
332  
begin() noexcept ->
332  
begin() noexcept ->
333  
    iterator
333  
    iterator
334  
{
334  
{
335  
    return &(*t_)[0];
335  
    return &(*t_)[0];
336  
}
336  
}
337  

337  

338  
auto
338  
auto
339  
array::
339  
array::
340  
begin() const noexcept ->
340  
begin() const noexcept ->
341  
    const_iterator
341  
    const_iterator
342  
{
342  
{
343  
    return &(*t_)[0];
343  
    return &(*t_)[0];
344  
}
344  
}
345  

345  

346  
auto
346  
auto
347  
array::
347  
array::
348  
cbegin() const noexcept ->
348  
cbegin() const noexcept ->
349  
    const_iterator
349  
    const_iterator
350  
{
350  
{
351  
    return &(*t_)[0];
351  
    return &(*t_)[0];
352  
}
352  
}
353  

353  

354  
auto
354  
auto
355  
array::
355  
array::
356  
end() noexcept ->
356  
end() noexcept ->
357  
    iterator
357  
    iterator
358  
{
358  
{
359  
    return &(*t_)[t_->size];
359  
    return &(*t_)[t_->size];
360  
}
360  
}
361  

361  

362  
auto
362  
auto
363  
array::
363  
array::
364  
end() const noexcept ->
364  
end() const noexcept ->
365  
    const_iterator
365  
    const_iterator
366  
{
366  
{
367  
    return &(*t_)[t_->size];
367  
    return &(*t_)[t_->size];
368  
}
368  
}
369  

369  

370  
auto
370  
auto
371  
array::
371  
array::
372  
cend() const noexcept ->
372  
cend() const noexcept ->
373  
    const_iterator
373  
    const_iterator
374  
{
374  
{
375  
    return &(*t_)[t_->size];
375  
    return &(*t_)[t_->size];
376  
}
376  
}
377  

377  

378  
auto
378  
auto
379  
array::
379  
array::
380  
rbegin() noexcept ->
380  
rbegin() noexcept ->
381  
    reverse_iterator
381  
    reverse_iterator
382  
{
382  
{
383  
    return reverse_iterator(end());
383  
    return reverse_iterator(end());
384  
}
384  
}
385  

385  

386  
auto
386  
auto
387  
array::
387  
array::
388  
rbegin() const noexcept ->
388  
rbegin() const noexcept ->
389  
    const_reverse_iterator
389  
    const_reverse_iterator
390  
{
390  
{
391  
    return const_reverse_iterator(end());
391  
    return const_reverse_iterator(end());
392  
}
392  
}
393  

393  

394  
auto
394  
auto
395  
array::
395  
array::
396  
crbegin() const noexcept ->
396  
crbegin() const noexcept ->
397  
    const_reverse_iterator
397  
    const_reverse_iterator
398  
{
398  
{
399  
    return const_reverse_iterator(end());
399  
    return const_reverse_iterator(end());
400  
}
400  
}
401  

401  

402  
auto
402  
auto
403  
array::
403  
array::
404  
rend() noexcept ->
404  
rend() noexcept ->
405  
    reverse_iterator
405  
    reverse_iterator
406  
{
406  
{
407  
    return reverse_iterator(begin());
407  
    return reverse_iterator(begin());
408  
}
408  
}
409  

409  

410  
auto
410  
auto
411  
array::
411  
array::
412  
rend() const noexcept ->
412  
rend() const noexcept ->
413  
    const_reverse_iterator
413  
    const_reverse_iterator
414  
{
414  
{
415  
    return const_reverse_iterator(begin());
415  
    return const_reverse_iterator(begin());
416  
}
416  
}
417  

417  

418  
auto
418  
auto
419  
array::
419  
array::
420  
crend() const noexcept ->
420  
crend() const noexcept ->
421  
    const_reverse_iterator
421  
    const_reverse_iterator
422  
{
422  
{
423  
    return const_reverse_iterator(begin());
423  
    return const_reverse_iterator(begin());
424  
}
424  
}
425  

425  

426  
//----------------------------------------------------------
426  
//----------------------------------------------------------
427  
//
427  
//
428  
// Capacity
428  
// Capacity
429  
//
429  
//
430  
//----------------------------------------------------------
430  
//----------------------------------------------------------
431  

431  

432  
std::size_t
432  
std::size_t
433  
array::
433  
array::
434  
size() const noexcept
434  
size() const noexcept
435  
{
435  
{
436  
    return t_->size;
436  
    return t_->size;
437  
}
437  
}
438  

438  

439  
constexpr
439  
constexpr
440  
std::size_t
440  
std::size_t
441  
array::
441  
array::
442  
max_size() noexcept
442  
max_size() noexcept
443  
{
443  
{
444  
    // max_size depends on the address model
444  
    // max_size depends on the address model
445  
    using min = std::integral_constant<std::size_t,
445  
    using min = std::integral_constant<std::size_t,
446  
        (std::size_t(-1) - sizeof(table)) / sizeof(value)>;
446  
        (std::size_t(-1) - sizeof(table)) / sizeof(value)>;
447  
    return min::value < BOOST_JSON_MAX_STRUCTURED_SIZE ?
447  
    return min::value < BOOST_JSON_MAX_STRUCTURED_SIZE ?
448  
        min::value : BOOST_JSON_MAX_STRUCTURED_SIZE;
448  
        min::value : BOOST_JSON_MAX_STRUCTURED_SIZE;
449  
}
449  
}
450  

450  

451  
std::size_t
451  
std::size_t
452  
array::
452  
array::
453  
capacity() const noexcept
453  
capacity() const noexcept
454  
{
454  
{
455  
    return t_->capacity;
455  
    return t_->capacity;
456  
}
456  
}
457  

457  

458  
bool
458  
bool
459  
array::
459  
array::
460  
empty() const noexcept
460  
empty() const noexcept
461  
{
461  
{
462  
    return t_->size == 0;
462  
    return t_->size == 0;
463  
}
463  
}
464  

464  

465  
void
465  
void
466  
array::
466  
array::
467  
reserve(
467  
reserve(
468  
    std::size_t new_capacity)
468  
    std::size_t new_capacity)
469  
{
469  
{
470  
    // never shrink
470  
    // never shrink
471  
    if(new_capacity <= t_->capacity)
471  
    if(new_capacity <= t_->capacity)
472  
        return;
472  
        return;
473  
    reserve_impl(new_capacity);
473  
    reserve_impl(new_capacity);
474  
}
474  
}
475  

475  

476  
//----------------------------------------------------------
476  
//----------------------------------------------------------
477  
//
477  
//
478  
// private
478  
// private
479  
//
479  
//
480  
//----------------------------------------------------------
480  
//----------------------------------------------------------
481  

481  

482  
template<class InputIt>
482  
template<class InputIt>
483  
array::
483  
array::
484  
array(
484  
array(
485  
    InputIt first, InputIt last,
485  
    InputIt first, InputIt last,
486  
    storage_ptr sp,
486  
    storage_ptr sp,
487  
    std::input_iterator_tag)
487  
    std::input_iterator_tag)
488  
    : sp_(std::move(sp))
488  
    : sp_(std::move(sp))
489  
    , t_(&empty_)
489  
    , t_(&empty_)
490  
{
490  
{
491  
    revert_construct r(*this);
491  
    revert_construct r(*this);
492  
    while(first != last)
492  
    while(first != last)
493  
    {
493  
    {
494  
        reserve(size() + 1);
494  
        reserve(size() + 1);
495  
        ::new(end()) value(
495  
        ::new(end()) value(
496  
            *first++, sp_);
496  
            *first++, sp_);
497  
        ++t_->size;
497  
        ++t_->size;
498  
    }
498  
    }
499  
    r.commit();
499  
    r.commit();
500  
}
500  
}
501  

501  

502  
template<class InputIt>
502  
template<class InputIt>
503  
array::
503  
array::
504  
array(
504  
array(
505  
    InputIt first, InputIt last,
505  
    InputIt first, InputIt last,
506  
    storage_ptr sp,
506  
    storage_ptr sp,
507  
    std::forward_iterator_tag)
507  
    std::forward_iterator_tag)
508  
    : sp_(std::move(sp))
508  
    : sp_(std::move(sp))
509  
{
509  
{
510  
    std::size_t n =
510  
    std::size_t n =
511  
        std::distance(first, last);
511  
        std::distance(first, last);
512  
    if( n == 0 )
512  
    if( n == 0 )
513  
    {
513  
    {
514  
        t_ = &empty_;
514  
        t_ = &empty_;
515  
        return;
515  
        return;
516  
    }
516  
    }
517  

517  

518  
    t_ = table::allocate(n, sp_);
518  
    t_ = table::allocate(n, sp_);
519  
    t_->size = 0;
519  
    t_->size = 0;
520  
    revert_construct r(*this);
520  
    revert_construct r(*this);
521  
    while(n--)
521  
    while(n--)
522  
    {
522  
    {
523  
        ::new(end()) value(
523  
        ::new(end()) value(
524  
            *first++, sp_);
524  
            *first++, sp_);
525  
        ++t_->size;
525  
        ++t_->size;
526  
    }
526  
    }
527  
    r.commit();
527  
    r.commit();
528  
}
528  
}
529  

529  

530  
template<class InputIt>
530  
template<class InputIt>
531  
auto
531  
auto
532  
array::
532  
array::
533  
insert(
533  
insert(
534  
    const_iterator pos,
534  
    const_iterator pos,
535  
    InputIt first, InputIt last,
535  
    InputIt first, InputIt last,
536  
    std::input_iterator_tag) ->
536  
    std::input_iterator_tag) ->
537  
        iterator
537  
        iterator
538  
{
538  
{
539  
    BOOST_ASSERT(
539  
    BOOST_ASSERT(
540  
        pos >= begin() && pos <= end());
540  
        pos >= begin() && pos <= end());
541  
    if(first == last)
541  
    if(first == last)
542  
        return data() + (pos - data());
542  
        return data() + (pos - data());
543  
    array temp(first, last, sp_);
543  
    array temp(first, last, sp_);
544  
    revert_insert r(
544  
    revert_insert r(
545  
        pos, temp.size(), *this);
545  
        pos, temp.size(), *this);
546  
    relocate(
546  
    relocate(
547  
        r.p,
547  
        r.p,
548  
        temp.data(),
548  
        temp.data(),
549  
        temp.size());
549  
        temp.size());
550  
    temp.t_->size = 0;
550  
    temp.t_->size = 0;
551  
    return r.commit();
551  
    return r.commit();
552  
}
552  
}
553  

553  

554  
template<class InputIt>
554  
template<class InputIt>
555  
auto
555  
auto
556  
array::
556  
array::
557  
insert(
557  
insert(
558  
    const_iterator pos,
558  
    const_iterator pos,
559  
    InputIt first, InputIt last,
559  
    InputIt first, InputIt last,
560  
    std::forward_iterator_tag) ->
560  
    std::forward_iterator_tag) ->
561  
        iterator
561  
        iterator
562  
{
562  
{
563  
    std::size_t n =
563  
    std::size_t n =
564  
        std::distance(first, last);
564  
        std::distance(first, last);
565  
    revert_insert r(pos, n, *this);
565  
    revert_insert r(pos, n, *this);
566  
    while(n--)
566  
    while(n--)
567  
    {
567  
    {
568  
        ::new(r.p) value(*first++);
568  
        ::new(r.p) value(*first++);
569  
        ++r.p;
569  
        ++r.p;
570  
    }
570  
    }
571  
    return r.commit();
571  
    return r.commit();
572  
}
572  
}
573  

573  

574  
} // namespace json
574  
} // namespace json
575  
} // namespace boost
575  
} // namespace boost
576  

576  

577  
#endif
577  
#endif