summaryrefslogtreecommitdiff
path: root/genericrange.h
diff options
context:
space:
mode:
authorBrian Potchik <brian@vector35.com>2024-11-14 10:47:04 -0500
committerBrian Potchik <brian@vector35.com>2024-11-14 10:47:04 -0500
commit8e7260067be13075e7d8b78d3dceec50dc7ddab4 (patch)
treec5da01d4381ec4c245b75df321573b460db060a8 /genericrange.h
parent1fa0e3e0b6b18d0071e5aec73bf92498211aab62 (diff)
Fix indentation for easier diffs.
Diffstat (limited to 'genericrange.h')
-rw-r--r--genericrange.h326
1 files changed, 163 insertions, 163 deletions
diff --git a/genericrange.h b/genericrange.h
index f21441bd..c46aa064 100644
--- a/genericrange.h
+++ b/genericrange.h
@@ -29,215 +29,215 @@ namespace BinaryNinjaCore
using namespace std;
#endif
-template <typename T>
-class GenericRange
-{
- uint64_t m_start;
- uint64_t m_end;
- vector<T> m_items;
+ template <typename T>
+ class GenericRange
+ {
+ uint64_t m_start;
+ uint64_t m_end;
+ vector<T> m_items;
-public:
- GenericRange(uint64_t s) : m_start(s), m_end(0) { }
- GenericRange(uint64_t s, uint64_t e, const T& item) : m_start(s), m_end(e), m_items{item} {}
- GenericRange(uint64_t s, uint64_t e, const vector<T>& items) : m_start(s), m_end(e), m_items{items} {}
+ public:
+ GenericRange(uint64_t s) : m_start(s), m_end(0) { }
+ GenericRange(uint64_t s, uint64_t e, const T& item) : m_start(s), m_end(e), m_items{item} {}
+ GenericRange(uint64_t s, uint64_t e, const vector<T>& items) : m_start(s), m_end(e), m_items{items} {}
- bool operator<(const GenericRange& other) const
- {
- if (m_start != other.m_start)
- return m_start < other.m_start;
- return m_end < other.m_end;
- }
+ bool operator<(const GenericRange& other) const
+ {
+ if (m_start != other.m_start)
+ return m_start < other.m_start;
+ return m_end < other.m_end;
+ }
- uint64_t GetStart() const { return m_start; }
- uint64_t GetEnd() const { return m_end; }
- const vector<T>& GetItems() const { return m_items; }
- vector<T>& GetMutableItems() { return m_items; }
+ uint64_t GetStart() const { return m_start; }
+ uint64_t GetEnd() const { return m_end; }
+ const vector<T>& GetItems() const { return m_items; }
+ vector<T>& GetMutableItems() { return m_items; }
- bool overlaps(const GenericRange& other) const { return !(other.m_start > m_end || m_start > other.m_end); }
+ bool overlaps(const GenericRange& other) const { return !(other.m_start > m_end || m_start > other.m_end); }
- vector<GenericRange> split(const GenericRange& nextInterval) const
- {
- vector<GenericRange> result;
- if (overlaps(nextInterval))
+ vector<GenericRange> split(const GenericRange& nextInterval) const
{
- // Find overlap start and end
- uint64_t intersectionStart = std::max(m_start, nextInterval.m_start);
- uint64_t intersectionEnd = std::min(m_end, nextInterval.m_end);
-
- // Add part of this section to before the intersecting region if it starts earlier
- if (m_start < intersectionStart)
- result.push_back({m_start, intersectionStart - 1, m_items});
+ vector<GenericRange> result;
+ if (overlaps(nextInterval))
+ {
+ // Find overlap start and end
+ uint64_t intersectionStart = std::max(m_start, nextInterval.m_start);
+ uint64_t intersectionEnd = std::min(m_end, nextInterval.m_end);
- // Add the intersecting range, plus both sets of items
- GenericRange intersection(intersectionStart, intersectionEnd, m_items);
- intersection.m_items.insert(intersection.m_items.end(), nextInterval.m_items.begin(), nextInterval.m_items.end());
- result.push_back(intersection);
+ // Add part of this section to before the intersecting region if it starts earlier
+ if (m_start < intersectionStart)
+ result.push_back({m_start, intersectionStart - 1, m_items});
- // If the an interval's end is after the intersection (only up to one will be) add it after
- if (nextInterval.m_end > intersectionEnd)
- result.push_back({intersectionEnd + 1, nextInterval.m_end, nextInterval.m_items});
- else if (m_end > intersectionEnd)
- result.push_back({intersectionEnd + 1, m_end, m_items});
- }
+ // Add the intersecting range, plus both sets of items
+ GenericRange intersection(intersectionStart, intersectionEnd, m_items);
+ intersection.m_items.insert(intersection.m_items.end(), nextInterval.m_items.begin(), nextInterval.m_items.end());
+ result.push_back(intersection);
- return result;
- }
-};
+ // If the an interval's end is after the intersection (only up to one will be) add it after
+ if (nextInterval.m_end > intersectionEnd)
+ result.push_back({intersectionEnd + 1, nextInterval.m_end, nextInterval.m_items});
+ else if (m_end > intersectionEnd)
+ result.push_back({intersectionEnd + 1, m_end, m_items});
+ }
-// A map of ranges to items. The ranges are flattened and sorted, and the map is used to quickly find the items. Range values are inclusive.
-template <typename T>
-class GenericRangeMap
-{
- vector<GenericRange<T>> m_sourceRanges;
- vector<GenericRange<T>> m_flattenedRanges;
- map<uint64_t, GenericRange<T>> m_rangeMap;
+ return result;
+ }
+ };
- void populateRangeMap()
+ // A map of ranges to items. The ranges are flattened and sorted, and the map is used to quickly find the items. Range values are inclusive.
+ template <typename T>
+ class GenericRangeMap
{
- uint64_t nextStart = 0;
- for (const auto& i : m_flattenedRanges)
+ vector<GenericRange<T>> m_sourceRanges;
+ vector<GenericRange<T>> m_flattenedRanges;
+ map<uint64_t, GenericRange<T>> m_rangeMap;
+
+ void populateRangeMap()
{
- if (i.GetStart() > nextStart)
- m_rangeMap.emplace(nextStart, GenericRange<T>(nextStart, i.GetStart() - 1, vector<T>()));
+ uint64_t nextStart = 0;
+ for (const auto& i : m_flattenedRanges)
+ {
+ if (i.GetStart() > nextStart)
+ m_rangeMap.emplace(nextStart, GenericRange<T>(nextStart, i.GetStart() - 1, vector<T>()));
+
+ m_rangeMap.emplace(i.GetStart(), GenericRange<T>(i.GetStart(), i.GetEnd(), i.GetItems()));
+ nextStart = i.GetEnd();
+ if (nextStart != std::numeric_limits<uint64_t>::max())
+ nextStart++;
+ }
- m_rangeMap.emplace(i.GetStart(), GenericRange<T>(i.GetStart(), i.GetEnd(), i.GetItems()));
- nextStart = i.GetEnd();
if (nextStart != std::numeric_limits<uint64_t>::max())
- nextStart++;
+ m_rangeMap.emplace(nextStart, GenericRange<T>(nextStart, std::numeric_limits<uint64_t>::max(), vector<T>()));
}
- if (nextStart != std::numeric_limits<uint64_t>::max())
- m_rangeMap.emplace(nextStart, GenericRange<T>(nextStart, std::numeric_limits<uint64_t>::max(), vector<T>()));
- }
-
-public:
- static void flatten(vector<GenericRange<T>>& intervals)
- {
- // Make a flat list of intervals, with each interval having all elements found in it
- // TODO: using a vector isn't ideal, since each modification not at front or back is O(n)
- std::sort(intervals.begin(), intervals.end());
- auto itr = intervals.begin();
- while (itr != intervals.end())
+ public:
+ static void flatten(vector<GenericRange<T>>& intervals)
{
- auto currentRange = *itr;
- auto nextRange = std::next(itr);
- if (nextRange == intervals.end()) // This is the last interval
- break;
-
- if (auto splitRanges = currentRange.split(*nextRange); splitRanges.size())
+ // Make a flat list of intervals, with each interval having all elements found in it
+ // TODO: using a vector isn't ideal, since each modification not at front or back is O(n)
+ std::sort(intervals.begin(), intervals.end());
+ auto itr = intervals.begin();
+ while (itr != intervals.end())
{
- itr = intervals.erase(itr, std::next(nextRange)); // Remove the two source ranges that were split
- size_t resetIndex = intervals.size() + splitRanges.size() - 1; // This is where the iterator will be moved to after inserting new ranges
- for (const auto& range : splitRanges)
+ auto currentRange = *itr;
+ auto nextRange = std::next(itr);
+ if (nextRange == intervals.end()) // This is the last interval
+ break;
+
+ if (auto splitRanges = currentRange.split(*nextRange); splitRanges.size())
{
- // For each split range, insert it in its sorted position
- auto rangeInsertItr = std::upper_bound(intervals.begin(), intervals.end(), range);
- size_t rangeInsertIndex = rangeInsertItr - intervals.begin();
- intervals.insert(rangeInsertItr, range);
- // Move the reset index to before the lowest inserted range's index; everything before is still sorted
- resetIndex = std::min(resetIndex, rangeInsertIndex == 0 ? 0 : rangeInsertIndex - 1);
+ itr = intervals.erase(itr, std::next(nextRange)); // Remove the two source ranges that were split
+ size_t resetIndex = intervals.size() + splitRanges.size() - 1; // This is where the iterator will be moved to after inserting new ranges
+ for (const auto& range : splitRanges)
+ {
+ // For each split range, insert it in its sorted position
+ auto rangeInsertItr = std::upper_bound(intervals.begin(), intervals.end(), range);
+ size_t rangeInsertIndex = rangeInsertItr - intervals.begin();
+ intervals.insert(rangeInsertItr, range);
+ // Move the reset index to before the lowest inserted range's index; everything before is still sorted
+ resetIndex = std::min(resetIndex, rangeInsertIndex == 0 ? 0 : rangeInsertIndex - 1);
+ }
+ itr = intervals.begin() + resetIndex;
}
- itr = intervals.begin() + resetIndex;
+ else
+ ++itr;
}
- else
- ++itr;
}
- }
- GenericRangeMap()
- {
- populateRangeMap();
- }
-
- GenericRangeMap(const vector<GenericRange<T>>& ranges)
- {
- m_sourceRanges = ranges;
- m_flattenedRanges = ranges;
- flatten(m_flattenedRanges);
- populateRangeMap();
- }
-
- GenericRangeMap(const vector<GenericRange<T>>& ranges, std::function<void(vector<T>&)> orderingStrategy)
- {
- m_sourceRanges = ranges;
- m_flattenedRanges = ranges;
- flatten(m_flattenedRanges);
- if (orderingStrategy)
+ GenericRangeMap()
{
- for (auto& i : m_flattenedRanges)
- orderingStrategy(i.GetMutableItems());
+ populateRangeMap();
}
- populateRangeMap();
- }
-
- const vector<GenericRange<T>>& GetSourceRanges() const { return m_sourceRanges; }
- const vector<GenericRange<T>>& GetRanges() const { return m_flattenedRanges; }
- const vector<T>& GetItemsAt(uint64_t addr) const
- {
- if (auto itr = m_rangeMap.upper_bound(addr); itr != m_rangeMap.begin())
+ GenericRangeMap(const vector<GenericRange<T>>& ranges)
{
- --itr;
- return itr->second.GetItems();
+ m_sourceRanges = ranges;
+ m_flattenedRanges = ranges;
+ flatten(m_flattenedRanges);
+ populateRangeMap();
}
- throw std::out_of_range("GenericRangeMap::GetItemsAt - Address not found in any range!");
- }
-
- const GenericRange<T>& GetGenericRangeAt(uint64_t addr) const
- {
- if (auto itr = m_rangeMap.upper_bound(addr); itr != m_rangeMap.begin())
+ GenericRangeMap(const vector<GenericRange<T>>& ranges, std::function<void(vector<T>&)> orderingStrategy)
{
- --itr;
- return itr->second;
+ m_sourceRanges = ranges;
+ m_flattenedRanges = ranges;
+ flatten(m_flattenedRanges);
+ if (orderingStrategy)
+ {
+ for (auto& i : m_flattenedRanges)
+ orderingStrategy(i.GetMutableItems());
+ }
+ populateRangeMap();
}
- throw std::out_of_range("GenericRangeMap::GetGenericRangeAt - Address not found in any range!");
- }
+ const vector<GenericRange<T>>& GetSourceRanges() const { return m_sourceRanges; }
+ const vector<GenericRange<T>>& GetRanges() const { return m_flattenedRanges; }
- GenericRange<T>& GetMutableGenericRangeAt(uint64_t addr)
- {
- if (auto itr = m_rangeMap.upper_bound(addr); itr != m_rangeMap.begin())
+ const vector<T>& GetItemsAt(uint64_t addr) const
{
- --itr;
- return itr->second;
+ if (auto itr = m_rangeMap.upper_bound(addr); itr != m_rangeMap.begin())
+ {
+ --itr;
+ return itr->second.GetItems();
+ }
+
+ throw std::out_of_range("GenericRangeMap::GetItemsAt - Address not found in any range!");
}
- throw std::out_of_range("GenericRangeMap::GetMutableGenericRangeAt - Address not found in any range!");
- }
+ const GenericRange<T>& GetGenericRangeAt(uint64_t addr) const
+ {
+ if (auto itr = m_rangeMap.upper_bound(addr); itr != m_rangeMap.begin())
+ {
+ --itr;
+ return itr->second;
+ }
- std::optional<std::pair<uint64_t, uint64_t>> GetNextValidRange(uint64_t addr, std::function<bool(const GenericRange<T>&)> predicate) const
- {
- auto itr = m_rangeMap.upper_bound(addr);
- if (itr != m_rangeMap.begin())
- --itr;
+ throw std::out_of_range("GenericRangeMap::GetGenericRangeAt - Address not found in any range!");
+ }
- while (itr != m_rangeMap.end())
+ GenericRange<T>& GetMutableGenericRangeAt(uint64_t addr)
{
- if (predicate(itr->second))
- return std::make_pair(itr->second.GetStart(), itr->second.GetEnd());
- ++itr;
+ if (auto itr = m_rangeMap.upper_bound(addr); itr != m_rangeMap.begin())
+ {
+ --itr;
+ return itr->second;
+ }
+
+ throw std::out_of_range("GenericRangeMap::GetMutableGenericRangeAt - Address not found in any range!");
}
- return std::nullopt;
- }
+ std::optional<std::pair<uint64_t, uint64_t>> GetNextValidRange(uint64_t addr, std::function<bool(const GenericRange<T>&)> predicate) const
+ {
+ auto itr = m_rangeMap.upper_bound(addr);
+ if (itr != m_rangeMap.begin())
+ --itr;
- std::optional<std::pair<uint64_t, uint64_t>> GetPreviousValidRange(uint64_t addr, std::function<bool(const GenericRange<T>&)> predicate) const
- {
- auto itr = m_rangeMap.upper_bound(addr);
- if (itr != m_rangeMap.begin())
- --itr;
+ while (itr != m_rangeMap.end())
+ {
+ if (predicate(itr->second))
+ return std::make_pair(itr->second.GetStart(), itr->second.GetEnd());
+ ++itr;
+ }
- while (itr != m_rangeMap.begin())
- {
- if (predicate(itr->second))
- return std::make_pair(itr->second.GetStart(), itr->second.GetEnd());
- --itr;
+ return std::nullopt;
}
- return std::nullopt;
- }
-};
+ std::optional<std::pair<uint64_t, uint64_t>> GetPreviousValidRange(uint64_t addr, std::function<bool(const GenericRange<T>&)> predicate) const
+ {
+ auto itr = m_rangeMap.upper_bound(addr);
+ if (itr != m_rangeMap.begin())
+ --itr;
+
+ while (itr != m_rangeMap.begin())
+ {
+ if (predicate(itr->second))
+ return std::make_pair(itr->second.GetStart(), itr->second.GetEnd());
+ --itr;
+ }
+
+ return std::nullopt;
+ }
+ };
#ifdef BINARYNINJACORE_LIBRARY
}