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  
#ifndef BOOST_CAPY_BUFFERS_SOME_BUFFERS_HPP
10  
#ifndef BOOST_CAPY_BUFFERS_SOME_BUFFERS_HPP
11  
#define BOOST_CAPY_BUFFERS_SOME_BUFFERS_HPP
11  
#define BOOST_CAPY_BUFFERS_SOME_BUFFERS_HPP
12  

12  

13  
#include <boost/capy/detail/config.hpp>
13  
#include <boost/capy/detail/config.hpp>
14  
#include <boost/capy/buffers.hpp>
14  
#include <boost/capy/buffers.hpp>
15  

15  

16  
#include <cstddef>
16  
#include <cstddef>
17  
#include <new>
17  
#include <new>
18  

18  

19  
namespace boost {
19  
namespace boost {
20  
namespace capy {
20  
namespace capy {
21  

21  

22  
namespace detail {
22  
namespace detail {
23  

23  

24  
template<class Buffer, class BS>
24  
template<class Buffer, class BS>
25  
std::size_t
25  
std::size_t
26  
fill_buffers(Buffer* arr, BS const& bs) noexcept
26  
fill_buffers(Buffer* arr, BS const& bs) noexcept
27  
{
27  
{
28  
    auto it = begin(bs);
28  
    auto it = begin(bs);
29  
    auto const last = end(bs);
29  
    auto const last = end(bs);
30  
    std::size_t n = 0;
30  
    std::size_t n = 0;
31  
    while(it != last && n < max_iovec_)
31  
    while(it != last && n < max_iovec_)
32  
    {
32  
    {
33  
        Buffer b(*it);
33  
        Buffer b(*it);
34  
        if(b.size() != 0)
34  
        if(b.size() != 0)
35  
            ::new(&arr[n++]) Buffer(b);
35  
            ::new(&arr[n++]) Buffer(b);
36  
        ++it;
36  
        ++it;
37  
    }
37  
    }
38  
    return n;
38  
    return n;
39  
}
39  
}
40  

40  

41  
} // detail
41  
} // detail
42  

42  

43  
//------------------------------------------------
43  
//------------------------------------------------
44  

44  

45  
/** A buffer sequence holding up to max_iovec_ const buffers.
45  
/** A buffer sequence holding up to max_iovec_ const buffers.
46  

46  

47  
    This class stores a fixed-size array of const_buffer
47  
    This class stores a fixed-size array of const_buffer
48  
    descriptors, populated from an arbitrary buffer sequence.
48  
    descriptors, populated from an arbitrary buffer sequence.
49  
    It provides efficient storage for small buffer sequences
49  
    It provides efficient storage for small buffer sequences
50  
    without dynamic allocation.
50  
    without dynamic allocation.
51  

51  

52  
    @par Usage
52  
    @par Usage
53  

53  

54  
    @code
54  
    @code
55  
    void process(ConstBufferSequence auto const& buffers)
55  
    void process(ConstBufferSequence auto const& buffers)
56  
    {
56  
    {
57  
        some_const_buffers bufs(buffers);
57  
        some_const_buffers bufs(buffers);
58  
        // use bufs.data(), bufs.size()
58  
        // use bufs.data(), bufs.size()
59  
    }
59  
    }
60  
    @endcode
60  
    @endcode
61  
*/
61  
*/
62  
class some_const_buffers
62  
class some_const_buffers
63  
{
63  
{
64  
    std::size_t n_ = 0;
64  
    std::size_t n_ = 0;
65  
    union {
65  
    union {
66  
        int dummy_;
66  
        int dummy_;
67  
        const_buffer arr_[detail::max_iovec_];
67  
        const_buffer arr_[detail::max_iovec_];
68  
    };
68  
    };
69  

69  

70  
public:
70  
public:
71  
    /** Default constructor.
71  
    /** Default constructor.
72  

72  

73  
        Constructs an empty buffer sequence.
73  
        Constructs an empty buffer sequence.
74  
    */
74  
    */
75  
    some_const_buffers() noexcept
75  
    some_const_buffers() noexcept
76  
        : dummy_(0)
76  
        : dummy_(0)
77  
    {
77  
    {
78  
    }
78  
    }
79  

79  

80  
    /** Copy constructor.
80  
    /** Copy constructor.
81  
    */
81  
    */
82  
    some_const_buffers(some_const_buffers const& other) noexcept
82  
    some_const_buffers(some_const_buffers const& other) noexcept
83  
        : n_(other.n_)
83  
        : n_(other.n_)
84  
    {
84  
    {
85  
        for(std::size_t i = 0; i < n_; ++i)
85  
        for(std::size_t i = 0; i < n_; ++i)
86  
            ::new(&arr_[i]) const_buffer(other.arr_[i]);
86  
            ::new(&arr_[i]) const_buffer(other.arr_[i]);
87  
    }
87  
    }
88  

88  

89  
    /** Construct from a buffer sequence.
89  
    /** Construct from a buffer sequence.
90  

90  

91  
        Copies up to @ref detail::max_iovec_ buffer descriptors
91  
        Copies up to @ref detail::max_iovec_ buffer descriptors
92  
        from the source sequence into the internal array.
92  
        from the source sequence into the internal array.
93  

93  

94  
        @param bs The buffer sequence to copy from.
94  
        @param bs The buffer sequence to copy from.
95  
    */
95  
    */
96  
    template<ConstBufferSequence BS>
96  
    template<ConstBufferSequence BS>
97  
    some_const_buffers(BS const& bs) noexcept
97  
    some_const_buffers(BS const& bs) noexcept
98  
        : n_(detail::fill_buffers(arr_, bs))
98  
        : n_(detail::fill_buffers(arr_, bs))
99  
    {
99  
    {
100  
    }
100  
    }
101  

101  

102  
    /** Destructor.
102  
    /** Destructor.
103  
    */
103  
    */
104  
    ~some_const_buffers()
104  
    ~some_const_buffers()
105  
    {
105  
    {
106  
        while(n_--)
106  
        while(n_--)
107  
            arr_[n_].~const_buffer();
107  
            arr_[n_].~const_buffer();
108  
    }
108  
    }
109  

109  

110  
    /** Return a pointer to the buffer array.
110  
    /** Return a pointer to the buffer array.
111  
    */
111  
    */
112  
    const_buffer*
112  
    const_buffer*
113  
    data() noexcept
113  
    data() noexcept
114  
    {
114  
    {
115  
        return arr_;
115  
        return arr_;
116  
    }
116  
    }
117  

117  

118  
    /** Return a pointer to the buffer array.
118  
    /** Return a pointer to the buffer array.
119  
    */
119  
    */
120  
    const_buffer const*
120  
    const_buffer const*
121  
    data() const noexcept
121  
    data() const noexcept
122  
    {
122  
    {
123  
        return arr_;
123  
        return arr_;
124  
    }
124  
    }
125  

125  

126  
    /** Return the number of buffers.
126  
    /** Return the number of buffers.
127  
    */
127  
    */
128  
    std::size_t
128  
    std::size_t
129  
    size() const noexcept
129  
    size() const noexcept
130  
    {
130  
    {
131  
        return n_;
131  
        return n_;
132  
    }
132  
    }
133  

133  

134  
    /** Return an iterator to the beginning.
134  
    /** Return an iterator to the beginning.
135  
    */
135  
    */
136  
    const_buffer*
136  
    const_buffer*
137  
    begin() noexcept
137  
    begin() noexcept
138  
    {
138  
    {
139  
        return arr_;
139  
        return arr_;
140  
    }
140  
    }
141  

141  

142  
    /** Return an iterator to the beginning.
142  
    /** Return an iterator to the beginning.
143  
    */
143  
    */
144  
    const_buffer const*
144  
    const_buffer const*
145  
    begin() const noexcept
145  
    begin() const noexcept
146  
    {
146  
    {
147  
        return arr_;
147  
        return arr_;
148  
    }
148  
    }
149  

149  

150  
    /** Return an iterator to the end.
150  
    /** Return an iterator to the end.
151  
    */
151  
    */
152  
    const_buffer*
152  
    const_buffer*
153  
    end() noexcept
153  
    end() noexcept
154  
    {
154  
    {
155  
        return arr_ + n_;
155  
        return arr_ + n_;
156  
    }
156  
    }
157  

157  

158  
    /** Return an iterator to the end.
158  
    /** Return an iterator to the end.
159  
    */
159  
    */
160  
    const_buffer const*
160  
    const_buffer const*
161  
    end() const noexcept
161  
    end() const noexcept
162  
    {
162  
    {
163  
        return arr_ + n_;
163  
        return arr_ + n_;
164  
    }
164  
    }
165  
};
165  
};
166  

166  

167  
//------------------------------------------------
167  
//------------------------------------------------
168  

168  

169  
/** A buffer sequence holding up to max_iovec_ mutable buffers.
169  
/** A buffer sequence holding up to max_iovec_ mutable buffers.
170  

170  

171  
    This class stores a fixed-size array of mutable_buffer
171  
    This class stores a fixed-size array of mutable_buffer
172  
    descriptors, populated from an arbitrary buffer sequence.
172  
    descriptors, populated from an arbitrary buffer sequence.
173  
    It provides efficient storage for small buffer sequences
173  
    It provides efficient storage for small buffer sequences
174  
    without dynamic allocation.
174  
    without dynamic allocation.
175  

175  

176  
    @par Usage
176  
    @par Usage
177  

177  

178  
    @code
178  
    @code
179  
    void process(MutableBufferSequence auto const& buffers)
179  
    void process(MutableBufferSequence auto const& buffers)
180  
    {
180  
    {
181  
        some_mutable_buffers bufs(buffers);
181  
        some_mutable_buffers bufs(buffers);
182  
        // use bufs.data(), bufs.size()
182  
        // use bufs.data(), bufs.size()
183  
    }
183  
    }
184  
    @endcode
184  
    @endcode
185  
*/
185  
*/
186  
class some_mutable_buffers
186  
class some_mutable_buffers
187  
{
187  
{
188  
    std::size_t n_ = 0;
188  
    std::size_t n_ = 0;
189  
    union {
189  
    union {
190  
        int dummy_;
190  
        int dummy_;
191  
        mutable_buffer arr_[detail::max_iovec_];
191  
        mutable_buffer arr_[detail::max_iovec_];
192  
    };
192  
    };
193  

193  

194  
public:
194  
public:
195  
    /** Default constructor.
195  
    /** Default constructor.
196  

196  

197  
        Constructs an empty buffer sequence.
197  
        Constructs an empty buffer sequence.
198  
    */
198  
    */
199  
    some_mutable_buffers() noexcept
199  
    some_mutable_buffers() noexcept
200  
        : dummy_(0)
200  
        : dummy_(0)
201  
    {
201  
    {
202  
    }
202  
    }
203  

203  

204  
    /** Copy constructor.
204  
    /** Copy constructor.
205  
    */
205  
    */
206  
    some_mutable_buffers(some_mutable_buffers const& other) noexcept
206  
    some_mutable_buffers(some_mutable_buffers const& other) noexcept
207  
        : n_(other.n_)
207  
        : n_(other.n_)
208  
    {
208  
    {
209  
        for(std::size_t i = 0; i < n_; ++i)
209  
        for(std::size_t i = 0; i < n_; ++i)
210  
            ::new(&arr_[i]) mutable_buffer(other.arr_[i]);
210  
            ::new(&arr_[i]) mutable_buffer(other.arr_[i]);
211  
    }
211  
    }
212  

212  

213  
    /** Construct from a buffer sequence.
213  
    /** Construct from a buffer sequence.
214  

214  

215  
        Copies up to @ref detail::max_iovec_ buffer descriptors
215  
        Copies up to @ref detail::max_iovec_ buffer descriptors
216  
        from the source sequence into the internal array.
216  
        from the source sequence into the internal array.
217  

217  

218  
        @param bs The buffer sequence to copy from.
218  
        @param bs The buffer sequence to copy from.
219  
    */
219  
    */
220  
    template<MutableBufferSequence BS>
220  
    template<MutableBufferSequence BS>
221  
    some_mutable_buffers(BS const& bs) noexcept
221  
    some_mutable_buffers(BS const& bs) noexcept
222  
        : n_(detail::fill_buffers(arr_, bs))
222  
        : n_(detail::fill_buffers(arr_, bs))
223  
    {
223  
    {
224  
    }
224  
    }
225  

225  

226  
    /** Destructor.
226  
    /** Destructor.
227  
    */
227  
    */
228  
    ~some_mutable_buffers()
228  
    ~some_mutable_buffers()
229  
    {
229  
    {
230  
        while(n_--)
230  
        while(n_--)
231  
            arr_[n_].~mutable_buffer();
231  
            arr_[n_].~mutable_buffer();
232  
    }
232  
    }
233  

233  

234  
    /** Return a pointer to the buffer array.
234  
    /** Return a pointer to the buffer array.
235  
    */
235  
    */
236  
    mutable_buffer*
236  
    mutable_buffer*
237  
    data() noexcept
237  
    data() noexcept
238  
    {
238  
    {
239  
        return arr_;
239  
        return arr_;
240  
    }
240  
    }
241  

241  

242  
    /** Return a pointer to the buffer array.
242  
    /** Return a pointer to the buffer array.
243  
    */
243  
    */
244  
    mutable_buffer const*
244  
    mutable_buffer const*
245  
    data() const noexcept
245  
    data() const noexcept
246  
    {
246  
    {
247  
        return arr_;
247  
        return arr_;
248  
    }
248  
    }
249  

249  

250  
    /** Return the number of buffers.
250  
    /** Return the number of buffers.
251  
    */
251  
    */
252  
    std::size_t
252  
    std::size_t
253  
    size() const noexcept
253  
    size() const noexcept
254  
    {
254  
    {
255  
        return n_;
255  
        return n_;
256  
    }
256  
    }
257  

257  

258  
    /** Return an iterator to the beginning.
258  
    /** Return an iterator to the beginning.
259  
    */
259  
    */
260  
    mutable_buffer*
260  
    mutable_buffer*
261  
    begin() noexcept
261  
    begin() noexcept
262  
    {
262  
    {
263  
        return arr_;
263  
        return arr_;
264  
    }
264  
    }
265  

265  

266  
    /** Return an iterator to the beginning.
266  
    /** Return an iterator to the beginning.
267  
    */
267  
    */
268  
    mutable_buffer const*
268  
    mutable_buffer const*
269  
    begin() const noexcept
269  
    begin() const noexcept
270  
    {
270  
    {
271  
        return arr_;
271  
        return arr_;
272  
    }
272  
    }
273  

273  

274  
    /** Return an iterator to the end.
274  
    /** Return an iterator to the end.
275  
    */
275  
    */
276  
    mutable_buffer*
276  
    mutable_buffer*
277  
    end() noexcept
277  
    end() noexcept
278  
    {
278  
    {
279  
        return arr_ + n_;
279  
        return arr_ + n_;
280  
    }
280  
    }
281  

281  

282  
    /** Return an iterator to the end.
282  
    /** Return an iterator to the end.
283  
    */
283  
    */
284  
    mutable_buffer const*
284  
    mutable_buffer const*
285  
    end() const noexcept
285  
    end() const noexcept
286  
    {
286  
    {
287  
        return arr_ + n_;
287  
        return arr_ + n_;
288  
    }
288  
    }
289  
};
289  
};
290  

290  

291  
} // namespace capy
291  
} // namespace capy
292  
} // namespace boost
292  
} // namespace boost
293  

293  

294  
#endif
294  
#endif