Bug 1271483 - p11. Implement comma-sep-string for-range iterator - r=cpearce
authorGerald Squelart <gsquelart@mozilla.com>
Thu, 26 May 2016 16:43:16 +1000
changeset 302282 93bc3bb0c1be31bfa9057782b7af069ac71bedf2
parent 302281 60ea602c56cd331055f3b1dbe37d6f47a68a22c7
child 302283 bbfd03f4dd55e48e79da005863abc9d1ded85dc5
push id78676
push usergsquelart@mozilla.com
push dateWed, 22 Jun 2016 03:54:32 +0000
treeherdermozilla-inbound@da005aa1d83c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscpearce
bugs1271483
milestone50.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 1271483 - p11. Implement comma-sep-string for-range iterator - r=cpearce Utility class&function that creates an iteratable range from a comma-separated string, where each iteration will give a dependent substring (i.e., no string copy happening). This will help with going through lists of unplayable formats, to see if issues have been solved. If useful enough, this could later be published to a more public location (e.g. mfbt or xpcom). MozReview-Commit-ID: 3XP5PwQZFA1
dom/media/DecoderDoctorDiagnostics.cpp
--- a/dom/media/DecoderDoctorDiagnostics.cpp
+++ b/dom/media/DecoderDoctorDiagnostics.cpp
@@ -232,16 +232,129 @@ DecoderDoctorDocumentWatcher::EnsureTime
     if (NS_WARN_IF(NS_FAILED(
           mTimer->InitWithCallback(
             this, sAnalysisPeriod_ms, nsITimer::TYPE_ONE_SHOT)))) {
       mTimer = nullptr;
     }
   }
 }
 
+template <typename String>
+class StringListRange
+{
+  typedef typename String::char_type CharType;
+  typedef const CharType* Pointer;
+
+public:
+  // Iterator into range, trims items and skips empty items.
+  class Iterator
+  {
+  public:
+    bool operator!=(const Iterator& a) const
+    {
+      return mStart != a.mStart || mEnd != a.mEnd;
+    }
+    Iterator& operator++()
+    {
+      SearchItemAt(mComma + 1);
+      return *this;
+    }
+    typedef decltype(Substring(Pointer(), Pointer())) DereferencedType;
+    DereferencedType operator*()
+    {
+      return Substring(mStart, mEnd);
+    }
+  private:
+    friend class StringListRange;
+    Iterator(const CharType* aRangeStart, uint32_t aLength)
+      : mRangeEnd(aRangeStart + aLength)
+    {
+      SearchItemAt(aRangeStart);
+    }
+    void SearchItemAt(Pointer start)
+    {
+      // First, skip leading whitespace.
+      for (Pointer p = start; ; ++p) {
+        if (p >= mRangeEnd) {
+          mStart = mEnd = mComma = mRangeEnd;
+          return;
+        }
+        auto c = *p;
+        if (c == CharType(',')) {
+          // Comma -> Empty item -> Skip.
+        } else if (c != CharType(' ')) {
+          mStart = p;
+          break;
+        }
+      }
+      // Find comma, recording start of trailing space.
+      Pointer trailingWhitespace = nullptr;
+      for (Pointer p = mStart + 1; ; ++p) {
+        if (p >= mRangeEnd) {
+          mEnd = trailingWhitespace ? trailingWhitespace : p;
+          mComma = p;
+          return;
+        }
+        auto c = *p;
+        if (c == CharType(',')) {
+          mEnd = trailingWhitespace ? trailingWhitespace : p;
+          mComma = p;
+          return;
+        }
+        if (c == CharType(' ')) {
+          // Found a whitespace -> Record as trailing if not first one.
+          if (!trailingWhitespace) {
+            trailingWhitespace = p;
+          }
+        } else {
+          // Found a non-whitespace -> Reset trailing whitespace if needed.
+          if (trailingWhitespace) {
+            trailingWhitespace = nullptr;
+          }
+        }
+      }
+    }
+    const Pointer mRangeEnd;
+    Pointer mStart;
+    Pointer mEnd;
+    Pointer mComma;
+  };
+
+  explicit StringListRange(const String& aList) : mList(aList) {}
+  Iterator begin()
+  {
+    return Iterator(mList.Data(), mList.Length());
+  }
+  Iterator end()
+  {
+    return Iterator(mList.Data() + mList.Length(), 0);
+  }
+private:
+  const String& mList;
+};
+
+template <typename String>
+StringListRange<String>
+MakeStringListRange(const String& aList)
+{
+  return StringListRange<String>(aList);
+}
+
+template <typename ListString, typename ItemString>
+static bool
+StringListContains(const ListString& aList, const ItemString& aItem)
+{
+  for (const auto& listItem : MakeStringListRange(aList)) {
+    if (listItem.Equals(aItem)) {
+      return true;
+    }
+  }
+  return false;
+}
+
 static void
 DispatchNotification(nsISupports* aSubject,
                      dom::DecoderDoctorNotificationType aNotificationType,
                      bool aIsSolved,
                      const char* aReportStringId,
                      const nsAString& aFormats)
 {
   if (!aSubject) {