Coverage Report

Created: 2025-06-13 06:26

/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
5.48k
    {
35
5.48k
        return (reinterpret_cast<
36
5.48k
            value*>(this + 1))[pos];
37
5.48k
    }
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
0
        : 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, source_location const& loc) &
208
{
209
    auto const& self = *this;
210
    return const_cast< value& >( self.at(pos, loc) );
211
}
212
213
value&&
214
array::
215
at(std::size_t pos, source_location const& loc) &&
216
{
217
    return std::move( at(pos, loc) );
218
}
219
220
value&
221
array::
222
operator[](std::size_t pos) & noexcept
223
{
224
    BOOST_ASSERT(pos < t_->size);
225
    return (*t_)[pos];
226
}
227
228
value&&
229
array::
230
operator[](std::size_t pos) && noexcept
231
{
232
    return std::move( (*this)[pos] );
233
}
234
235
value const&
236
array::
237
operator[](std::size_t pos) const& noexcept
238
0
{
239
0
    BOOST_ASSERT(pos < t_->size);
240
0
    return (*t_)[pos];
241
0
}
242
243
value&
244
array::
245
front() & noexcept
246
{
247
    BOOST_ASSERT(t_->size > 0);
248
    return (*t_)[0];
249
}
250
251
value&&
252
array::
253
front() && noexcept
254
{
255
    return std::move( front() );
256
}
257
258
value const&
259
array::
260
front() const& noexcept
261
{
262
    BOOST_ASSERT(t_->size > 0);
263
    return (*t_)[0];
264
}
265
266
value&
267
array::
268
back() & noexcept
269
0
{
270
0
    BOOST_ASSERT(
271
0
        t_->size > 0);
272
0
    return (*t_)[t_->size - 1];
273
0
}
274
275
value&&
276
array::
277
back() && noexcept
278
{
279
    return std::move( back() );
280
}
281
282
value const&
283
array::
284
back() const& noexcept
285
{
286
    BOOST_ASSERT(
287
        t_->size > 0);
288
    return (*t_)[t_->size - 1];
289
}
290
291
value*
292
array::
293
data() noexcept
294
1.18k
{
295
1.18k
    return &(*t_)[0];
296
1.18k
}
297
298
value const*
299
array::
300
data() const noexcept
301
0
{
302
0
    return &(*t_)[0];
303
0
}
304
305
value const*
306
array::
307
if_contains(
308
    std::size_t pos) const noexcept
309
0
{
310
0
    if( pos < t_->size )
311
0
        return &(*t_)[pos];
312
0
    return nullptr;
313
0
}
314
315
value*
316
array::
317
if_contains(
318
    std::size_t pos) noexcept
319
{
320
    if( pos < t_->size )
321
        return &(*t_)[pos];
322
    return nullptr;
323
}
324
325
//----------------------------------------------------------
326
//
327
// Iterators
328
//
329
//----------------------------------------------------------
330
331
auto
332
array::
333
begin() noexcept ->
334
    iterator
335
2.14k
{
336
2.14k
    return &(*t_)[0];
337
2.14k
}
338
339
auto
340
array::
341
begin() const noexcept ->
342
    const_iterator
343
0
{
344
0
    return &(*t_)[0];
345
0
}
346
347
auto
348
array::
349
cbegin() const noexcept ->
350
    const_iterator
351
{
352
    return &(*t_)[0];
353
}
354
355
auto
356
array::
357
end() noexcept ->
358
    iterator
359
2.14k
{
360
2.14k
    return &(*t_)[t_->size];
361
2.14k
}
362
363
auto
364
array::
365
end() const noexcept ->
366
    const_iterator
367
0
{
368
0
    return &(*t_)[t_->size];
369
0
}
370
371
auto
372
array::
373
cend() const noexcept ->
374
    const_iterator
375
{
376
    return &(*t_)[t_->size];
377
}
378
379
auto
380
array::
381
rbegin() noexcept ->
382
    reverse_iterator
383
{
384
    return reverse_iterator(end());
385
}
386
387
auto
388
array::
389
rbegin() const noexcept ->
390
    const_reverse_iterator
391
{
392
    return const_reverse_iterator(end());
393
}
394
395
auto
396
array::
397
crbegin() const noexcept ->
398
    const_reverse_iterator
399
{
400
    return const_reverse_iterator(end());
401
}
402
403
auto
404
array::
405
rend() noexcept ->
406
    reverse_iterator
407
{
408
    return reverse_iterator(begin());
409
}
410
411
auto
412
array::
413
rend() const noexcept ->
414
    const_reverse_iterator
415
{
416
    return const_reverse_iterator(begin());
417
}
418
419
auto
420
array::
421
crend() const noexcept ->
422
    const_reverse_iterator
423
{
424
    return const_reverse_iterator(begin());
425
}
426
427
//----------------------------------------------------------
428
//
429
// Capacity
430
//
431
//----------------------------------------------------------
432
433
std::size_t
434
array::
435
size() const noexcept
436
0
{
437
0
    return t_->size;
438
0
}
439
440
constexpr
441
std::size_t
442
array::
443
max_size() noexcept
444
1.18k
{
445
    // max_size depends on the address model
446
1.18k
    using min = std::integral_constant<std::size_t,
447
1.18k
        (std::size_t(-1) - sizeof(table)) / sizeof(value)>;
448
1.18k
    return min::value < BOOST_JSON_MAX_STRUCTURED_SIZE ?
449
1.18k
        min::value : BOOST_JSON_MAX_STRUCTURED_SIZE;
450
1.18k
}
451
452
std::size_t
453
array::
454
capacity() const noexcept
455
0
{
456
0
    return t_->capacity;
457
0
}
458
459
bool
460
array::
461
empty() const noexcept
462
0
{
463
0
    return t_->size == 0;
464
0
}
465
466
void
467
array::
468
reserve(
469
    std::size_t new_capacity)
470
0
{
471
    // never shrink
472
0
    if(new_capacity <= t_->capacity)
473
0
        return;
474
0
    reserve_impl(new_capacity);
475
0
}
476
477
//----------------------------------------------------------
478
//
479
// private
480
//
481
//----------------------------------------------------------
482
483
template<class InputIt>
484
array::
485
array(
486
    InputIt first, InputIt last,
487
    storage_ptr sp,
488
    std::input_iterator_tag)
489
    : sp_(std::move(sp))
490
    , t_(&empty_)
491
{
492
    revert_construct r(*this);
493
    while(first != last)
494
    {
495
        reserve(size() + 1);
496
        ::new(end()) value(
497
            *first++, sp_);
498
        ++t_->size;
499
    }
500
    r.commit();
501
}
502
503
template<class InputIt>
504
array::
505
array(
506
    InputIt first, InputIt last,
507
    storage_ptr sp,
508
    std::forward_iterator_tag)
509
    : sp_(std::move(sp))
510
{
511
    std::size_t n =
512
        std::distance(first, last);
513
    if( n == 0 )
514
    {
515
        t_ = &empty_;
516
        return;
517
    }
518
519
    t_ = table::allocate(n, sp_);
520
    t_->size = 0;
521
    revert_construct r(*this);
522
    while(n--)
523
    {
524
        ::new(end()) value(
525
            *first++, sp_);
526
        ++t_->size;
527
    }
528
    r.commit();
529
}
530
531
template<class InputIt>
532
auto
533
array::
534
insert(
535
    const_iterator pos,
536
    InputIt first, InputIt last,
537
    std::input_iterator_tag) ->
538
        iterator
539
{
540
    BOOST_ASSERT(
541
        pos >= begin() && pos <= end());
542
    if(first == last)
543
        return data() + (pos - data());
544
    array temp(first, last, sp_);
545
    revert_insert r(
546
        pos, temp.size(), *this);
547
    relocate(
548
        r.p,
549
        temp.data(),
550
        temp.size());
551
    temp.t_->size = 0;
552
    return r.commit();
553
}
554
555
template<class InputIt>
556
auto
557
array::
558
insert(
559
    const_iterator pos,
560
    InputIt first, InputIt last,
561
    std::forward_iterator_tag) ->
562
        iterator
563
{
564
    std::size_t n =
565
        std::distance(first, last);
566
    revert_insert r(pos, n, *this);
567
    while(n--)
568
    {
569
        ::new(r.p) value(*first++);
570
        ++r.p;
571
    }
572
    return r.commit();
573
}
574
575
} // namespace json
576
} // namespace boost
577
578
#endif