on master help sign in
Implement breakSubstring

--HG-- extra : convert_revision : 26fca70db6022c71d0aed9856c1bcf26ab029bc3

commit82674d9fcefcff25254e366d4eb75a99ae326532 authorBryan O'Sullivan <bos@serpentine.com> dateThu 12 Feb 2009, 08:54 (18 years ago) parent2aaff6d
2 files changed+49−1
Data/Text.hs+40−1 tests/Properties.hs+9
Data/Text.hs+40−1
@@ -106,7 +106,7 @@ module Data.Text
106106 -- ** Breaking into many substrings
107107 , split
108108 , splitWith
109− -- , breakSubstring
109+ , breakSubstring
110110
111111 -- ** Breaking into lines and words
112112 , lines
@@ -758,6 +758,45 @@ find :: (Char -> Bool) -> Text -> Maybe Char
758758find p t = S.find p (stream t)
759759{-# INLINE find #-}
760760
761+-- | Break a string on a substring, returning a pair of the part of the
762+-- string prior to the match, and the rest of the string.
763+--
764+-- The following relationships hold:
765+--
766+-- > break (== c) l == breakSubstring (singleton c) l
767+--
768+-- and:
769+--
770+-- > findSubstring s l ==
771+-- > if null s then Just 0
772+-- > else case breakSubstring s l of
773+-- > (x,y) | null y -> Nothing
774+-- > | otherwise -> Just (length x)
775+--
776+-- For example, to tokenise a string, dropping delimiters:
777+--
778+-- > tokenise x y = h : if null t then [] else tokenise x (drop (length x) t)
779+-- > where (h,t) = breakSubstring x y
780+--
781+-- To skip to the first occurence of a string:
782+--
783+-- > snd (breakSubstring x y)
784+--
785+-- To take the parts of a string before a delimiter:
786+--
787+-- > fst (breakSubstring x y)
788+--
789+breakSubstring :: Text -- ^ String to search for
790+ -> Text -- ^ String to search in
791+ -> (Text,Text) -- ^ Head and tail of string broken at substring
792+
793+breakSubstring pat src = search 0 src
794+ where
795+ search !n !s
796+ | null s = (src,empty) -- not found
797+ | pat `isPrefixOf` s = (take n src,s)
798+ | otherwise = search (n+1) (tail s)
799+
761800-- | /O(n)/ 'filter', applied to a predicate and a 'Text',
762801-- returns a 'Text' containing those characters that satisfy the
763802-- predicate.
tests/Properties.hs+9
@@ -137,6 +137,13 @@ splitWith p xs = h : splitWith p (whale t)
137137 whale xs = xs
138138-}
139139
140+prop_breakSubstring_isInfixOf s l
141+ = T.isInfixOf s l ==
142+ T.null s || (not . T.null . snd $ T.breakSubstring s l)
143+prop_breakSubstringC c
144+ = L.break (==c) `eqP`
145+ (unpack2 . T.breakSubstring (T.singleton c))
146+
140147prop_lines = L.lines `eqP` (map unpack . T.lines)
141148prop_words = L.words `eqP` (map unpack . T.words)
142149prop_unlines = L.unlines `eq` (unpack . T.unlines . map pack)
@@ -236,6 +243,8 @@ tests = [
236243
237244 ("prop_split_i", mytest prop_split_i),
238245--("prop_splitWith", mytest prop_splitWith),
246+ ("prop_breakSubstringC", mytest prop_breakSubstringC),
247+ ("prop_breakSubstring_isInfixOf", mytest prop_breakSubstring_isInfixOf),
239248
240249 ("prop_lines", mytest prop_lines),
241250 ("prop_words", mytest prop_words),