1 //===-- RangeMap.h ----------------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #ifndef liblldb_RangeMap_h_
11 #define liblldb_RangeMap_h_
18 // Other libraries and framework includes
19 #include "llvm/ADT/SmallVector.h"
22 #include "lldb/lldb-private.h"
24 // Uncomment to make sure all Range objects are sorted when needed
25 //#define ASSERT_RANGEMAP_ARE_SORTED
27 namespace lldb_private {
29 //----------------------------------------------------------------------
30 // Templatized classes for dealing with generic ranges and also
31 // collections of ranges, or collections of ranges that have associated
33 //----------------------------------------------------------------------
35 //----------------------------------------------------------------------
36 // A simple range class where you get to define the type of the range
37 // base "B", and the type used for the range byte size "S".
38 //----------------------------------------------------------------------
39 template <typename B, typename S>
54 Range (BaseType b, SizeType s) :
61 Clear (BaseType b = 0)
67 // Set the start value for the range, and keep the same size
75 SetRangeBase (BaseType b)
81 Slide (BaseType slide)
93 SetRangeEnd (BaseType end)
108 SetByteSize (SizeType s)
120 Contains (BaseType r) const
122 return (GetRangeBase() <= r) && (r < GetRangeEnd());
126 ContainsEndInclusive (BaseType r) const
128 return (GetRangeBase() <= r) && (r <= GetRangeEnd());
132 Contains (const Range& range) const
134 return Contains(range.GetRangeBase()) && ContainsEndInclusive(range.GetRangeEnd());
137 // Returns true if the two ranges adjoing or intersect
139 DoesAdjoinOrIntersect (const Range &rhs) const
141 const BaseType lhs_base = this->GetRangeBase();
142 const BaseType rhs_base = rhs.GetRangeBase();
143 const BaseType lhs_end = this->GetRangeEnd();
144 const BaseType rhs_end = rhs.GetRangeEnd();
145 bool result = (lhs_base <= rhs_end) && (lhs_end >= rhs_base);
149 // Returns true if the two ranges intersect
151 DoesIntersect (const Range &rhs) const
153 const BaseType lhs_base = this->GetRangeBase();
154 const BaseType rhs_base = rhs.GetRangeBase();
155 const BaseType lhs_end = this->GetRangeEnd();
156 const BaseType rhs_end = rhs.GetRangeEnd();
157 bool result = (lhs_base < rhs_end) && (lhs_end > rhs_base);
162 operator < (const Range &rhs) const
164 if (base == rhs.base)
165 return size < rhs.size;
166 return base < rhs.base;
170 operator == (const Range &rhs) const
172 return base == rhs.base && size == rhs.size;
176 operator != (const Range &rhs) const
178 return base != rhs.base || size != rhs.size;
182 //----------------------------------------------------------------------
183 // A range array class where you get to define the type of the ranges
184 // that the collection contains.
185 //----------------------------------------------------------------------
187 template <typename B, typename S, unsigned N>
193 typedef Range<B,S> Entry;
194 typedef llvm::SmallVector<Entry, N> Collection;
196 RangeArray() = default;
198 ~RangeArray() = default;
201 Append (const Entry &entry)
203 m_entries.push_back (entry);
207 Append (B base, S size)
209 m_entries.emplace_back(base, size);
213 RemoveEntrtAtIndex (uint32_t idx)
215 if (idx < m_entries.size())
217 m_entries.erase (m_entries.begin() + idx);
226 if (m_entries.size() > 1)
227 std::stable_sort (m_entries.begin(), m_entries.end());
230 #ifdef ASSERT_RANGEMAP_ARE_SORTED
234 typename Collection::const_iterator pos, end, prev;
235 // First we determine if we can combine any of the Entry objects so we
236 // don't end up allocating and making a new collection for no reason
237 for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++)
239 if (prev != end && *pos < *prev)
247 CombineConsecutiveRanges ()
249 #ifdef ASSERT_RANGEMAP_ARE_SORTED
252 // Can't combine if ranges if we have zero or one range
253 if (m_entries.size() > 1)
255 // The list should be sorted prior to calling this function
256 typename Collection::iterator pos;
257 typename Collection::iterator end;
258 typename Collection::iterator prev;
259 bool can_combine = false;
260 // First we determine if we can combine any of the Entry objects so we
261 // don't end up allocating and making a new collection for no reason
262 for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++)
264 if (prev != end && prev->DoesAdjoinOrIntersect(*pos))
271 // We we can combine at least one entry, then we make a new collection
272 // and populate it accordingly, and then swap it into place.
275 Collection minimal_ranges;
276 for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++)
278 if (prev != end && prev->DoesAdjoinOrIntersect(*pos))
279 minimal_ranges.back().SetRangeEnd (std::max<BaseType>(prev->GetRangeEnd(), pos->GetRangeEnd()));
281 minimal_ranges.push_back (*pos);
283 // Use the swap technique in case our new vector is much smaller.
284 // We must swap when using the STL because std::vector objects never
285 // release or reduce the memory once it has been allocated/reserved.
286 m_entries.swap (minimal_ranges);
292 GetMinRangeBase (BaseType fail_value) const
294 #ifdef ASSERT_RANGEMAP_ARE_SORTED
297 if (m_entries.empty())
299 // m_entries must be sorted, so if we aren't empty, we grab the
300 // first range's base
301 return m_entries.front().GetRangeBase();
305 GetMaxRangeEnd (BaseType fail_value) const
307 #ifdef ASSERT_RANGEMAP_ARE_SORTED
310 if (m_entries.empty())
312 // m_entries must be sorted, so if we aren't empty, we grab the
314 return m_entries.back().GetRangeEnd();
318 Slide (BaseType slide)
320 typename Collection::iterator pos, end;
321 for (pos = m_entries.begin(), end = m_entries.end(); pos != end; ++pos)
334 return m_entries.empty();
340 return m_entries.size();
344 GetEntryAtIndex (size_t i) const
346 return ((i < m_entries.size()) ? &m_entries[i] : nullptr);
349 // Clients must ensure that "i" is a valid index prior to calling this function
351 GetEntryRef (size_t i) const
359 return (m_entries.empty() ? nullptr : &m_entries.back());
365 return (m_entries.empty() ? nullptr : &m_entries.back());
369 BaseLessThan (const Entry& lhs, const Entry& rhs)
371 return lhs.GetRangeBase() < rhs.GetRangeBase();
375 FindEntryIndexThatContains (B addr) const
377 #ifdef ASSERT_RANGEMAP_ARE_SORTED
380 if (!m_entries.empty())
382 Entry entry (addr, 1);
383 typename Collection::const_iterator begin = m_entries.begin();
384 typename Collection::const_iterator end = m_entries.end();
385 typename Collection::const_iterator pos = std::lower_bound (begin, end, entry, BaseLessThan);
387 if (pos != end && pos->Contains(addr))
389 return std::distance (begin, pos);
391 else if (pos != begin)
394 if (pos->Contains(addr))
395 return std::distance (begin, pos);
402 FindEntryThatContains (B addr) const
404 #ifdef ASSERT_RANGEMAP_ARE_SORTED
407 if (!m_entries.empty())
409 Entry entry (addr, 1);
410 typename Collection::const_iterator begin = m_entries.begin();
411 typename Collection::const_iterator end = m_entries.end();
412 typename Collection::const_iterator pos = std::lower_bound (begin, end, entry, BaseLessThan);
414 if (pos != end && pos->Contains(addr))
418 else if (pos != begin)
421 if (pos->Contains(addr))
431 FindEntryThatContains (const Entry &range) const
433 #ifdef ASSERT_RANGEMAP_ARE_SORTED
436 if (!m_entries.empty())
438 typename Collection::const_iterator begin = m_entries.begin();
439 typename Collection::const_iterator end = m_entries.end();
440 typename Collection::const_iterator pos = std::lower_bound (begin, end, range, BaseLessThan);
442 if (pos != end && pos->Contains(range))
446 else if (pos != begin)
449 if (pos->Contains(range))
459 Collection m_entries;
462 template <typename B, typename S>
468 typedef Range<B,S> Entry;
469 typedef std::vector<Entry> Collection;
471 RangeVector() = default;
473 ~RangeVector() = default;
476 Append (const Entry &entry)
478 m_entries.push_back (entry);
482 Append (B base, S size)
484 m_entries.emplace_back(base, size);
488 RemoveEntrtAtIndex (uint32_t idx)
490 if (idx < m_entries.size())
492 m_entries.erase (m_entries.begin() + idx);
501 if (m_entries.size() > 1)
502 std::stable_sort (m_entries.begin(), m_entries.end());
505 #ifdef ASSERT_RANGEMAP_ARE_SORTED
509 typename Collection::const_iterator pos, end, prev;
510 // First we determine if we can combine any of the Entry objects so we
511 // don't end up allocating and making a new collection for no reason
512 for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++)
514 if (prev != end && *pos < *prev)
522 CombineConsecutiveRanges ()
524 #ifdef ASSERT_RANGEMAP_ARE_SORTED
527 // Can't combine if ranges if we have zero or one range
528 if (m_entries.size() > 1)
530 // The list should be sorted prior to calling this function
531 typename Collection::iterator pos;
532 typename Collection::iterator end;
533 typename Collection::iterator prev;
534 bool can_combine = false;
535 // First we determine if we can combine any of the Entry objects so we
536 // don't end up allocating and making a new collection for no reason
537 for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++)
539 if (prev != end && prev->DoesAdjoinOrIntersect(*pos))
546 // We we can combine at least one entry, then we make a new collection
547 // and populate it accordingly, and then swap it into place.
550 Collection minimal_ranges;
551 for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++)
553 if (prev != end && prev->DoesAdjoinOrIntersect(*pos))
554 minimal_ranges.back().SetRangeEnd (std::max<BaseType>(prev->GetRangeEnd(), pos->GetRangeEnd()));
556 minimal_ranges.push_back (*pos);
558 // Use the swap technique in case our new vector is much smaller.
559 // We must swap when using the STL because std::vector objects never
560 // release or reduce the memory once it has been allocated/reserved.
561 m_entries.swap (minimal_ranges);
567 GetMinRangeBase (BaseType fail_value) const
569 #ifdef ASSERT_RANGEMAP_ARE_SORTED
572 if (m_entries.empty())
574 // m_entries must be sorted, so if we aren't empty, we grab the
575 // first range's base
576 return m_entries.front().GetRangeBase();
580 GetMaxRangeEnd (BaseType fail_value) const
582 #ifdef ASSERT_RANGEMAP_ARE_SORTED
585 if (m_entries.empty())
587 // m_entries must be sorted, so if we aren't empty, we grab the
589 return m_entries.back().GetRangeEnd();
593 Slide (BaseType slide)
595 typename Collection::iterator pos, end;
596 for (pos = m_entries.begin(), end = m_entries.end(); pos != end; ++pos)
607 Reserve (typename Collection::size_type size)
609 m_entries.reserve (size);
615 return m_entries.empty();
621 return m_entries.size();
625 GetEntryAtIndex (size_t i) const
627 return ((i < m_entries.size()) ? &m_entries[i] : nullptr);
630 // Clients must ensure that "i" is a valid index prior to calling this function
632 GetEntryRef (size_t i) const
640 return (m_entries.empty() ? nullptr : &m_entries.back());
646 return (m_entries.empty() ? nullptr : &m_entries.back());
650 BaseLessThan (const Entry& lhs, const Entry& rhs)
652 return lhs.GetRangeBase() < rhs.GetRangeBase();
656 FindEntryIndexThatContains (B addr) const
658 #ifdef ASSERT_RANGEMAP_ARE_SORTED
661 if (!m_entries.empty())
663 Entry entry (addr, 1);
664 typename Collection::const_iterator begin = m_entries.begin();
665 typename Collection::const_iterator end = m_entries.end();
666 typename Collection::const_iterator pos = std::lower_bound (begin, end, entry, BaseLessThan);
668 if (pos != end && pos->Contains(addr))
670 return std::distance (begin, pos);
672 else if (pos != begin)
675 if (pos->Contains(addr))
676 return std::distance (begin, pos);
683 FindEntryThatContains (B addr) const
685 #ifdef ASSERT_RANGEMAP_ARE_SORTED
688 if (!m_entries.empty())
690 Entry entry (addr, 1);
691 typename Collection::const_iterator begin = m_entries.begin();
692 typename Collection::const_iterator end = m_entries.end();
693 typename Collection::const_iterator pos = std::lower_bound (begin, end, entry, BaseLessThan);
695 if (pos != end && pos->Contains(addr))
699 else if (pos != begin)
702 if (pos->Contains(addr))
712 FindEntryThatContains (const Entry &range) const
714 #ifdef ASSERT_RANGEMAP_ARE_SORTED
717 if (!m_entries.empty())
719 typename Collection::const_iterator begin = m_entries.begin();
720 typename Collection::const_iterator end = m_entries.end();
721 typename Collection::const_iterator pos = std::lower_bound (begin, end, range, BaseLessThan);
723 if (pos != end && pos->Contains(range))
727 else if (pos != begin)
730 if (pos->Contains(range))
740 Collection m_entries;
743 //----------------------------------------------------------------------
744 // A simple range with data class where you get to define the type of
745 // the range base "B", the type used for the range byte size "S", and
746 // the type for the associated data "T".
747 //----------------------------------------------------------------------
748 template <typename B, typename S, typename T>
749 struct RangeData : public Range<B,S>
761 RangeData (B base, S size) :
762 Range<B,S> (base, size),
767 RangeData (B base, S size, DataType d) :
768 Range<B,S> (base, size),
774 operator < (const RangeData &rhs) const
776 if (this->base == rhs.base)
778 if (this->size == rhs.size)
779 return this->data < rhs.data;
781 return this->size < rhs.size;
783 return this->base < rhs.base;
787 operator == (const RangeData &rhs) const
789 return this->GetRangeBase() == rhs.GetRangeBase() &&
790 this->GetByteSize() == rhs.GetByteSize() &&
791 this->data == rhs.data;
795 operator != (const RangeData &rhs) const
797 return this->GetRangeBase() != rhs.GetRangeBase() ||
798 this->GetByteSize() != rhs.GetByteSize() ||
799 this->data != rhs.data;
803 template <typename B, typename S, typename T, unsigned N>
807 typedef RangeData<B,S,T> Entry;
808 typedef llvm::SmallVector<Entry, N> Collection;
810 RangeDataArray() = default;
812 ~RangeDataArray() = default;
815 Append (const Entry &entry)
817 m_entries.push_back (entry);
823 if (m_entries.size() > 1)
824 std::stable_sort (m_entries.begin(), m_entries.end());
827 #ifdef ASSERT_RANGEMAP_ARE_SORTED
831 typename Collection::const_iterator pos, end, prev;
832 // First we determine if we can combine any of the Entry objects so we
833 // don't end up allocating and making a new collection for no reason
834 for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++)
836 if (prev != end && *pos < *prev)
844 CombineConsecutiveEntriesWithEqualData ()
846 #ifdef ASSERT_RANGEMAP_ARE_SORTED
849 typename Collection::iterator pos;
850 typename Collection::iterator end;
851 typename Collection::iterator prev;
852 bool can_combine = false;
853 // First we determine if we can combine any of the Entry objects so we
854 // don't end up allocating and making a new collection for no reason
855 for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++)
857 if (prev != end && prev->data == pos->data)
864 // We we can combine at least one entry, then we make a new collection
865 // and populate it accordingly, and then swap it into place.
868 Collection minimal_ranges;
869 for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++)
871 if (prev != end && prev->data == pos->data)
872 minimal_ranges.back().SetRangeEnd (pos->GetRangeEnd());
874 minimal_ranges.push_back (*pos);
876 // Use the swap technique in case our new vector is much smaller.
877 // We must swap when using the STL because std::vector objects never
878 // release or reduce the memory once it has been allocated/reserved.
879 m_entries.swap (minimal_ranges);
892 return m_entries.empty();
898 return m_entries.size();
902 GetEntryAtIndex (size_t i) const
904 return ((i < m_entries.size()) ? &m_entries[i] : nullptr);
907 // Clients must ensure that "i" is a valid index prior to calling this function
909 GetEntryRef (size_t i) const
915 BaseLessThan (const Entry& lhs, const Entry& rhs)
917 return lhs.GetRangeBase() < rhs.GetRangeBase();
921 FindEntryIndexThatContains (B addr) const
923 #ifdef ASSERT_RANGEMAP_ARE_SORTED
926 if ( !m_entries.empty() )
928 Entry entry (addr, 1);
929 typename Collection::const_iterator begin = m_entries.begin();
930 typename Collection::const_iterator end = m_entries.end();
931 typename Collection::const_iterator pos = std::lower_bound (begin, end, entry, BaseLessThan);
933 if (pos != end && pos->Contains(addr))
935 return std::distance (begin, pos);
937 else if (pos != begin)
940 if (pos->Contains(addr))
941 return std::distance (begin, pos);
948 FindEntryThatContains (B addr)
950 #ifdef ASSERT_RANGEMAP_ARE_SORTED
953 if ( !m_entries.empty() )
956 entry.SetRangeBase(addr);
957 entry.SetByteSize(1);
958 typename Collection::iterator begin = m_entries.begin();
959 typename Collection::iterator end = m_entries.end();
960 typename Collection::iterator pos = std::lower_bound (begin, end, entry, BaseLessThan);
962 if (pos != end && pos->Contains(addr))
966 else if (pos != begin)
969 if (pos->Contains(addr))
979 FindEntryThatContains (B addr) const
981 #ifdef ASSERT_RANGEMAP_ARE_SORTED
984 if ( !m_entries.empty() )
987 entry.SetRangeBase(addr);
988 entry.SetByteSize(1);
989 typename Collection::const_iterator begin = m_entries.begin();
990 typename Collection::const_iterator end = m_entries.end();
991 typename Collection::const_iterator pos = std::lower_bound (begin, end, entry, BaseLessThan);
993 if (pos != end && pos->Contains(addr))
997 else if (pos != begin)
1000 if (pos->Contains(addr))
1010 FindEntryThatContains (const Entry &range) const
1012 #ifdef ASSERT_RANGEMAP_ARE_SORTED
1013 assert (IsSorted());
1015 if ( !m_entries.empty() )
1017 typename Collection::const_iterator begin = m_entries.begin();
1018 typename Collection::const_iterator end = m_entries.end();
1019 typename Collection::const_iterator pos = std::lower_bound (begin, end, range, BaseLessThan);
1021 if (pos != end && pos->Contains(range))
1025 else if (pos != begin)
1028 if (pos->Contains(range))
1040 return (m_entries.empty() ? nullptr : &m_entries.back());
1046 return (m_entries.empty() ? nullptr : &m_entries.back());
1050 Collection m_entries;
1053 // Same as RangeDataArray, but uses std::vector as to not
1054 // require static storage of N items in the class itself
1055 template <typename B, typename S, typename T>
1056 class RangeDataVector
1059 typedef RangeData<B,S,T> Entry;
1060 typedef std::vector<Entry> Collection;
1062 RangeDataVector() = default;
1064 ~RangeDataVector() = default;
1067 Append (const Entry &entry)
1069 m_entries.push_back (entry);
1075 if (m_entries.size() > 1)
1076 std::stable_sort (m_entries.begin(), m_entries.end());
1079 #ifdef ASSERT_RANGEMAP_ARE_SORTED
1083 typename Collection::const_iterator pos, end, prev;
1084 // First we determine if we can combine any of the Entry objects so we
1085 // don't end up allocating and making a new collection for no reason
1086 for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++)
1088 if (prev != end && *pos < *prev)
1096 CombineConsecutiveEntriesWithEqualData ()
1098 #ifdef ASSERT_RANGEMAP_ARE_SORTED
1099 assert (IsSorted());
1101 typename Collection::iterator pos;
1102 typename Collection::iterator end;
1103 typename Collection::iterator prev;
1104 bool can_combine = false;
1105 // First we determine if we can combine any of the Entry objects so we
1106 // don't end up allocating and making a new collection for no reason
1107 for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++)
1109 if (prev != end && prev->data == pos->data)
1116 // We we can combine at least one entry, then we make a new collection
1117 // and populate it accordingly, and then swap it into place.
1120 Collection minimal_ranges;
1121 for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++)
1123 if (prev != end && prev->data == pos->data)
1124 minimal_ranges.back().SetRangeEnd (pos->GetRangeEnd());
1126 minimal_ranges.push_back (*pos);
1128 // Use the swap technique in case our new vector is much smaller.
1129 // We must swap when using the STL because std::vector objects never
1130 // release or reduce the memory once it has been allocated/reserved.
1131 m_entries.swap (minimal_ranges);
1135 // Calculate the byte size of ranges with zero byte sizes by finding
1136 // the next entry with a base address > the current base address
1138 CalculateSizesOfZeroByteSizeRanges (S full_size = 0)
1140 #ifdef ASSERT_RANGEMAP_ARE_SORTED
1141 assert (IsSorted());
1143 typename Collection::iterator pos;
1144 typename Collection::iterator end;
1145 typename Collection::iterator next;
1146 for (pos = m_entries.begin(), end = m_entries.end(); pos != end; ++pos)
1148 if (pos->GetByteSize() == 0)
1150 // Watch out for multiple entries with same address and make sure
1151 // we find an entry that is greater than the current base address
1152 // before we use that for the size
1153 auto curr_base = pos->GetRangeBase();
1154 for (next = pos + 1; next != end; ++next)
1156 auto next_base = next->GetRangeBase();
1157 if (next_base > curr_base)
1159 pos->SetByteSize (next_base - curr_base);
1163 if (next == end && full_size > curr_base)
1164 pos->SetByteSize (full_size - curr_base);
1176 Reserve (typename Collection::size_type size)
1178 m_entries.resize (size);
1184 return m_entries.empty();
1190 return m_entries.size();
1194 GetEntryAtIndex (size_t i) const
1196 return ((i < m_entries.size()) ? &m_entries[i] : nullptr);
1200 GetMutableEntryAtIndex (size_t i)
1202 return ((i < m_entries.size()) ? &m_entries[i] : nullptr);
1205 // Clients must ensure that "i" is a valid index prior to calling this function
1207 GetEntryRef (size_t i) const
1209 return m_entries[i];
1213 BaseLessThan (const Entry& lhs, const Entry& rhs)
1215 return lhs.GetRangeBase() < rhs.GetRangeBase();
1219 FindEntryIndexThatContains (B addr) const
1221 #ifdef ASSERT_RANGEMAP_ARE_SORTED
1222 assert (IsSorted());
1224 if ( !m_entries.empty() )
1226 Entry entry (addr, 1);
1227 typename Collection::const_iterator begin = m_entries.begin();
1228 typename Collection::const_iterator end = m_entries.end();
1229 typename Collection::const_iterator pos = std::lower_bound (begin, end, entry, BaseLessThan);
1231 while(pos != begin && pos[-1].Contains(addr))
1234 if (pos != end && pos->Contains(addr))
1235 return std::distance (begin, pos);
1241 FindEntryIndexesThatContain(B addr, std::vector<uint32_t> &indexes) const
1243 #ifdef ASSERT_RANGEMAP_ARE_SORTED
1244 assert (IsSorted());
1247 if (!m_entries.empty())
1249 typename Collection::const_iterator pos;
1250 for (const auto &entry : m_entries)
1252 if (entry.Contains(addr))
1253 indexes.push_back(entry.data);
1256 return indexes.size() ;
1260 FindEntryThatContains (B addr)
1262 #ifdef ASSERT_RANGEMAP_ARE_SORTED
1263 assert (IsSorted());
1265 if ( !m_entries.empty() )
1268 entry.SetRangeBase(addr);
1269 entry.SetByteSize(1);
1270 typename Collection::iterator begin = m_entries.begin();
1271 typename Collection::iterator end = m_entries.end();
1272 typename Collection::iterator pos = std::lower_bound (begin, end, entry, BaseLessThan);
1274 while(pos != begin && pos[-1].Contains(addr))
1277 if (pos != end && pos->Contains(addr))
1284 FindEntryThatContains (B addr) const
1286 #ifdef ASSERT_RANGEMAP_ARE_SORTED
1287 assert (IsSorted());
1289 if ( !m_entries.empty() )
1292 entry.SetRangeBase(addr);
1293 entry.SetByteSize(1);
1294 typename Collection::const_iterator begin = m_entries.begin();
1295 typename Collection::const_iterator end = m_entries.end();
1296 typename Collection::const_iterator pos = std::lower_bound (begin, end, entry, BaseLessThan);
1298 while(pos != begin && pos[-1].Contains(addr))
1301 if (pos != end && pos->Contains(addr))
1308 FindEntryThatContains (const Entry &range) const
1310 #ifdef ASSERT_RANGEMAP_ARE_SORTED
1311 assert (IsSorted());
1313 if ( !m_entries.empty() )
1315 typename Collection::const_iterator begin = m_entries.begin();
1316 typename Collection::const_iterator end = m_entries.end();
1317 typename Collection::const_iterator pos = std::lower_bound (begin, end, range, BaseLessThan);
1319 while(pos != begin && pos[-1].Contains(range))
1322 if (pos != end && pos->Contains(range))
1329 FindEntryStartsAt (B addr) const
1331 #ifdef ASSERT_RANGEMAP_ARE_SORTED
1332 assert (IsSorted());
1334 if (!m_entries.empty())
1336 auto begin = m_entries.begin(), end = m_entries.end();
1337 auto pos = std::lower_bound (begin, end, Entry(addr, 1), BaseLessThan);
1338 if (pos != end && pos->base == addr)
1345 FindEntryThatContainsOrFollows(B addr) const
1347 #ifdef ASSERT_RANGEMAP_ARE_SORTED
1350 if (!m_entries.empty())
1352 typename Collection::const_iterator end = m_entries.end();
1353 typename Collection::const_iterator pos =
1354 std::lower_bound(m_entries.begin(), end, addr, [](const Entry &lhs, B rhs_base) -> bool {
1355 return lhs.GetRangeEnd() <= rhs_base;
1367 return (m_entries.empty() ? nullptr : &m_entries.back());
1373 return (m_entries.empty() ? nullptr : &m_entries.back());
1377 Collection m_entries;
1380 //----------------------------------------------------------------------
1381 // A simple range with data class where you get to define the type of
1382 // the range base "B", the type used for the range byte size "S", and
1383 // the type for the associated data "T".
1384 //----------------------------------------------------------------------
1385 template <typename B, typename T>
1400 AddressData (B a, DataType d) :
1407 operator < (const AddressData &rhs) const
1409 if (this->addr == rhs.addr)
1410 return this->data < rhs.data;
1411 return this->addr < rhs.addr;
1415 operator == (const AddressData &rhs) const
1417 return this->addr == rhs.addr &&
1418 this->data == rhs.data;
1422 operator != (const AddressData &rhs) const
1424 return this->addr != rhs.addr ||
1425 this->data == rhs.data;
1429 template <typename B, typename T, unsigned N>
1430 class AddressDataArray
1433 typedef AddressData<B,T> Entry;
1434 typedef llvm::SmallVector<Entry, N> Collection;
1436 AddressDataArray() = default;
1438 ~AddressDataArray() = default;
1441 Append (const Entry &entry)
1443 m_entries.push_back (entry);
1449 if (m_entries.size() > 1)
1450 std::stable_sort (m_entries.begin(), m_entries.end());
1453 #ifdef ASSERT_RANGEMAP_ARE_SORTED
1457 typename Collection::const_iterator pos, end, prev;
1458 // First we determine if we can combine any of the Entry objects so we
1459 // don't end up allocating and making a new collection for no reason
1460 for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++)
1462 if (prev != end && *pos < *prev)
1478 return m_entries.empty();
1484 return m_entries.size();
1488 GetEntryAtIndex (size_t i) const
1490 return ((i < m_entries.size()) ? &m_entries[i] : nullptr);
1493 // Clients must ensure that "i" is a valid index prior to calling this function
1495 GetEntryRef (size_t i) const
1497 return m_entries[i];
1501 BaseLessThan (const Entry& lhs, const Entry& rhs)
1503 return lhs.addr < rhs.addr;
1507 FindEntry (B addr, bool exact_match_only)
1509 #ifdef ASSERT_RANGEMAP_ARE_SORTED
1510 assert (IsSorted());
1512 if ( !m_entries.empty() )
1516 typename Collection::iterator begin = m_entries.begin();
1517 typename Collection::iterator end = m_entries.end();
1518 typename Collection::iterator pos = std::lower_bound (begin, end, entry, BaseLessThan);
1520 while(pos != begin && pos[-1].addr == addr)
1525 if (pos->addr == addr || !exact_match_only)
1533 FindNextEntry (const Entry *entry)
1535 if (entry >= &*m_entries.begin() && entry + 1 < &*m_entries.end())
1543 return (m_entries.empty() ? nullptr : &m_entries.back());
1549 return (m_entries.empty() ? nullptr : &m_entries.back());
1553 Collection m_entries;
1556 } // namespace lldb_private
1558 #endif // liblldb_RangeMap_h_