Bug 1543304 - Add iterators to nsCSSPropertyIDSet; r=heycam
authorBrian Birtles <birtles@gmail.com>
Sun, 14 Apr 2019 23:47:51 +0000
changeset 469445 fa9332a8ea937098a1a6d79ed4bc9028e3917e62
parent 469441 ec1f3a922d56e0a9393415872ee1d30c2f895fd7
child 469446 587b7bc9ad81e868c672c540907843bf46658071
push id112792
push userncsoregi@mozilla.com
push dateMon, 15 Apr 2019 09:49:11 +0000
treeherdermozilla-inbound@a57f27d3ccd0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersheycam
bugs1543304
milestone68.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1543304 - Add iterators to nsCSSPropertyIDSet; r=heycam Differential Revision: https://phabricator.services.mozilla.com/D26855
layout/style/nsCSSPropertyIDSet.h
--- a/layout/style/nsCSSPropertyIDSet.h
+++ b/layout/style/nsCSSPropertyIDSet.h
@@ -183,13 +183,91 @@ class nsCSSPropertyIDSet {
   }
   bool HasPropertyAt(size_t aChunk, size_t aBit) const {
     return (mProperties[aChunk] & (property_set_type(1) << aBit)) != 0;
   }
   static nsCSSPropertyID CSSPropertyAt(size_t aChunk, size_t aBit) {
     return nsCSSPropertyID(aChunk * kBitsInChunk + aBit);
   }
 
+  // Iterator for use in range-based for loops
+  class Iterator {
+   public:
+    Iterator(Iterator&& aOther)
+        : mPropertySet(aOther.mPropertySet),
+          mChunk(aOther.mChunk),
+          mBit(aOther.mBit) {}
+
+    static Iterator BeginIterator(const nsCSSPropertyIDSet& aPropertySet) {
+      Iterator result(aPropertySet);
+
+      // Search for the first property.
+      // Unsigned integer overflow is defined so the following is safe.
+      result.mBit = -1;
+      ++result;
+
+      return result;
+    }
+
+    static Iterator EndIterator(const nsCSSPropertyIDSet& aPropertySet) {
+      Iterator result(aPropertySet);
+      result.mChunk = kChunkCount;
+      result.mBit = 0;
+      return result;
+    }
+
+    bool operator!=(const Iterator& aOther) const {
+      return mChunk != aOther.mChunk || mBit != aOther.mBit;
+    }
+
+    Iterator& operator++() {
+      MOZ_ASSERT(mChunk < kChunkCount, "Should not iterate beyond end");
+
+      do {
+        mBit++;
+      } while (mBit < kBitsInChunk &&
+               !mPropertySet.HasPropertyAt(mChunk, mBit));
+      if (mBit != kBitsInChunk) {
+        return *this;
+      }
+
+      do {
+        mChunk++;
+      } while (mChunk < kChunkCount &&
+               !mPropertySet.HasPropertyInChunk(mChunk));
+      mBit = 0;
+      if (mChunk != kChunkCount) {
+        while (mBit < kBitsInChunk &&
+               !mPropertySet.HasPropertyAt(mChunk, mBit)) {
+          mBit++;
+        }
+      }
+
+      return *this;
+    }
+
+    nsCSSPropertyID operator*() {
+      MOZ_ASSERT(mChunk < kChunkCount, "Should not dereference beyond end");
+      return nsCSSPropertyIDSet::CSSPropertyAt(mChunk, mBit);
+    }
+
+   private:
+    explicit Iterator(const nsCSSPropertyIDSet& aPropertySet)
+        : mPropertySet(aPropertySet) {}
+
+    Iterator() = delete;
+    Iterator(const Iterator&) = delete;
+    Iterator& operator=(const Iterator&) = delete;
+    Iterator& operator=(const Iterator&&) = delete;
+
+    const nsCSSPropertyIDSet& mPropertySet;
+    size_t mChunk = 0;
+    size_t mBit = 0;
+  };
+
+  Iterator begin() const { return Iterator::BeginIterator(*this); }
+  Iterator end() const { return Iterator::EndIterator(*this); }
+
  private:
   property_set_type mProperties[kChunkCount];
 };
 
 #endif /* !defined(nsCSSPropertyIDSet_h__) */