Coverage Report

Created: 2025-01-23 06:32

/src/immer/immer/detail/arrays/with_capacity.hpp
Line
Count
Source (jump to first uncovered line)
1
//
2
// immer: immutable data structures for C++
3
// Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
4
//
5
// This software is distributed under the Boost Software License, Version 1.0.
6
// See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
7
//
8
9
#pragma once
10
11
#include <immer/config.hpp>
12
#include <immer/detail/arrays/no_capacity.hpp>
13
14
#include <cassert>
15
#include <cstddef>
16
#include <stdexcept>
17
18
namespace immer {
19
namespace detail {
20
namespace arrays {
21
22
template <typename T, typename MemoryPolicy>
23
struct with_capacity
24
{
25
    using no_capacity_t = no_capacity<T, MemoryPolicy>;
26
27
    using node_t = node<T, MemoryPolicy>;
28
    using edit_t = typename MemoryPolicy::transience_t::edit;
29
    using size_t = std::size_t;
30
31
    node_t* ptr;
32
    size_t size;
33
    size_t capacity;
34
35
    static const with_capacity& empty()
36
183k
    {
37
183k
        static const with_capacity empty_{node_t::make_n(1), 0, 1};
38
183k
        return empty_;
39
183k
    }
immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false> >::empty()
Line
Count
Source
36
22.1k
    {
37
22.1k
        static const with_capacity empty_{node_t::make_n(1), 0, 1};
38
22.1k
        return empty_;
39
22.1k
    }
immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >::empty()
Line
Count
Source
36
161k
    {
37
161k
        static const with_capacity empty_{node_t::make_n(1), 0, 1};
38
161k
        return empty_;
39
161k
    }
40
41
    with_capacity(node_t* p, size_t s, size_t c)
42
        : ptr{p}
43
        , size{s}
44
        , capacity{c}
45
377k
    {
46
377k
    }
immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false> >::with_capacity(immer::detail::arrays::node<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false> >*, unsigned long, unsigned long)
Line
Count
Source
45
53.3k
    {
46
53.3k
    }
immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >::with_capacity(immer::detail::arrays::node<int, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >*, unsigned long, unsigned long)
Line
Count
Source
45
324k
    {
46
324k
    }
47
48
    with_capacity(const with_capacity& other)
49
        : with_capacity{other.ptr, other.size, other.capacity}
50
183k
    {
51
183k
        inc();
52
183k
    }
immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false> >::with_capacity(immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false> > const&)
Line
Count
Source
50
22.1k
    {
51
22.1k
        inc();
52
22.1k
    }
immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >::with_capacity(immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> > const&)
Line
Count
Source
50
161k
    {
51
161k
        inc();
52
161k
    }
53
54
    with_capacity(const no_capacity_t& other)
55
        : with_capacity{other.ptr, other.size, other.size}
56
18.1k
    {
57
18.1k
        inc();
58
18.1k
    }
59
60
    with_capacity(with_capacity&& other)
61
        : with_capacity{empty()}
62
176k
    {
63
176k
        swap(*this, other);
64
176k
    }
immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false> >::with_capacity(immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false> >&&)
Line
Count
Source
62
18.1k
    {
63
18.1k
        swap(*this, other);
64
18.1k
    }
immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >::with_capacity(immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >&&)
Line
Count
Source
62
158k
    {
63
158k
        swap(*this, other);
64
158k
    }
65
66
    with_capacity& operator=(const with_capacity& other)
67
    {
68
        auto next = other;
69
        swap(*this, next);
70
        return *this;
71
    }
72
73
    with_capacity& operator=(with_capacity&& other)
74
404k
    {
75
404k
        swap(*this, other);
76
404k
        return *this;
77
404k
    }
immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false> >::operator=(immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false> >&&)
Line
Count
Source
74
31.2k
    {
75
31.2k
        swap(*this, other);
76
31.2k
        return *this;
77
31.2k
    }
immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >::operator=(immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >&&)
Line
Count
Source
74
373k
    {
75
373k
        swap(*this, other);
76
373k
        return *this;
77
373k
    }
78
79
    friend void swap(with_capacity& x, with_capacity& y)
80
581k
    {
81
581k
        using std::swap;
82
581k
        swap(x.ptr, y.ptr);
83
581k
        swap(x.size, y.size);
84
581k
        swap(x.capacity, y.capacity);
85
581k
    }
immer::detail::arrays::swap(immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false> >&, immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false> >&)
Line
Count
Source
80
49.4k
    {
81
49.4k
        using std::swap;
82
49.4k
        swap(x.ptr, y.ptr);
83
49.4k
        swap(x.size, y.size);
84
49.4k
        swap(x.capacity, y.capacity);
85
49.4k
    }
immer::detail::arrays::swap(immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >&, immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >&)
Line
Count
Source
80
532k
    {
81
532k
        using std::swap;
82
532k
        swap(x.ptr, y.ptr);
83
532k
        swap(x.size, y.size);
84
532k
        swap(x.capacity, y.capacity);
85
532k
    }
86
87
377k
    ~with_capacity() { dec(); }
immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false> >::~with_capacity()
Line
Count
Source
87
53.3k
    ~with_capacity() { dec(); }
immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >::~with_capacity()
Line
Count
Source
87
324k
    ~with_capacity() { dec(); }
88
89
    void inc()
90
201k
    {
91
201k
        using immer::detail::get;
92
201k
        ptr->refs().inc();
93
201k
    }
immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false> >::inc()
Line
Count
Source
90
40.2k
    {
91
40.2k
        using immer::detail::get;
92
40.2k
        ptr->refs().inc();
93
40.2k
    }
immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >::inc()
Line
Count
Source
90
161k
    {
91
161k
        using immer::detail::get;
92
161k
        ptr->refs().inc();
93
161k
    }
94
95
    void dec()
96
377k
    {
97
377k
        using immer::detail::get;
98
377k
        if (ptr->refs().dec())
99
163k
            node_t::delete_n(ptr, size, capacity);
100
377k
    }
immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false> >::dec()
Line
Count
Source
96
53.3k
    {
97
53.3k
        using immer::detail::get;
98
53.3k
        if (ptr->refs().dec())
99
0
            node_t::delete_n(ptr, size, capacity);
100
53.3k
    }
immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >::dec()
Line
Count
Source
96
324k
    {
97
324k
        using immer::detail::get;
98
324k
        if (ptr->refs().dec())
99
163k
            node_t::delete_n(ptr, size, capacity);
100
324k
    }
101
102
    const T* data() const { return ptr->data(); }
103
1.67M
    T* data() { return ptr->data(); }
immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false> >::data()
Line
Count
Source
103
1.47M
    T* data() { return ptr->data(); }
immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >::data()
Line
Count
Source
103
205k
    T* data() { return ptr->data(); }
104
105
    T* data_mut(edit_t e)
106
    {
107
        if (!ptr->can_mutate(e)) {
108
            auto p = node_t::copy_e(e, capacity, ptr, size);
109
            dec();
110
            ptr = p;
111
        }
112
        return data();
113
    }
114
115
    operator no_capacity_t() const
116
2.74k
    {
117
2.74k
        if (size == capacity) {
118
1.05k
            ptr->refs().inc();
119
1.05k
            return {ptr, size};
120
1.69k
        } else {
121
1.69k
            return {node_t::copy_n(size, ptr, size), size};
122
1.69k
        }
123
2.74k
    }
124
125
    template <typename Iter,
126
              typename Sent,
127
              std::enable_if_t<is_forward_iterator_v<Iter> &&
128
                                   compatible_sentinel_v<Iter, Sent>,
129
                               bool> = true>
130
    static with_capacity from_range(Iter first, Sent last)
131
    {
132
        auto count = static_cast<size_t>(detail::distance(first, last));
133
        if (count == 0)
134
            return empty();
135
        else
136
            return {node_t::copy_n(count, first, last), count, count};
137
    }
138
139
    template <typename U>
140
    static with_capacity from_initializer_list(std::initializer_list<U> values)
141
    {
142
        using namespace std;
143
        return from_range(begin(values), end(values));
144
    }
145
146
    static with_capacity from_fill(size_t n, T v)
147
    {
148
        return {node_t::fill_n(n, v), n, n};
149
    }
150
151
    template <typename Fn>
152
    void for_each_chunk(Fn&& fn) const
153
    {
154
        std::forward<Fn>(fn)(data(), data() + size);
155
    }
156
157
    template <typename Fn>
158
    bool for_each_chunk_p(Fn&& fn) const
159
    {
160
        return std::forward<Fn>(fn)(data(), data() + size);
161
    }
162
163
    const T& get(std::size_t index) const { return data()[index]; }
164
165
    const T& get_check(std::size_t index) const
166
    {
167
        if (index >= size)
168
            IMMER_THROW(std::out_of_range{"out of range"});
169
        return data()[index];
170
    }
171
172
    bool equals(const with_capacity& other) const
173
    {
174
        return ptr == other.ptr ||
175
               (size == other.size &&
176
                std::equal(data(), data() + size, other.data()));
177
    }
178
179
    static size_t recommend_up(size_t sz, size_t cap)
180
163k
    {
181
163k
        auto max = std::numeric_limits<size_t>::max();
182
163k
        return sz <= cap        ? cap
183
163k
               : cap >= max / 2 ? max
184
                                /* otherwise */
185
22.0k
                                : std::max(2 * cap, sz);
186
163k
    }
immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false> >::recommend_up(unsigned long, unsigned long)
Line
Count
Source
180
11.6k
    {
181
11.6k
        auto max = std::numeric_limits<size_t>::max();
182
11.6k
        return sz <= cap        ? cap
183
11.6k
               : cap >= max / 2 ? max
184
                                /* otherwise */
185
10.4k
                                : std::max(2 * cap, sz);
186
11.6k
    }
immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >::recommend_up(unsigned long, unsigned long)
Line
Count
Source
180
152k
    {
181
152k
        auto max = std::numeric_limits<size_t>::max();
182
152k
        return sz <= cap        ? cap
183
152k
               : cap >= max / 2 ? max
184
                                /* otherwise */
185
11.5k
                                : std::max(2 * cap, sz);
186
152k
    }
187
188
    static size_t recommend_down(size_t sz, size_t cap)
189
6.99k
    {
190
6.99k
        return sz == 0        ? 1
191
6.99k
               : sz < cap / 2 ? sz * 2
192
3.92k
                              :
193
3.92k
                              /* otherwise */ cap;
194
6.99k
    }
immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false> >::recommend_down(unsigned long, unsigned long)
Line
Count
Source
189
1.22k
    {
190
1.22k
        return sz == 0        ? 1
191
1.22k
               : sz < cap / 2 ? sz * 2
192
673
                              :
193
673
                              /* otherwise */ cap;
194
1.22k
    }
immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >::recommend_down(unsigned long, unsigned long)
Line
Count
Source
189
5.76k
    {
190
5.76k
        return sz == 0        ? 1
191
5.76k
               : sz < cap / 2 ? sz * 2
192
3.25k
                              :
193
3.25k
                              /* otherwise */ cap;
194
5.76k
    }
195
196
    with_capacity push_back(T value) const
197
147k
    {
198
147k
        auto cap = recommend_up(size + 1, capacity);
199
147k
        auto p   = node_t::copy_n(cap, ptr, size);
200
147k
        IMMER_TRY {
201
147k
            new (p->data() + size) T{std::move(value)};
202
147k
            return {p, size + 1, cap};
203
147k
        }
204
147k
        IMMER_CATCH (...) {
205
0
            node_t::delete_n(p, size, cap);
206
0
            IMMER_RETHROW;
207
0
        }
208
147k
    }
209
210
    void push_back_mut(edit_t e, T value)
211
1.68M
    {
212
1.68M
        if (ptr->can_mutate(e) && capacity > size) {
213
1.66M
            new (data() + size) T{std::move(value)};
214
1.66M
            ++size;
215
1.66M
        } else {
216
16.1k
            auto cap = recommend_up(size + 1, capacity);
217
16.1k
            auto p   = node_t::copy_e(e, cap, ptr, size);
218
16.1k
            IMMER_TRY {
219
16.1k
                new (p->data() + size) T{std::move(value)};
220
16.1k
                *this = {p, size + 1, cap};
221
16.1k
            }
222
16.1k
            IMMER_CATCH (...) {
223
0
                node_t::delete_n(p, size, cap);
224
0
                IMMER_RETHROW;
225
0
            }
226
16.1k
        }
227
1.68M
    }
immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false> >::push_back_mut(immer::gc_transience_policy::apply<immer::heap_policy<immer::gc_heap> >::type::edit, int)
Line
Count
Source
211
1.48M
    {
212
1.48M
        if (ptr->can_mutate(e) && capacity > size) {
213
1.47M
            new (data() + size) T{std::move(value)};
214
1.47M
            ++size;
215
1.47M
        } else {
216
11.6k
            auto cap = recommend_up(size + 1, capacity);
217
11.6k
            auto p   = node_t::copy_e(e, cap, ptr, size);
218
11.6k
            IMMER_TRY {
219
11.6k
                new (p->data() + size) T{std::move(value)};
220
11.6k
                *this = {p, size + 1, cap};
221
11.6k
            }
222
11.6k
            IMMER_CATCH (...) {
223
0
                node_t::delete_n(p, size, cap);
224
0
                IMMER_RETHROW;
225
0
            }
226
11.6k
        }
227
1.48M
    }
immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >::push_back_mut(immer::no_transience_policy::apply<immer::free_list_heap_policy<immer::cpp_heap, 1024ul> >::type::edit, int)
Line
Count
Source
211
201k
    {
212
201k
        if (ptr->can_mutate(e) && capacity > size) {
213
196k
            new (data() + size) T{std::move(value)};
214
196k
            ++size;
215
196k
        } else {
216
4.57k
            auto cap = recommend_up(size + 1, capacity);
217
4.57k
            auto p   = node_t::copy_e(e, cap, ptr, size);
218
4.57k
            IMMER_TRY {
219
4.57k
                new (p->data() + size) T{std::move(value)};
220
4.57k
                *this = {p, size + 1, cap};
221
4.57k
            }
222
4.57k
            IMMER_CATCH (...) {
223
0
                node_t::delete_n(p, size, cap);
224
0
                IMMER_RETHROW;
225
0
            }
226
4.57k
        }
227
201k
    }
228
229
    with_capacity assoc(std::size_t idx, T value) const
230
    {
231
        auto p = node_t::copy_n(capacity, ptr, size);
232
        IMMER_TRY {
233
            p->data()[idx] = std::move(value);
234
            return {p, size, capacity};
235
        }
236
        IMMER_CATCH (...) {
237
            node_t::delete_n(p, size, capacity);
238
            IMMER_RETHROW;
239
        }
240
    }
241
242
    void assoc_mut(edit_t e, std::size_t idx, T value)
243
    {
244
        if (ptr->can_mutate(e)) {
245
            data()[idx] = std::move(value);
246
        } else {
247
            auto p = node_t::copy_n(capacity, ptr, size);
248
            IMMER_TRY {
249
                p->data()[idx] = std::move(value);
250
                *this          = {p, size, capacity};
251
            }
252
            IMMER_CATCH (...) {
253
                node_t::delete_n(p, size, capacity);
254
                IMMER_RETHROW;
255
            }
256
        }
257
    }
258
259
    template <typename Fn>
260
    with_capacity update(std::size_t idx, Fn&& op) const
261
5.06k
    {
262
5.06k
        auto p = node_t::copy_n(capacity, ptr, size);
263
5.06k
        IMMER_TRY {
264
5.06k
            auto& elem = p->data()[idx];
265
5.06k
            elem       = std::forward<Fn>(op)(std::move(elem));
266
5.06k
            return {p, size, capacity};
267
5.06k
        }
268
5.06k
        IMMER_CATCH (...) {
269
0
            node_t::delete_n(p, size, capacity);
270
0
            IMMER_RETHROW;
271
0
        }
272
5.06k
    }
273
274
    template <typename Fn>
275
    void update_mut(edit_t e, std::size_t idx, Fn&& op)
276
7.51k
    {
277
7.51k
        if (ptr->can_mutate(e)) {
278
7.27k
            auto& elem = data()[idx];
279
7.27k
            elem       = std::forward<Fn>(op)(std::move(elem));
280
7.27k
        } else {
281
243
            auto p = node_t::copy_e(e, capacity, ptr, size);
282
243
            IMMER_TRY {
283
243
                auto& elem = p->data()[idx];
284
243
                elem       = std::forward<Fn>(op)(std::move(elem));
285
243
                *this      = {p, size, capacity};
286
243
            }
287
243
            IMMER_CATCH (...) {
288
0
                node_t::delete_n(p, size, capacity);
289
0
                IMMER_RETHROW;
290
0
            }
291
243
        }
292
7.51k
    }
array-gc.cpp:void immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false> >::update_mut<LLVMFuzzerTestOneInput::$_4::operator()<fuzzer_input>(fuzzer_input&) const::{lambda(auto:1)#2}>(immer::gc_transience_policy::apply<immer::heap_policy<immer::gc_heap> >::type::edit, unsigned long, fuzzer_input&&)
Line
Count
Source
276
872
    {
277
872
        if (ptr->can_mutate(e)) {
278
629
            auto& elem = data()[idx];
279
629
            elem       = std::forward<Fn>(op)(std::move(elem));
280
629
        } else {
281
243
            auto p = node_t::copy_e(e, capacity, ptr, size);
282
243
            IMMER_TRY {
283
243
                auto& elem = p->data()[idx];
284
243
                elem       = std::forward<Fn>(op)(std::move(elem));
285
243
                *this      = {p, size, capacity};
286
243
            }
287
243
            IMMER_CATCH (...) {
288
0
                node_t::delete_n(p, size, capacity);
289
0
                IMMER_RETHROW;
290
0
            }
291
243
        }
292
872
    }
array.cpp:void immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >::update_mut<LLVMFuzzerTestOneInput::$_4::operator()<fuzzer_input>(fuzzer_input&) const::{lambda(auto:1)#2}>(immer::no_transience_policy::apply<immer::free_list_heap_policy<immer::cpp_heap, 1024ul> >::type::edit, unsigned long, fuzzer_input&&)
Line
Count
Source
276
6.64k
    {
277
6.64k
        if (ptr->can_mutate(e)) {
278
6.64k
            auto& elem = data()[idx];
279
6.64k
            elem       = std::forward<Fn>(op)(std::move(elem));
280
6.64k
        } else {
281
0
            auto p = node_t::copy_e(e, capacity, ptr, size);
282
0
            IMMER_TRY {
283
0
                auto& elem = p->data()[idx];
284
0
                elem       = std::forward<Fn>(op)(std::move(elem));
285
0
                *this      = {p, size, capacity};
286
0
            }
287
0
            IMMER_CATCH (...) {
288
0
                node_t::delete_n(p, size, capacity);
289
0
                IMMER_RETHROW;
290
0
            }
291
0
        }
292
6.64k
    }
293
294
    with_capacity take(std::size_t sz) const
295
5.67k
    {
296
5.67k
        assert(sz <= size);
297
0
        auto cap = recommend_down(sz, capacity);
298
5.67k
        auto p   = node_t::copy_n(cap, ptr, sz);
299
5.67k
        return {p, sz, cap};
300
5.67k
    }
301
302
    void take_mut(edit_t e, std::size_t sz)
303
5.47k
    {
304
5.47k
        assert(sz <= size);
305
5.47k
        if (ptr->can_mutate(e)) {
306
4.16k
            detail::destroy_n(data() + size, size - sz);
307
4.16k
            size = sz;
308
4.16k
        } else {
309
1.31k
            auto cap = recommend_down(sz, capacity);
310
1.31k
            auto p   = node_t::copy_e(e, cap, ptr, sz);
311
1.31k
            *this    = {p, sz, cap};
312
1.31k
        }
313
5.47k
    }
immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::heap_policy<immer::gc_heap>, immer::no_refcount_policy, immer::spinlock_policy, immer::gc_transience_policy, false, false> >::take_mut(immer::gc_transience_policy::apply<immer::heap_policy<immer::gc_heap> >::type::edit, unsigned long)
Line
Count
Source
303
3.19k
    {
304
3.19k
        assert(sz <= size);
305
3.19k
        if (ptr->can_mutate(e)) {
306
1.97k
            detail::destroy_n(data() + size, size - sz);
307
1.97k
            size = sz;
308
1.97k
        } else {
309
1.22k
            auto cap = recommend_down(sz, capacity);
310
1.22k
            auto p   = node_t::copy_e(e, cap, ptr, sz);
311
1.22k
            *this    = {p, sz, cap};
312
1.22k
        }
313
3.19k
    }
immer::detail::arrays::with_capacity<int, immer::memory_policy<immer::free_list_heap_policy<immer::cpp_heap, 1024ul>, immer::refcount_policy, immer::spinlock_policy, immer::no_transience_policy, false, true> >::take_mut(immer::no_transience_policy::apply<immer::free_list_heap_policy<immer::cpp_heap, 1024ul> >::type::edit, unsigned long)
Line
Count
Source
303
2.28k
    {
304
2.28k
        assert(sz <= size);
305
2.28k
        if (ptr->can_mutate(e)) {
306
2.18k
            detail::destroy_n(data() + size, size - sz);
307
2.18k
            size = sz;
308
2.18k
        } else {
309
93
            auto cap = recommend_down(sz, capacity);
310
93
            auto p   = node_t::copy_e(e, cap, ptr, sz);
311
93
            *this    = {p, sz, cap};
312
93
        }
313
2.28k
    }
314
};
315
316
} // namespace arrays
317
} // namespace detail
318
} // namespace immer