GCC Code Coverage Report


Directory: libs/json/include/boost/json/
File: impl/array.hpp
Date: 2025-12-23 17:20:53
Exec Total Coverage
Lines: 163 163 100.0%
Functions: 78 78 100.0%
Branches: 50 64 78.1%

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