Bryan O'Sullivan avatar Bryan O'Sullivan committed 3fb7d2c

Make the split* functions undefined over empty delimiters as inputs.

Comments (0)

Files changed (1)

     , findIndices
     , elemIndex
     , elemIndices
+    , count
     , countChar
 
     -- * Zipping and unzipping
 -- are slices of the original.
 
 -- | /O(m)*O(n)/ Break a 'Text' into pieces separated by the first
--- 'Text' argument, consuming the delimiter. Examples:
+-- 'Text' argument, consuming the delimiter. An empty delimiter is
+-- invalid, and will cause an error to be raised.
+--
+-- Examples:
 --
 -- > split "\r\n" "a\r\nb\r\nd\r\ne" == ["a","b","d","e"]
 -- > split "aaa"  "aaaXaaaXaaaXaaa"  == ["","X","X","X",""]
       -> Text                   -- ^ Input text
       -> [Text]
 split pat src0
-    | l == 0    = [src0]
-    | l == 1    = splitWith (== (head pat)) src0
+    | l == 0    = emptyError "split"
+    | l == 1    = splitWith (== (unsafeHead pat)) src0
     | otherwise = go src0
   where
     l      = length pat
 -- and consuming the delimiter.  The last element of the list contains
 -- the remaining text after the number of times to split has been
 -- reached.  A value of zero or less for @k@ causes no splitting to
--- occur.
+-- occur. An empty delimiter is invalid, and will cause an error to be
+-- raised.
 --
 -- Examples:
 --
            -> Text              -- ^ Input text
            -> [Text]
 splitTimes k pat src0
-    | k <= 0 || l == 0 = [src0]
-    | otherwise        = go k src0
+    | k <= 0    = [src0]
+    | l == 0    = emptyError "splitTimes"
+    | otherwise = go k src0
   where
     l         = length pat
     go !i src = search 0 src
 elemIndices c t = S.elemIndices c (stream t)
 {-# INLINE elemIndices #-}
 
+-- | /O(n*m)/ The 'count' function returns the number of times the
+-- query string appears in the given 'Text'.
+count :: Text -> Text -> Int
+count pat src0
+    | l == 0    = length src0 + 1
+    | l == 1    = countChar (unsafeHead pat) src0
+    | otherwise = go 0 src0
+  where
+    l = length pat
+    go !n src = search src
+      where
+        search s | null s             = n
+                 | pat `isPrefixOf` s = go (n+1) (drop l s)
+                 | otherwise          = search (unsafeTail s)
+{-# INLINE [1] count #-}
+
 -- | /O(n)/ The 'countChar' function returns the number of times the
 -- query element appears in the given 'Text'. Subject to fusion.
 countChar :: Char -> Text -> Int
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.