LLDB mainline
RangeMap.h
Go to the documentation of this file.
1//===-- RangeMap.h ----------------------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLDB_UTILITY_RANGEMAP_H
10#define LLDB_UTILITY_RANGEMAP_H
11
12#include <algorithm>
13#include <vector>
14
15#include "llvm/ADT/SmallVector.h"
16
17#include "lldb/lldb-private.h"
18
19// Uncomment to make sure all Range objects are sorted when needed
20//#define ASSERT_RANGEMAP_ARE_SORTED
21
22namespace lldb_private {
23
24// Templatized classes for dealing with generic ranges and also collections of
25// ranges, or collections of ranges that have associated data.
26
27// A simple range class where you get to define the type of the range
28// base "B", and the type used for the range byte size "S".
29template <typename B, typename S> struct Range {
30 typedef B BaseType;
31 typedef S SizeType;
32
35
36 Range() : base(0), size(0) {}
37
38 Range(BaseType b, SizeType s) : base(b), size(s) {}
39
40 void Clear(BaseType b = 0) {
41 base = b;
42 size = 0;
43 }
44
45 BaseType GetRangeBase() const { return base; }
46
47 /// Set the start value for the range, and keep the same size
48 void SetRangeBase(BaseType b) { base = b; }
49
50 void Slide(BaseType slide) { base += slide; }
51
52 void ShrinkFront(S s) {
53 base += s;
54 size -= std::min(s, size);
55 }
56
57 bool Union(const Range &rhs) {
58 if (DoesAdjoinOrIntersect(rhs)) {
59 auto new_end = std::max<BaseType>(GetRangeEnd(), rhs.GetRangeEnd());
60 base = std::min<BaseType>(base, rhs.base);
61 size = new_end - base;
62 return true;
63 }
64 return false;
65 }
66
67 Range Intersect(const Range &rhs) const {
68 const BaseType lhs_base = this->GetRangeBase();
69 const BaseType rhs_base = rhs.GetRangeBase();
70 const BaseType lhs_end = this->GetRangeEnd();
71 const BaseType rhs_end = rhs.GetRangeEnd();
72 Range range;
73 range.SetRangeBase(std::max(lhs_base, rhs_base));
74 range.SetRangeEnd(std::min(lhs_end, rhs_end));
75 return range;
76 }
77
78 BaseType GetRangeEnd() const { return base + size; }
79
81 if (end > base)
82 size = end - base;
83 else
84 size = 0;
85 }
86
87 SizeType GetByteSize() const { return size; }
88
89 void SetByteSize(SizeType s) { size = s; }
90
91 bool IsValid() const { return size > 0; }
92
93 bool Contains(BaseType r) const {
94 return (GetRangeBase() <= r) && (r < GetRangeEnd());
95 }
96
98 return (GetRangeBase() <= r) && (r <= GetRangeEnd());
99 }
100
101 bool Contains(const Range &range) const {
102 return Contains(range.GetRangeBase()) &&
104 }
105
106 // Returns true if the two ranges adjoing or intersect
107 bool DoesAdjoinOrIntersect(const Range &rhs) const {
108 const BaseType lhs_base = this->GetRangeBase();
109 const BaseType rhs_base = rhs.GetRangeBase();
110 const BaseType lhs_end = this->GetRangeEnd();
111 const BaseType rhs_end = rhs.GetRangeEnd();
112 bool result = (lhs_base <= rhs_end) && (lhs_end >= rhs_base);
113 return result;
114 }
115
116 // Returns true if the two ranges intersect
117 bool DoesIntersect(const Range &rhs) const {
118 return Intersect(rhs).IsValid();
119 }
120
121 bool operator<(const Range &rhs) const {
122 if (base == rhs.base)
123 return size < rhs.size;
124 return base < rhs.base;
125 }
126
127 bool operator==(const Range &rhs) const {
128 return base == rhs.base && size == rhs.size;
129 }
130
131 bool operator!=(const Range &rhs) const {
132 return base != rhs.base || size != rhs.size;
133 }
134};
135
136template <typename B, typename S, unsigned N = 0> class RangeVector {
137public:
138 typedef B BaseType;
139 typedef S SizeType;
141 typedef llvm::SmallVector<Entry, N> Collection;
142
143 RangeVector() = default;
144
145 ~RangeVector() = default;
146
148 const RangeVector &vec2) {
149#ifdef ASSERT_RANGEMAP_ARE_SORTED
150 assert(vec1.IsSorted() && vec2.IsSorted());
151#endif
152 RangeVector result;
153 auto pos1 = vec1.begin();
154 auto end1 = vec1.end();
155 auto pos2 = vec2.begin();
156 auto end2 = vec2.end();
157 while (pos1 != end1 && pos2 != end2) {
158 Entry entry = pos1->Intersect(*pos2);
159 if (entry.IsValid())
160 result.Append(entry);
161 if (pos1->GetRangeEnd() < pos2->GetRangeEnd())
162 ++pos1;
163 else
164 ++pos2;
165 }
166 return result;
167 }
168
169 bool operator==(const RangeVector &rhs) const {
170 if (GetSize() != rhs.GetSize())
171 return false;
172 for (size_t i = 0; i < GetSize(); ++i) {
173 if (GetEntryRef(i) != rhs.GetEntryRef(i))
174 return false;
175 }
176 return true;
177 }
178
179 void Append(const Entry &entry) { m_entries.push_back(entry); }
180
181 void Append(B base, S size) { m_entries.emplace_back(base, size); }
182
183 // Insert an item into a sorted list and optionally combine it with any
184 // adjacent blocks if requested.
185 void Insert(const Entry &entry, bool combine) {
186 if (m_entries.empty()) {
187 m_entries.push_back(entry);
188 return;
189 }
190 auto begin = m_entries.begin();
191 auto end = m_entries.end();
192 auto pos = std::lower_bound(begin, end, entry);
193 if (combine) {
194 if (pos != end && pos->Union(entry)) {
196 return;
197 }
198 if (pos != begin) {
199 auto prev = pos - 1;
200 if (prev->Union(entry)) {
201 CombinePrevAndNext(prev);
202 return;
203 }
204 }
205 }
206 m_entries.insert(pos, entry);
207 }
208
209 bool RemoveEntryAtIndex(uint32_t idx) {
210 if (idx < m_entries.size()) {
211 m_entries.erase(m_entries.begin() + idx);
212 return true;
213 }
214 return false;
215 }
216
217 void Sort() {
218 if (m_entries.size() > 1)
219 std::stable_sort(m_entries.begin(), m_entries.end());
220 }
221
222#ifdef ASSERT_RANGEMAP_ARE_SORTED
223 bool IsSorted() const {
224 typename Collection::const_iterator pos, end, prev;
225 // First we determine if we can combine any of the Entry objects so we
226 // don't end up allocating and making a new collection for no reason
227 for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end;
228 prev = pos++) {
229 if (prev != end && *pos < *prev)
230 return false;
231 }
232 return true;
233 }
234#endif
235
237#ifdef ASSERT_RANGEMAP_ARE_SORTED
238 assert(IsSorted());
239#endif
240 auto first_intersect = std::adjacent_find(
241 m_entries.begin(), m_entries.end(), [](const Entry &a, const Entry &b) {
242 return a.DoesAdjoinOrIntersect(b);
243 });
244 if (first_intersect == m_entries.end())
245 return;
246
247 // We can combine at least one entry, then we make a new collection and
248 // populate it accordingly, and then swap it into place.
249 auto pos = std::next(first_intersect);
250 Collection minimal_ranges(m_entries.begin(), pos);
251 for (; pos != m_entries.end(); ++pos) {
252 Entry &back = minimal_ranges.back();
253 if (back.DoesAdjoinOrIntersect(*pos))
254 back.SetRangeEnd(std::max(back.GetRangeEnd(), pos->GetRangeEnd()));
255 else
256 minimal_ranges.push_back(*pos);
257 }
258 m_entries.swap(minimal_ranges);
259 }
260
262#ifdef ASSERT_RANGEMAP_ARE_SORTED
263 assert(IsSorted());
264#endif
265 if (m_entries.empty())
266 return fail_value;
267 // m_entries must be sorted, so if we aren't empty, we grab the first
268 // range's base
269 return m_entries.front().GetRangeBase();
270 }
271
272 BaseType GetMaxRangeEnd(BaseType fail_value) const {
273#ifdef ASSERT_RANGEMAP_ARE_SORTED
274 assert(IsSorted());
275#endif
276 if (m_entries.empty())
277 return fail_value;
278 // m_entries must be sorted, so if we aren't empty, we grab the last
279 // range's end
280 return m_entries.back().GetRangeEnd();
281 }
282
283 void Slide(BaseType slide) {
284 typename Collection::iterator pos, end;
285 for (pos = m_entries.begin(), end = m_entries.end(); pos != end; ++pos)
286 pos->Slide(slide);
287 }
288
289 void Clear() { m_entries.clear(); }
290
291 void Reserve(typename Collection::size_type size) { m_entries.reserve(size); }
292
293 bool IsEmpty() const { return m_entries.empty(); }
294
295 size_t GetSize() const { return m_entries.size(); }
296
297 const Entry *GetEntryAtIndex(size_t i) const {
298 return ((i < m_entries.size()) ? &m_entries[i] : nullptr);
299 }
300
301 // Clients must ensure that "i" is a valid index prior to calling this
302 // function
303 Entry &GetEntryRef(size_t i) { return m_entries[i]; }
304 const Entry &GetEntryRef(size_t i) const { return m_entries[i]; }
305
306 Entry *Back() { return (m_entries.empty() ? nullptr : &m_entries.back()); }
307
308 const Entry *Back() const {
309 return (m_entries.empty() ? nullptr : &m_entries.back());
310 }
311
312 static bool BaseLessThan(const Entry &lhs, const Entry &rhs) {
313 return lhs.GetRangeBase() < rhs.GetRangeBase();
314 }
315
316 uint32_t FindEntryIndexThatContains(B addr) const {
317#ifdef ASSERT_RANGEMAP_ARE_SORTED
318 assert(IsSorted());
319#endif
320 if (!m_entries.empty()) {
321 Entry entry(addr, 1);
322 typename Collection::const_iterator begin = m_entries.begin();
323 typename Collection::const_iterator end = m_entries.end();
324 typename Collection::const_iterator pos =
325 std::lower_bound(begin, end, entry, BaseLessThan);
326
327 if (pos != end && pos->Contains(addr)) {
328 return std::distance(begin, pos);
329 } else if (pos != begin) {
330 --pos;
331 if (pos->Contains(addr))
332 return std::distance(begin, pos);
333 }
334 }
335 return UINT32_MAX;
336 }
337
338 const Entry *FindEntryThatContains(B addr) const {
339#ifdef ASSERT_RANGEMAP_ARE_SORTED
340 assert(IsSorted());
341#endif
342 if (!m_entries.empty()) {
343 Entry entry(addr, 1);
344 typename Collection::const_iterator begin = m_entries.begin();
345 typename Collection::const_iterator end = m_entries.end();
346 typename Collection::const_iterator pos =
347 std::lower_bound(begin, end, entry, BaseLessThan);
348
349 if (pos != end && pos->Contains(addr)) {
350 return &(*pos);
351 } else if (pos != begin) {
352 --pos;
353 if (pos->Contains(addr)) {
354 return &(*pos);
355 }
356 }
357 }
358 return nullptr;
359 }
360
361 const Entry *FindEntryThatContains(const Entry &range) const {
362#ifdef ASSERT_RANGEMAP_ARE_SORTED
363 assert(IsSorted());
364#endif
365 if (!m_entries.empty()) {
366 typename Collection::const_iterator begin = m_entries.begin();
367 typename Collection::const_iterator end = m_entries.end();
368 typename Collection::const_iterator pos =
369 std::lower_bound(begin, end, range, BaseLessThan);
370
371 if (pos != end && pos->Contains(range)) {
372 return &(*pos);
373 } else if (pos != begin) {
374 --pos;
375 if (pos->Contains(range)) {
376 return &(*pos);
377 }
378 }
379 }
380 return nullptr;
381 }
382
383 using const_iterator = typename Collection::const_iterator;
384 const_iterator begin() const { return m_entries.begin(); }
385 const_iterator end() const { return m_entries.end(); }
386
387protected:
388 void CombinePrevAndNext(typename Collection::iterator pos) {
389 // Check if the prev or next entries in case they need to be unioned with
390 // the entry pointed to by "pos".
391 if (pos != m_entries.begin()) {
392 auto prev = pos - 1;
393 if (prev->Union(*pos))
394 m_entries.erase(pos);
395 pos = prev;
396 }
397
398 auto end = m_entries.end();
399 if (pos != end) {
400 auto next = pos + 1;
401 if (next != end) {
402 if (pos->Union(*next))
403 m_entries.erase(next);
404 }
405 }
406 }
407
409};
410
411// A simple range with data class where you get to define the type of
412// the range base "B", the type used for the range byte size "S", and the type
413// for the associated data "T".
414template <typename B, typename S, typename T>
415struct RangeData : public Range<B, S> {
416 typedef T DataType;
417
419
420 RangeData() : Range<B, S>(), data() {}
421
422 RangeData(B base, S size) : Range<B, S>(base, size), data() {}
423
424 RangeData(B base, S size, DataType d) : Range<B, S>(base, size), data(d) {}
425};
426
427// We can treat the vector as a flattened Binary Search Tree, augmenting it
428// with upper bounds (max of range endpoints) for every index allows us to
429// query for range containment quicker.
430template <typename B, typename S, typename T>
431struct AugmentedRangeData : public RangeData<B, S, T> {
433
435 : RangeData<B, S, T>(rd), upper_bound() {}
436};
437
438template <typename B, typename S, typename T, unsigned N = 0,
439 class Compare = std::less<T>>
441public:
445 typedef llvm::SmallVector<AugmentedEntry, N> Collection;
446
448
449 ~RangeDataVector() = default;
450
451 void Append(const Entry &entry) { m_entries.emplace_back(entry); }
452
453 /// Append a range with data to the vector
454 /// \param B The base of the memory range
455 /// \param S The size of the memory range
456 /// \param T The data associated with the memory range
457 void Append(B &&b, S &&s, T &&t) { m_entries.emplace_back(Entry(b, s, t)); }
458
459 bool Erase(uint32_t start, uint32_t end) {
460 if (start >= end || end > m_entries.size())
461 return false;
462 m_entries.erase(begin() + start, begin() + end);
463 return true;
464 }
465
466 void Sort() {
467 if (m_entries.size() > 1)
468 std::stable_sort(m_entries.begin(), m_entries.end(),
469 [&compare = m_compare](const Entry &a, const Entry &b) {
470 if (a.base != b.base)
471 return a.base < b.base;
472 if (a.size != b.size)
473 return a.size < b.size;
474 return compare(a.data, b.data);
475 });
476 if (!m_entries.empty())
477 ComputeUpperBounds(0, m_entries.size());
478 }
479
480#ifdef ASSERT_RANGEMAP_ARE_SORTED
481 bool IsSorted() const {
482 typename Collection::const_iterator pos, end, prev;
483 for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end;
484 prev = pos++) {
485 if (prev != end && *pos < *prev)
486 return false;
487 }
488 return true;
489 }
490#endif
491
493#ifdef ASSERT_RANGEMAP_ARE_SORTED
494 assert(IsSorted());
495#endif
496 typename Collection::iterator pos;
497 typename Collection::iterator end;
498 typename Collection::iterator prev;
499 bool can_combine = false;
500 // First we determine if we can combine any of the Entry objects so we
501 // don't end up allocating and making a new collection for no reason
502 for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end;
503 prev = pos++) {
504 if (prev != end && prev->data == pos->data) {
505 can_combine = true;
506 break;
507 }
508 }
509
510 // We can combine at least one entry, then we make a new collection and
511 // populate it accordingly, and then swap it into place.
512 if (can_combine) {
513 Collection minimal_ranges;
514 for (pos = m_entries.begin(), end = m_entries.end(), prev = end;
515 pos != end; prev = pos++) {
516 if (prev != end && prev->data == pos->data)
517 minimal_ranges.back().SetRangeEnd(pos->GetRangeEnd());
518 else
519 minimal_ranges.push_back(*pos);
520 }
521 // Use the swap technique in case our new vector is much smaller. We must
522 // swap when using the STL because std::vector objects never release or
523 // reduce the memory once it has been allocated/reserved.
524 m_entries.swap(minimal_ranges);
525 }
526 }
527
528 void Clear() { m_entries.clear(); }
529
530 bool IsEmpty() const { return m_entries.empty(); }
531
532 size_t GetSize() const { return m_entries.size(); }
533
534 const Entry *GetEntryAtIndex(size_t i) const {
535 return ((i < m_entries.size()) ? &m_entries[i] : nullptr);
536 }
537
539 return ((i < m_entries.size()) ? &m_entries[i] : nullptr);
540 }
541
542 // Clients must ensure that "i" is a valid index prior to calling this
543 // function
544 Entry &GetEntryRef(size_t i) { return m_entries[i]; }
545 const Entry &GetEntryRef(size_t i) const { return m_entries[i]; }
546
547 static bool BaseLessThan(const Entry &lhs, const Entry &rhs) {
548 return lhs.GetRangeBase() < rhs.GetRangeBase();
549 }
550
551 uint32_t FindEntryIndexThatContains(B addr) const {
552 const AugmentedEntry *entry =
553 static_cast<const AugmentedEntry *>(FindEntryThatContains(addr));
554 if (entry)
555 return std::distance(m_entries.begin(), entry);
556 return UINT32_MAX;
557 }
558
559 uint32_t FindEntryIndexesThatContain(B addr, std::vector<uint32_t> &indexes) {
560#ifdef ASSERT_RANGEMAP_ARE_SORTED
561 assert(IsSorted());
562#endif
563 if (!m_entries.empty())
564 FindEntryIndexesThatContain(addr, 0, m_entries.size(), indexes);
565
566 return indexes.size();
567 }
568
570 return const_cast<Entry *>(
571 static_cast<const RangeDataVector *>(this)->FindEntryThatContains(
572 addr));
573 }
574
575 const Entry *FindEntryThatContains(B addr) const {
576 return FindEntryThatContains(Entry(addr, 1));
577 }
578
579 const Entry *FindEntryThatContains(const Entry &range) const {
580#ifdef ASSERT_RANGEMAP_ARE_SORTED
581 assert(IsSorted());
582#endif
583 if (!m_entries.empty()) {
584 typename Collection::const_iterator begin = m_entries.begin();
585 typename Collection::const_iterator end = m_entries.end();
586 typename Collection::const_iterator pos =
587 std::lower_bound(begin, end, range, BaseLessThan);
588
589 while (pos != begin && pos[-1].Contains(range))
590 --pos;
591
592 if (pos != end && pos->Contains(range))
593 return &(*pos);
594 }
595 return nullptr;
596 }
597
598 const Entry *FindEntryStartsAt(B addr) const {
599#ifdef ASSERT_RANGEMAP_ARE_SORTED
600 assert(IsSorted());
601#endif
602 if (!m_entries.empty()) {
603 auto begin = m_entries.begin(), end = m_entries.end();
604 auto pos = std::lower_bound(begin, end, Entry(addr, 1), BaseLessThan);
605 if (pos != end && pos->base == addr)
606 return &(*pos);
607 }
608 return nullptr;
609 }
610
611 // This method will return the entry that contains the given address, or the
612 // entry following that address. If you give it an address of 0 and the
613 // first entry starts at address 0x100, you will get the entry at 0x100.
614 //
615 // For most uses, FindEntryThatContains is the correct one to use, this is a
616 // less commonly needed behavior. It was added for core file memory regions,
617 // where we want to present a gap in the memory regions as a distinct region,
618 // so we need to know the start address of the next memory section that
619 // exists.
621#ifdef ASSERT_RANGEMAP_ARE_SORTED
622 assert(IsSorted());
623#endif
624 if (!m_entries.empty()) {
625 typename Collection::const_iterator begin = m_entries.begin();
626 typename Collection::const_iterator end = m_entries.end();
627 typename Collection::const_iterator pos = llvm::lower_bound(
628 m_entries, addr, [](const Entry &lhs, B rhs_base) -> bool {
629 return lhs.GetRangeEnd() <= rhs_base;
630 });
631
632 while (pos != begin && pos[-1].Contains(addr))
633 --pos;
634
635 if (pos != end)
636 return &(*pos);
637 }
638 return nullptr;
639 }
640
642#ifdef ASSERT_RANGEMAP_ARE_SORTED
643 assert(IsSorted());
644#endif
645 const AugmentedEntry *entry = static_cast<const AugmentedEntry *>(
647 if (entry)
648 return std::distance(m_entries.begin(), entry);
649 return UINT32_MAX;
650 }
651
652 Entry *Back() { return (m_entries.empty() ? nullptr : &m_entries.back()); }
653
654 const Entry *Back() const {
655 return (m_entries.empty() ? nullptr : &m_entries.back());
656 }
657
658 using const_iterator = typename Collection::const_iterator;
659 const_iterator begin() const { return m_entries.begin(); }
660 const_iterator end() const { return m_entries.end(); }
661
662protected:
665
666private:
667 // Compute extra information needed for search
668 B ComputeUpperBounds(size_t lo, size_t hi) {
669 size_t mid = (lo + hi) / 2;
670 AugmentedEntry &entry = m_entries[mid];
671
672 entry.upper_bound = entry.base + entry.size;
673
674 if (lo < mid)
675 entry.upper_bound =
676 std::max(entry.upper_bound, ComputeUpperBounds(lo, mid));
677
678 if (mid + 1 < hi)
679 entry.upper_bound =
680 std::max(entry.upper_bound, ComputeUpperBounds(mid + 1, hi));
681
682 return entry.upper_bound;
683 }
684
685 // This is based on the augmented tree implementation found at
686 // https://en.wikipedia.org/wiki/Interval_tree#Augmented_tree
687 void FindEntryIndexesThatContain(B addr, size_t lo, size_t hi,
688 std::vector<uint32_t> &indexes) {
689 size_t mid = (lo + hi) / 2;
690 const AugmentedEntry &entry = m_entries[mid];
691
692 // addr is greater than the rightmost point of any interval below mid
693 // so there are cannot be any matches.
694 if (addr > entry.upper_bound)
695 return;
696
697 // Recursively search left subtree
698 if (lo < mid)
699 FindEntryIndexesThatContain(addr, lo, mid, indexes);
700
701 // If addr is smaller than the start of the current interval it
702 // cannot contain it nor can any of its right subtree.
703 if (addr < entry.base)
704 return;
705
706 if (entry.Contains(addr))
707 indexes.push_back(entry.data);
708
709 // Recursively search right subtree
710 if (mid + 1 < hi)
711 FindEntryIndexesThatContain(addr, mid + 1, hi, indexes);
712 }
713};
714
715// A simple range with data class where you get to define the type of
716// the range base "B", the type used for the range byte size "S", and the type
717// for the associated data "T".
718template <typename B, typename T> struct AddressData {
719 typedef B BaseType;
720 typedef T DataType;
721
724
726
727 AddressData(B a, DataType d) : addr(a), data(d) {}
728
729 bool operator<(const AddressData &rhs) const {
730 if (this->addr == rhs.addr)
731 return this->data < rhs.data;
732 return this->addr < rhs.addr;
733 }
734
735 bool operator==(const AddressData &rhs) const {
736 return this->addr == rhs.addr && this->data == rhs.data;
737 }
738
739 bool operator!=(const AddressData &rhs) const {
740 return this->addr != rhs.addr || this->data == rhs.data;
741 }
742};
743
744template <typename B, typename T, unsigned N> class AddressDataArray {
745public:
747 typedef llvm::SmallVector<Entry, N> Collection;
748
749 AddressDataArray() = default;
750
751 ~AddressDataArray() = default;
752
753 void Append(const Entry &entry) { m_entries.push_back(entry); }
754
755 void Sort() {
756 if (m_entries.size() > 1)
757 std::stable_sort(m_entries.begin(), m_entries.end());
758 }
759
760#ifdef ASSERT_RANGEMAP_ARE_SORTED
761 bool IsSorted() const {
762 typename Collection::const_iterator pos, end, prev;
763 // First we determine if we can combine any of the Entry objects so we
764 // don't end up allocating and making a new collection for no reason
765 for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end;
766 prev = pos++) {
767 if (prev != end && *pos < *prev)
768 return false;
769 }
770 return true;
771 }
772#endif
773
774 void Clear() { m_entries.clear(); }
775
776 bool IsEmpty() const { return m_entries.empty(); }
777
778 size_t GetSize() const { return m_entries.size(); }
779
780 const Entry *GetEntryAtIndex(size_t i) const {
781 return ((i < m_entries.size()) ? &m_entries[i] : nullptr);
782 }
783
784 // Clients must ensure that "i" is a valid index prior to calling this
785 // function
786 const Entry &GetEntryRef(size_t i) const { return m_entries[i]; }
787
788 static bool BaseLessThan(const Entry &lhs, const Entry &rhs) {
789 return lhs.addr < rhs.addr;
790 }
791
792 Entry *FindEntry(B addr, bool exact_match_only) {
793#ifdef ASSERT_RANGEMAP_ARE_SORTED
794 assert(IsSorted());
795#endif
796 if (!m_entries.empty()) {
797 Entry entry;
798 entry.addr = addr;
799 typename Collection::iterator begin = m_entries.begin();
800 typename Collection::iterator end = m_entries.end();
801 typename Collection::iterator pos =
802 llvm::lower_bound(m_entries, entry, BaseLessThan);
803
804 while (pos != begin && pos[-1].addr == addr)
805 --pos;
806
807 if (pos != end) {
808 if (pos->addr == addr || !exact_match_only)
809 return &(*pos);
810 }
811 }
812 return nullptr;
813 }
814
815 const Entry *FindNextEntry(const Entry *entry) {
816 if (entry >= &*m_entries.begin() && entry + 1 < &*m_entries.end())
817 return entry + 1;
818 return nullptr;
819 }
820
821 Entry *Back() { return (m_entries.empty() ? nullptr : &m_entries.back()); }
822
823 const Entry *Back() const {
824 return (m_entries.empty() ? nullptr : &m_entries.back());
825 }
826
827protected:
829};
830
831} // namespace lldb_private
832
833#endif // LLDB_UTILITY_RANGEMAP_H
static bool Compare(BreakpointLocationSP lhs, lldb::break_id_t val)
Entry * FindEntry(B addr, bool exact_match_only)
Definition: RangeMap.h:792
llvm::SmallVector< Entry, N > Collection
Definition: RangeMap.h:747
AddressData< B, T > Entry
Definition: RangeMap.h:746
const Entry * GetEntryAtIndex(size_t i) const
Definition: RangeMap.h:780
const Entry * Back() const
Definition: RangeMap.h:823
const Entry & GetEntryRef(size_t i) const
Definition: RangeMap.h:786
void Append(const Entry &entry)
Definition: RangeMap.h:753
static bool BaseLessThan(const Entry &lhs, const Entry &rhs)
Definition: RangeMap.h:788
const Entry * FindNextEntry(const Entry *entry)
Definition: RangeMap.h:815
const Entry * FindEntryThatContains(B addr) const
Definition: RangeMap.h:575
AugmentedRangeData< B, S, T > AugmentedEntry
Definition: RangeMap.h:444
void CombineConsecutiveEntriesWithEqualData()
Definition: RangeMap.h:492
uint32_t FindEntryIndexThatContainsOrFollows(B addr) const
Definition: RangeMap.h:641
uint32_t FindEntryIndexesThatContain(B addr, std::vector< uint32_t > &indexes)
Definition: RangeMap.h:559
Entry & GetEntryRef(size_t i)
Definition: RangeMap.h:544
uint32_t FindEntryIndexThatContains(B addr) const
Definition: RangeMap.h:551
B ComputeUpperBounds(size_t lo, size_t hi)
Definition: RangeMap.h:668
const Entry * FindEntryThatContains(const Entry &range) const
Definition: RangeMap.h:579
static bool BaseLessThan(const Entry &lhs, const Entry &rhs)
Definition: RangeMap.h:547
const_iterator end() const
Definition: RangeMap.h:660
const Entry * GetEntryAtIndex(size_t i) const
Definition: RangeMap.h:534
Entry * GetMutableEntryAtIndex(size_t i)
Definition: RangeMap.h:538
const Entry & GetEntryRef(size_t i) const
Definition: RangeMap.h:545
typename Collection::const_iterator const_iterator
Definition: RangeMap.h:658
const Entry * Back() const
Definition: RangeMap.h:654
RangeData< B, S, T > Entry
Definition: RangeMap.h:443
const_iterator begin() const
Definition: RangeMap.h:659
const Entry * FindEntryStartsAt(B addr) const
Definition: RangeMap.h:598
const Entry * FindEntryThatContainsOrFollows(B addr) const
Definition: RangeMap.h:620
void Append(const Entry &entry)
Definition: RangeMap.h:451
void Append(B &&b, S &&s, T &&t)
Append a range with data to the vector.
Definition: RangeMap.h:457
lldb_private::Range< B, S > Range
Definition: RangeMap.h:442
RangeDataVector(Compare compare=Compare())
Definition: RangeMap.h:447
bool Erase(uint32_t start, uint32_t end)
Definition: RangeMap.h:459
void FindEntryIndexesThatContain(B addr, size_t lo, size_t hi, std::vector< uint32_t > &indexes)
Definition: RangeMap.h:687
llvm::SmallVector< AugmentedEntry, N > Collection
Definition: RangeMap.h:445
Entry * FindEntryThatContains(B addr)
Definition: RangeMap.h:569
const Entry * FindEntryThatContains(B addr) const
Definition: RangeMap.h:338
typename Collection::const_iterator const_iterator
Definition: RangeMap.h:383
uint32_t FindEntryIndexThatContains(B addr) const
Definition: RangeMap.h:316
const Entry & GetEntryRef(size_t i) const
Definition: RangeMap.h:304
void Slide(BaseType slide)
Definition: RangeMap.h:283
const Entry * GetEntryAtIndex(size_t i) const
Definition: RangeMap.h:297
void CombinePrevAndNext(typename Collection::iterator pos)
Definition: RangeMap.h:388
const_iterator begin() const
Definition: RangeMap.h:384
BaseType GetMaxRangeEnd(BaseType fail_value) const
Definition: RangeMap.h:272
void Append(B base, S size)
Definition: RangeMap.h:181
Entry & GetEntryRef(size_t i)
Definition: RangeMap.h:303
bool RemoveEntryAtIndex(uint32_t idx)
Definition: RangeMap.h:209
static bool BaseLessThan(const Entry &lhs, const Entry &rhs)
Definition: RangeMap.h:312
void Append(const Entry &entry)
Definition: RangeMap.h:179
Range< B, S > Entry
Definition: RangeMap.h:140
llvm::SmallVector< Entry, N > Collection
Definition: RangeMap.h:141
BaseType GetMinRangeBase(BaseType fail_value) const
Definition: RangeMap.h:261
static RangeVector GetOverlaps(const RangeVector &vec1, const RangeVector &vec2)
Definition: RangeMap.h:147
bool IsEmpty() const
Definition: RangeMap.h:293
size_t GetSize() const
Definition: RangeMap.h:295
void Reserve(typename Collection::size_type size)
Definition: RangeMap.h:291
const_iterator end() const
Definition: RangeMap.h:385
void Insert(const Entry &entry, bool combine)
Definition: RangeMap.h:185
const Entry * Back() const
Definition: RangeMap.h:308
bool operator==(const RangeVector &rhs) const
Definition: RangeMap.h:169
const Entry * FindEntryThatContains(const Entry &range) const
Definition: RangeMap.h:361
#define UINT32_MAX
Definition: lldb-defines.h:19
A class that represents a running process on the host machine.
llvm::APFloat::cmpResult compare(Scalar lhs, Scalar rhs)
Definition: Scalar.cpp:855
bool operator==(const AddressData &rhs) const
Definition: RangeMap.h:735
bool operator<(const AddressData &rhs) const
Definition: RangeMap.h:729
bool operator!=(const AddressData &rhs) const
Definition: RangeMap.h:739
AddressData(B a, DataType d)
Definition: RangeMap.h:727
AugmentedRangeData(const RangeData< B, S, T > &rd)
Definition: RangeMap.h:434
RangeData(B base, S size, DataType d)
Definition: RangeMap.h:424
RangeData(B base, S size)
Definition: RangeMap.h:422
bool ContainsEndInclusive(BaseType r) const
Definition: RangeMap.h:97
bool DoesAdjoinOrIntersect(const Range &rhs) const
Definition: RangeMap.h:107
void Clear(BaseType b=0)
Definition: RangeMap.h:40
bool Contains(const Range &range) const
Definition: RangeMap.h:101
bool Contains(BaseType r) const
Definition: RangeMap.h:93
BaseType GetRangeBase() const
Definition: RangeMap.h:45
Range(BaseType b, SizeType s)
Definition: RangeMap.h:38
bool operator==(const Range &rhs) const
Definition: RangeMap.h:127
bool IsValid() const
Definition: RangeMap.h:91
bool Union(const Range &rhs)
Definition: RangeMap.h:57
void ShrinkFront(S s)
Definition: RangeMap.h:52
void SetRangeEnd(BaseType end)
Definition: RangeMap.h:80
SizeType GetByteSize() const
Definition: RangeMap.h:87
void SetRangeBase(BaseType b)
Set the start value for the range, and keep the same size.
Definition: RangeMap.h:48
BaseType GetRangeEnd() const
Definition: RangeMap.h:78
bool DoesIntersect(const Range &rhs) const
Definition: RangeMap.h:117
bool operator<(const Range &rhs) const
Definition: RangeMap.h:121
void Slide(BaseType slide)
Definition: RangeMap.h:50
bool operator!=(const Range &rhs) const
Definition: RangeMap.h:131
Range Intersect(const Range &rhs) const
Definition: RangeMap.h:67
void SetByteSize(SizeType s)
Definition: RangeMap.h:89