@@ -165,6 +165,7 @@ module Data.Text.Lazy
165 -- ** View patterns
165 -- ** View patterns
166 , stripPrefix
166 , stripPrefix
167 , stripSuffix
167 , stripSuffix
169 -- * Searching
170 -- * Searching
@@ -189,7 +190,7 @@ module Data.Text.Lazy
189import Prelude (Char, Bool(..), Maybe(..), String,
190import Prelude (Char, Bool(..), Maybe(..), String,
190 Eq(..), Ord(..), Ordering(..), Read(..), Show(..),
191 Eq(..), Ord(..), Ordering(..), Read(..), Show(..),
191 (&&), (||), (+), (-), (.), ($), (++),
192 (&&), (||), (+), (-), (.), ($), (++),
192− div, error, flip, fromIntegral, not, otherwise)
193+ div, error, flip, fmap, fromIntegral, not, otherwise)
193import qualified Prelude as P
194import qualified Prelude as P
194#if defined(HAVE_DEEPSEQ)
195#if defined(HAVE_DEEPSEQ)
195import Control.DeepSeq (NFData(..))
196import Control.DeepSeq (NFData(..))
@@ -1325,51 +1326,77 @@ isInfixOf needle haystack
1325-------------------------------------------------------------------------------
1326-------------------------------------------------------------------------------
1326-- * View patterns
1327-- * View patterns
1328−-- | /O(n)/ Returns the suffix of the second string if its prefix
1329+-- | /O(n)/ Return the suffix of the second string if its prefix
1329−-- matches the first.
1330+-- matches the entire first string.
1331-- Examples:
1332-- Examples:
1333-- > stripPrefix "foo" "foobar" == Just "bar"
1334-- > stripPrefix "foo" "foobar" == Just "bar"
1335+-- > stripPrefix "" "baz" == Just "baz"
1334-- > stripPrefix "foo" "quux" == Nothing
1336-- > stripPrefix "foo" "quux" == Nothing
1336-- This is particularly useful with the @ViewPatterns@ extension to
1338-- This is particularly useful with the @ViewPatterns@ extension to
1337-- GHC, as follows:
1339-- GHC, as follows:
1339-- > {-# LANGUAGE ViewPatterns #-}
1341-- > {-# LANGUAGE ViewPatterns #-}
1340−-- > import Data.Text as T
1342+-- > import Data.Text.Lazy as T
1342-- > fnordLength :: Text -> Int
1344-- > fnordLength :: Text -> Int
1343-- > fnordLength (stripPrefix "fnord" -> Just suf) = T.length suf
1345-- > fnordLength (stripPrefix "fnord" -> Just suf) = T.length suf
1344−-- > fnordLength _ = -1
1346+-- > fnordLength _ = -1
1345stripPrefix :: Text -> Text -> Maybe Text
1347stripPrefix :: Text -> Text -> Maybe Text
1346−-- Yes, this could be much more efficient.
1347stripPrefix p t
1348stripPrefix p t
1348− | p `isPrefixOf` t = Just (drop (length p) t)
1349+ | null p = Just t
1350+ | otherwise = case commonPrefixes p t of
1351+ Just (_,c,r) | null c -> Just r
1349− | otherwise = Nothing
1352+ _ -> Nothing
1354+-- | /O(n)/ Find the longest non-empty common prefix of two strings
1355+-- and return it, along with the suffixes of each string at which they
1358+-- If the strings do not have a common prefix or either one is empty,
1359+-- this function returns 'Nothing'.
1363+-- > commonPrefixes "foobar" "fooquux" == Just ("foo","bar","quux")
1364+-- > commonPrefixes "veeble" "fetzer" == Nothing
1365+-- > commonPrefixes "" "baz" == Nothing
1366+commonPrefixes :: Text -> Text -> Maybe (Text,Text,Text)
1367+commonPrefixes Empty _ = Nothing
1368+commonPrefixes _ Empty = Nothing
1369+commonPrefixes a0 b0 = Just (go a0 b0 [])
1371+ go t0@(Chunk x xs) t1@(Chunk y ys) ps
1372+ = case T.commonPrefixes x y of
1374+ | T.null a -> go xs (chunk b ys) (p:ps)
1375+ | T.null b -> go (chunk a xs) ys (p:ps)
1376+ | otherwise -> (fromChunks (L.reverse (p:ps)),chunk a xs, chunk b ys)
1377+ Nothing -> (fromChunks (L.reverse ps),t0,t1)
1378+ go t0 t1 ps = (fromChunks (L.reverse ps),t0,t1)
1351−-- | /O(n)/ Returns the prefix of the second string if its suffix
1380+-- | /O(n)/ Return the prefix of the second string if its suffix
1352−-- matches the first.
1381+-- matches the entire first string.
1354-- Examples:
1383-- Examples:
1356-- > stripSuffix "bar" "foobar" == Just "foo"
1385-- > stripSuffix "bar" "foobar" == Just "foo"
1386+-- > stripSuffix "" "baz" == Just "baz"
1357-- > stripSuffix "foo" "quux" == Nothing
1387-- > stripSuffix "foo" "quux" == Nothing
1359-- This is particularly useful with the @ViewPatterns@ extension to
1389-- This is particularly useful with the @ViewPatterns@ extension to
1360-- GHC, as follows:
1390-- GHC, as follows:
1362-- > {-# LANGUAGE ViewPatterns #-}
1392-- > {-# LANGUAGE ViewPatterns #-}
1363−-- > import Data.Text as T
1393+-- > import Data.Text.Lazy as T
1365-- > quuxLength :: Text -> Int
1395-- > quuxLength :: Text -> Int
1366-- > quuxLength (stripSuffix "quux" -> Just pre) = T.length pre
1396-- > quuxLength (stripSuffix "quux" -> Just pre) = T.length pre
1367−-- > quuxLength _ = -1
1397+-- > quuxLength _ = -1
1368stripSuffix :: Text -> Text -> Maybe Text
1398stripSuffix :: Text -> Text -> Maybe Text
1369−-- Yes, this could be much more efficient.
1370−stripSuffix p t
1399+stripSuffix p t = reverse `fmap` stripPrefix (reverse p) (reverse t)
1371− | p `isSuffixOf` t = Just (take (length t - length p) t)
1372− | otherwise = Nothing
1374-- | /O(n)/ 'filter', applied to a predicate and a 'Text',
1401-- | /O(n)/ 'filter', applied to a predicate and a 'Text',
1375-- returns a 'Text' containing those characters that satisfy the
1402-- returns a 'Text' containing those characters that satisfy the