1  
//
1  
//
2  
// Copyright (c) 2025 Vinnie Falco (vinnie.falco@gmail.com)
2  
// Copyright (c) 2025 Vinnie Falco (vinnie.falco@gmail.com)
3  
//
3  
//
4  
// Distributed under the Boost Software License, Version 1.0. (See accompanying
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)
5  
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6  
//
6  
//
7  
// Official repository: https://github.com/cppalliance/capy
7  
// Official repository: https://github.com/cppalliance/capy
8  
//
8  
//
9  

9  

10  
#include <boost/capy/buffers/buffer_array.hpp>
10  
#include <boost/capy/buffers/buffer_array.hpp>
11  

11  

12  
namespace boost {
12  
namespace boost {
13  
namespace capy {
13  
namespace capy {
14  
namespace detail {
14  
namespace detail {
15  

15  

16  
namespace {
16  
namespace {
17  

17  

18  
template<class Buffer>
18  
template<class Buffer>
19  
void
19  
void
20  
do_remove_prefix(
20  
do_remove_prefix(
21  
    Buffer* arr,
21  
    Buffer* arr,
22  
    std::size_t* count,
22  
    std::size_t* count,
23  
    std::size_t* total_size,
23  
    std::size_t* total_size,
24  
    std::size_t n) noexcept
24  
    std::size_t n) noexcept
25  
{
25  
{
26  
    if(n >= *total_size)
26  
    if(n >= *total_size)
27  
    {
27  
    {
28  
        while(*count > 0)
28  
        while(*count > 0)
29  
            arr[--(*count)].~Buffer();
29  
            arr[--(*count)].~Buffer();
30  
        *total_size = 0;
30  
        *total_size = 0;
31  
        return;
31  
        return;
32  
    }
32  
    }
33  

33  

34  
    std::size_t i = 0;
34  
    std::size_t i = 0;
35  
    while(i < *count && n > 0)
35  
    while(i < *count && n > 0)
36  
    {
36  
    {
37  
        auto& b = arr[i];
37  
        auto& b = arr[i];
38  
        if(n < b.size())
38  
        if(n < b.size())
39  
        {
39  
        {
40  
            b += n;
40  
            b += n;
41  
            *total_size -= n;
41  
            *total_size -= n;
42  
            break;
42  
            break;
43  
        }
43  
        }
44  
        n -= b.size();
44  
        n -= b.size();
45  
        *total_size -= b.size();
45  
        *total_size -= b.size();
46  
        b.~Buffer();
46  
        b.~Buffer();
47  
        ++i;
47  
        ++i;
48  
    }
48  
    }
49  

49  

50  
    // Compact: move remaining buffers to front
50  
    // Compact: move remaining buffers to front
51  
    if(i > 0)
51  
    if(i > 0)
52  
    {
52  
    {
53  
        std::size_t j = 0;
53  
        std::size_t j = 0;
54  
        while(i < *count)
54  
        while(i < *count)
55  
        {
55  
        {
56  
            arr[j] = arr[i];
56  
            arr[j] = arr[i];
57  
            arr[i].~Buffer();
57  
            arr[i].~Buffer();
58  
            ++i;
58  
            ++i;
59  
            ++j;
59  
            ++j;
60  
        }
60  
        }
61  
        *count = j;
61  
        *count = j;
62  
    }
62  
    }
63  
}
63  
}
64  

64  

65  
template<class Buffer>
65  
template<class Buffer>
66  
void
66  
void
67  
do_keep_prefix(
67  
do_keep_prefix(
68  
    Buffer* arr,
68  
    Buffer* arr,
69  
    std::size_t* count,
69  
    std::size_t* count,
70  
    std::size_t* total_size,
70  
    std::size_t* total_size,
71  
    std::size_t n) noexcept
71  
    std::size_t n) noexcept
72  
{
72  
{
73  
    if(n >= *total_size)
73  
    if(n >= *total_size)
74  
        return;
74  
        return;
75  

75  

76  
    if(n == 0)
76  
    if(n == 0)
77  
    {
77  
    {
78  
        while(*count > 0)
78  
        while(*count > 0)
79  
            arr[--(*count)].~Buffer();
79  
            arr[--(*count)].~Buffer();
80  
        *total_size = 0;
80  
        *total_size = 0;
81  
        return;
81  
        return;
82  
    }
82  
    }
83  

83  

84  
    std::size_t remaining = n;
84  
    std::size_t remaining = n;
85  
    std::size_t i = 0;
85  
    std::size_t i = 0;
86  
    while(i < *count && remaining > 0)
86  
    while(i < *count && remaining > 0)
87  
    {
87  
    {
88  
        auto& b = arr[i];
88  
        auto& b = arr[i];
89  
        if(remaining < b.size())
89  
        if(remaining < b.size())
90  
        {
90  
        {
91  
            b = Buffer(b.data(), remaining);
91  
            b = Buffer(b.data(), remaining);
92  
            ++i;
92  
            ++i;
93  
            break;
93  
            break;
94  
        }
94  
        }
95  
        remaining -= b.size();
95  
        remaining -= b.size();
96  
        ++i;
96  
        ++i;
97  
    }
97  
    }
98  

98  

99  
    // Destruct elements beyond the new count
99  
    // Destruct elements beyond the new count
100  
    while(*count > i)
100  
    while(*count > i)
101  
        arr[--(*count)].~Buffer();
101  
        arr[--(*count)].~Buffer();
102  

102  

103  
    *total_size = n;
103  
    *total_size = n;
104  
}
104  
}
105  

105  

106  
} // anonymous namespace
106  
} // anonymous namespace
107  

107  

108  
void
108  
void
109  
buffer_array_remove_prefix(
109  
buffer_array_remove_prefix(
110  
    const_buffer* arr,
110  
    const_buffer* arr,
111  
    std::size_t* count,
111  
    std::size_t* count,
112  
    std::size_t* total_size,
112  
    std::size_t* total_size,
113  
    std::size_t n) noexcept
113  
    std::size_t n) noexcept
114  
{
114  
{
115  
    do_remove_prefix(arr, count, total_size, n);
115  
    do_remove_prefix(arr, count, total_size, n);
116  
}
116  
}
117  

117  

118  
void
118  
void
119  
buffer_array_remove_prefix(
119  
buffer_array_remove_prefix(
120  
    mutable_buffer* arr,
120  
    mutable_buffer* arr,
121  
    std::size_t* count,
121  
    std::size_t* count,
122  
    std::size_t* total_size,
122  
    std::size_t* total_size,
123  
    std::size_t n) noexcept
123  
    std::size_t n) noexcept
124  
{
124  
{
125  
    do_remove_prefix(arr, count, total_size, n);
125  
    do_remove_prefix(arr, count, total_size, n);
126  
}
126  
}
127  

127  

128  
void
128  
void
129  
buffer_array_keep_prefix(
129  
buffer_array_keep_prefix(
130  
    const_buffer* arr,
130  
    const_buffer* arr,
131  
    std::size_t* count,
131  
    std::size_t* count,
132  
    std::size_t* total_size,
132  
    std::size_t* total_size,
133  
    std::size_t n) noexcept
133  
    std::size_t n) noexcept
134  
{
134  
{
135  
    do_keep_prefix(arr, count, total_size, n);
135  
    do_keep_prefix(arr, count, total_size, n);
136  
}
136  
}
137  

137  

138  
void
138  
void
139  
buffer_array_keep_prefix(
139  
buffer_array_keep_prefix(
140  
    mutable_buffer* arr,
140  
    mutable_buffer* arr,
141  
    std::size_t* count,
141  
    std::size_t* count,
142  
    std::size_t* total_size,
142  
    std::size_t* total_size,
143  
    std::size_t n) noexcept
143  
    std::size_t n) noexcept
144  
{
144  
{
145  
    do_keep_prefix(arr, count, total_size, n);
145  
    do_keep_prefix(arr, count, total_size, n);
146  
}
146  
}
147  

147  

148  
} // namespace detail
148  
} // namespace detail
149  
} // namespace capy
149  
} // namespace capy
150  
} // namespace boost
150  
} // namespace boost