diff --git a/Data/ByteString/Char8.hs b/Data/ByteString/Char8.hs index 070d0864e..c9ec666f1 100644 --- a/Data/ByteString/Char8.hs +++ b/Data/ByteString/Char8.hs @@ -282,7 +282,7 @@ import Data.ByteString.ReadNat import Data.Char ( isSpace ) -- See bytestring #70 import GHC.Char (eqChar) -import qualified Data.List as List (concatMap) +import qualified Data.List as List import System.IO (Handle,stdout) import Foreign @@ -965,10 +965,21 @@ lines (BS x l) = go x l else return [BS f i] -} --- | 'unlines' is an inverse operation to 'lines'. It joins lines, --- after appending a terminating newline to each. +-- | 'unlines' joins lines, appending a terminating newline after each. +-- +-- Equivalent to +-- @'concat' . Data.List.concatMap (\\x -> [x, 'singleton' \'\\n'])@. unlines :: [ByteString] -> ByteString -unlines = concat . List.concatMap (\x -> [x, singleton '\n']) +unlines = \li -> let + totLen = List.foldl' (\acc s -> acc +! length s +! 1) 0 li + (+!) = checkedAdd "Char8.unlines" + + go [] _ = pure () + go (BS srcFP len : srcs) dest = do + unsafeWithForeignPtr srcFP $ \src -> memcpy dest src len + pokeElemOff dest len (c2w '\n') + go srcs $ dest `plusPtr` (len + 1) + in unsafeCreate totLen (go li) -- | 'words' breaks a ByteString up into a list of words, which -- were delimited by Chars representing white space. diff --git a/Data/ByteString/Lazy/Char8.hs b/Data/ByteString/Lazy/Char8.hs index ee7325278..9dd647494 100644 --- a/Data/ByteString/Lazy/Char8.hs +++ b/Data/ByteString/Lazy/Char8.hs @@ -908,10 +908,12 @@ lines (Chunk c0 cs0) = loop0 c0 cs0 let !c' = revChunks (B.unsafeTake n c : line) in c' : loop0 (B.unsafeDrop (n+1) c) cs --- | 'unlines' is an inverse operation to 'lines'. It joins lines, --- after appending a terminating newline to each. +-- | 'unlines' joins lines, appending a terminating newline after each. +-- +-- Equivalent to +-- @'concat' . Data.List.concatMap (\\x -> [x, 'singleton' \'\\n'])@. unlines :: [ByteString] -> ByteString -unlines = concat . List.concatMap (\x -> [x, singleton '\n']) +unlines = List.foldr (\x t -> x `append` cons '\n' t) Empty -- | 'words' breaks a ByteString up into a list of words, which -- were delimited by Chars representing white space. And