Coverage Report

Created: 2023-06-07 06:25

/src/boost/boost/json/impl/array.hpp
Line
Count
Source (jump to first uncovered line)
1
//
2
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3
//
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)
6
//
7
// Official repository: https://github.com/boostorg/json
8
//
9
10
#ifndef BOOST_JSON_IMPL_ARRAY_HPP
11
#define BOOST_JSON_IMPL_ARRAY_HPP
12
13
#include <boost/json/value.hpp>
14
#include <boost/json/detail/except.hpp>
15
#include <algorithm>
16
#include <stdexcept>
17
#include <type_traits>
18
19
namespace boost {
20
namespace json {
21
22
//----------------------------------------------------------
23
24
struct alignas(value)
25
    array::table
26
{
27
    std::uint32_t size = 0;
28
    std::uint32_t capacity = 0;
29
30
    constexpr table();
31
32
    value&
33
    operator[](std::size_t pos) noexcept
34
69.4k
    {
35
69.4k
        return (reinterpret_cast<
36
69.4k
            value*>(this + 1))[pos];
37
69.4k
    }
38
39
    BOOST_JSON_DECL
40
    static
41
    table*
42
    allocate(
43
        std::size_t capacity,
44
        storage_ptr const& sp);
45
46
    BOOST_JSON_DECL
47
    static
48
    void
49
    deallocate(
50
        table* p,
51
        storage_ptr const& sp);
52
};
53
54
//----------------------------------------------------------
55
56
class array::revert_construct
57
{
58
    array* arr_;
59
60
public:
61
    explicit
62
    revert_construct(
63
        array& arr) noexcept
64
        : arr_(&arr)
65
0
    {
66
0
    }
67
68
    ~revert_construct()
69
0
    {
70
0
        if(! arr_)
71
0
            return;
72
0
        arr_->destroy();
73
0
    }
74
75
    void
76
    commit() noexcept
77
0
    {
78
0
        arr_ = nullptr;
79
0
    }
80
};
81
82
//----------------------------------------------------------
83
84
class array::revert_insert
85
{
86
    array* arr_;
87
    std::size_t const i_;
88
    std::size_t const n_;
89
90
public:
91
    value* p;
92
93
    BOOST_JSON_DECL
94
    revert_insert(
95
        const_iterator pos,
96
        std::size_t n,
97
        array& arr);
98
99
    BOOST_JSON_DECL
100
    ~revert_insert();
101
102
    value*
103
    commit() noexcept
104
0
    {
105
0
        auto it =
106
0
            arr_->data() + i_;
107
0
        arr_ = nullptr;
108
0
        return it;
109
0
    }
110
};
111
112
//----------------------------------------------------------
113
114
void
115
array::
116
relocate(
117
    value* dest,
118
    value* src,
119
    std::size_t n) noexcept
120
0
{
121
0
    if(n == 0)
122
0
        return;
123
0
    std::memmove(
124
0
        static_cast<void*>(dest),
125
0
        static_cast<void const*>(src),
126
0
        n * sizeof(value));
127
0
}
128
129
//----------------------------------------------------------
130
//
131
// Construction
132
//
133
//----------------------------------------------------------
134
135
template<class InputIt, class>
136
array::
137
array(
138
    InputIt first, InputIt last,
139
    storage_ptr sp)
140
    : array(
141
        first, last,
142
        std::move(sp),
143
        iter_cat<InputIt>{})
144
{
145
    BOOST_STATIC_ASSERT(
146
        std::is_constructible<value,
147
            decltype(*first)>::value);
148
}
149
150
//----------------------------------------------------------
151
//
152
// Modifiers
153
//
154
//----------------------------------------------------------
155
156
template<class InputIt, class>
157
auto
158
array::
159
insert(
160
    const_iterator pos,
161
    InputIt first, InputIt last) ->
162
        iterator
163
{
164
    BOOST_STATIC_ASSERT(
165
        std::is_constructible<value,
166
            decltype(*first)>::value);
167
    return insert(pos, first, last,
168
        iter_cat<InputIt>{});
169
}
170
171
template<class Arg>
172
auto
173
array::
174
emplace(
175
    const_iterator pos,
176
    Arg&& arg) ->
177
        iterator
178
0
{
179
0
    BOOST_ASSERT(
180
0
        pos >= begin() &&
181
0
        pos <= end());
182
0
    value jv(
183
0
        std::forward<Arg>(arg),
184
0
        storage());
185
0
    return insert(pos, pilfer(jv));
186
0
}
Unexecuted instantiation: boost::json::value* boost::json::array::emplace<boost::json::value const&>(boost::json::value const*, boost::json::value const&)
Unexecuted instantiation: boost::json::value* boost::json::array::emplace<boost::json::value>(boost::json::value const*, boost::json::value&&)
187
188
template<class Arg>
189
value&
190
array::
191
emplace_back(Arg&& arg)
192
0
{
193
0
    value jv(
194
0
        std::forward<Arg>(arg),
195
0
        storage());
196
0
    return push_back(pilfer(jv));
197
0
}
Unexecuted instantiation: boost::json::value& boost::json::array::emplace_back<boost::json::value const&>(boost::json::value const&)
Unexecuted instantiation: boost::json::value& boost::json::array::emplace_back<boost::json::value>(boost::json::value&&)
198
199
//----------------------------------------------------------
200
//
201
// Element access
202
//
203
//----------------------------------------------------------
204
205
value&
206
array::
207
at(std::size_t pos) &
208
0
{
209
0
    auto const& self = *this;
210
0
    return const_cast< value& >( self.at(pos) );
211
0
}
212
213
value&&
214
array::
215
at(std::size_t pos) &&
216
0
{
217
0
    return std::move( at(pos) );
218
0
}
219
220
value const&
221
array::
222
at(std::size_t pos) const&
223
0
{
224
0
    if(pos >= t_->size)
225
0
    {
226
0
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
227
0
        detail::throw_system_error( error::out_of_range, &loc );
228
0
    }
229
0
    return (*t_)[pos];
230
0
}
231
232
value&
233
array::
234
operator[](std::size_t pos) & noexcept
235
0
{
236
0
    BOOST_ASSERT(pos < t_->size);
237
0
    return (*t_)[pos];
238
0
}
239
240
value&&
241
array::
242
operator[](std::size_t pos) && noexcept
243
0
{
244
0
    return std::move( (*this)[pos] );
245
0
}
246
247
value const&
248
array::
249
operator[](std::size_t pos) const& noexcept
250
0
{
251
0
    BOOST_ASSERT(pos < t_->size);
252
0
    return (*t_)[pos];
253
0
}
254
255
value&
256
array::
257
front() & noexcept
258
0
{
259
0
    BOOST_ASSERT(t_->size > 0);
260
0
    return (*t_)[0];
261
0
}
262
263
value&&
264
array::
265
front() && noexcept
266
0
{
267
0
    return std::move( front() );
268
0
}
269
270
value const&
271
array::
272
front() const& noexcept
273
0
{
274
0
    BOOST_ASSERT(t_->size > 0);
275
0
    return (*t_)[0];
276
0
}
277
278
value&
279
array::
280
back() & noexcept
281
0
{
282
0
    BOOST_ASSERT(
283
0
        t_->size > 0);
284
0
    return (*t_)[t_->size - 1];
285
0
}
286
287
value&&
288
array::
289
back() && noexcept
290
0
{
291
0
    return std::move( back() );
292
0
}
293
294
value const&
295
array::
296
back() const& noexcept
297
0
{
298
0
    BOOST_ASSERT(
299
0
        t_->size > 0);
300
0
    return (*t_)[t_->size - 1];
301
0
}
302
303
value*
304
array::
305
data() noexcept
306
11.6k
{
307
11.6k
    return &(*t_)[0];
308
11.6k
}
309
310
value const*
311
array::
312
data() const noexcept
313
0
{
314
0
    return &(*t_)[0];
315
0
}
316
317
value const*
318
array::
319
if_contains(
320
    std::size_t pos) const noexcept
321
0
{
322
0
    if( pos < t_->size )
323
0
        return &(*t_)[pos];
324
0
    return nullptr;
325
0
}
326
327
value*
328
array::
329
if_contains(
330
    std::size_t pos) noexcept
331
0
{
332
0
    if( pos < t_->size )
333
0
        return &(*t_)[pos];
334
0
    return nullptr;
335
0
}
336
337
//----------------------------------------------------------
338
//
339
// Iterators
340
//
341
//----------------------------------------------------------
342
343
auto
344
array::
345
begin() noexcept ->
346
    iterator
347
14.4k
{
348
14.4k
    return &(*t_)[0];
349
14.4k
}
350
351
auto
352
array::
353
begin() const noexcept ->
354
    const_iterator
355
11.4k
{
356
11.4k
    return &(*t_)[0];
357
11.4k
}
358
359
auto
360
array::
361
cbegin() const noexcept ->
362
    const_iterator
363
0
{
364
0
    return &(*t_)[0];
365
0
}
366
367
auto
368
array::
369
end() noexcept ->
370
    iterator
371
14.4k
{
372
14.4k
    return &(*t_)[t_->size];
373
14.4k
}
374
375
auto
376
array::
377
end() const noexcept ->
378
    const_iterator
379
17.3k
{
380
17.3k
    return &(*t_)[t_->size];
381
17.3k
}
382
383
auto
384
array::
385
cend() const noexcept ->
386
    const_iterator
387
0
{
388
0
    return &(*t_)[t_->size];
389
0
}
390
391
auto
392
array::
393
rbegin() noexcept ->
394
    reverse_iterator
395
0
{
396
0
    return reverse_iterator(end());
397
0
}
398
399
auto
400
array::
401
rbegin() const noexcept ->
402
    const_reverse_iterator
403
0
{
404
0
    return const_reverse_iterator(end());
405
0
}
406
407
auto
408
array::
409
crbegin() const noexcept ->
410
    const_reverse_iterator
411
0
{
412
0
    return const_reverse_iterator(end());
413
0
}
414
415
auto
416
array::
417
rend() noexcept ->
418
    reverse_iterator
419
0
{
420
0
    return reverse_iterator(begin());
421
0
}
422
423
auto
424
array::
425
rend() const noexcept ->
426
    const_reverse_iterator
427
0
{
428
0
    return const_reverse_iterator(begin());
429
0
}
430
431
auto
432
array::
433
crend() const noexcept ->
434
    const_reverse_iterator
435
0
{
436
0
    return const_reverse_iterator(begin());
437
0
}
438
439
//----------------------------------------------------------
440
//
441
// Capacity
442
//
443
//----------------------------------------------------------
444
445
std::size_t
446
array::
447
size() const noexcept
448
0
{
449
0
    return t_->size;
450
0
}
451
452
constexpr
453
std::size_t
454
array::
455
max_size() noexcept
456
11.6k
{
457
    // max_size depends on the address model
458
11.6k
    using min = std::integral_constant<std::size_t,
459
11.6k
        (std::size_t(-1) - sizeof(table)) / sizeof(value)>;
460
11.6k
    return min::value < BOOST_JSON_MAX_STRUCTURED_SIZE ?
461
11.6k
        min::value : BOOST_JSON_MAX_STRUCTURED_SIZE;
462
11.6k
}
463
464
std::size_t
465
array::
466
capacity() const noexcept
467
0
{
468
0
    return t_->capacity;
469
0
}
470
471
bool
472
array::
473
empty() const noexcept
474
0
{
475
0
    return t_->size == 0;
476
0
}
477
478
void
479
array::
480
reserve(
481
    std::size_t new_capacity)
482
0
{
483
    // never shrink
484
0
    if(new_capacity <= t_->capacity)
485
0
        return;
486
0
    reserve_impl(new_capacity);
487
0
}
488
489
//----------------------------------------------------------
490
//
491
// private
492
//
493
//----------------------------------------------------------
494
495
template<class InputIt>
496
array::
497
array(
498
    InputIt first, InputIt last,
499
    storage_ptr sp,
500
    std::input_iterator_tag)
501
    : sp_(std::move(sp))
502
    , t_(&empty_)
503
{
504
    revert_construct r(*this);
505
    while(first != last)
506
    {
507
        reserve(size() + 1);
508
        ::new(end()) value(
509
            *first++, sp_);
510
        ++t_->size;
511
    }
512
    r.commit();
513
}
514
515
template<class InputIt>
516
array::
517
array(
518
    InputIt first, InputIt last,
519
    storage_ptr sp,
520
    std::forward_iterator_tag)
521
    : sp_(std::move(sp))
522
{
523
    std::size_t n =
524
        std::distance(first, last);
525
    if( n == 0 )
526
    {
527
        t_ = &empty_;
528
        return;
529
    }
530
531
    t_ = table::allocate(n, sp_);
532
    t_->size = 0;
533
    revert_construct r(*this);
534
    while(n--)
535
    {
536
        ::new(end()) value(
537
            *first++, sp_);
538
        ++t_->size;
539
    }
540
    r.commit();
541
}
542
543
template<class InputIt>
544
auto
545
array::
546
insert(
547
    const_iterator pos,
548
    InputIt first, InputIt last,
549
    std::input_iterator_tag) ->
550
        iterator
551
{
552
    BOOST_ASSERT(
553
        pos >= begin() && pos <= end());
554
    if(first == last)
555
        return data() + (pos - data());
556
    array temp(first, last, sp_);
557
    revert_insert r(
558
        pos, temp.size(), *this);
559
    relocate(
560
        r.p,
561
        temp.data(),
562
        temp.size());
563
    temp.t_->size = 0;
564
    return r.commit();
565
}
566
567
template<class InputIt>
568
auto
569
array::
570
insert(
571
    const_iterator pos,
572
    InputIt first, InputIt last,
573
    std::forward_iterator_tag) ->
574
        iterator
575
{
576
    std::size_t n =
577
        std::distance(first, last);
578
    revert_insert r(pos, n, *this);
579
    while(n--)
580
    {
581
        ::new(r.p) value(*first++);
582
        ++r.p;
583
    }
584
    return r.commit();
585
}
586
587
} // namespace json
588
} // namespace boost
589
590
#endif