OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 "content/child/blob_storage/blob_consolidation.h" | 5 #include "content/child/blob_storage/blob_consolidation.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <limits> | 8 #include <limits> |
9 #include <string> | 9 #include <string> |
10 | 10 |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
119 | 119 |
120 const ConsolidatedItem& item = consolidated_items_[consolidated_item_index]; | 120 const ConsolidatedItem& item = consolidated_items_[consolidated_item_index]; |
121 if (item.type != DataElement::TYPE_BYTES) | 121 if (item.type != DataElement::TYPE_BYTES) |
122 return ReadStatus::ERROR_WRONG_TYPE; | 122 return ReadStatus::ERROR_WRONG_TYPE; |
123 | 123 |
124 if (consolidated_size + consolidated_offset > item.length) { | 124 if (consolidated_size + consolidated_offset > item.length) { |
125 return ReadStatus::ERROR_OUT_OF_BOUNDS; | 125 return ReadStatus::ERROR_OUT_OF_BOUNDS; |
126 } | 126 } |
127 | 127 |
128 // We do a binary search to find the correct data to start with in the data | 128 // We do a binary search to find the correct data to start with in the data |
129 // elements. This is slightly customized due to our unique storage and | 129 // elements. |
130 // constraints. | 130 const auto& offsets = item.offsets; |
131 size_t mid = 0; | 131 size_t item_index = |
132 size_t offset_from_mid = consolidated_offset; | 132 std::upper_bound(offsets.begin(), offsets.end(), consolidated_offset) - |
| 133 offsets.begin(); |
| 134 uint64_t item_offset = item_index == 0 |
| 135 ? consolidated_offset |
| 136 : consolidated_offset - offsets[item_index - 1]; |
| 137 |
| 138 DCHECK_LT(item_offset, item.data[item_index].size()); |
| 139 // Read starting from 'item_index' and 'item_offset'. |
133 size_t num_items = item.data.size(); | 140 size_t num_items = item.data.size(); |
134 if (!item.offsets.empty()) { | |
135 size_t low = 0; | |
136 size_t high = num_items - 1; | |
137 while (true) { | |
138 mid = (high + low) / 2; | |
139 // Note: we don't include the implicit '0' for the first item in offsets. | |
140 size_t item_offset = (mid == 0 ? 0 : item.offsets[mid - 1]); | |
141 offset_from_mid = consolidated_offset - item_offset; | |
142 size_t next_item_offset = (mid + 1 == num_items ? 0 : item.offsets[mid]); | |
143 if (item_offset == consolidated_offset) { | |
144 // found exact match. | |
145 break; | |
146 } else if (item_offset > consolidated_offset) { | |
147 high = mid - 1; | |
148 } else if (mid + 1 == num_items || | |
149 next_item_offset > consolidated_offset) { | |
150 // We are at the last item, or the next offset is greater than the one | |
151 // we want, so the current item wins. | |
152 break; | |
153 } else { | |
154 low = mid + 1; | |
155 } | |
156 } | |
157 } | |
158 | |
159 DCHECK_LT(offset_from_mid, item.data[mid].size()); | |
160 // Read starting from 'mid' and 'offset_from_mid'. | |
161 for (size_t memory_read = 0; | 141 for (size_t memory_read = 0; |
162 mid < num_items && memory_read < consolidated_size; mid++) { | 142 item_index < num_items && memory_read < consolidated_size; |
163 size_t read_size = std::min(item.data[mid].size() - offset_from_mid, | 143 item_index++) { |
| 144 size_t read_size = std::min(item.data[item_index].size() - item_offset, |
164 consolidated_size - memory_read); | 145 consolidated_size - memory_read); |
165 bool continu = | 146 bool continu = |
166 visitor.Run(item.data[mid].data() + offset_from_mid, read_size); | 147 visitor.Run(item.data[item_index].data() + item_offset, read_size); |
167 if (!continu) | 148 if (!continu) |
168 return ReadStatus::CANCELLED_BY_VISITOR; | 149 return ReadStatus::CANCELLED_BY_VISITOR; |
169 offset_from_mid = 0; | 150 item_offset = 0; |
170 memory_read += read_size; | 151 memory_read += read_size; |
171 } | 152 } |
172 return ReadStatus::OK; | 153 return ReadStatus::OK; |
173 } | 154 } |
174 | 155 |
175 ReadStatus BlobConsolidation::ReadMemory(size_t consolidated_item_index, | 156 ReadStatus BlobConsolidation::ReadMemory(size_t consolidated_item_index, |
176 size_t consolidated_offset, | 157 size_t consolidated_offset, |
177 size_t consolidated_size, | 158 size_t consolidated_size, |
178 void* memory_out) const { | 159 void* memory_out) const { |
179 size_t total_read = 0; | 160 size_t total_read = 0; |
180 return VisitMemory(consolidated_item_index, consolidated_offset, | 161 return VisitMemory(consolidated_item_index, consolidated_offset, |
181 consolidated_size, | 162 consolidated_size, |
182 base::Bind(&WriteMemory, memory_out, &total_read)); | 163 base::Bind(&WriteMemory, memory_out, &total_read)); |
183 } | 164 } |
184 | 165 |
185 } // namespace content | 166 } // namespace content |
OLD | NEW |