Bug 1271483 - p11. Implement comma-sep-string for-range iterator - r?cpearce draft
authorGerald Squelart <gsquelart@mozilla.com>
Wed, 25 May 2016 03:23:11 +1000
changeset 370940 784a13fa558e4496b71d6860a4866d753a35d668
parent 370939 5b9a301adbb7b6afec93e155f33cd724f7106283
child 370941 f8774aed93d47f0a5aecabe6ebcf89e119dcd389
push id19183
push usergsquelart@mozilla.com
push dateWed, 25 May 2016 16:13:39 +0000
reviewerscpearce
bugs1271483
milestone49.0a1
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) {