Bug 1035884 - Template-ify nsCharSeparatedTokenizer to remove duplicate code. r=froydnj
authorBirunthan Mohanathas <birunthan@mohanathas.com>
Fri, 18 Jul 2014 14:52:29 -0700
changeset 195582 4301c7932cfd647c3bea48a06def1df4eee3b3fe
parent 195581 17e28bbaaac8c49f29841192d92e939de78288c5
child 195583 ea01a75b73b1472cfdfce863d08bb850a3fab436
push id27188
push usercbook@mozilla.com
push dateWed, 23 Jul 2014 13:53:43 +0000
treeherdermozilla-central@785acfd2ae48 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj
bugs1035884
milestone34.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 1035884 - Template-ify nsCharSeparatedTokenizer to remove duplicate code. r=froydnj
xpcom/ds/nsCharSeparatedTokenizer.h
--- a/xpcom/ds/nsCharSeparatedTokenizer.h
+++ b/xpcom/ds/nsCharSeparatedTokenizer.h
@@ -24,29 +24,33 @@
  * "foo , bar hi , baz" -> "foo" "bar hi" "baz"
  * "foo, ,bar,baz" ->      "foo" "" "bar" "baz"
  * "foo,,bar,baz" ->       "foo" "" "bar" "baz"
  * "foo,bar,baz," ->       "foo" "bar" "baz"
  *
  * The function used for whitespace detection is a template argument.
  * By default, it is NS_IsAsciiWhitespace.
  */
-template<bool IsWhitespace(char16_t) = NS_IsAsciiWhitespace>
-class nsCharSeparatedTokenizerTemplate
+template<typename SubstringType,
+         typename DependentSubstringType,
+         bool IsWhitespace(char16_t)>
+class nsTCharSeparatedTokenizer
 {
+  typedef typename SubstringType::char_type CharType;
+
 public:
     // Flags -- only one for now. If we need more, they should be defined to
     // be 1 << 1, 1 << 2, etc. (They're masks, and aFlags is a bitfield.)
     enum {
         SEPARATOR_OPTIONAL = 1
     };
 
-    nsCharSeparatedTokenizerTemplate(const nsSubstring& aSource,
-                                     char16_t aSeparatorChar,
-                                     uint32_t  aFlags = 0)
+    nsTCharSeparatedTokenizer(const SubstringType& aSource,
+                              CharType aSeparatorChar,
+                              uint32_t aFlags = 0)
         : mIter(aSource.Data(), aSource.Length()),
           mEnd(aSource.Data() + aSource.Length(), aSource.Data(),
                aSource.Length()),
           mSeparatorChar(aSeparatorChar),
           mWhitespaceBeforeFirstToken(false),
           mWhitespaceAfterCurrentToken(false),
           mSeparatorAfterCurrentToken(false),
           mSeparatorOptional(aFlags & SEPARATOR_OPTIONAL)
@@ -93,19 +97,20 @@ public:
     bool whitespaceAfterCurrentToken() const
     {
         return mWhitespaceAfterCurrentToken;
     }
 
     /**
      * Returns the next token.
      */
-    const nsDependentSubstring nextToken()
+    const DependentSubstringType nextToken()
     {
-        mozilla::RangedPtr<const char16_t> tokenStart = mIter, tokenEnd = mIter;
+        mozilla::RangedPtr<const CharType> tokenStart = mIter;
+        mozilla::RangedPtr<const CharType> tokenEnd = mIter;
 
         MOZ_ASSERT(mIter == mEnd || !IsWhitespace(*mIter),
                    "Should be at beginning of token if there is one");
 
         // Search until we hit separator or end (or whitespace, if a separator
         // isn't required -- see clause with 'break' below).
         while (mIter < mEnd && *mIter != mSeparatorChar) {
           // Skip to end of the current word.
@@ -145,170 +150,76 @@ public:
                 ++mIter;
             }
         }
 
         return Substring(tokenStart.get(), tokenEnd.get());
     }
 
 private:
-    mozilla::RangedPtr<const char16_t> mIter;
-    const mozilla::RangedPtr<const char16_t> mEnd;
-    char16_t mSeparatorChar;
+    mozilla::RangedPtr<const CharType> mIter;
+    const mozilla::RangedPtr<const CharType> mEnd;
+    CharType mSeparatorChar;
     bool mWhitespaceBeforeFirstToken;
     bool mWhitespaceAfterCurrentToken;
     bool mSeparatorAfterCurrentToken;
     bool mSeparatorOptional;
 };
 
-class nsCharSeparatedTokenizer: public nsCharSeparatedTokenizerTemplate<>
+template<bool IsWhitespace(char16_t) = NS_IsAsciiWhitespace>
+class nsCharSeparatedTokenizerTemplate
+  : public nsTCharSeparatedTokenizer<nsSubstring,
+                                     nsDependentSubstring,
+                                     IsWhitespace>
 {
 public:
-    nsCharSeparatedTokenizer(const nsSubstring& aSource,
-                             char16_t aSeparatorChar,
-                             uint32_t  aFlags = 0)
-      : nsCharSeparatedTokenizerTemplate<>(aSource, aSeparatorChar, aFlags)
-    {
-    }
+  nsCharSeparatedTokenizerTemplate(const nsSubstring& aSource,
+                                   char16_t aSeparatorChar,
+                                   uint32_t aFlags = 0)
+    : nsTCharSeparatedTokenizer<nsSubstring,
+                                nsDependentSubstring,
+                                IsWhitespace>(aSource, aSeparatorChar, aFlags)
+  {
+  }
+};
+
+class nsCharSeparatedTokenizer
+  : public nsCharSeparatedTokenizerTemplate<>
+{
+public:
+  nsCharSeparatedTokenizer(const nsSubstring& aSource,
+                           char16_t aSeparatorChar,
+                           uint32_t aFlags = 0)
+    : nsCharSeparatedTokenizerTemplate<>(aSource, aSeparatorChar, aFlags)
+  {
+  }
 };
 
 template<bool IsWhitespace(char16_t) = NS_IsAsciiWhitespace>
 class nsCCharSeparatedTokenizerTemplate
+  : public nsTCharSeparatedTokenizer<nsCSubstring,
+                                     nsDependentCSubstring,
+                                     IsWhitespace>
 {
 public:
-    // Flags -- only one for now. If we need more, they should be defined to
-    // be 1 << 1, 1 << 2, etc. (They're masks, and aFlags is a bitfield.)
-    enum {
-        SEPARATOR_OPTIONAL = 1
-    };
-
-    nsCCharSeparatedTokenizerTemplate(const nsCSubstring& aSource,
-                                      char aSeparatorChar,
-                                      uint32_t  aFlags = 0)
-        : mIter(aSource.Data(), aSource.Length()),
-          mEnd(aSource.Data() + aSource.Length(), aSource.Data(),
-               aSource.Length()),
-          mSeparatorChar(aSeparatorChar),
-          mWhitespaceBeforeFirstToken(false),
-          mWhitespaceAfterCurrentToken(false),
-          mSeparatorAfterCurrentToken(false),
-          mSeparatorOptional(aFlags & SEPARATOR_OPTIONAL)
-    {
-        // Skip initial whitespace
-        while (mIter < mEnd && IsWhitespace(*mIter)) {
-            mWhitespaceBeforeFirstToken = true;
-            ++mIter;
-        }
-    }
-
-    /**
-     * Checks if any more tokens are available.
-     */
-    bool hasMoreTokens() const
-    {
-        MOZ_ASSERT(mIter == mEnd || !IsWhitespace(*mIter),
-                   "Should be at beginning of token if there is one");
-
-        return mIter < mEnd;
-    }
-
-    /*
-     * Returns true if there is whitespace prior to the first token.
-     */
-    bool whitespaceBeforeFirstToken() const
-    {
-        return mWhitespaceBeforeFirstToken;
-    }
-
-    /*
-     * Returns true if there is a separator after the current token.
-     * Useful if you want to check whether the last token has a separator
-     * after it which may not be valid.
-     */
-    bool separatorAfterCurrentToken() const
-    {
-        return mSeparatorAfterCurrentToken;
-    }
-
-    /*
-     * Returns true if there is any whitespace after the current token.
-     */
-    bool whitespaceAfterCurrentToken() const
-    {
-        return mWhitespaceAfterCurrentToken;
-    }
-
-    /**
-     * Returns the next token.
-     */
-    const nsDependentCSubstring nextToken()
-    {
-        mozilla::RangedPtr<const char> tokenStart = mIter, tokenEnd = mIter;
-
-        MOZ_ASSERT(mIter == mEnd || !IsWhitespace(*mIter),
-                   "Should be at beginning of token if there is one");
-
-        // Search until we hit separator or end (or whitespace, if a separator
-        // isn't required -- see clause with 'break' below).
-        while (mIter < mEnd && *mIter != mSeparatorChar) {
-          // Skip to end of the current word.
-          while (mIter < mEnd &&
-                 !IsWhitespace(*mIter) && *mIter != mSeparatorChar) {
-              ++mIter;
-          }
-          tokenEnd = mIter;
-
-          // Skip whitespace after the current word.
-          mWhitespaceAfterCurrentToken = false;
-          while (mIter < mEnd && IsWhitespace(*mIter)) {
-              mWhitespaceAfterCurrentToken = true;
-              ++mIter;
-          }
-          if (mSeparatorOptional) {
-            // We've hit (and skipped) whitespace, and that's sufficient to end
-            // our token, regardless of whether we've reached a SeparatorChar.
-            break;
-          } // (else, we'll keep looping until we hit mEnd or SeparatorChar)
-        }
-
-        mSeparatorAfterCurrentToken = (mIter != mEnd &&
-                                       *mIter == mSeparatorChar);
-        MOZ_ASSERT(mSeparatorOptional ||
-                   (mSeparatorAfterCurrentToken == (mIter < mEnd)),
-                   "If we require a separator and haven't hit the end of "
-                   "our string, then we shouldn't have left the loop "
-                   "unless we hit a separator");
-
-        // Skip separator (and any whitespace after it), if we're at one.
-        if (mSeparatorAfterCurrentToken) {
-            ++mIter;
-
-            while (mIter < mEnd && IsWhitespace(*mIter)) {
-                mWhitespaceAfterCurrentToken = true;
-                ++mIter;
-            }
-        }
-
-        return Substring(tokenStart.get(), tokenEnd.get());
-    }
-
-private:
-    mozilla::RangedPtr<const char> mIter;
-    const mozilla::RangedPtr<const char> mEnd;
-    char mSeparatorChar;
-    bool mWhitespaceBeforeFirstToken;
-    bool mWhitespaceAfterCurrentToken;
-    bool mSeparatorAfterCurrentToken;
-    bool mSeparatorOptional;
+  nsCCharSeparatedTokenizerTemplate(const nsCSubstring& aSource,
+                                    char aSeparatorChar,
+                                    uint32_t aFlags = 0)
+    : nsTCharSeparatedTokenizer<nsCSubstring,
+                                nsDependentCSubstring,
+                                IsWhitespace>(aSource, aSeparatorChar, aFlags)
+  {
+  }
 };
 
-class nsCCharSeparatedTokenizer: public nsCCharSeparatedTokenizerTemplate<>
+class nsCCharSeparatedTokenizer
+  : public nsCCharSeparatedTokenizerTemplate<>
 {
 public:
-    nsCCharSeparatedTokenizer(const nsCSubstring& aSource,
-                              char aSeparatorChar,
-                              uint32_t aFlags = 0)
-      : nsCCharSeparatedTokenizerTemplate<>(aSource, aSeparatorChar, aFlags)
-    {
-    }
+  nsCCharSeparatedTokenizer(const nsCSubstring& aSource,
+                            char aSeparatorChar,
+                            uint32_t aFlags = 0)
+    : nsCCharSeparatedTokenizerTemplate<>(aSource, aSeparatorChar, aFlags)
+  {
+  }
 };
 
 #endif /* __nsCharSeparatedTokenizer_h */