| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/common/partial_circular_buffer.h" | 5 #include "chrome/common/partial_circular_buffer.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 | 10 |
| 11 namespace { | 11 namespace { |
| 12 | 12 |
| 13 inline uint32 Min3(uint32 a, uint32 b, uint32 c) { | 13 inline uint32_t Min3(uint32_t a, uint32_t b, uint32_t c) { |
| 14 return std::min(a, std::min(b, c)); | 14 return std::min(a, std::min(b, c)); |
| 15 } | 15 } |
| 16 | 16 |
| 17 } // namespace | 17 } // namespace |
| 18 | 18 |
| 19 PartialCircularBuffer::PartialCircularBuffer(void* buffer, | 19 PartialCircularBuffer::PartialCircularBuffer(void* buffer, uint32_t buffer_size) |
| 20 uint32 buffer_size) | |
| 21 : buffer_data_(reinterpret_cast<BufferData*>(buffer)), | 20 : buffer_data_(reinterpret_cast<BufferData*>(buffer)), |
| 22 memory_buffer_size_(buffer_size), | 21 memory_buffer_size_(buffer_size), |
| 23 data_size_(0), | 22 data_size_(0), |
| 24 position_(0), | 23 position_(0), |
| 25 total_read_(0) { | 24 total_read_(0) { |
| 26 uint32 header_size = | 25 uint32_t header_size = |
| 27 buffer_data_->data - reinterpret_cast<uint8*>(buffer_data_); | 26 buffer_data_->data - reinterpret_cast<uint8_t*>(buffer_data_); |
| 28 data_size_ = memory_buffer_size_ - header_size; | 27 data_size_ = memory_buffer_size_ - header_size; |
| 29 | 28 |
| 30 DCHECK(buffer_data_); | 29 DCHECK(buffer_data_); |
| 31 DCHECK_GE(memory_buffer_size_, header_size); | 30 DCHECK_GE(memory_buffer_size_, header_size); |
| 32 DCHECK_LE(buffer_data_->total_written, data_size_); | 31 DCHECK_LE(buffer_data_->total_written, data_size_); |
| 33 DCHECK_LT(buffer_data_->wrap_position, data_size_); | 32 DCHECK_LT(buffer_data_->wrap_position, data_size_); |
| 34 DCHECK_LT(buffer_data_->end_position, data_size_); | 33 DCHECK_LT(buffer_data_->end_position, data_size_); |
| 35 } | 34 } |
| 36 | 35 |
| 37 PartialCircularBuffer::PartialCircularBuffer(void* buffer, | 36 PartialCircularBuffer::PartialCircularBuffer(void* buffer, |
| 38 uint32 buffer_size, | 37 uint32_t buffer_size, |
| 39 uint32 wrap_position, | 38 uint32_t wrap_position, |
| 40 bool append) | 39 bool append) |
| 41 : buffer_data_(reinterpret_cast<BufferData*>(buffer)), | 40 : buffer_data_(reinterpret_cast<BufferData*>(buffer)), |
| 42 memory_buffer_size_(buffer_size), | 41 memory_buffer_size_(buffer_size), |
| 43 data_size_(0), | 42 data_size_(0), |
| 44 position_(0), | 43 position_(0), |
| 45 total_read_(0) { | 44 total_read_(0) { |
| 46 uint32 header_size = | 45 uint32_t header_size = |
| 47 buffer_data_->data - reinterpret_cast<uint8*>(buffer_data_); | 46 buffer_data_->data - reinterpret_cast<uint8_t*>(buffer_data_); |
| 48 data_size_ = memory_buffer_size_ - header_size; | 47 data_size_ = memory_buffer_size_ - header_size; |
| 49 | 48 |
| 50 DCHECK(buffer_data_); | 49 DCHECK(buffer_data_); |
| 51 DCHECK_GE(memory_buffer_size_, header_size); | 50 DCHECK_GE(memory_buffer_size_, header_size); |
| 52 | 51 |
| 53 if (append) { | 52 if (append) { |
| 54 DCHECK_LT(buffer_data_->wrap_position, data_size_); | 53 DCHECK_LT(buffer_data_->wrap_position, data_size_); |
| 55 position_ = buffer_data_->end_position; | 54 position_ = buffer_data_->end_position; |
| 56 } else { | 55 } else { |
| 57 DCHECK_LT(wrap_position, data_size_); | 56 DCHECK_LT(wrap_position, data_size_); |
| 58 buffer_data_->total_written = 0; | 57 buffer_data_->total_written = 0; |
| 59 buffer_data_->wrap_position = wrap_position; | 58 buffer_data_->wrap_position = wrap_position; |
| 60 buffer_data_->end_position = 0; | 59 buffer_data_->end_position = 0; |
| 61 } | 60 } |
| 62 } | 61 } |
| 63 | 62 |
| 64 uint32 PartialCircularBuffer::Read(void* buffer, uint32 buffer_size) { | 63 uint32_t PartialCircularBuffer::Read(void* buffer, uint32_t buffer_size) { |
| 65 DCHECK(buffer_data_); | 64 DCHECK(buffer_data_); |
| 66 if (total_read_ >= buffer_data_->total_written) | 65 if (total_read_ >= buffer_data_->total_written) |
| 67 return 0; | 66 return 0; |
| 68 | 67 |
| 69 uint8* buffer_uint8 = reinterpret_cast<uint8*>(buffer); | 68 uint8_t* buffer_uint8 = reinterpret_cast<uint8_t*>(buffer); |
| 70 uint32 read = 0; | 69 uint32_t read = 0; |
| 71 | 70 |
| 72 // Read from beginning part. | 71 // Read from beginning part. |
| 73 if (position_ < buffer_data_->wrap_position) { | 72 if (position_ < buffer_data_->wrap_position) { |
| 74 uint32 to_wrap_pos = buffer_data_->wrap_position - position_; | 73 uint32_t to_wrap_pos = buffer_data_->wrap_position - position_; |
| 75 uint32 to_eow = buffer_data_->total_written - total_read_; | 74 uint32_t to_eow = buffer_data_->total_written - total_read_; |
| 76 uint32 to_read = Min3(buffer_size, to_wrap_pos, to_eow); | 75 uint32_t to_read = Min3(buffer_size, to_wrap_pos, to_eow); |
| 77 memcpy(buffer_uint8, buffer_data_->data + position_, to_read); | 76 memcpy(buffer_uint8, buffer_data_->data + position_, to_read); |
| 78 position_ += to_read; | 77 position_ += to_read; |
| 79 total_read_ += to_read; | 78 total_read_ += to_read; |
| 80 read += to_read; | 79 read += to_read; |
| 81 if (position_ == buffer_data_->wrap_position && | 80 if (position_ == buffer_data_->wrap_position && |
| 82 buffer_data_->total_written == data_size_) { | 81 buffer_data_->total_written == data_size_) { |
| 83 // We've read all the beginning part, set the position to the middle part. | 82 // We've read all the beginning part, set the position to the middle part. |
| 84 // (The second condition above checks if the wrapping part is filled, i.e. | 83 // (The second condition above checks if the wrapping part is filled, i.e. |
| 85 // writing has wrapped.) | 84 // writing has wrapped.) |
| 86 position_ = buffer_data_->end_position; | 85 position_ = buffer_data_->end_position; |
| 87 } | 86 } |
| 88 if (read >= buffer_size) { | 87 if (read >= buffer_size) { |
| 89 DCHECK_EQ(read, buffer_size); | 88 DCHECK_EQ(read, buffer_size); |
| 90 return read; | 89 return read; |
| 91 } | 90 } |
| 92 if (read >= to_eow) { | 91 if (read >= to_eow) { |
| 93 DCHECK_EQ(read, to_eow); | 92 DCHECK_EQ(read, to_eow); |
| 94 DCHECK_EQ(total_read_, buffer_data_->total_written); | 93 DCHECK_EQ(total_read_, buffer_data_->total_written); |
| 95 return read; | 94 return read; |
| 96 } | 95 } |
| 97 } | 96 } |
| 98 | 97 |
| 99 // Read from middle part. | 98 // Read from middle part. |
| 100 DCHECK_GE(position_, buffer_data_->wrap_position); | 99 DCHECK_GE(position_, buffer_data_->wrap_position); |
| 101 if (position_ >= buffer_data_->end_position) { | 100 if (position_ >= buffer_data_->end_position) { |
| 102 uint32 remaining_buffer_size = buffer_size - read; | 101 uint32_t remaining_buffer_size = buffer_size - read; |
| 103 uint32 to_eof = data_size_ - position_; | 102 uint32_t to_eof = data_size_ - position_; |
| 104 uint32 to_eow = buffer_data_->total_written - total_read_; | 103 uint32_t to_eow = buffer_data_->total_written - total_read_; |
| 105 uint32 to_read = Min3(remaining_buffer_size, to_eof, to_eow); | 104 uint32_t to_read = Min3(remaining_buffer_size, to_eof, to_eow); |
| 106 memcpy(buffer_uint8 + read, buffer_data_->data + position_, to_read); | 105 memcpy(buffer_uint8 + read, buffer_data_->data + position_, to_read); |
| 107 position_ += to_read; | 106 position_ += to_read; |
| 108 total_read_ += to_read; | 107 total_read_ += to_read; |
| 109 read += to_read; | 108 read += to_read; |
| 110 if (position_ == data_size_) { | 109 if (position_ == data_size_) { |
| 111 // We've read all the middle part, set position to the end part. | 110 // We've read all the middle part, set position to the end part. |
| 112 position_ = buffer_data_->wrap_position; | 111 position_ = buffer_data_->wrap_position; |
| 113 } | 112 } |
| 114 if (read >= buffer_size) { | 113 if (read >= buffer_size) { |
| 115 DCHECK_EQ(read, buffer_size); | 114 DCHECK_EQ(read, buffer_size); |
| 116 return read; | 115 return read; |
| 117 } | 116 } |
| 118 if (total_read_ >= buffer_data_->total_written) { | 117 if (total_read_ >= buffer_data_->total_written) { |
| 119 DCHECK_EQ(total_read_, buffer_data_->total_written); | 118 DCHECK_EQ(total_read_, buffer_data_->total_written); |
| 120 return read; | 119 return read; |
| 121 } | 120 } |
| 122 } | 121 } |
| 123 | 122 |
| 124 // Read from end part. | 123 // Read from end part. |
| 125 DCHECK_GE(position_, buffer_data_->wrap_position); | 124 DCHECK_GE(position_, buffer_data_->wrap_position); |
| 126 DCHECK_LT(position_, buffer_data_->end_position); | 125 DCHECK_LT(position_, buffer_data_->end_position); |
| 127 uint32 remaining_buffer_size = buffer_size - read; | 126 uint32_t remaining_buffer_size = buffer_size - read; |
| 128 uint32 to_eob = buffer_data_->end_position - position_; | 127 uint32_t to_eob = buffer_data_->end_position - position_; |
| 129 uint32 to_eow = buffer_data_->total_written - total_read_; | 128 uint32_t to_eow = buffer_data_->total_written - total_read_; |
| 130 uint32 to_read = Min3(remaining_buffer_size, to_eob, to_eow); | 129 uint32_t to_read = Min3(remaining_buffer_size, to_eob, to_eow); |
| 131 memcpy(buffer_uint8 + read, buffer_data_->data + position_, to_read); | 130 memcpy(buffer_uint8 + read, buffer_data_->data + position_, to_read); |
| 132 position_ += to_read; | 131 position_ += to_read; |
| 133 total_read_ += to_read; | 132 total_read_ += to_read; |
| 134 read += to_read; | 133 read += to_read; |
| 135 DCHECK_LE(read, buffer_size); | 134 DCHECK_LE(read, buffer_size); |
| 136 DCHECK_LE(total_read_, buffer_data_->total_written); | 135 DCHECK_LE(total_read_, buffer_data_->total_written); |
| 137 return read; | 136 return read; |
| 138 } | 137 } |
| 139 | 138 |
| 140 void PartialCircularBuffer::Write(const void* buffer, uint32 buffer_size) { | 139 void PartialCircularBuffer::Write(const void* buffer, uint32_t buffer_size) { |
| 141 DCHECK(buffer_data_); | 140 DCHECK(buffer_data_); |
| 142 const uint8* input = static_cast<const uint8*>(buffer); | 141 const uint8_t* input = static_cast<const uint8_t*>(buffer); |
| 143 uint32 wrap_position = buffer_data_->wrap_position; | 142 uint32_t wrap_position = buffer_data_->wrap_position; |
| 144 uint32 cycle_size = data_size_ - wrap_position; | 143 uint32_t cycle_size = data_size_ - wrap_position; |
| 145 | 144 |
| 146 // First write the non-wrapping part. | 145 // First write the non-wrapping part. |
| 147 if (position_ < wrap_position) { | 146 if (position_ < wrap_position) { |
| 148 uint32 space_left = wrap_position - position_; | 147 uint32_t space_left = wrap_position - position_; |
| 149 uint32 write_size = std::min(buffer_size, space_left); | 148 uint32_t write_size = std::min(buffer_size, space_left); |
| 150 DoWrite(input, write_size); | 149 DoWrite(input, write_size); |
| 151 input += write_size; | 150 input += write_size; |
| 152 buffer_size -= write_size; | 151 buffer_size -= write_size; |
| 153 } | 152 } |
| 154 | 153 |
| 155 // Skip the part that would overlap. | 154 // Skip the part that would overlap. |
| 156 if (buffer_size > cycle_size) { | 155 if (buffer_size > cycle_size) { |
| 157 uint32 skip = buffer_size - cycle_size; | 156 uint32_t skip = buffer_size - cycle_size; |
| 158 input += skip; | 157 input += skip; |
| 159 buffer_size -= skip; | 158 buffer_size -= skip; |
| 160 position_ = wrap_position + (position_ - wrap_position + skip) % cycle_size; | 159 position_ = wrap_position + (position_ - wrap_position + skip) % cycle_size; |
| 161 } | 160 } |
| 162 | 161 |
| 163 // Finally write the wrapping part. | 162 // Finally write the wrapping part. |
| 164 DoWrite(input, buffer_size); | 163 DoWrite(input, buffer_size); |
| 165 } | 164 } |
| 166 | 165 |
| 167 void PartialCircularBuffer::DoWrite(const uint8* input, uint32 input_size) { | 166 void PartialCircularBuffer::DoWrite(const uint8_t* input, uint32_t input_size) { |
| 168 DCHECK_LT(position_, data_size_); | 167 DCHECK_LT(position_, data_size_); |
| 169 buffer_data_->total_written = | 168 buffer_data_->total_written = |
| 170 std::min(buffer_data_->total_written + input_size, data_size_); | 169 std::min(buffer_data_->total_written + input_size, data_size_); |
| 171 | 170 |
| 172 // Write() skips any overlapping part, so this loop will run at most twice. | 171 // Write() skips any overlapping part, so this loop will run at most twice. |
| 173 while (input_size > 0) { | 172 while (input_size > 0) { |
| 174 uint32 space_left = data_size_ - position_; | 173 uint32_t space_left = data_size_ - position_; |
| 175 uint32 write_size = std::min(input_size, space_left); | 174 uint32_t write_size = std::min(input_size, space_left); |
| 176 memcpy(buffer_data_->data + position_, input, write_size); | 175 memcpy(buffer_data_->data + position_, input, write_size); |
| 177 input += write_size; | 176 input += write_size; |
| 178 input_size -= write_size; | 177 input_size -= write_size; |
| 179 position_ += write_size; | 178 position_ += write_size; |
| 180 if (position_ >= data_size_) { | 179 if (position_ >= data_size_) { |
| 181 DCHECK_EQ(position_, data_size_); | 180 DCHECK_EQ(position_, data_size_); |
| 182 position_ = buffer_data_->wrap_position; | 181 position_ = buffer_data_->wrap_position; |
| 183 } | 182 } |
| 184 } | 183 } |
| 185 | 184 |
| 186 buffer_data_->end_position = position_; | 185 buffer_data_->end_position = position_; |
| 187 } | 186 } |
| OLD | NEW |