]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/llvm/tools/lldb/include/lldb/Core/RangeMap.h
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / llvm / tools / lldb / include / lldb / Core / RangeMap.h
1 //===-- RangeMap.h ----------------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #ifndef liblldb_RangeMap_h_
11 #define liblldb_RangeMap_h_
12
13 #include <vector>
14
15 #include "lldb/lldb-private.h"
16 #include "llvm/ADT/SmallVector.h"
17
18 // Uncomment to make sure all Range objects are sorted when needed
19 //#define ASSERT_RANGEMAP_ARE_SORTED
20
21 namespace lldb_private {
22
23     
24     //----------------------------------------------------------------------
25     // Templatized classes for dealing with generic ranges and also
26     // collections of ranges, or collections of ranges that have associated
27     // data.
28     //----------------------------------------------------------------------
29     
30     //----------------------------------------------------------------------
31     // A simple range class where you get to define the type of the range
32     // base "B", and the type used for the range byte size "S".
33     //----------------------------------------------------------------------
34     template <typename B, typename S>
35     struct Range
36     {
37         typedef B BaseType;
38         typedef S SizeType;
39
40         BaseType base;
41         SizeType size;
42         
43         Range () :
44             base (0),
45             size (0)
46         {
47         }
48         
49         Range (BaseType b, SizeType s) :
50             base (b),
51             size (s)
52         {
53         }
54         
55         void
56         Clear (BaseType b = 0)
57         {
58             base = b;
59             size = 0;
60         }
61
62         // Set the start value for the range, and keep the same size
63         BaseType
64         GetRangeBase () const
65         {
66             return base;
67         }
68         
69         void
70         SetRangeBase (BaseType b)
71         {
72             base = b;
73         }
74         
75         void
76         Slide (BaseType slide)
77         {
78             base += slide;
79         }
80         
81         BaseType
82         GetRangeEnd () const
83         {
84             return base + size;
85         }
86         
87         void
88         SetRangeEnd (BaseType end)
89         {
90             if (end > base)
91                 size = end - base;
92             else
93                 size = 0;
94         }
95         
96         SizeType
97         GetByteSize () const
98         {
99             return size;
100         }
101         
102         void
103         SetByteSize (SizeType s)
104         {
105             size = s;
106         }
107         
108         bool
109         IsValid() const
110         {
111             return size > 0;
112         }
113         
114         bool
115         Contains (BaseType r) const
116         {
117             return (GetRangeBase() <= r) && (r < GetRangeEnd());
118         }
119         
120         bool
121         ContainsEndInclusive (BaseType r) const
122         {
123             return (GetRangeBase() <= r) && (r <= GetRangeEnd());
124         }
125         
126         bool 
127         Contains (const Range& range) const
128         {
129             return Contains(range.GetRangeBase()) && ContainsEndInclusive(range.GetRangeEnd());
130         }
131         
132         bool
133         Overlap (const Range &rhs) const
134         {
135             const BaseType lhs_base = this->GetRangeBase();
136             const BaseType rhs_base = rhs.GetRangeBase();
137             const BaseType lhs_end = this->GetRangeEnd();
138             const BaseType rhs_end = rhs.GetRangeEnd();
139             bool result = (lhs_base <= rhs_end) && (lhs_end >= rhs_base);
140             return result;
141         }
142         
143         bool
144         operator < (const Range &rhs) const
145         {
146             if (base == rhs.base)
147                 return size < rhs.size;
148             return base < rhs.base;
149         }
150         
151         bool
152         operator == (const Range &rhs) const
153         {
154             return base == rhs.base && size == rhs.size;
155         }
156         
157         bool
158         operator != (const Range &rhs) const
159         {
160             return  base != rhs.base || size != rhs.size;
161         }
162     };
163     
164     //----------------------------------------------------------------------
165     // A range array class where you get to define the type of the ranges
166     // that the collection contains.
167     //----------------------------------------------------------------------
168
169     template <typename B, typename S, unsigned N>
170     class RangeArray
171     {
172     public:
173         typedef B BaseType;
174         typedef S SizeType;
175         typedef Range<B,S> Entry;
176         typedef llvm::SmallVector<Entry, N> Collection;
177         
178         RangeArray () :
179             m_entries ()
180         {
181         }
182         
183         ~RangeArray()
184         {
185         }
186         
187         void
188         Append (const Entry &entry)
189         {
190             m_entries.push_back (entry);
191         }
192         
193         bool
194         RemoveEntrtAtIndex (uint32_t idx)
195         {
196             if (idx < m_entries.size())
197             {
198                 m_entries.erase (m_entries.begin() + idx);
199                 return true;
200             }
201             return false;
202         }
203         
204         void
205         Sort ()
206         {
207             if (m_entries.size() > 1)
208                 std::stable_sort (m_entries.begin(), m_entries.end());
209         }
210         
211 #ifdef ASSERT_RANGEMAP_ARE_SORTED
212         bool
213         IsSorted () const
214         {
215             typename Collection::const_iterator pos, end, prev;
216             // First we determine if we can combine any of the Entry objects so we
217             // don't end up allocating and making a new collection for no reason
218             for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++)
219             {
220                 if (prev != end && *pos < *prev)
221                     return false;
222             }
223             return true;
224         }
225 #endif        
226         void
227         CombineConsecutiveRanges ()
228         {
229 #ifdef ASSERT_RANGEMAP_ARE_SORTED
230             assert (IsSorted());
231 #endif
232             // Can't combine if ranges if we have zero or one range
233             if (m_entries.size() > 1)
234             {
235                 // The list should be sorted prior to calling this function
236                 typename Collection::iterator pos;
237                 typename Collection::iterator end;
238                 typename Collection::iterator prev;
239                 bool can_combine = false;
240                 // First we determine if we can combine any of the Entry objects so we
241                 // don't end up allocating and making a new collection for no reason
242                 for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++)
243                 {
244                     if (prev != end && prev->Overlap(*pos))
245                     {
246                         can_combine = true;
247                         break;
248                     }
249                 }
250                 
251                 // We we can combine at least one entry, then we make a new collection
252                 // and populate it accordingly, and then swap it into place. 
253                 if (can_combine)
254                 {
255                     Collection minimal_ranges;
256                     for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++)
257                     {
258                         if (prev != end && prev->Overlap(*pos))
259                             minimal_ranges.back().SetRangeEnd (std::max<BaseType>(prev->GetRangeEnd(), pos->GetRangeEnd()));
260                         else
261                             minimal_ranges.push_back (*pos);
262                     }
263                     // Use the swap technique in case our new vector is much smaller.
264                     // We must swap when using the STL because std::vector objects never
265                     // release or reduce the memory once it has been allocated/reserved.
266                     m_entries.swap (minimal_ranges);
267                 }
268             }
269         }
270
271         
272         BaseType
273         GetMinRangeBase (BaseType fail_value) const
274         {
275 #ifdef ASSERT_RANGEMAP_ARE_SORTED
276             assert (IsSorted());
277 #endif
278             if (m_entries.empty())
279                 return fail_value;
280             // m_entries must be sorted, so if we aren't empty, we grab the
281             // first range's base
282             return m_entries.front().GetRangeBase();
283         }
284
285         BaseType
286         GetMaxRangeEnd (BaseType fail_value) const
287         {
288 #ifdef ASSERT_RANGEMAP_ARE_SORTED
289             assert (IsSorted());
290 #endif
291             if (m_entries.empty())
292                 return fail_value;
293             // m_entries must be sorted, so if we aren't empty, we grab the
294             // last range's end
295             return m_entries.back().GetRangeEnd();
296         }
297         
298         void
299         Slide (BaseType slide)
300         {
301             typename Collection::iterator pos, end;
302             for (pos = m_entries.begin(), end = m_entries.end(); pos != end; ++pos)
303                 pos->Slide (slide);
304         }
305         
306         void
307         Clear ()
308         {
309             m_entries.clear();
310         }
311         
312         bool
313         IsEmpty () const
314         {
315             return m_entries.empty();
316         }
317         
318         size_t
319         GetSize () const
320         {
321             return m_entries.size();
322         }
323         
324         const Entry *
325         GetEntryAtIndex (size_t i) const
326         {
327             if (i<m_entries.size())
328                 return &m_entries[i];
329             return NULL;
330         }
331         
332         // Clients must ensure that "i" is a valid index prior to calling this function
333         const Entry &
334         GetEntryRef (size_t i) const
335         {
336             return m_entries[i];
337         }
338
339         Entry *
340         Back()
341         {
342             if (m_entries.empty())
343                 return NULL;
344             return &m_entries.back();
345         }
346
347         const Entry *
348         Back() const
349         {
350             if (m_entries.empty())
351                 return NULL;
352             return &m_entries.back();
353         }
354
355         static bool 
356         BaseLessThan (const Entry& lhs, const Entry& rhs)
357         {
358             return lhs.GetRangeBase() < rhs.GetRangeBase();
359         }
360         
361         uint32_t
362         FindEntryIndexThatContains (B addr) const
363         {
364 #ifdef ASSERT_RANGEMAP_ARE_SORTED
365             assert (IsSorted());
366 #endif
367             if (!m_entries.empty())
368             {
369                 Entry entry (addr, 1);
370                 typename Collection::const_iterator begin = m_entries.begin();
371                 typename Collection::const_iterator end = m_entries.end();
372                 typename Collection::const_iterator pos = std::lower_bound (begin, end, entry, BaseLessThan);
373                 
374                 if (pos != end && pos->Contains(addr))
375                 {
376                     return std::distance (begin, pos);
377                 }
378                 else if (pos != begin)
379                 {
380                     --pos;
381                     if (pos->Contains(addr))
382                         return std::distance (begin, pos);
383                 }
384             }
385             return UINT32_MAX;
386         }
387
388         const Entry *
389         FindEntryThatContains (B addr) const
390         {
391 #ifdef ASSERT_RANGEMAP_ARE_SORTED
392             assert (IsSorted());
393 #endif
394             if (!m_entries.empty())
395             {
396                 Entry entry (addr, 1);
397                 typename Collection::const_iterator begin = m_entries.begin();
398                 typename Collection::const_iterator end = m_entries.end();
399                 typename Collection::const_iterator pos = std::lower_bound (begin, end, entry, BaseLessThan);
400                 
401                 if (pos != end && pos->Contains(addr))
402                 {
403                     return &(*pos); 
404                 }
405                 else if (pos != begin)
406                 {
407                     --pos;
408                     if (pos->Contains(addr))
409                     {
410                         return &(*pos); 
411                     }
412                 }
413             }
414             return NULL;
415         }
416
417         const Entry *
418         FindEntryThatContains (const Entry &range) const
419         {
420 #ifdef ASSERT_RANGEMAP_ARE_SORTED
421             assert (IsSorted());
422 #endif
423             if (!m_entries.empty())
424             {
425                 typename Collection::const_iterator begin = m_entries.begin();
426                 typename Collection::const_iterator end = m_entries.end();
427                 typename Collection::const_iterator pos = std::lower_bound (begin, end, range, BaseLessThan);
428                 
429                 if (pos != end && pos->Contains(range))
430                 {
431                     return &(*pos); 
432                 }
433                 else if (pos != begin)
434                 {
435                     --pos;
436                     if (pos->Contains(range))
437                     {
438                         return &(*pos); 
439                     }
440                 }
441             }
442             return NULL;
443         }
444
445     protected:
446         Collection m_entries;
447     };
448
449     template <typename B, typename S>
450     class RangeVector
451     {
452     public:
453         typedef B BaseType;
454         typedef S SizeType;
455         typedef Range<B,S> Entry;
456         typedef std::vector<Entry> Collection;
457         
458         RangeVector () :
459             m_entries ()
460         {
461         }
462         
463         ~RangeVector()
464         {
465         }
466         
467         void
468         Append (const Entry &entry)
469         {
470             m_entries.push_back (entry);
471         }
472         
473         bool
474         RemoveEntrtAtIndex (uint32_t idx)
475         {
476             if (idx < m_entries.size())
477             {
478                 m_entries.erase (m_entries.begin() + idx);
479                 return true;
480             }
481             return false;
482         }
483         
484         void
485         Sort ()
486         {
487             if (m_entries.size() > 1)
488                 std::stable_sort (m_entries.begin(), m_entries.end());
489         }
490         
491 #ifdef ASSERT_RANGEMAP_ARE_SORTED
492         bool
493         IsSorted () const
494         {
495             typename Collection::const_iterator pos, end, prev;
496             // First we determine if we can combine any of the Entry objects so we
497             // don't end up allocating and making a new collection for no reason
498             for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++)
499             {
500                 if (prev != end && *pos < *prev)
501                     return false;
502             }
503             return true;
504         }
505 #endif
506         void
507         CombineConsecutiveRanges ()
508         {
509 #ifdef ASSERT_RANGEMAP_ARE_SORTED
510             assert (IsSorted());
511 #endif
512             // Can't combine if ranges if we have zero or one range
513             if (m_entries.size() > 1)
514             {
515                 // The list should be sorted prior to calling this function
516                 typename Collection::iterator pos;
517                 typename Collection::iterator end;
518                 typename Collection::iterator prev;
519                 bool can_combine = false;
520                 // First we determine if we can combine any of the Entry objects so we
521                 // don't end up allocating and making a new collection for no reason
522                 for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++)
523                 {
524                     if (prev != end && prev->Overlap(*pos))
525                     {
526                         can_combine = true;
527                         break;
528                     }
529                 }
530                 
531                 // We we can combine at least one entry, then we make a new collection
532                 // and populate it accordingly, and then swap it into place.
533                 if (can_combine)
534                 {
535                     Collection minimal_ranges;
536                     for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++)
537                     {
538                         if (prev != end && prev->Overlap(*pos))
539                             minimal_ranges.back().SetRangeEnd (std::max<BaseType>(prev->GetRangeEnd(), pos->GetRangeEnd()));
540                         else
541                             minimal_ranges.push_back (*pos);
542                     }
543                     // Use the swap technique in case our new vector is much smaller.
544                     // We must swap when using the STL because std::vector objects never
545                     // release or reduce the memory once it has been allocated/reserved.
546                     m_entries.swap (minimal_ranges);
547                 }
548             }
549         }
550         
551         
552         BaseType
553         GetMinRangeBase (BaseType fail_value) const
554         {
555 #ifdef ASSERT_RANGEMAP_ARE_SORTED
556             assert (IsSorted());
557 #endif
558             if (m_entries.empty())
559                 return fail_value;
560             // m_entries must be sorted, so if we aren't empty, we grab the
561             // first range's base
562             return m_entries.front().GetRangeBase();
563         }
564         
565         BaseType
566         GetMaxRangeEnd (BaseType fail_value) const
567         {
568 #ifdef ASSERT_RANGEMAP_ARE_SORTED
569             assert (IsSorted());
570 #endif
571             if (m_entries.empty())
572                 return fail_value;
573             // m_entries must be sorted, so if we aren't empty, we grab the
574             // last range's end
575             return m_entries.back().GetRangeEnd();
576         }
577         
578         void
579         Slide (BaseType slide)
580         {
581             typename Collection::iterator pos, end;
582             for (pos = m_entries.begin(), end = m_entries.end(); pos != end; ++pos)
583                 pos->Slide (slide);
584         }
585         
586         void
587         Clear ()
588         {
589             m_entries.clear();
590         }
591
592         void
593         Reserve (typename Collection::size_type size)
594         {
595             m_entries.resize (size);
596         }
597
598         bool
599         IsEmpty () const
600         {
601             return m_entries.empty();
602         }
603         
604         size_t
605         GetSize () const
606         {
607             return m_entries.size();
608         }
609         
610         const Entry *
611         GetEntryAtIndex (size_t i) const
612         {
613             if (i<m_entries.size())
614                 return &m_entries[i];
615             return NULL;
616         }
617         
618         // Clients must ensure that "i" is a valid index prior to calling this function
619         const Entry &
620         GetEntryRef (size_t i) const
621         {
622             return m_entries[i];
623         }
624         
625         Entry *
626         Back()
627         {
628             if (m_entries.empty())
629                 return NULL;
630             return &m_entries.back();
631         }
632         
633         const Entry *
634         Back() const
635         {
636             if (m_entries.empty())
637                 return NULL;
638             return &m_entries.back();
639         }
640         
641         static bool
642         BaseLessThan (const Entry& lhs, const Entry& rhs)
643         {
644             return lhs.GetRangeBase() < rhs.GetRangeBase();
645         }
646         
647         uint32_t
648         FindEntryIndexThatContains (B addr) const
649         {
650 #ifdef ASSERT_RANGEMAP_ARE_SORTED
651             assert (IsSorted());
652 #endif
653             if (!m_entries.empty())
654             {
655                 Entry entry (addr, 1);
656                 typename Collection::const_iterator begin = m_entries.begin();
657                 typename Collection::const_iterator end = m_entries.end();
658                 typename Collection::const_iterator pos = std::lower_bound (begin, end, entry, BaseLessThan);
659                 
660                 if (pos != end && pos->Contains(addr))
661                 {
662                     return std::distance (begin, pos);
663                 }
664                 else if (pos != begin)
665                 {
666                     --pos;
667                     if (pos->Contains(addr))
668                         return std::distance (begin, pos);
669                 }
670             }
671             return UINT32_MAX;
672         }
673         
674         const Entry *
675         FindEntryThatContains (B addr) const
676         {
677 #ifdef ASSERT_RANGEMAP_ARE_SORTED
678             assert (IsSorted());
679 #endif
680             if (!m_entries.empty())
681             {
682                 Entry entry (addr, 1);
683                 typename Collection::const_iterator begin = m_entries.begin();
684                 typename Collection::const_iterator end = m_entries.end();
685                 typename Collection::const_iterator pos = std::lower_bound (begin, end, entry, BaseLessThan);
686                 
687                 if (pos != end && pos->Contains(addr))
688                 {
689                     return &(*pos);
690                 }
691                 else if (pos != begin)
692                 {
693                     --pos;
694                     if (pos->Contains(addr))
695                     {
696                         return &(*pos);
697                     }
698                 }
699             }
700             return NULL;
701         }
702         
703         const Entry *
704         FindEntryThatContains (const Entry &range) const
705         {
706 #ifdef ASSERT_RANGEMAP_ARE_SORTED
707             assert (IsSorted());
708 #endif
709             if (!m_entries.empty())
710             {
711                 typename Collection::const_iterator begin = m_entries.begin();
712                 typename Collection::const_iterator end = m_entries.end();
713                 typename Collection::const_iterator pos = std::lower_bound (begin, end, range, BaseLessThan);
714                 
715                 if (pos != end && pos->Contains(range))
716                 {
717                     return &(*pos);
718                 }
719                 else if (pos != begin)
720                 {
721                     --pos;
722                     if (pos->Contains(range))
723                     {
724                         return &(*pos);
725                     }
726                 }
727             }
728             return NULL;
729         }
730         
731     protected:
732         Collection m_entries;
733     };
734
735     //----------------------------------------------------------------------
736     // A simple range  with data class where you get to define the type of
737     // the range base "B", the type used for the range byte size "S", and
738     // the type for the associated data "T".
739     //----------------------------------------------------------------------
740     template <typename B, typename S, typename T>
741     struct RangeData : public Range<B,S>
742     {
743         typedef T DataType;
744         
745         DataType data;
746         
747         RangeData () :
748             Range<B,S> (),
749             data ()
750         {
751         }
752         
753         RangeData (B base, S size) :
754             Range<B,S> (base, size),
755             data ()
756         {
757         }
758         
759         RangeData (B base, S size, DataType d) :
760             Range<B,S> (base, size),
761             data (d)
762         {
763         }
764         
765         bool
766         operator < (const RangeData &rhs) const
767         {
768             if (this->base == rhs.base)
769             {
770                 if (this->size == rhs.size)
771                     return this->data < rhs.data;
772                 else
773                     return this->size < rhs.size;
774             }
775             return this->base < rhs.base;
776         }
777         
778         bool
779         operator == (const RangeData &rhs) const
780         {
781             return this->GetRangeBase() == rhs.GetRangeBase() &&
782                    this->GetByteSize() == rhs.GetByteSize() &&
783                    this->data      == rhs.data;
784         }
785         
786         bool
787         operator != (const RangeData &rhs) const
788         {
789             return this->GetRangeBase() != rhs.GetRangeBase() ||
790                    this->GetByteSize() != rhs.GetByteSize() ||
791                    this->data      != rhs.data;
792         }
793     };
794     
795     template <typename B, typename S, typename T, unsigned N>
796     class RangeDataArray
797     {
798     public:
799         typedef RangeData<B,S,T> Entry;
800         typedef llvm::SmallVector<Entry, N> Collection;
801
802
803         RangeDataArray ()
804         {
805         }
806         
807         ~RangeDataArray()
808         {
809         }
810         
811         void
812         Append (const Entry &entry)
813         {
814             m_entries.push_back (entry);
815         }
816     
817         void
818         Sort ()
819         {
820             if (m_entries.size() > 1)
821                 std::stable_sort (m_entries.begin(), m_entries.end());
822         }
823     
824 #ifdef ASSERT_RANGEMAP_ARE_SORTED
825         bool
826         IsSorted () const
827         {
828             typename Collection::const_iterator pos, end, prev;
829             // First we determine if we can combine any of the Entry objects so we
830             // don't end up allocating and making a new collection for no reason
831             for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++)
832             {
833                 if (prev != end && *pos < *prev)
834                     return false;
835             }
836             return true;
837         }
838 #endif
839
840         void
841         CombineConsecutiveEntriesWithEqualData ()
842         {
843 #ifdef ASSERT_RANGEMAP_ARE_SORTED
844             assert (IsSorted());
845 #endif
846             typename Collection::iterator pos;
847             typename Collection::iterator end;
848             typename Collection::iterator prev;
849             bool can_combine = false;
850             // First we determine if we can combine any of the Entry objects so we
851             // don't end up allocating and making a new collection for no reason
852             for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++)
853             {
854                 if (prev != end && prev->data == pos->data)
855                 {
856                     can_combine = true;
857                     break;
858                 }
859             }
860             
861             // We we can combine at least one entry, then we make a new collection
862             // and populate it accordingly, and then swap it into place. 
863             if (can_combine)
864             {
865                 Collection minimal_ranges;
866                 for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++)
867                 {
868                     if (prev != end && prev->data == pos->data)
869                         minimal_ranges.back().SetRangeEnd (pos->GetRangeEnd());
870                     else
871                         minimal_ranges.push_back (*pos);
872                 }
873                 // Use the swap technique in case our new vector is much smaller.
874                 // We must swap when using the STL because std::vector objects never
875                 // release or reduce the memory once it has been allocated/reserved.
876                 m_entries.swap (minimal_ranges);
877             }
878         }
879     
880         void
881         Clear ()
882         {
883             m_entries.clear();
884         }
885         
886         bool
887         IsEmpty () const
888         {
889             return m_entries.empty();
890         }
891         
892         size_t
893         GetSize () const
894         {
895             return m_entries.size();
896         }
897         
898         const Entry *
899         GetEntryAtIndex (size_t i) const
900         {
901             if (i<m_entries.size())
902                 return &m_entries[i];
903             return NULL;
904         }
905
906         // Clients must ensure that "i" is a valid index prior to calling this function
907         const Entry &
908         GetEntryRef (size_t i) const
909         {
910             return m_entries[i];
911         }
912
913         static bool
914         BaseLessThan (const Entry& lhs, const Entry& rhs)
915         {
916             return lhs.GetRangeBase() < rhs.GetRangeBase();
917         }
918         
919         uint32_t
920         FindEntryIndexThatContains (B addr) const
921         {
922 #ifdef ASSERT_RANGEMAP_ARE_SORTED
923             assert (IsSorted());
924 #endif
925             if ( !m_entries.empty() )
926             {
927                 Entry entry (addr, 1);
928                 typename Collection::const_iterator begin = m_entries.begin();
929                 typename Collection::const_iterator end = m_entries.end();
930                 typename Collection::const_iterator pos = std::lower_bound (begin, end, entry, BaseLessThan);
931                 
932                 if (pos != end && pos->Contains(addr))
933                 {
934                     return std::distance (begin, pos);
935                 }
936                 else if (pos != begin)
937                 {
938                     --pos;
939                     if (pos->Contains(addr))
940                         return std::distance (begin, pos);
941                 }
942             }
943             return UINT32_MAX;
944         }
945
946         Entry *
947         FindEntryThatContains (B addr)
948         {
949 #ifdef ASSERT_RANGEMAP_ARE_SORTED
950             assert (IsSorted());
951 #endif
952             if ( !m_entries.empty() )
953             {
954                 Entry entry;
955                 entry.SetRangeBase(addr);
956                 entry.SetByteSize(1);
957                 typename Collection::iterator begin = m_entries.begin();
958                 typename Collection::iterator end = m_entries.end();
959                 typename Collection::iterator pos = std::lower_bound (begin, end, entry, BaseLessThan);
960                 
961                 if (pos != end && pos->Contains(addr))
962                 {
963                     return &(*pos); 
964                 }
965                 else if (pos != begin)
966                 {
967                     --pos;
968                     if (pos->Contains(addr))
969                     {
970                         return &(*pos); 
971                     }
972                 }
973             }
974             return NULL;
975         }
976         const Entry *
977         FindEntryThatContains (B addr) const
978         {
979 #ifdef ASSERT_RANGEMAP_ARE_SORTED
980             assert (IsSorted());
981 #endif
982             if ( !m_entries.empty() )
983             {
984                 Entry entry;
985                 entry.SetRangeBase(addr);
986                 entry.SetByteSize(1);
987                 typename Collection::const_iterator begin = m_entries.begin();
988                 typename Collection::const_iterator end = m_entries.end();
989                 typename Collection::const_iterator pos = std::lower_bound (begin, end, entry, BaseLessThan);
990                 
991                 if (pos != end && pos->Contains(addr))
992                 {
993                     return &(*pos); 
994                 }
995                 else if (pos != begin)
996                 {
997                     --pos;
998                     if (pos->Contains(addr))
999                     {
1000                         return &(*pos); 
1001                     }
1002                 }
1003             }
1004             return NULL;
1005         }
1006         
1007         const Entry *
1008         FindEntryThatContains (const Entry &range) const
1009         {
1010 #ifdef ASSERT_RANGEMAP_ARE_SORTED
1011             assert (IsSorted());
1012 #endif
1013             if ( !m_entries.empty() )
1014             {
1015                 typename Collection::const_iterator begin = m_entries.begin();
1016                 typename Collection::const_iterator end = m_entries.end();
1017                 typename Collection::const_iterator pos = std::lower_bound (begin, end, range, BaseLessThan);
1018                 
1019                 if (pos != end && pos->Contains(range))
1020                 {
1021                     return &(*pos); 
1022                 }
1023                 else if (pos != begin)
1024                 {
1025                     --pos;
1026                     if (pos->Contains(range))
1027                     {
1028                         return &(*pos); 
1029                     }
1030                 }
1031             }
1032             return NULL;
1033         }
1034         
1035         Entry *
1036         Back()
1037         {
1038             if (!m_entries.empty())
1039                 return &m_entries.back();
1040             return NULL;
1041         }
1042
1043         const Entry *
1044         Back() const
1045         {
1046             if (!m_entries.empty())
1047                 return &m_entries.back();
1048             return NULL;
1049         }
1050
1051     protected:
1052         Collection m_entries;
1053     };
1054
1055     // Same as RangeDataArray, but uses std::vector as to not
1056     // require static storage of N items in the class itself
1057     template <typename B, typename S, typename T>
1058     class RangeDataVector
1059     {
1060     public:
1061         typedef RangeData<B,S,T> Entry;
1062         typedef std::vector<Entry> Collection;
1063         
1064         RangeDataVector ()
1065         {
1066         }
1067         
1068         ~RangeDataVector()
1069         {
1070         }
1071         
1072         void
1073         Append (const Entry &entry)
1074         {
1075             m_entries.push_back (entry);
1076         }
1077         
1078         void
1079         Sort ()
1080         {
1081             if (m_entries.size() > 1)
1082                 std::stable_sort (m_entries.begin(), m_entries.end());
1083         }
1084         
1085 #ifdef ASSERT_RANGEMAP_ARE_SORTED
1086         bool
1087         IsSorted () const
1088         {
1089             typename Collection::const_iterator pos, end, prev;
1090             // First we determine if we can combine any of the Entry objects so we
1091             // don't end up allocating and making a new collection for no reason
1092             for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++)
1093             {
1094                 if (prev != end && *pos < *prev)
1095                     return false;
1096             }
1097             return true;
1098         }
1099 #endif
1100         
1101         void
1102         CombineConsecutiveEntriesWithEqualData ()
1103         {
1104 #ifdef ASSERT_RANGEMAP_ARE_SORTED
1105             assert (IsSorted());
1106 #endif
1107             typename Collection::iterator pos;
1108             typename Collection::iterator end;
1109             typename Collection::iterator prev;
1110             bool can_combine = false;
1111             // First we determine if we can combine any of the Entry objects so we
1112             // don't end up allocating and making a new collection for no reason
1113             for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++)
1114             {
1115                 if (prev != end && prev->data == pos->data)
1116                 {
1117                     can_combine = true;
1118                     break;
1119                 }
1120             }
1121             
1122             // We we can combine at least one entry, then we make a new collection
1123             // and populate it accordingly, and then swap it into place.
1124             if (can_combine)
1125             {
1126                 Collection minimal_ranges;
1127                 for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++)
1128                 {
1129                     if (prev != end && prev->data == pos->data)
1130                         minimal_ranges.back().SetRangeEnd (pos->GetRangeEnd());
1131                     else
1132                         minimal_ranges.push_back (*pos);
1133                 }
1134                 // Use the swap technique in case our new vector is much smaller.
1135                 // We must swap when using the STL because std::vector objects never
1136                 // release or reduce the memory once it has been allocated/reserved.
1137                 m_entries.swap (minimal_ranges);
1138             }
1139         }
1140         
1141         // Calculate the byte size of ranges with zero byte sizes by finding
1142         // the next entry with a base address > the current base address
1143         void
1144         CalculateSizesOfZeroByteSizeRanges ()
1145         {
1146 #ifdef ASSERT_RANGEMAP_ARE_SORTED
1147             assert (IsSorted());
1148 #endif
1149             typename Collection::iterator pos;
1150             typename Collection::iterator end;
1151             typename Collection::iterator next;
1152             for (pos = m_entries.begin(), end = m_entries.end(); pos != end; ++pos)
1153             {
1154                 if (pos->GetByteSize() == 0)
1155                 {
1156                     // Watch out for multiple entries with same address and make sure
1157                     // we find an entry that is greater than the current base address
1158                     // before we use that for the size
1159                     auto curr_base = pos->GetRangeBase();
1160                     for (next = pos + 1; next != end; ++next)
1161                     {
1162                         auto next_base = next->GetRangeBase();
1163                         if (next_base > curr_base)
1164                         {
1165                             pos->SetByteSize (next_base - curr_base);
1166                             break;
1167                         }
1168                     }
1169                 }
1170             }
1171             
1172         }
1173         
1174         void
1175         Clear ()
1176         {
1177             m_entries.clear();
1178         }
1179
1180         void
1181         Reserve (typename Collection::size_type size)
1182         {
1183             m_entries.resize (size);
1184         }
1185
1186         bool
1187         IsEmpty () const
1188         {
1189             return m_entries.empty();
1190         }
1191         
1192         size_t
1193         GetSize () const
1194         {
1195             return m_entries.size();
1196         }
1197         
1198         const Entry *
1199         GetEntryAtIndex (size_t i) const
1200         {
1201             if (i<m_entries.size())
1202                 return &m_entries[i];
1203             return NULL;
1204         }
1205         
1206         // Clients must ensure that "i" is a valid index prior to calling this function
1207         const Entry &
1208         GetEntryRef (size_t i) const
1209         {
1210             return m_entries[i];
1211         }
1212         
1213         static bool
1214         BaseLessThan (const Entry& lhs, const Entry& rhs)
1215         {
1216             return lhs.GetRangeBase() < rhs.GetRangeBase();
1217         }
1218         
1219         uint32_t
1220         FindEntryIndexThatContains (B addr) const
1221         {
1222 #ifdef ASSERT_RANGEMAP_ARE_SORTED
1223             assert (IsSorted());
1224 #endif
1225             if ( !m_entries.empty() )
1226             {
1227                 Entry entry (addr, 1);
1228                 typename Collection::const_iterator begin = m_entries.begin();
1229                 typename Collection::const_iterator end = m_entries.end();
1230                 typename Collection::const_iterator pos = std::lower_bound (begin, end, entry, BaseLessThan);
1231                 
1232                 if (pos != end && pos->Contains(addr))
1233                 {
1234                     return std::distance (begin, pos);
1235                 }
1236                 else if (pos != begin)
1237                 {
1238                     --pos;
1239                     if (pos->Contains(addr))
1240                         return std::distance (begin, pos);
1241                 }
1242             }
1243             return UINT32_MAX;
1244         }
1245         
1246         Entry *
1247         FindEntryThatContains (B addr)
1248         {
1249 #ifdef ASSERT_RANGEMAP_ARE_SORTED
1250             assert (IsSorted());
1251 #endif
1252             if ( !m_entries.empty() )
1253             {
1254                 Entry entry;
1255                 entry.SetRangeBase(addr);
1256                 entry.SetByteSize(1);
1257                 typename Collection::iterator begin = m_entries.begin();
1258                 typename Collection::iterator end = m_entries.end();
1259                 typename Collection::iterator pos = std::lower_bound (begin, end, entry, BaseLessThan);
1260                 
1261                 if (pos != end && pos->Contains(addr))
1262                 {
1263                     return &(*pos);
1264                 }
1265                 else if (pos != begin)
1266                 {
1267                     --pos;
1268                     if (pos->Contains(addr))
1269                     {
1270                         return &(*pos);
1271                     }
1272                 }
1273             }
1274             return NULL;
1275         }
1276         const Entry *
1277         FindEntryThatContains (B addr) const
1278         {
1279 #ifdef ASSERT_RANGEMAP_ARE_SORTED
1280             assert (IsSorted());
1281 #endif
1282             if ( !m_entries.empty() )
1283             {
1284                 Entry entry;
1285                 entry.SetRangeBase(addr);
1286                 entry.SetByteSize(1);
1287                 typename Collection::const_iterator begin = m_entries.begin();
1288                 typename Collection::const_iterator end = m_entries.end();
1289                 typename Collection::const_iterator pos = std::lower_bound (begin, end, entry, BaseLessThan);
1290                 
1291                 if (pos != end && pos->Contains(addr))
1292                 {
1293                     return &(*pos); 
1294                 }
1295                 else if (pos != begin)
1296                 {
1297                     --pos;
1298                     if (pos->Contains(addr))
1299                     {
1300                         return &(*pos); 
1301                     }
1302                 }
1303             }
1304             return NULL;
1305         }
1306         
1307         const Entry *
1308         FindEntryThatContains (const Entry &range) const
1309         {
1310 #ifdef ASSERT_RANGEMAP_ARE_SORTED
1311             assert (IsSorted());
1312 #endif
1313             if ( !m_entries.empty() )
1314             {
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);
1318                 
1319                 if (pos != end && pos->Contains(range))
1320                 {
1321                     return &(*pos); 
1322                 }
1323                 else if (pos != begin)
1324                 {
1325                     --pos;
1326                     if (pos->Contains(range))
1327                     {
1328                         return &(*pos); 
1329                     }
1330                 }
1331             }
1332             return NULL;
1333         }
1334         
1335         Entry *
1336         Back()
1337         {
1338             if (!m_entries.empty())
1339                 return &m_entries.back();
1340             return NULL;
1341         }
1342         
1343         const Entry *
1344         Back() const
1345         {
1346             if (!m_entries.empty())
1347                 return &m_entries.back();
1348             return NULL;
1349         }
1350         
1351     protected:
1352         Collection m_entries;
1353     };
1354                     
1355                 
1356     //----------------------------------------------------------------------
1357     // A simple range  with data class where you get to define the type of
1358     // the range base "B", the type used for the range byte size "S", and
1359     // the type for the associated data "T".
1360     //----------------------------------------------------------------------
1361     template <typename B, typename T>
1362     struct AddressData
1363     {
1364         typedef B BaseType;
1365         typedef T DataType;
1366         
1367         BaseType addr;
1368         DataType data;
1369         
1370         AddressData () :
1371             addr (),
1372             data ()
1373         {
1374         }
1375         
1376         AddressData (B a, DataType d) :
1377             addr (a),
1378             data (d)
1379         {
1380         }
1381         
1382         bool
1383         operator < (const AddressData &rhs) const
1384         {
1385             if (this->addr == rhs.addr)
1386                 return this->data < rhs.data;
1387             return this->addr < rhs.addr;
1388         }
1389         
1390         bool
1391         operator == (const AddressData &rhs) const
1392         {
1393             return this->addr == rhs.addr &&
1394                    this->data == rhs.data;
1395         }
1396         
1397         bool
1398         operator != (const AddressData &rhs) const
1399         {
1400             return this->addr != rhs.addr ||
1401                    this->data == rhs.data;
1402         }
1403     };
1404
1405
1406     template <typename B, typename T, unsigned N>
1407     class AddressDataArray
1408     {
1409     public:
1410         typedef AddressData<B,T> Entry;
1411         typedef llvm::SmallVector<Entry, N> Collection;
1412
1413
1414         AddressDataArray ()
1415         {
1416         }
1417         
1418         ~AddressDataArray()
1419         {
1420         }
1421         
1422         void
1423         Append (const Entry &entry)
1424         {
1425             m_entries.push_back (entry);
1426         }
1427     
1428         void
1429         Sort ()
1430         {
1431             if (m_entries.size() > 1)
1432                 std::stable_sort (m_entries.begin(), m_entries.end());
1433         }
1434     
1435 #ifdef ASSERT_RANGEMAP_ARE_SORTED
1436         bool
1437         IsSorted () const
1438         {
1439             typename Collection::const_iterator pos, end, prev;
1440             // First we determine if we can combine any of the Entry objects so we
1441             // don't end up allocating and making a new collection for no reason
1442             for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++)
1443             {
1444                 if (prev != end && *pos < *prev)
1445                     return false;
1446             }
1447             return true;
1448         }
1449 #endif
1450
1451         void
1452         Clear ()
1453         {
1454             m_entries.clear();
1455         }
1456         
1457         bool
1458         IsEmpty () const
1459         {
1460             return m_entries.empty();
1461         }
1462         
1463         size_t
1464         GetSize () const
1465         {
1466             return m_entries.size();
1467         }
1468         
1469         const Entry *
1470         GetEntryAtIndex (size_t i) const
1471         {
1472             if (i<m_entries.size())
1473                 return &m_entries[i];
1474             return NULL;
1475         }
1476
1477         // Clients must ensure that "i" is a valid index prior to calling this function
1478         const Entry &
1479         GetEntryRef (size_t i) const
1480         {
1481             return m_entries[i];
1482         }
1483
1484         static bool 
1485         BaseLessThan (const Entry& lhs, const Entry& rhs)
1486         {
1487             return lhs.addr < rhs.addr;
1488         }
1489         
1490         Entry *
1491         FindEntry (B addr, bool exact_match_only)
1492         {
1493 #ifdef ASSERT_RANGEMAP_ARE_SORTED
1494             assert (IsSorted());
1495 #endif
1496             if ( !m_entries.empty() )
1497             {
1498                 Entry entry;
1499                 entry.addr = addr;
1500                 typename Collection::iterator begin = m_entries.begin();
1501                 typename Collection::iterator end = m_entries.end();
1502                 typename Collection::iterator pos = std::lower_bound (begin, end, entry, BaseLessThan);
1503                 
1504                 if (pos != end)
1505                 {
1506                     if (pos->addr == addr || !exact_match_only)
1507                         return &(*pos);
1508                 }
1509            }
1510             return NULL;
1511         }
1512         
1513         const Entry *
1514         FindNextEntry (const Entry *entry)
1515         {
1516             if (entry >= &*m_entries.begin() && entry + 1 < &*m_entries.end())
1517                 return entry + 1;
1518             return NULL;
1519         }
1520         
1521         Entry *
1522         Back()
1523         {
1524             if (!m_entries.empty())
1525                 return &m_entries.back();
1526             return NULL;
1527         }
1528
1529         const Entry *
1530         Back() const
1531         {
1532             if (!m_entries.empty())
1533                 return &m_entries.back();
1534             return NULL;
1535         }
1536
1537     protected:
1538         Collection m_entries;
1539     };
1540
1541 } // namespace lldb_private
1542
1543 #endif  // liblldb_RangeMap_h_