| 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 size_t item_offset = base::checked_cast<size_t>( |
| 135 item_index == 0 ? 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 |