Branch data Line data Source code
1 : : /* 2 : : ** Copyright (C) 2023 Sylvain Fargier 3 : : ** 4 : : ** This software is provided 'as-is', without any express or implied 5 : : ** warranty. In no event will the authors be held liable for any damages 6 : : ** arising from the use of this software. 7 : : ** 8 : : ** Permission is granted to anyone to use this software for any purpose, 9 : : ** including commercial applications, and to alter it and redistribute it 10 : : ** freely, subject to the following restrictions: 11 : : ** 12 : : ** 1. The origin of this software must not be misrepresented; you must not 13 : : ** claim that you wrote the original software. If you use this software 14 : : ** in a product, an acknowledgment in the product documentation would be 15 : : ** appreciated but is not required. 16 : : ** 2. Altered source versions must be plainly marked as such, and must not be 17 : : ** misrepresented as being the original software. 18 : : ** 3. This notice may not be removed or altered from any source distribution. 19 : : ** 20 : : ** Created on: 2023-12-14T18:45:41 21 : : ** Author: Sylvain Fargier <fargier.sylvain@gmail.com> 22 : : */ 23 : : 24 : : #ifndef SHAREDBUFFER_HPP__ 25 : : #define SHAREDBUFFER_HPP__ 26 : : 27 : : #include <cstdint> 28 : : #include <vector> 29 : : 30 : : #include <logger/Logger.hpp> 31 : : 32 : : #include "Cow.hpp" 33 : : #include "utils.hpp" 34 : : 35 : : namespace ccut { 36 : : /** 37 : : * @addtogroup data data: data manipulation helpers 38 : : * @{ 39 : : */ 40 : : 41 : : /** 42 : : * @brief basic buffer with endianness aware primitives 43 : : */ 44 : : class Buffer : public std::vector<uint8_t> 45 : : { 46 : : public: 47 : : using std::vector<uint8_t>::vector; 48 : : 49 : : template<typename T> 50 : : Buffer &write(size_t offset, const T &value, bool be = false); 51 : : 52 : : template<typename T> 53 : : T read(size_t offset, bool be = false) const; 54 : : 55 : 2 : inline uint8_t read(size_t offset) const { return (data())[offset]; } 56 : : }; 57 : : 58 : : /** data-type typedef */ 59 : : typedef Buffer buffer_t; 60 : : 61 : : /** 62 : : * @brief buffer-like object to access a sub-part of a buffer 63 : : * 64 : : * @tparam shared_buffer_t likely a cow_ptr<buffer_t> 65 : : */ 66 : : template<typename shared_buffer_t = cow_ptr<buffer_t>> 67 : : class BufferView 68 : : { 69 : : public: 70 : : typedef shared_buffer_t shared_buffer_type; 71 : : typedef typename shared_buffer_t::element_type::value_type value_type; 72 : : typedef typename shared_buffer_t::element_type::iterator iterator; 73 : : typedef 74 : : typename shared_buffer_t::element_type::const_iterator const_iterator; 75 : : 76 : 16 : BufferView(const shared_buffer_t &buffer, size_t offset, size_t len) : 77 : 16 : m_buffer(buffer), 78 : 16 : m_offset(offset), 79 : 16 : m_size(len) 80 : 16 : {} 81 : : // cppcheck-suppress noExplicitConstructor 82 : 25 : BufferView(const shared_buffer_t &buffer, size_t offset = 0) : 83 : 25 : m_buffer(buffer), 84 : 25 : m_offset(offset), 85 : 25 : m_size(buffer ? (buffer->size() - offset) : 0) 86 : 25 : {} 87 : 20 : BufferView() : m_offset(0), m_size(0) {} 88 : 27 : BufferView(const BufferView &) = default; 89 : 7 : BufferView &operator=(const BufferView &) = default; 90 : 21 : BufferView &operator=(const shared_buffer_t &buffer) 91 : : { 92 : 21 : if (buffer != m_buffer) 93 : 16 : m_buffer = buffer; 94 : 21 : m_offset = 0; 95 : 21 : m_size = buffer ? buffer->size() : 0; 96 : 21 : return *this; 97 : : } 98 : : 99 : 0 : inline void reset(const shared_buffer_t &buffer) 100 : : { 101 : 0 : this->operator=(buffer); 102 : 0 : } 103 : : 104 : 2 : inline void reset() 105 : : { 106 : 2 : m_buffer.reset(); 107 : 2 : m_offset = 0; 108 : 2 : m_size = 0; 109 : 2 : } 110 : : 111 : 264 : operator bool() const 112 : : { 113 : 264 : return bool(m_buffer) && (m_buffer->size() >= m_offset + m_size); 114 : : } 115 : : 116 : 1 : BufferView &setBuffer(const shared_buffer_t &buffer) 117 : : { 118 : 1 : m_buffer = buffer; 119 : 1 : return *this; 120 : : } 121 : : 122 : : inline size_t offset() const { return m_offset; } 123 : 4 : BufferView &setOffset(size_t offset) 124 : : { 125 : 4 : if (offset >= m_offset + m_size) 126 : 1 : m_size = 0; 127 : : else 128 : 3 : m_size -= offset; 129 : 4 : m_offset = offset; 130 : 4 : return *this; 131 : : } 132 : : 133 : 347 : inline size_t size() const { return m_size; } 134 : 5 : BufferView &setSize(size_t size) 135 : : { 136 : 5 : m_size = size; 137 : 5 : return *this; 138 : : } 139 : : 140 : : bool empty() const { return m_size == 0; } 141 : : 142 : 48 : inline const value_type &operator[](size_t index) const 143 : : { 144 : 48 : return (*m_buffer)[index + m_offset]; 145 : : } 146 : : 147 : 28 : inline value_type &operator[](size_t index) 148 : : { 149 : 28 : return (*m_buffer)[index + m_offset]; 150 : : } 151 : : 152 : 3 : value_type *data() { return m_buffer->data() + m_offset; } 153 : 53 : value_type const *data() const { return m_buffer->data() + m_offset; } 154 : : 155 : 7 : iterator begin() { return m_buffer->begin() + m_offset; } 156 : 3 : const_iterator begin() const { return m_buffer->cbegin() + m_offset; } 157 : 5 : const_iterator cbegin() const { return m_buffer->cbegin() + m_offset; } 158 : : 159 : 4 : iterator end() { return m_buffer->begin() + m_offset + m_size; } 160 : 3 : const_iterator end() const 161 : : { 162 : 3 : return m_buffer->cbegin() + m_offset + m_size; 163 : : } 164 : 5 : const_iterator cend() const 165 : : { 166 : 5 : return m_buffer->cbegin() + m_offset + m_size; 167 : : } 168 : : 169 : : template<typename T> 170 : 122 : BufferView &write(size_t offset, const T &value, bool be = false) 171 : : { 172 : 122 : m_buffer->template write<T>(offset + m_offset, value, be); 173 : 122 : return *this; 174 : : } 175 : : 176 : : template<typename T> 177 : 77 : T read(size_t offset, bool be = false) const 178 : : { 179 : 77 : return m_buffer->template read<T>(offset + m_offset, be); 180 : : } 181 : : 182 : 38 : inline uint8_t read(size_t offset) const { return read<uint8_t>(offset); } 183 : : 184 : 17 : inline shared_buffer_t &buffer() { return m_buffer; } 185 : 16 : inline const shared_buffer_t &buffer() const { return m_buffer; } 186 : : 187 : : /** 188 : : * @brief return sub-view from current view perspective 189 : : * 190 : : * @param offset new offset in current view 191 : : * @param len length 192 : : * @return BufferView<shared_buffer_t> new view object 193 : : */ 194 : 12 : BufferView sub(size_t offset, size_t len) const 195 : : { 196 : 12 : return BufferView(buffer(), m_offset + offset, len); 197 : : } 198 : : 199 : 4 : BufferView sub(size_t offset) const 200 : : { 201 : 4 : return BufferView(buffer(), m_offset + offset, m_size - offset); 202 : : } 203 : : 204 : : protected: 205 : : shared_buffer_t m_buffer; 206 : : size_t m_offset; 207 : : size_t m_size; 208 : : }; 209 : : 210 : : template<typename shared_buffer_t = cow_ptr<buffer_t>> 211 : : using buffer_view_t = BufferView<shared_buffer_t>; 212 : : 213 : : /** 214 : : * @brief host to little-endian conversion 215 : : * 216 : : * @tparam T unsigned int 16, 32 or 64 217 : : * @param[in] value value to convert 218 : : * @return T converted value 219 : : */ 220 : : template<typename T> 221 : : T htole(T value); 222 : : 223 : : /** 224 : : * @brief host to big-endian conversion 225 : : * 226 : : * @tparam T unsigned int 16, 32 or 64 227 : : * @param[in] value value to convert 228 : : * @return T converted value 229 : : */ 230 : : template<typename T> 231 : : T htobe(T value); 232 : : 233 : : /** 234 : : * @brief little-endian to host conversion 235 : : * 236 : : * @tparam T unsigned int 16, 32 or 64 237 : : * @param[in] value value to convert 238 : : * @return T converted value 239 : : */ 240 : : template<typename T> 241 : : T letoh(T value); 242 : : 243 : : /** 244 : : * @brief big-endian to host conversion 245 : : * 246 : : * @tparam T unsigned int 16, 32 or 64 247 : : * @param[in] value value to convert 248 : : * @return T converted value 249 : : */ 250 : : template<typename T> 251 : : T betoh(T value); 252 : : 253 : : /** @} */ 254 : : } // namespace ccut 255 : : 256 : : #include "Buffer.hxx" 257 : : 258 : : #endif