| 179 | // Map entries that intersect range.begin or range.end are split at the intersection point. |
| 180 | template <typename InfillUpdateOps> |
| 181 | AccessMap::iterator InfillUpdateRange(AccessMap &map, AccessMap::iterator pos, const AccessRange &range, |
| 182 | const InfillUpdateOps &ops) { |
| 183 | assert(range.non_empty()); |
| 184 | |
| 185 | const auto end = map.end(); |
| 186 | assert(pos == map.LowerBound(range.begin) || pos->first.strictly_less(range)); |
| 187 | |
| 188 | if (pos != end && pos->first.strictly_less(range)) { |
| 189 | // pos is not a lower bound for the range (pos < range), but if the range is |
| 190 | // monotonically increasing, the next map entry may be the lower bound |
| 191 | ++pos; |
| 192 | |
| 193 | // If the new pos is not a lower bound, run the full search |
| 194 | if (pos != end && pos->first.strictly_less(range)) { |
| 195 | pos = map.LowerBound(range.begin); |
| 196 | } |
| 197 | } |
| 198 | assert(pos == map.LowerBound(range.begin)); |
| 199 | |
| 200 | if (pos != end && range.begin > pos->first.begin) { |
| 201 | // Lower bound starts before the range. |
| 202 | // Split the entry so that a new entry starts exactly at the range.begin |
| 203 | pos = map.Split(pos, range.begin); |
| 204 | ++pos; |
| 205 | } |
| 206 | |
| 207 | AccessMap::index_type current_begin = range.begin; |
| 208 | while (pos != end && current_begin < range.end) { |
| 209 | if (current_begin < pos->first.begin) { // infill the gap |
| 210 | const AccessRange gap_range(current_begin, std::min(range.end, pos->first.begin)); |
| 211 | |
| 212 | ops.infill(map, pos, gap_range); |
| 213 | |
| 214 | // Advance current location. |
| 215 | // Do not advance pos, as it's the next map entry to visit |
| 216 | current_begin = pos->first.begin; |
| 217 | } else { // update existing entry |
| 218 | assert(current_begin == pos->first.begin); |
| 219 | |
| 220 | // Split the current map entry if it goes beyond range.end. |
| 221 | // This ensures the update is restricted to the given range. |
| 222 | if (pos->first.end > range.end) { |
| 223 | pos = map.Split(pos, range.end); |
| 224 | } |
| 225 | |
| 226 | ops.update(pos); |
| 227 | |
| 228 | // Advance both current location and map entry |
| 229 | current_begin = pos->first.end; |
| 230 | ++pos; |
| 231 | } |
| 232 | } |
| 233 | |
| 234 | // Fill to the end if needed |
| 235 | if (current_begin < range.end) { |
| 236 | ops.infill(map, pos, AccessRange(current_begin, range.end)); |
| 237 | } |
| 238 | return pos; |
no test coverage detected