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 |