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  
#ifndef BOOST_CAPY_BUFFERS_BUFFER_COPY_HPP
10  
#ifndef BOOST_CAPY_BUFFERS_BUFFER_COPY_HPP
11  
#define BOOST_CAPY_BUFFERS_BUFFER_COPY_HPP
11  
#define BOOST_CAPY_BUFFERS_BUFFER_COPY_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  
#include <cstring>
15  
#include <cstring>
16  
#include <utility>
16  
#include <utility>
17  

17  

18  
namespace boost {
18  
namespace boost {
19  
namespace capy {
19  
namespace capy {
20  

20  

21  
/** Copy the contents of a buffer sequence into another buffer sequence.
21  
/** Copy the contents of a buffer sequence into another buffer sequence.
22  

22  

23  
    This function copies bytes from the constant buffer sequence `src` into
23  
    This function copies bytes from the constant buffer sequence `src` into
24  
    the mutable buffer sequence `dest`, stopping when any limit is reached.
24  
    the mutable buffer sequence `dest`, stopping when any limit is reached.
25  

25  

26  
    @par Constraints
26  
    @par Constraints
27  
    @code
27  
    @code
28  
    MutableBufferSequence<decltype(dest)> &&
28  
    MutableBufferSequence<decltype(dest)> &&
29  
    ConstBufferSequence<decltype(src)>
29  
    ConstBufferSequence<decltype(src)>
30  
    @endcode
30  
    @endcode
31  

31  

32  
    @return The number of bytes copied, equal to
32  
    @return The number of bytes copied, equal to
33  
    `std::min(size(dest), size(src), at_most)`.
33  
    `std::min(size(dest), size(src), at_most)`.
34  

34  

35  
    @param dest The destination buffer sequence.
35  
    @param dest The destination buffer sequence.
36  
    @param src The source buffer sequence.
36  
    @param src The source buffer sequence.
37  
    @param at_most The maximum bytes to copy. Default copies all available.
37  
    @param at_most The maximum bytes to copy. Default copies all available.
38  
*/
38  
*/
39  
constexpr struct buffer_copy_mrdocs_workaround_t
39  
constexpr struct buffer_copy_mrdocs_workaround_t
40  
{
40  
{
41  
    template<
41  
    template<
42  
        MutableBufferSequence MB,
42  
        MutableBufferSequence MB,
43  
        ConstBufferSequence CB>
43  
        ConstBufferSequence CB>
44  
    std::size_t
44  
    std::size_t
45  
    operator()(
45  
    operator()(
46  
        MB const& dest,
46  
        MB const& dest,
47  
        CB const& src,
47  
        CB const& src,
48  
        std::size_t at_most = std::size_t(-1)) const noexcept
48  
        std::size_t at_most = std::size_t(-1)) const noexcept
49  
    {
49  
    {
50  
        std::size_t total = 0;
50  
        std::size_t total = 0;
51  
        std::size_t pos0 = 0;
51  
        std::size_t pos0 = 0;
52  
        std::size_t pos1 = 0;
52  
        std::size_t pos1 = 0;
53  
        auto const end0 = end(src);
53  
        auto const end0 = end(src);
54  
        auto const end1 = end(dest);
54  
        auto const end1 = end(dest);
55  
        auto it0 = begin(src);
55  
        auto it0 = begin(src);
56  
        auto it1 = begin(dest);
56  
        auto it1 = begin(dest);
57  
        while(
57  
        while(
58  
            total < at_most &&
58  
            total < at_most &&
59  
            it0 != end0 &&
59  
            it0 != end0 &&
60  
            it1 != end1)
60  
            it1 != end1)
61  
        {
61  
        {
62  
            const_buffer b0 = *it0;
62  
            const_buffer b0 = *it0;
63  
            mutable_buffer b1 = *it1;
63  
            mutable_buffer b1 = *it1;
64  
            b0 += pos0;
64  
            b0 += pos0;
65  
            b1 += pos1;
65  
            b1 += pos1;
66  
            std::size_t const amount =
66  
            std::size_t const amount =
67  
            [&]
67  
            [&]
68  
            {
68  
            {
69  
                std::size_t n = b0.size();
69  
                std::size_t n = b0.size();
70  
                if( n > b1.size())
70  
                if( n > b1.size())
71  
                    n = b1.size();
71  
                    n = b1.size();
72  
                if( n > at_most - total)
72  
                if( n > at_most - total)
73  
                    n = at_most - total;
73  
                    n = at_most - total;
74  
                if(n != 0)
74  
                if(n != 0)
75  
                    std::memcpy(
75  
                    std::memcpy(
76  
                        b1.data(),
76  
                        b1.data(),
77  
                        b0.data(),
77  
                        b0.data(),
78  
                        n);
78  
                        n);
79  
                return n;
79  
                return n;
80  
            }();
80  
            }();
81  
            total += amount;
81  
            total += amount;
82  
            if(amount == b1.size())
82  
            if(amount == b1.size())
83  
            {
83  
            {
84  
                ++it1;
84  
                ++it1;
85  
                pos1 = 0;
85  
                pos1 = 0;
86  
            }
86  
            }
87  
            else
87  
            else
88  
            {
88  
            {
89  
                pos1 += amount;
89  
                pos1 += amount;
90  
            }
90  
            }
91  
            if(amount == b0.size())
91  
            if(amount == b0.size())
92  
            {
92  
            {
93  
                ++it0;
93  
                ++it0;
94  
                pos0 = 0;
94  
                pos0 = 0;
95  
            }
95  
            }
96  
            else
96  
            else
97  
            {
97  
            {
98  
                pos0 += amount;
98  
                pos0 += amount;
99  
            }
99  
            }
100  
        }
100  
        }
101  
        return total;
101  
        return total;
102  
    }
102  
    }
103  
} buffer_copy {};
103  
} buffer_copy {};
104  

104  

105  
} // capy
105  
} // capy
106  
} // boost
106  
} // boost
107  

107  

108  
#endif
108  
#endif