#include "buffer.h" #include #include #include #include #include namespace saw { error buffer::push(const uint8_t &value) { size_t write_remain = write_composite_length(); if (write_remain > 0) { write() = value; write_advance(1); } else { return recoverable_error("Buffer too small"); } return no_error(); } error buffer::push(const uint8_t &buffer, size_t size) { error error = write_require_length(size); if (error.failed()) { return error; } const uint8_t *buffer_ptr = &buffer; while (size > 0) { size_t segment = std::min(write_segment_length(), size); memcpy(&write(), buffer_ptr, segment); write_advance(segment); size -= segment; buffer_ptr += segment; } return no_error(); } error buffer::pop(uint8_t &value) { if (read_composite_length() > 0) { value = read(); read_advance(1); } else { return recoverable_error("Buffer too small"); } return no_error(); } error buffer::pop(uint8_t &buffer, size_t size) { if (read_composite_length() >= size) { uint8_t *buffer_ptr = &buffer; while (size > 0) { size_t segment = std::min(read_segment_length(), size); memcpy(buffer_ptr, &read(), segment); read_advance(segment); size -= segment; buffer_ptr += segment; } } else { return recoverable_error("Buffer too small"); } return no_error(); } std::string buffer::to_string() const { std::ostringstream oss; for (size_t i = 0; i < read_composite_length(); ++i) { oss << read(i); } return oss.str(); } std::string buffer::to_hex() const { std::ostringstream oss; oss << std::hex << std::setfill('0'); for (size_t i = 0; i < read_composite_length(); ++i) { oss << std::setw(2) << (uint16_t)read(i); if ((i + 1) < read_composite_length()) { oss << ((i % 4 == 3) ? '\n' : ' '); } } return oss.str(); } buffer_view::buffer_view(buffer &buffer) : buffer_{buffer}, read_offset_{0}, write_offset_{0} {} size_t buffer_view::read_position() const { return read_offset_ + buffer_.read_position(); } size_t buffer_view::read_composite_length() const { assert(read_offset_ <= buffer_.read_composite_length()); if (read_offset_ > buffer_.read_composite_length()) { return 0; } return buffer_.read_composite_length() - read_offset_; } size_t buffer_view::read_segment_length(size_t offset) const { size_t off = offset + read_offset_; assert(off <= buffer_.read_composite_length()); if (off > buffer_.read_composite_length()) { return 0; } return buffer_.read_segment_length(off); } void buffer_view::read_advance(size_t bytes) { size_t offset = bytes + read_offset_; assert(offset <= buffer_.read_composite_length()); if (offset > buffer_.read_composite_length()) { read_offset_ += buffer_.read_composite_length(); return; } read_offset_ += bytes; } uint8_t &buffer_view::read(size_t i) { size_t pos = i + read_offset_; assert(pos < buffer_.read_composite_length()); return buffer_.read(pos); } const uint8_t &buffer_view::read(size_t i) const { size_t pos = i + read_offset_; assert(pos < buffer_.read_composite_length()); return buffer_.read(pos); } size_t buffer_view::write_position() const { return write_offset_ + buffer_.write_position(); } size_t buffer_view::write_composite_length() const { assert(write_offset_ <= buffer_.write_composite_length()); if (write_offset_ > buffer_.write_composite_length()) { return 0; } return buffer_.write_composite_length() - write_offset_; } size_t buffer_view::write_segment_length(size_t offset) const { size_t off = offset + write_offset_; assert(off <= buffer_.write_composite_length()); if (off > buffer_.write_composite_length()) { return 0; } return buffer_.write_segment_length(off); } void buffer_view::write_advance(size_t bytes) { size_t offset = bytes + write_offset_; assert(offset <= buffer_.write_composite_length()); if (offset > buffer_.write_composite_length()) { write_offset_ += buffer_.write_composite_length(); return; } write_offset_ += bytes; } uint8_t &buffer_view::write(size_t i) { size_t pos = i + write_offset_; assert(pos < buffer_.write_composite_length()); return buffer_.write(pos); } const uint8_t &buffer_view::write(size_t i) const { size_t pos = i + write_offset_; assert(pos < buffer_.write_composite_length()); return buffer_.write(pos); } error buffer_view::write_require_length(size_t bytes) { return buffer_.write_require_length(bytes + write_offset_); } size_t buffer_view::read_offset() const { return read_offset_; } size_t buffer_view::write_offset() const { return write_offset_; } ring_buffer::ring_buffer() : read_position_{0}, write_position_{0} { buffer_.resize(RING_BUFFER_MAX_SIZE); } ring_buffer::ring_buffer(size_t size) : read_position_{0}, write_position_{0} { buffer_.resize(size); } size_t ring_buffer::read_position() const { return read_position_; } /* * If write is ahead of read it is a simple distance, but if read ist ahead of * write then there are two segments * */ size_t ring_buffer::read_composite_length() const { return write_position() < read_position() ? buffer_.size() - (read_position() - write_position()) : (write_reached_read_ ? buffer_.size() : write_position() - read_position()); } /* * If write is ahead then it's the simple distance again. If read is ahead it's * until the end of the buffer/segment */ size_t ring_buffer::read_segment_length(size_t offset) const { size_t read_composite = read_composite_length(); assert(offset <= read_composite); offset = std::min(offset, read_composite); size_t remaining = read_composite - offset; size_t read_offset = read_position() + offset; read_offset = read_offset >= buffer_.size() ? read_offset - buffer_.size() : read_offset; // case 1 write is located before read and reached read // then offset can be used normally // case 2 write is located at read, but read reached write // then it is set to zero by readCompositeLength() // case 3 write is located after read // since std::min you can use simple subtraction if (write_position() < read_offset) { return buffer_.size() - read_offset; } if (write_position() == read_offset) { if (remaining > 0) { return buffer_.size() - read_offset; } else { return 0; } } return write_position() - read_offset; } void ring_buffer::read_advance(size_t bytes) { size_t read_composite = read_composite_length(); assert(bytes <= read_composite); bytes = std::min(bytes, read_composite); size_t advanced = read_position_ + bytes; read_position_ = advanced >= buffer_.size() ? advanced - buffer_.size() : advanced; write_reached_read_ = bytes > 0 ? false : write_reached_read_; } uint8_t &ring_buffer::read(size_t i) { assert(i < read_composite_length()); size_t pos = read_position_ + i; pos = pos >= buffer_.size() ? pos - buffer_.size() : pos; return buffer_[pos]; } const uint8_t &ring_buffer::read(size_t i) const { assert(i < read_composite_length()); size_t pos = read_position_ + i; pos = pos >= buffer_.size() ? pos - buffer_.size() : pos; return buffer_[pos]; } size_t ring_buffer::write_position() const { return write_position_; } size_t ring_buffer::write_composite_length() const { return read_position() > write_position() ? (read_position() - write_position()) : (write_reached_read_ ? 0 : buffer_.size() - (write_position() - read_position())); } size_t ring_buffer::write_segment_length(size_t offset) const { size_t write_composite = write_composite_length(); assert(offset <= write_composite); offset = std::min(offset, write_composite); size_t write_offset = write_position() + offset; write_offset = write_offset >= buffer_.size() ? write_offset - buffer_.size() : write_offset; if (read_position_ > write_offset) { return read_position_ - write_offset; } if (write_reached_read_) { return 0; } return buffer_.size() - write_offset; } void ring_buffer::write_advance(size_t bytes) { assert(bytes <= write_composite_length()); size_t advanced = write_position_ + bytes; write_position_ = advanced >= buffer_.size() ? advanced - buffer_.size() : advanced; write_reached_read_ = (write_position_ == read_position_ && bytes > 0 ? true : false); } uint8_t &ring_buffer::write(size_t i) { assert(i < write_composite_length()); size_t pos = write_position_ + i; pos = pos >= buffer_.size() ? pos - buffer_.size() : pos; return buffer_[pos]; } const uint8_t &ring_buffer::write(size_t i) const { assert(i < write_composite_length()); size_t pos = write_position_ + i; pos = pos >= buffer_.size() ? pos - buffer_.size() : pos; return buffer_[pos]; } /* Error RingBuffer::increaseSize(size_t size){ size_t old_size = buffer.size(); size_t new_size = old_size + size; buffer.resize(new_size); if(readPosition() > writePosition() || (readPosition() == writePosition() && write_reached_read)){ size_t remaining = old_size - writePosition(); size_t real_remaining = 0; while(remaining > 0){ size_t segment = std::min(remaining, size); memcpy(&buffer[new_size-segment], &buffer[old_size-segment], segment); remaining -= segment; size -= segment; old_size -= segment; new_size -= segment; } } return noError(); } */ error ring_buffer::write_require_length(size_t bytes) { size_t write_remain = write_composite_length(); if (bytes > write_remain) { return recoverable_error("Buffer too small"); } return no_error(); } array_buffer::array_buffer(size_t size) : read_position_{0}, write_position_{0} { buffer_.resize(size); } size_t array_buffer::read_position() const { return read_position_; } size_t array_buffer::read_composite_length() const { return write_position_ - read_position_; } size_t array_buffer::read_segment_length(size_t offset) const { size_t read_composite = read_composite_length(); assert(offset <= read_composite); offset = std::min(read_composite, offset); size_t read_offset = read_position_ + offset; return write_position_ - read_offset; } void array_buffer::read_advance(size_t bytes) { assert(bytes <= read_composite_length()); read_position_ += bytes; } uint8_t &array_buffer::read(size_t i) { assert(i < read_composite_length()); return buffer_[i + read_position_]; } const uint8_t &array_buffer::read(size_t i) const { assert(i + read_position_ < buffer_.size()); return buffer_[i + read_position_]; } size_t array_buffer::write_position() const { return write_position_; } size_t array_buffer::write_composite_length() const { assert(write_position_ <= buffer_.size()); return buffer_.size() - write_position_; } size_t array_buffer::write_segment_length(size_t offset) const { assert(write_position_ <= buffer_.size()); size_t write_composite = write_composite_length(); assert(offset <= write_composite); offset = std::min(write_composite, offset); size_t write_offset = write_position_ + offset; return buffer_.size() - write_offset; } void array_buffer::write_advance(size_t bytes) { assert(bytes <= write_composite_length()); write_position_ += bytes; } uint8_t &array_buffer::write(size_t i) { assert(i < write_composite_length()); return buffer_[i + write_position_]; } const uint8_t &array_buffer::write(size_t i) const { assert(i < write_composite_length()); return buffer_[i + write_position_]; } error array_buffer::write_require_length(size_t bytes) { size_t write_remain = write_composite_length(); if (bytes > write_remain) { return recoverable_error("Buffer too small"); } return no_error(); } } // namespace saw