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 RemoveEntrtAtIndex (uint32_t idx)
209 if (idx < m_entries.size())
211 m_entries.erase (m_entries.begin() + idx);
220 if (m_entries.size() > 1)
221 std::stable_sort (m_entries.begin(), m_entries.end());
224 #ifdef ASSERT_RANGEMAP_ARE_SORTED
228 typename Collection::const_iterator pos, end, prev;
229 // First we determine if we can combine any of the Entry objects so we
230 // don't end up allocating and making a new collection for no reason
231 for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++)
233 if (prev != end && *pos < *prev)
241 CombineConsecutiveRanges ()
243 #ifdef ASSERT_RANGEMAP_ARE_SORTED
246 // Can't combine if ranges if we have zero or one range
247 if (m_entries.size() > 1)
249 // The list should be sorted prior to calling this function
250 typename Collection::iterator pos;
251 typename Collection::iterator end;
252 typename Collection::iterator prev;
253 bool can_combine = false;
254 // First we determine if we can combine any of the Entry objects so we
255 // don't end up allocating and making a new collection for no reason
256 for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++)
258 if (prev != end && prev->DoesAdjoinOrIntersect(*pos))
265 // We we can combine at least one entry, then we make a new collection
266 // and populate it accordingly, and then swap it into place.
269 Collection minimal_ranges;
270 for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++)
272 if (prev != end && prev->DoesAdjoinOrIntersect(*pos))
273 minimal_ranges.back().SetRangeEnd (std::max<BaseType>(prev->GetRangeEnd(), pos->GetRangeEnd()));
275 minimal_ranges.push_back (*pos);
277 // Use the swap technique in case our new vector is much smaller.
278 // We must swap when using the STL because std::vector objects never
279 // release or reduce the memory once it has been allocated/reserved.
280 m_entries.swap (minimal_ranges);
286 GetMinRangeBase (BaseType fail_value) const
288 #ifdef ASSERT_RANGEMAP_ARE_SORTED
291 if (m_entries.empty())
293 // m_entries must be sorted, so if we aren't empty, we grab the
294 // first range's base
295 return m_entries.front().GetRangeBase();
299 GetMaxRangeEnd (BaseType fail_value) const
301 #ifdef ASSERT_RANGEMAP_ARE_SORTED
304 if (m_entries.empty())
306 // m_entries must be sorted, so if we aren't empty, we grab the
308 return m_entries.back().GetRangeEnd();
312 Slide (BaseType slide)
314 typename Collection::iterator pos, end;
315 for (pos = m_entries.begin(), end = m_entries.end(); pos != end; ++pos)
328 return m_entries.empty();
334 return m_entries.size();
338 GetEntryAtIndex (size_t i) const
340 return ((i < m_entries.size()) ? &m_entries[i] : nullptr);
343 // Clients must ensure that "i" is a valid index prior to calling this function
345 GetEntryRef (size_t i) const
353 return (m_entries.empty() ? nullptr : &m_entries.back());
359 return (m_entries.empty() ? nullptr : &m_entries.back());
363 BaseLessThan (const Entry& lhs, const Entry& rhs)
365 return lhs.GetRangeBase() < rhs.GetRangeBase();
369 FindEntryIndexThatContains (B addr) const
371 #ifdef ASSERT_RANGEMAP_ARE_SORTED
374 if (!m_entries.empty())
376 Entry entry (addr, 1);
377 typename Collection::const_iterator begin = m_entries.begin();
378 typename Collection::const_iterator end = m_entries.end();
379 typename Collection::const_iterator pos = std::lower_bound (begin, end, entry, BaseLessThan);
381 if (pos != end && pos->Contains(addr))
383 return std::distance (begin, pos);
385 else if (pos != begin)
388 if (pos->Contains(addr))
389 return std::distance (begin, pos);
396 FindEntryThatContains (B addr) const
398 #ifdef ASSERT_RANGEMAP_ARE_SORTED
401 if (!m_entries.empty())
403 Entry entry (addr, 1);
404 typename Collection::const_iterator begin = m_entries.begin();
405 typename Collection::const_iterator end = m_entries.end();
406 typename Collection::const_iterator pos = std::lower_bound (begin, end, entry, BaseLessThan);
408 if (pos != end && pos->Contains(addr))
412 else if (pos != begin)
415 if (pos->Contains(addr))
425 FindEntryThatContains (const Entry &range) const
427 #ifdef ASSERT_RANGEMAP_ARE_SORTED
430 if (!m_entries.empty())
432 typename Collection::const_iterator begin = m_entries.begin();
433 typename Collection::const_iterator end = m_entries.end();
434 typename Collection::const_iterator pos = std::lower_bound (begin, end, range, BaseLessThan);
436 if (pos != end && pos->Contains(range))
440 else if (pos != begin)
443 if (pos->Contains(range))
453 Collection m_entries;
456 template <typename B, typename S>
462 typedef Range<B,S> Entry;
463 typedef std::vector<Entry> Collection;
465 RangeVector() = default;
467 ~RangeVector() = default;
470 Append (const Entry &entry)
472 m_entries.push_back (entry);
476 RemoveEntrtAtIndex (uint32_t idx)
478 if (idx < m_entries.size())
480 m_entries.erase (m_entries.begin() + idx);
489 if (m_entries.size() > 1)
490 std::stable_sort (m_entries.begin(), m_entries.end());
493 #ifdef ASSERT_RANGEMAP_ARE_SORTED
497 typename Collection::const_iterator pos, end, prev;
498 // First we determine if we can combine any of the Entry objects so we
499 // don't end up allocating and making a new collection for no reason
500 for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++)
502 if (prev != end && *pos < *prev)
510 CombineConsecutiveRanges ()
512 #ifdef ASSERT_RANGEMAP_ARE_SORTED
515 // Can't combine if ranges if we have zero or one range
516 if (m_entries.size() > 1)
518 // The list should be sorted prior to calling this function
519 typename Collection::iterator pos;
520 typename Collection::iterator end;
521 typename Collection::iterator prev;
522 bool can_combine = false;
523 // First we determine if we can combine any of the Entry objects so we
524 // don't end up allocating and making a new collection for no reason
525 for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++)
527 if (prev != end && prev->DoesAdjoinOrIntersect(*pos))
534 // We we can combine at least one entry, then we make a new collection
535 // and populate it accordingly, and then swap it into place.
538 Collection minimal_ranges;
539 for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++)
541 if (prev != end && prev->DoesAdjoinOrIntersect(*pos))
542 minimal_ranges.back().SetRangeEnd (std::max<BaseType>(prev->GetRangeEnd(), pos->GetRangeEnd()));
544 minimal_ranges.push_back (*pos);
546 // Use the swap technique in case our new vector is much smaller.
547 // We must swap when using the STL because std::vector objects never
548 // release or reduce the memory once it has been allocated/reserved.
549 m_entries.swap (minimal_ranges);
555 GetMinRangeBase (BaseType fail_value) const
557 #ifdef ASSERT_RANGEMAP_ARE_SORTED
560 if (m_entries.empty())
562 // m_entries must be sorted, so if we aren't empty, we grab the
563 // first range's base
564 return m_entries.front().GetRangeBase();
568 GetMaxRangeEnd (BaseType fail_value) const
570 #ifdef ASSERT_RANGEMAP_ARE_SORTED
573 if (m_entries.empty())
575 // m_entries must be sorted, so if we aren't empty, we grab the
577 return m_entries.back().GetRangeEnd();
581 Slide (BaseType slide)
583 typename Collection::iterator pos, end;
584 for (pos = m_entries.begin(), end = m_entries.end(); pos != end; ++pos)
595 Reserve (typename Collection::size_type size)
597 m_entries.reserve (size);
603 return m_entries.empty();
609 return m_entries.size();
613 GetEntryAtIndex (size_t i) const
615 return ((i < m_entries.size()) ? &m_entries[i] : nullptr);
618 // Clients must ensure that "i" is a valid index prior to calling this function
620 GetEntryRef (size_t i) const
628 return (m_entries.empty() ? nullptr : &m_entries.back());
634 return (m_entries.empty() ? nullptr : &m_entries.back());
638 BaseLessThan (const Entry& lhs, const Entry& rhs)
640 return lhs.GetRangeBase() < rhs.GetRangeBase();
644 FindEntryIndexThatContains (B addr) const
646 #ifdef ASSERT_RANGEMAP_ARE_SORTED
649 if (!m_entries.empty())
651 Entry entry (addr, 1);
652 typename Collection::const_iterator begin = m_entries.begin();
653 typename Collection::const_iterator end = m_entries.end();
654 typename Collection::const_iterator pos = std::lower_bound (begin, end, entry, BaseLessThan);
656 if (pos != end && pos->Contains(addr))
658 return std::distance (begin, pos);
660 else if (pos != begin)
663 if (pos->Contains(addr))
664 return std::distance (begin, pos);
671 FindEntryThatContains (B addr) const
673 #ifdef ASSERT_RANGEMAP_ARE_SORTED
676 if (!m_entries.empty())
678 Entry entry (addr, 1);
679 typename Collection::const_iterator begin = m_entries.begin();
680 typename Collection::const_iterator end = m_entries.end();
681 typename Collection::const_iterator pos = std::lower_bound (begin, end, entry, BaseLessThan);
683 if (pos != end && pos->Contains(addr))
687 else if (pos != begin)
690 if (pos->Contains(addr))
700 FindEntryThatContains (const Entry &range) const
702 #ifdef ASSERT_RANGEMAP_ARE_SORTED
705 if (!m_entries.empty())
707 typename Collection::const_iterator begin = m_entries.begin();
708 typename Collection::const_iterator end = m_entries.end();
709 typename Collection::const_iterator pos = std::lower_bound (begin, end, range, BaseLessThan);
711 if (pos != end && pos->Contains(range))
715 else if (pos != begin)
718 if (pos->Contains(range))
728 Collection m_entries;
731 //----------------------------------------------------------------------
732 // A simple range with data class where you get to define the type of
733 // the range base "B", the type used for the range byte size "S", and
734 // the type for the associated data "T".
735 //----------------------------------------------------------------------
736 template <typename B, typename S, typename T>
737 struct RangeData : public Range<B,S>
749 RangeData (B base, S size) :
750 Range<B,S> (base, size),
755 RangeData (B base, S size, DataType d) :
756 Range<B,S> (base, size),
762 operator < (const RangeData &rhs) const
764 if (this->base == rhs.base)
766 if (this->size == rhs.size)
767 return this->data < rhs.data;
769 return this->size < rhs.size;
771 return this->base < rhs.base;
775 operator == (const RangeData &rhs) const
777 return this->GetRangeBase() == rhs.GetRangeBase() &&
778 this->GetByteSize() == rhs.GetByteSize() &&
779 this->data == rhs.data;
783 operator != (const RangeData &rhs) const
785 return this->GetRangeBase() != rhs.GetRangeBase() ||
786 this->GetByteSize() != rhs.GetByteSize() ||
787 this->data != rhs.data;
791 template <typename B, typename S, typename T, unsigned N>
795 typedef RangeData<B,S,T> Entry;
796 typedef llvm::SmallVector<Entry, N> Collection;
798 RangeDataArray() = default;
800 ~RangeDataArray() = default;
803 Append (const Entry &entry)
805 m_entries.push_back (entry);
811 if (m_entries.size() > 1)
812 std::stable_sort (m_entries.begin(), m_entries.end());
815 #ifdef ASSERT_RANGEMAP_ARE_SORTED
819 typename Collection::const_iterator pos, end, prev;
820 // First we determine if we can combine any of the Entry objects so we
821 // don't end up allocating and making a new collection for no reason
822 for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++)
824 if (prev != end && *pos < *prev)
832 CombineConsecutiveEntriesWithEqualData ()
834 #ifdef ASSERT_RANGEMAP_ARE_SORTED
837 typename Collection::iterator pos;
838 typename Collection::iterator end;
839 typename Collection::iterator prev;
840 bool can_combine = false;
841 // First we determine if we can combine any of the Entry objects so we
842 // don't end up allocating and making a new collection for no reason
843 for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++)
845 if (prev != end && prev->data == pos->data)
852 // We we can combine at least one entry, then we make a new collection
853 // and populate it accordingly, and then swap it into place.
856 Collection minimal_ranges;
857 for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++)
859 if (prev != end && prev->data == pos->data)
860 minimal_ranges.back().SetRangeEnd (pos->GetRangeEnd());
862 minimal_ranges.push_back (*pos);
864 // Use the swap technique in case our new vector is much smaller.
865 // We must swap when using the STL because std::vector objects never
866 // release or reduce the memory once it has been allocated/reserved.
867 m_entries.swap (minimal_ranges);
880 return m_entries.empty();
886 return m_entries.size();
890 GetEntryAtIndex (size_t i) const
892 return ((i < m_entries.size()) ? &m_entries[i] : nullptr);
895 // Clients must ensure that "i" is a valid index prior to calling this function
897 GetEntryRef (size_t i) const
903 BaseLessThan (const Entry& lhs, const Entry& rhs)
905 return lhs.GetRangeBase() < rhs.GetRangeBase();
909 FindEntryIndexThatContains (B addr) const
911 #ifdef ASSERT_RANGEMAP_ARE_SORTED
914 if ( !m_entries.empty() )
916 Entry entry (addr, 1);
917 typename Collection::const_iterator begin = m_entries.begin();
918 typename Collection::const_iterator end = m_entries.end();
919 typename Collection::const_iterator pos = std::lower_bound (begin, end, entry, BaseLessThan);
921 if (pos != end && pos->Contains(addr))
923 return std::distance (begin, pos);
925 else if (pos != begin)
928 if (pos->Contains(addr))
929 return std::distance (begin, pos);
936 FindEntryThatContains (B addr)
938 #ifdef ASSERT_RANGEMAP_ARE_SORTED
941 if ( !m_entries.empty() )
944 entry.SetRangeBase(addr);
945 entry.SetByteSize(1);
946 typename Collection::iterator begin = m_entries.begin();
947 typename Collection::iterator end = m_entries.end();
948 typename Collection::iterator pos = std::lower_bound (begin, end, entry, BaseLessThan);
950 if (pos != end && pos->Contains(addr))
954 else if (pos != begin)
957 if (pos->Contains(addr))
967 FindEntryThatContains (B addr) const
969 #ifdef ASSERT_RANGEMAP_ARE_SORTED
972 if ( !m_entries.empty() )
975 entry.SetRangeBase(addr);
976 entry.SetByteSize(1);
977 typename Collection::const_iterator begin = m_entries.begin();
978 typename Collection::const_iterator end = m_entries.end();
979 typename Collection::const_iterator pos = std::lower_bound (begin, end, entry, BaseLessThan);
981 if (pos != end && pos->Contains(addr))
985 else if (pos != begin)
988 if (pos->Contains(addr))
998 FindEntryThatContains (const Entry &range) const
1000 #ifdef ASSERT_RANGEMAP_ARE_SORTED
1001 assert (IsSorted());
1003 if ( !m_entries.empty() )
1005 typename Collection::const_iterator begin = m_entries.begin();
1006 typename Collection::const_iterator end = m_entries.end();
1007 typename Collection::const_iterator pos = std::lower_bound (begin, end, range, BaseLessThan);
1009 if (pos != end && pos->Contains(range))
1013 else if (pos != begin)
1016 if (pos->Contains(range))
1028 return (m_entries.empty() ? nullptr : &m_entries.back());
1034 return (m_entries.empty() ? nullptr : &m_entries.back());
1038 Collection m_entries;
1041 // Same as RangeDataArray, but uses std::vector as to not
1042 // require static storage of N items in the class itself
1043 template <typename B, typename S, typename T>
1044 class RangeDataVector
1047 typedef RangeData<B,S,T> Entry;
1048 typedef std::vector<Entry> Collection;
1050 RangeDataVector() = default;
1052 ~RangeDataVector() = default;
1055 Append (const Entry &entry)
1057 m_entries.push_back (entry);
1063 if (m_entries.size() > 1)
1064 std::stable_sort (m_entries.begin(), m_entries.end());
1067 #ifdef ASSERT_RANGEMAP_ARE_SORTED
1071 typename Collection::const_iterator pos, end, prev;
1072 // First we determine if we can combine any of the Entry objects so we
1073 // don't end up allocating and making a new collection for no reason
1074 for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++)
1076 if (prev != end && *pos < *prev)
1084 CombineConsecutiveEntriesWithEqualData ()
1086 #ifdef ASSERT_RANGEMAP_ARE_SORTED
1087 assert (IsSorted());
1089 typename Collection::iterator pos;
1090 typename Collection::iterator end;
1091 typename Collection::iterator prev;
1092 bool can_combine = false;
1093 // First we determine if we can combine any of the Entry objects so we
1094 // don't end up allocating and making a new collection for no reason
1095 for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++)
1097 if (prev != end && prev->data == pos->data)
1104 // We we can combine at least one entry, then we make a new collection
1105 // and populate it accordingly, and then swap it into place.
1108 Collection minimal_ranges;
1109 for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++)
1111 if (prev != end && prev->data == pos->data)
1112 minimal_ranges.back().SetRangeEnd (pos->GetRangeEnd());
1114 minimal_ranges.push_back (*pos);
1116 // Use the swap technique in case our new vector is much smaller.
1117 // We must swap when using the STL because std::vector objects never
1118 // release or reduce the memory once it has been allocated/reserved.
1119 m_entries.swap (minimal_ranges);
1123 // Calculate the byte size of ranges with zero byte sizes by finding
1124 // the next entry with a base address > the current base address
1126 CalculateSizesOfZeroByteSizeRanges ()
1128 #ifdef ASSERT_RANGEMAP_ARE_SORTED
1129 assert (IsSorted());
1131 typename Collection::iterator pos;
1132 typename Collection::iterator end;
1133 typename Collection::iterator next;
1134 for (pos = m_entries.begin(), end = m_entries.end(); pos != end; ++pos)
1136 if (pos->GetByteSize() == 0)
1138 // Watch out for multiple entries with same address and make sure
1139 // we find an entry that is greater than the current base address
1140 // before we use that for the size
1141 auto curr_base = pos->GetRangeBase();
1142 for (next = pos + 1; next != end; ++next)
1144 auto next_base = next->GetRangeBase();
1145 if (next_base > curr_base)
1147 pos->SetByteSize (next_base - curr_base);
1162 Reserve (typename Collection::size_type size)
1164 m_entries.resize (size);
1170 return m_entries.empty();
1176 return m_entries.size();
1180 GetEntryAtIndex (size_t i) const
1182 return ((i < m_entries.size()) ? &m_entries[i] : nullptr);
1185 // Clients must ensure that "i" is a valid index prior to calling this function
1187 GetEntryRef (size_t i) const
1189 return m_entries[i];
1193 BaseLessThan (const Entry& lhs, const Entry& rhs)
1195 return lhs.GetRangeBase() < rhs.GetRangeBase();
1199 FindEntryIndexThatContains (B addr) const
1201 #ifdef ASSERT_RANGEMAP_ARE_SORTED
1202 assert (IsSorted());
1204 if ( !m_entries.empty() )
1206 Entry entry (addr, 1);
1207 typename Collection::const_iterator begin = m_entries.begin();
1208 typename Collection::const_iterator end = m_entries.end();
1209 typename Collection::const_iterator pos = std::lower_bound (begin, end, entry, BaseLessThan);
1211 while(pos != begin && pos[-1].Contains(addr))
1214 if (pos != end && pos->Contains(addr))
1215 return std::distance (begin, pos);
1221 FindEntryThatContains (B addr)
1223 #ifdef ASSERT_RANGEMAP_ARE_SORTED
1224 assert (IsSorted());
1226 if ( !m_entries.empty() )
1229 entry.SetRangeBase(addr);
1230 entry.SetByteSize(1);
1231 typename Collection::iterator begin = m_entries.begin();
1232 typename Collection::iterator end = m_entries.end();
1233 typename Collection::iterator pos = std::lower_bound (begin, end, entry, BaseLessThan);
1235 while(pos != begin && pos[-1].Contains(addr))
1238 if (pos != end && pos->Contains(addr))
1245 FindEntryThatContains (B addr) const
1247 #ifdef ASSERT_RANGEMAP_ARE_SORTED
1248 assert (IsSorted());
1250 if ( !m_entries.empty() )
1253 entry.SetRangeBase(addr);
1254 entry.SetByteSize(1);
1255 typename Collection::const_iterator begin = m_entries.begin();
1256 typename Collection::const_iterator end = m_entries.end();
1257 typename Collection::const_iterator pos = std::lower_bound (begin, end, entry, BaseLessThan);
1259 while(pos != begin && pos[-1].Contains(addr))
1262 if (pos != end && pos->Contains(addr))
1269 FindEntryThatContains (const Entry &range) const
1271 #ifdef ASSERT_RANGEMAP_ARE_SORTED
1272 assert (IsSorted());
1274 if ( !m_entries.empty() )
1276 typename Collection::const_iterator begin = m_entries.begin();
1277 typename Collection::const_iterator end = m_entries.end();
1278 typename Collection::const_iterator pos = std::lower_bound (begin, end, range, BaseLessThan);
1280 while(pos != begin && pos[-1].Contains(range))
1283 if (pos != end && pos->Contains(range))
1292 return (m_entries.empty() ? nullptr : &m_entries.back());
1298 return (m_entries.empty() ? nullptr : &m_entries.back());
1302 Collection m_entries;
1305 //----------------------------------------------------------------------
1306 // A simple range with data class where you get to define the type of
1307 // the range base "B", the type used for the range byte size "S", and
1308 // the type for the associated data "T".
1309 //----------------------------------------------------------------------
1310 template <typename B, typename T>
1325 AddressData (B a, DataType d) :
1332 operator < (const AddressData &rhs) const
1334 if (this->addr == rhs.addr)
1335 return this->data < rhs.data;
1336 return this->addr < rhs.addr;
1340 operator == (const AddressData &rhs) const
1342 return this->addr == rhs.addr &&
1343 this->data == rhs.data;
1347 operator != (const AddressData &rhs) const
1349 return this->addr != rhs.addr ||
1350 this->data == rhs.data;
1354 template <typename B, typename T, unsigned N>
1355 class AddressDataArray
1358 typedef AddressData<B,T> Entry;
1359 typedef llvm::SmallVector<Entry, N> Collection;
1361 AddressDataArray() = default;
1363 ~AddressDataArray() = default;
1366 Append (const Entry &entry)
1368 m_entries.push_back (entry);
1374 if (m_entries.size() > 1)
1375 std::stable_sort (m_entries.begin(), m_entries.end());
1378 #ifdef ASSERT_RANGEMAP_ARE_SORTED
1382 typename Collection::const_iterator pos, end, prev;
1383 // First we determine if we can combine any of the Entry objects so we
1384 // don't end up allocating and making a new collection for no reason
1385 for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++)
1387 if (prev != end && *pos < *prev)
1403 return m_entries.empty();
1409 return m_entries.size();
1413 GetEntryAtIndex (size_t i) const
1415 return ((i < m_entries.size()) ? &m_entries[i] : nullptr);
1418 // Clients must ensure that "i" is a valid index prior to calling this function
1420 GetEntryRef (size_t i) const
1422 return m_entries[i];
1426 BaseLessThan (const Entry& lhs, const Entry& rhs)
1428 return lhs.addr < rhs.addr;
1432 FindEntry (B addr, bool exact_match_only)
1434 #ifdef ASSERT_RANGEMAP_ARE_SORTED
1435 assert (IsSorted());
1437 if ( !m_entries.empty() )
1441 typename Collection::iterator begin = m_entries.begin();
1442 typename Collection::iterator end = m_entries.end();
1443 typename Collection::iterator pos = std::lower_bound (begin, end, entry, BaseLessThan);
1445 while(pos != begin && pos[-1].addr == addr)
1450 if (pos->addr == addr || !exact_match_only)
1458 FindNextEntry (const Entry *entry)
1460 if (entry >= &*m_entries.begin() && entry + 1 < &*m_entries.end())
1468 return (m_entries.empty() ? nullptr : &m_entries.back());
1474 return (m_entries.empty() ? nullptr : &m_entries.back());
1478 Collection m_entries;
1481 } // namespace lldb_private
1483 #endif // liblldb_RangeMap_h_