@@ -110,6 +110,7 @@ module Data.Text
110110
111111 -- ** Breaking into lines and words
112112 , lines
113+ , lines'
113114 , words
114115 , unlines
115116 , unwords
@@ -143,7 +144,7 @@ module Data.Text
143144 ) where
144145
145146import Prelude (Char, Bool(..), Functor(..), Int, Maybe(..), String,
146− Eq, (==), (++),
147+ Eq(..), (++),
147148 Read(..), Show(..),
148149 (&&), (||), (+), (-), (<), (>), (<=), (>=), (.), ($),
149150 not, return, otherwise)
@@ -904,16 +905,34 @@ words t@(Text arr off len) = loop 0 0
904905
905906-- | /O(n)/ Breaks a 'Text' up into a list of 'Text's at
906907-- newline 'Char's. The resulting strings do not contain newlines.
907−--
908908lines :: Text -> [Text]
909−lines ps
910− | null ps = []
911− | otherwise = case search ps of
912− Nothing -> [ps]
913− Just n -> take n ps : lines (drop (n+1) ps)
914− where search = elemIndex '\n'
909+lines ps | null ps = []
910+ | otherwise = h : if null t
911+ then []
912+ else lines (unsafeTail t)
913+ where (h,t) = span (/= '\n') ps
915914{-# INLINE lines #-}
916915
916+-- | /O(n)/ Portably breaks a 'Text' up into a list of 'Text's at line
917+-- boundaries.
918+--
919+-- A line boundary is considered to be either a line feed, a carriage
920+-- return immediately followed by a line feed, or a carriage return.
921+-- This accounts for both Unix and Windows line ending conventions,
922+-- and for the old convention used on Mac OS 9 and earlier.
923+lines' :: Text -> [Text]
924+lines' ps | null ps = []
925+ | otherwise = h : case uncons t of
926+ Nothing -> []
927+ Just (c,t')
928+ | c == '\n' -> lines t'
929+ | c == '\r' -> case uncons t' of
930+ Just ('\n',t'') -> lines t''
931+ _ -> lines t'
932+ where (h,t) = span notEOL ps
933+ notEOL c = c /= '\n' && c /= '\r'
934+{-# INLINE lines' #-}
935+
917936-- | /O(n)/ Joins lines, after appending a terminating newline to
918937-- each.
919938unlines :: [Text] -> Text