Coverage Report

Created: 2026-03-09 06:23

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