xenia-canary/src/xenia/base/ring_buffer.cc

119 lines
3.4 KiB
C++
Raw Normal View History

2015-06-02 15:11:59 +00:00
/**
2015-07-20 01:32:48 +00:00
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2015 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
2015-06-02 15:11:59 +00:00
#include "xenia/base/ring_buffer.h"
2015-06-19 14:50:54 +00:00
#include <algorithm>
2015-06-17 05:08:05 +00:00
#include <cstring>
2015-06-02 15:11:59 +00:00
namespace xe {
RingBuffer::RingBuffer(uint8_t* buffer, size_t capacity)
: buffer_(buffer), capacity_(capacity) {}
void RingBuffer::AdvanceRead(size_t count) {
if (read_offset_ + count < capacity_) {
read_offset_ += count;
} else {
size_t left_half = capacity_ - read_offset_;
size_t right_half = count - left_half;
read_offset_ = right_half;
}
}
void RingBuffer::AdvanceWrite(size_t count) {
if (write_offset_ + count < capacity_) {
write_offset_ += count;
} else {
size_t left_half = capacity_ - write_offset_;
size_t right_half = count - left_half;
write_offset_ = right_half;
}
}
RingBuffer::ReadRange RingBuffer::BeginRead(size_t count) {
count = std::min(count, capacity_);
if (!count) {
return {0};
}
if (read_offset_ + count < capacity_) {
return {buffer_ + read_offset_, count, nullptr, 0};
} else {
size_t left_half = capacity_ - read_offset_;
size_t right_half = count - left_half;
return {buffer_ + read_offset_, left_half, buffer_, right_half};
}
}
void RingBuffer::EndRead(ReadRange read_range) {
if (read_range.second) {
read_offset_ = read_range.second_length;
} else {
read_offset_ += read_range.first_length;
}
}
size_t RingBuffer::Read(uint8_t* buffer, size_t count) {
count = std::min(count, capacity_);
if (!count) {
2015-06-19 14:50:54 +00:00
return 0;
}
2015-06-03 16:12:55 +00:00
// Sanity check: Make sure we don't read over the write offset.
if (read_offset_ < write_offset_) {
assert_true(read_offset_ + count <= write_offset_);
} else if (read_offset_ + count >= capacity_) {
size_t left_half = capacity_ - read_offset_;
assert_true(count - left_half <= write_offset_);
}
if (read_offset_ + count < capacity_) {
std::memcpy(buffer, buffer_ + read_offset_, count);
read_offset_ += count;
2015-06-19 14:50:54 +00:00
} else {
size_t left_half = capacity_ - read_offset_;
size_t right_half = count - left_half;
std::memcpy(buffer, buffer_ + read_offset_, left_half);
std::memcpy(buffer + left_half, buffer_, right_half);
2015-06-19 14:50:54 +00:00
read_offset_ = right_half;
2015-06-02 15:11:59 +00:00
}
return count;
2015-06-02 15:11:59 +00:00
}
size_t RingBuffer::Write(const uint8_t* buffer, size_t count) {
count = std::min(count, capacity_);
if (!count) {
2015-06-19 14:50:54 +00:00
return 0;
2015-06-03 16:12:55 +00:00
}
// Sanity check: Make sure we don't write over the read offset.
if (write_offset_ < read_offset_) {
assert_true(write_offset_ + count <= read_offset_);
} else if (write_offset_ + count >= capacity_) {
size_t left_half = capacity_ - write_offset_;
assert_true(count - left_half <= read_offset_);
}
if (write_offset_ + count < capacity_) {
std::memcpy(buffer_ + write_offset_, buffer, count);
write_offset_ += count;
2015-06-02 15:11:59 +00:00
} else {
size_t left_half = capacity_ - write_offset_;
size_t right_half = count - left_half;
std::memcpy(buffer_ + write_offset_, buffer, left_half);
std::memcpy(buffer_, buffer + left_half, right_half);
2015-06-19 14:50:54 +00:00
write_offset_ = right_half;
2015-06-02 15:11:59 +00:00
}
2015-06-19 14:50:54 +00:00
return count;
2015-06-02 15:11:59 +00:00
}
} // namespace xe