1868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file. 4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 5868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/common/partial_circular_buffer.h" 6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <algorithm> 8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/logging.h" 10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace { 12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)inline uint32 Min3(uint32 a, uint32 b, uint32 c) { 14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return std::min(a, std::min(b, c)); 15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} // namespace 18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)PartialCircularBuffer::PartialCircularBuffer(void* buffer, 20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) uint32 buffer_size) 21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) : buffer_data_(reinterpret_cast<BufferData*>(buffer)), 22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) memory_buffer_size_(buffer_size), 23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) data_size_(0), 24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) position_(0), 25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) total_read_(0) { 26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) uint32 header_size = 27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) buffer_data_->data - reinterpret_cast<uint8*>(buffer_data_); 28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) data_size_ = memory_buffer_size_ - header_size; 29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(buffer_data_); 31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_GE(memory_buffer_size_, header_size); 32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_LE(buffer_data_->total_written, data_size_); 33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_LT(buffer_data_->wrap_position, data_size_); 34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_LT(buffer_data_->end_position, data_size_); 35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)PartialCircularBuffer::PartialCircularBuffer(void* buffer, 38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) uint32 buffer_size, 397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) uint32 wrap_position, 407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) bool append) 41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) : buffer_data_(reinterpret_cast<BufferData*>(buffer)), 42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) memory_buffer_size_(buffer_size), 43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) data_size_(0), 44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) position_(0), 45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) total_read_(0) { 46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) uint32 header_size = 47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) buffer_data_->data - reinterpret_cast<uint8*>(buffer_data_); 48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) data_size_ = memory_buffer_size_ - header_size; 49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(buffer_data_); 51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_GE(memory_buffer_size_, header_size); 52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (append) { 547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) DCHECK_LT(buffer_data_->wrap_position, data_size_); 557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) position_ = buffer_data_->end_position; 567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } else { 577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) DCHECK_LT(wrap_position, data_size_); 587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) buffer_data_->total_written = 0; 597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) buffer_data_->wrap_position = wrap_position; 607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) buffer_data_->end_position = 0; 617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)uint32 PartialCircularBuffer::Read(void* buffer, uint32 buffer_size) { 65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(buffer_data_); 66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (total_read_ >= buffer_data_->total_written) 67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return 0; 68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) uint8* buffer_uint8 = reinterpret_cast<uint8*>(buffer); 70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) uint32 read = 0; 71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Read from beginning part. 73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (position_ < buffer_data_->wrap_position) { 74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) uint32 to_wrap_pos = buffer_data_->wrap_position - position_; 75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) uint32 to_eow = buffer_data_->total_written - total_read_; 76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) uint32 to_read = Min3(buffer_size, to_wrap_pos, to_eow); 77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) memcpy(buffer_uint8, buffer_data_->data + position_, to_read); 78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) position_ += to_read; 79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) total_read_ += to_read; 80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) read += to_read; 81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (position_ == buffer_data_->wrap_position && 82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) buffer_data_->total_written == data_size_) { 83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // We've read all the beginning part, set the position to the middle part. 84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // (The second condition above checks if the wrapping part is filled, i.e. 85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // writing has wrapped.) 86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) position_ = buffer_data_->end_position; 87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (read >= buffer_size) { 89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_EQ(read, buffer_size); 90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return read; 91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (read >= to_eow) { 93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_EQ(read, to_eow); 94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_EQ(total_read_, buffer_data_->total_written); 95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return read; 96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Read from middle part. 100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_GE(position_, buffer_data_->wrap_position); 101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (position_ >= buffer_data_->end_position) { 102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) uint32 remaining_buffer_size = buffer_size - read; 103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) uint32 to_eof = data_size_ - position_; 104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) uint32 to_eow = buffer_data_->total_written - total_read_; 105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) uint32 to_read = Min3(remaining_buffer_size, to_eof, to_eow); 106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) memcpy(buffer_uint8 + read, buffer_data_->data + position_, to_read); 107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) position_ += to_read; 108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) total_read_ += to_read; 109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) read += to_read; 110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (position_ == data_size_) { 111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // We've read all the middle part, set position to the end part. 112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) position_ = buffer_data_->wrap_position; 113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (read >= buffer_size) { 115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_EQ(read, buffer_size); 116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return read; 117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (total_read_ >= buffer_data_->total_written) { 119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_EQ(total_read_, buffer_data_->total_written); 120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return read; 121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Read from end part. 125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_GE(position_, buffer_data_->wrap_position); 126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_LT(position_, buffer_data_->end_position); 127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) uint32 remaining_buffer_size = buffer_size - read; 128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) uint32 to_eob = buffer_data_->end_position - position_; 129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) uint32 to_eow = buffer_data_->total_written - total_read_; 130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) uint32 to_read = Min3(remaining_buffer_size, to_eob, to_eow); 131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) memcpy(buffer_uint8 + read, buffer_data_->data + position_, to_read); 132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) position_ += to_read; 133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) total_read_ += to_read; 134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) read += to_read; 135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_LE(read, buffer_size); 136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_LE(total_read_, buffer_data_->total_written); 137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return read; 138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void PartialCircularBuffer::Write(const void* buffer, uint32 buffer_size) { 141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(buffer_data_); 142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) uint32 position_before_write = position_; 143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) uint32 to_eof = data_size_ - position_; 145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) uint32 to_write = std::min(buffer_size, to_eof); 146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DoWrite(buffer_data_->data + position_, buffer, to_write); 147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (position_ >= data_size_) { 148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_EQ(position_, data_size_); 149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) position_ = buffer_data_->wrap_position; 150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (to_write < buffer_size) { 153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) uint32 remainder_to_write = buffer_size - to_write; 154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_LT(position_, position_before_write); 155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_LE(position_ + remainder_to_write, position_before_write); 156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DoWrite(buffer_data_->data + position_, 157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) reinterpret_cast<const uint8*>(buffer) + to_write, 158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) remainder_to_write); 159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void PartialCircularBuffer::DoWrite(void* dest, const void* src, uint32 num) { 163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) memcpy(dest, src, num); 164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) position_ += num; 165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) buffer_data_->total_written = 166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::min(buffer_data_->total_written + num, data_size_); 167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) buffer_data_->end_position = position_; 168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 169