| 112 | |
| 113 | public: |
| 114 | static void flatten(vector<GenericRange<T>>& intervals) |
| 115 | { |
| 116 | // Make a flat list of intervals, with each interval having all elements found in it |
| 117 | // TODO: using a vector isn't ideal, since each modification not at front or back is O(n) |
| 118 | std::sort(intervals.begin(), intervals.end()); |
| 119 | auto itr = intervals.begin(); |
| 120 | while (itr != intervals.end()) |
| 121 | { |
| 122 | auto currentRange = *itr; |
| 123 | auto nextRange = std::next(itr); |
| 124 | if (nextRange == intervals.end()) // This is the last interval |
| 125 | break; |
| 126 | |
| 127 | if (auto splitRanges = currentRange.split(*nextRange); splitRanges.size()) |
| 128 | { |
| 129 | itr = intervals.erase(itr, std::next(nextRange)); // Remove the two source ranges that were split |
| 130 | size_t resetIndex = intervals.size() + splitRanges.size() - 1; // This is where the iterator will be moved to after inserting new ranges |
| 131 | for (const auto& range : splitRanges) |
| 132 | { |
| 133 | // For each split range, insert it in its sorted position |
| 134 | auto rangeInsertItr = std::upper_bound(intervals.begin(), intervals.end(), range); |
| 135 | size_t rangeInsertIndex = rangeInsertItr - intervals.begin(); |
| 136 | intervals.insert(rangeInsertItr, range); |
| 137 | // Move the reset index to before the lowest inserted range's index; everything before is still sorted |
| 138 | resetIndex = std::min(resetIndex, rangeInsertIndex == 0 ? 0 : rangeInsertIndex - 1); |
| 139 | } |
| 140 | itr = intervals.begin() + resetIndex; |
| 141 | } |
| 142 | else |
| 143 | ++itr; |
| 144 | } |
| 145 | } |
| 146 | |
| 147 | GenericRangeMap() |
| 148 | { |