1  
//
1  
//
2  
// Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com)
2  
// Copyright (c) 2023 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/circular_dynamic_buffer.hpp>
10  
#include <boost/capy/buffers/circular_dynamic_buffer.hpp>
11  
#include <boost/capy/detail/except.hpp>
11  
#include <boost/capy/detail/except.hpp>
12  

12  

13  
namespace boost {
13  
namespace boost {
14  
namespace capy {
14  
namespace capy {
15  

15  

16  
auto
16  
auto
17  
circular_dynamic_buffer::
17  
circular_dynamic_buffer::
18  
data() const noexcept ->
18  
data() const noexcept ->
19  
    const_buffers_type
19  
    const_buffers_type
20  
{
20  
{
21  
    if(in_pos_ + in_len_ <= cap_)
21  
    if(in_pos_ + in_len_ <= cap_)
22  
        return {{
22  
        return {{
23  
            const_buffer{ base_ + in_pos_, in_len_ },
23  
            const_buffer{ base_ + in_pos_, in_len_ },
24  
            const_buffer{ base_, 0} }};
24  
            const_buffer{ base_, 0} }};
25  
    return {{
25  
    return {{
26  
        const_buffer{ base_ + in_pos_, cap_ - in_pos_},
26  
        const_buffer{ base_ + in_pos_, cap_ - in_pos_},
27  
        const_buffer{ base_, in_len_- (cap_ - in_pos_)} }};
27  
        const_buffer{ base_, in_len_- (cap_ - in_pos_)} }};
28  
}
28  
}
29  

29  

30  
auto
30  
auto
31  
circular_dynamic_buffer::
31  
circular_dynamic_buffer::
32  
prepare(std::size_t n) ->
32  
prepare(std::size_t n) ->
33  
    mutable_buffers_type
33  
    mutable_buffers_type
34  
{
34  
{
35  
    // Buffer is too small for n
35  
    // Buffer is too small for n
36  
    if(n > cap_ - in_len_)
36  
    if(n > cap_ - in_len_)
37  
        detail::throw_length_error();
37  
        detail::throw_length_error();
38  

38  

39  
    out_size_ = n;
39  
    out_size_ = n;
40  
    auto const pos = (
40  
    auto const pos = (
41  
        in_pos_ + in_len_) % cap_;
41  
        in_pos_ + in_len_) % cap_;
42  
    if(pos + n <= cap_)
42  
    if(pos + n <= cap_)
43  
        return {{
43  
        return {{
44  
            mutable_buffer{ base_ + pos, n },
44  
            mutable_buffer{ base_ + pos, n },
45  
            mutable_buffer{ base_, 0 } }};
45  
            mutable_buffer{ base_, 0 } }};
46  
    return {{
46  
    return {{
47  
        mutable_buffer{ base_ + pos, cap_ - pos },
47  
        mutable_buffer{ base_ + pos, cap_ - pos },
48  
        mutable_buffer{ base_, n - (cap_ - pos) } }};
48  
        mutable_buffer{ base_, n - (cap_ - pos) } }};
49  
}
49  
}
50  

50  

51  
void
51  
void
52  
circular_dynamic_buffer::
52  
circular_dynamic_buffer::
53  
commit(
53  
commit(
54  
    std::size_t n) noexcept
54  
    std::size_t n) noexcept
55  
{
55  
{
56  
    if(n < out_size_)
56  
    if(n < out_size_)
57  
        in_len_ += n;
57  
        in_len_ += n;
58  
    else
58  
    else
59  
        in_len_ += out_size_;
59  
        in_len_ += out_size_;
60  
    out_size_ = 0;
60  
    out_size_ = 0;
61  
}
61  
}
62  

62  

63  
void
63  
void
64  
circular_dynamic_buffer::
64  
circular_dynamic_buffer::
65  
consume(
65  
consume(
66  
    std::size_t n) noexcept
66  
    std::size_t n) noexcept
67  
{
67  
{
68  
    if(n < in_len_)
68  
    if(n < in_len_)
69  
    {
69  
    {
70  
        in_pos_ = (in_pos_ + n) % cap_;
70  
        in_pos_ = (in_pos_ + n) % cap_;
71  
        in_len_ -= n;
71  
        in_len_ -= n;
72  
    }
72  
    }
73  
    else
73  
    else
74  
    {
74  
    {
75  
        // preserve in_pos_ if there is
75  
        // preserve in_pos_ if there is
76  
        // a prepared buffer
76  
        // a prepared buffer
77  
        if(out_size_ != 0)
77  
        if(out_size_ != 0)
78  
        {
78  
        {
79  
            in_pos_ = (in_pos_ + in_len_) % cap_;
79  
            in_pos_ = (in_pos_ + in_len_) % cap_;
80  
            in_len_ = 0;
80  
            in_len_ = 0;
81  
        }
81  
        }
82  
        else
82  
        else
83  
        {
83  
        {
84  
            // make prepare return a
84  
            // make prepare return a
85  
            // bigger single buffer
85  
            // bigger single buffer
86  
            in_pos_ = 0;
86  
            in_pos_ = 0;
87  
            in_len_ = 0;
87  
            in_len_ = 0;
88  
        }
88  
        }
89  
    }
89  
    }
90  
}
90  
}
91  

91  

92  
} // capy
92  
} // capy
93  
} // boost
93  
} // boost