[llvm-commits] [llvm] r121935 - /llvm/trunk/include/llvm/ADT/IntervalMap.h

Jakob Stoklund Olesen stoklund at 2pi.dk
Wed Dec 15 17:18:29 PST 2010


Author: stoklund
Date: Wed Dec 15 19:18:29 2010
New Revision: 121935

URL: http://llvm.org/viewvc/llvm-project?rev=121935&view=rev
Log:
Add IntervalMapOverlaps - An iterator for overlapping intervals in two
IntervalMaps.

The IntervalMaps can have different template parameters, but the KeyT and Traits
types must be the same.

Tests are forthcoming.

Modified:
    llvm/trunk/include/llvm/ADT/IntervalMap.h

Modified: llvm/trunk/include/llvm/ADT/IntervalMap.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/IntervalMap.h?rev=121935&r1=121934&r2=121935&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ADT/IntervalMap.h (original)
+++ llvm/trunk/include/llvm/ADT/IntervalMap.h Wed Dec 15 19:18:29 2010
@@ -940,6 +940,7 @@
 
 public:
   typedef typename Sizer::Allocator Allocator;
+  typedef Traits KeyTraits;
 
 private:
   // The root data is either a RootLeaf or a RootBranchData instance.
@@ -2006,6 +2007,96 @@
   return SplitRoot;
 }
 
+//===----------------------------------------------------------------------===//
+//---                       IntervalMapOverlaps                           ----//
+//===----------------------------------------------------------------------===//
+
+/// IntervalMapOverlaps - Iterate over the overlaps of mapped intervals in two
+/// IntervalMaps. The maps may be different, but the KeyT and Traits types
+/// should be the same.
+///
+/// Typical uses:
+///
+/// 1. Test for overlap:
+///    bool overlap = IntervalMapOverlaps(a, b).valid();
+///
+/// 2. Enumerate overlaps:
+///    for (IntervalMapOverlaps I(a, b); I.valid() ; ++I) { ... }
+///
+template <typename MapA, typename MapB>
+class IntervalMapOverlaps {
+  typedef typename MapA::KeyTraits Traits;
+  typename MapA::const_iterator posA;
+  typename MapB::const_iterator posB;
+
+  /// advance - Move posA and posB forward until reaching an overlap, or until
+  /// either meets end.
+  /// Don't move the iterators if they are already overlapping.
+  void advance() {
+    for (;;) {
+      // Make a.end > b.start.
+      posA.advanceTo(posB.start());
+      if (!posA.valid() || !Traits::stopLess(posB.end(), posA.start()))
+        return;
+      // Make b.end > a.start.
+      posB.advanceTo(posA.start());
+      if (!posB.valid() || !Traits::stopLess(posA.end(), posB.start()))
+        return;
+    }
+  }
+
+public:
+  /// IntervalMapOverlaps - Create an iterator for the overlaps of a and b.
+  IntervalMapOverlaps(const MapA &a, const MapB &b)
+    : posA(b.empty() ? a.end() : a.find(b.start())),
+      posB(posA.valid() ? b.find(posA.start()) : b.end()) {
+    if (valid())
+      advance();
+  }
+
+  /// valid - Return true if iterator is at an overlap.
+  bool valid() const {
+    return posA.valid() && posB.valid();
+  }
+
+  /// a - access the left hand side in the overlap.
+  const typename MapA::const_iterator &a() const { return posA; }
+
+  /// b - access the right hand side in the overlap.
+  const typename MapB::const_iterator &b() const { return posB; }
+
+  /// skipA - Move to the next overlap that doesn't involve a().
+  void skipA() {
+    ++posA;
+    if (!posA.valid() || !Traits::stopLess(posB.end(), posA.start()))
+      return;
+    // Second half-loop of advance().
+    posB.advanceTo(posA.start());
+    if (!posB.valid() || !Traits::stopLess(posA.end(), posB.start()))
+      return ;
+    advance();
+  }
+
+  /// skipB - Move to the next overlap that doesn't involve b().
+  void skipB() {
+    ++posB;
+    if (!posB.valid() || !Traits::stopLess(posA.end(), posB.start()))
+        return;
+    advance();
+  }
+
+  /// Preincrement - Move to the next overlap.
+  IntervalMapOverlaps &operator++() {
+    // Bump the iterator that ends first. The other one may have more overlaps.
+    if (Traits::startLess(posB.end(), posA.end()))
+      skipB();
+    else
+      skipA();
+    return *this;
+  }
+};
+
+
 } // namespace llvm
 
 #endif





More information about the llvm-commits mailing list