File indexing completed on 2025-04-19 08:33:52
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_MYSQL_IMPL_INTERNAL_SANSIO_READ_BUFFER_HPP
0009 #define BOOST_MYSQL_IMPL_INTERNAL_SANSIO_READ_BUFFER_HPP
0010
0011 #include <boost/mysql/client_errc.hpp>
0012 #include <boost/mysql/error_code.hpp>
0013
0014 #include <boost/assert.hpp>
0015 #include <boost/config.hpp>
0016 #include <boost/core/span.hpp>
0017
0018 #include <cstddef>
0019 #include <cstdint>
0020 #include <cstring>
0021 #include <vector>
0022
0023 namespace boost {
0024 namespace mysql {
0025 namespace detail {
0026
0027
0028
0029
0030
0031
0032
0033
0034 class read_buffer
0035 {
0036 std::vector<std::uint8_t> buffer_;
0037 std::size_t current_message_offset_{0};
0038 std::size_t pending_offset_{0};
0039 std::size_t free_offset_{0};
0040 std::size_t max_size_;
0041
0042 public:
0043 read_buffer(std::size_t size, std::size_t max_size = static_cast<std::size_t>(-1))
0044 : buffer_(size), max_size_(max_size)
0045 {
0046 BOOST_ASSERT(size <= max_size_);
0047 }
0048
0049 void reset() noexcept
0050 {
0051 current_message_offset_ = 0;
0052 pending_offset_ = 0;
0053 free_offset_ = 0;
0054 }
0055
0056
0057 const std::uint8_t* first() const noexcept { return buffer_.data(); }
0058 std::size_t size() const noexcept { return buffer_.size(); }
0059 std::size_t max_size() const { return max_size_; }
0060
0061
0062 std::uint8_t* reserved_first() noexcept { return buffer_.data(); }
0063 const std::uint8_t* reserved_first() const noexcept { return buffer_.data(); }
0064 std::uint8_t* current_message_first() noexcept { return buffer_.data() + current_message_offset_; }
0065 const std::uint8_t* current_message_first() const noexcept
0066 {
0067 return buffer_.data() + current_message_offset_;
0068 }
0069 std::uint8_t* pending_first() noexcept { return buffer_.data() + pending_offset_; }
0070 const std::uint8_t* pending_first() const noexcept { return buffer_.data() + pending_offset_; }
0071 std::uint8_t* free_first() noexcept { return buffer_.data() + free_offset_; }
0072 const std::uint8_t* free_first() const noexcept { return buffer_.data() + free_offset_; }
0073
0074 std::size_t reserved_size() const noexcept { return current_message_offset_; }
0075 std::size_t current_message_size() const noexcept { return pending_offset_ - current_message_offset_; }
0076 std::size_t pending_size() const noexcept { return free_offset_ - pending_offset_; }
0077 std::size_t free_size() const noexcept { return buffer_.size() - free_offset_; }
0078
0079 span<const std::uint8_t> reserved_area() const noexcept { return {reserved_first(), reserved_size()}; }
0080 span<const std::uint8_t> current_message() const noexcept
0081 {
0082 return {current_message_first(), current_message_size()};
0083 }
0084 span<const std::uint8_t> pending_area() const noexcept { return {pending_first(), pending_size()}; }
0085 span<std::uint8_t> free_area() noexcept { return {free_first(), free_size()}; }
0086
0087
0088 void move_to_pending(std::size_t length) noexcept
0089 {
0090 BOOST_ASSERT(length <= free_size());
0091 free_offset_ += length;
0092 }
0093
0094
0095 void move_to_current_message(std::size_t length) noexcept
0096 {
0097 BOOST_ASSERT(length <= pending_size());
0098 pending_offset_ += length;
0099 }
0100
0101
0102
0103
0104 void remove_current_message_last(std::size_t length) noexcept
0105 {
0106 BOOST_ASSERT(length <= current_message_size());
0107 BOOST_ASSERT(length > 0);
0108 std::memmove(pending_first() - length, pending_first(), pending_size());
0109 pending_offset_ -= length;
0110 free_offset_ -= length;
0111 }
0112
0113
0114
0115 void move_to_reserved(std::size_t length) noexcept
0116 {
0117 BOOST_ASSERT(length <= current_message_size());
0118 current_message_offset_ += length;
0119 }
0120
0121
0122 void remove_reserved() noexcept
0123 {
0124 if (reserved_size() > 0)
0125 {
0126
0127 void* to = buffer_.data();
0128 const void* from = current_message_first();
0129 BOOST_ASSERT(to != nullptr);
0130 BOOST_ASSERT(from != nullptr);
0131 std::size_t currmsg_size = current_message_size();
0132 std::size_t pend_size = pending_size();
0133 std::memmove(to, from, currmsg_size + pend_size);
0134 current_message_offset_ = 0;
0135 pending_offset_ = currmsg_size;
0136 free_offset_ = currmsg_size + pend_size;
0137 }
0138 }
0139
0140
0141 BOOST_ATTRIBUTE_NODISCARD
0142 error_code grow_to_fit(std::size_t n)
0143 {
0144 if (free_size() < n)
0145 {
0146 std::size_t new_size = buffer_.size() + n - free_size();
0147 if (new_size > max_size_)
0148 return client_errc::max_buffer_size_exceeded;
0149 buffer_.resize(new_size);
0150 }
0151 return error_code();
0152 }
0153 };
0154
0155 }
0156 }
0157 }
0158
0159 #endif