module Data.Iteratee.Char (
printLines
,printLinesUnterminated
,enumLines
,enumLinesBS
,enumWords
,enumWordsBS
)
where
import Data.Iteratee.Iteratee
import qualified Data.Iteratee.ListLike as I
import Data.Iteratee.ListLike (heads)
import Data.Char
import Data.Monoid
import qualified Data.ListLike as LL
import Control.Monad (liftM)
import Control.Monad.IO.Class
import qualified Data.ByteString.Char8 as BC
printLines :: Iteratee String IO ()
printLines = lines'
where
lines' = I.break (`elem` "\r\n") >>= \l -> terminators >>= check l
check _ 0 = return ()
check "" _ = return ()
check l _ = liftIO (putStrLn l) >> lines'
printLinesUnterminated :: forall s el.
(Eq el, Nullable s, LL.StringLike s, LL.ListLike s el)
=> Iteratee s IO ()
printLinesUnterminated = lines'
where
lines' = do
joinI $ I.breakE (`LL.elem` t1) (I.mapChunksM_ (putStr . LL.toString))
terminators >>= check
check 0 = return ()
check _ = liftIO (putStrLn "") >> lines'
t1 :: s
t1 = LL.fromString "\r\n"
terminators :: (Eq el, Nullable s, LL.StringLike s, LL.ListLike s el)
=> Iteratee s IO Int
terminators = do
l <- heads (LL.fromString "\r\n")
if l == 0 then heads (LL.fromString "\n") else return l
enumLines
:: (LL.ListLike s el, LL.StringLike s, Nullable s, Monad m) =>
Enumeratee s [s] m a
enumLines = convStream getter
where
getter = icont step Nothing
lChar = (== '\n') . last . LL.toString
step (Chunk xs)
| LL.null xs = getter
| lChar xs = idone (LL.lines xs) mempty
| otherwise = icont (step' xs) Nothing
step _str = getter
step' xs (Chunk ys)
| LL.null ys = icont (step' xs) Nothing
| lChar ys = idone (LL.lines . mappend xs $ ys) mempty
| otherwise = let w' = LL.lines $ mappend xs ys
ws = init w'
ck = last w'
in idone ws (Chunk ck)
step' xs str = idone (LL.lines xs) str
enumWords :: (LL.ListLike s Char, Nullable s, Monad m) => Enumeratee s [s] m a
enumWords = convStream $ I.dropWhile isSpace >> liftM (:[]) (I.break isSpace)
enumWordsBS
:: (Monad m) => Enumeratee BC.ByteString [BC.ByteString] m a
enumWordsBS iter = convStream getter iter
where
getter = liftI step
lChar = isSpace . BC.last
step (Chunk xs)
| BC.null xs = getter
| lChar xs = idone (BC.words xs) (Chunk BC.empty)
| otherwise = icont (step' xs) Nothing
step str = idone mempty str
step' xs (Chunk ys)
| BC.null ys = icont (step' xs) Nothing
| lChar ys = idone (BC.words . BC.append xs $ ys) mempty
| otherwise = let w' = BC.words . BC.append xs $ ys
ws = init w'
ck = last w'
in idone ws (Chunk ck)
step' xs str = idone (BC.words xs) str
enumLinesBS :: (Monad m) => Enumeratee BC.ByteString [BC.ByteString] m a
enumLinesBS = convStream getter
where
getter = icont step Nothing
lChar = (== '\n') . BC.last
step (Chunk xs)
| BC.null xs = getter
| lChar xs = idone (BC.lines xs) (Chunk BC.empty)
| otherwise = icont (step' xs) Nothing
step str = idone mempty str
step' xs (Chunk ys)
| BC.null ys = icont (step' xs) Nothing
| lChar ys = idone (BC.lines . BC.append xs $ ys) mempty
| otherwise = let w' = BC.lines $ BC.append xs ys
ws = init w'
ck = last w'
in idone ws (Chunk ck)
step' xs str = idone (BC.lines xs) str