packages feed

netlines 0.2.1 → 0.3.0

raw patch · 3 files changed

+195/−142 lines, 3 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Network.NetLines: enumHandleTimeout :: MonadIO m => Int -> Int -> Handle -> Enumerator ByteString m b
- Network.NetLines: netLine :: Monad m => Int -> MaybeT r (Iteratee ByteString m) ByteString
- Network.NetLines: netLineEmpty :: Monad m => Int -> MaybeT r (Iteratee ByteString m) ByteString
- Network.NetLines: netLines :: Monad m => Int -> Enumeratee ByteString ByteString m b
- Network.NetLines: netLinesEmpty :: Monad m => Int -> Enumeratee ByteString ByteString m b
+ Data.Enumerator.NetLines: enumHandleTimeout :: MonadIO m => Int -> Int -> Handle -> Enumerator ByteString m b
+ Data.Enumerator.NetLines: netLine :: Monad m => Int -> Iteratee ByteString m (Maybe ByteString)
+ Data.Enumerator.NetLines: netLineEmpty :: Monad m => Int -> Iteratee ByteString m (Maybe ByteString)
+ Data.Enumerator.NetLines: netLines :: Monad m => Int -> Enumeratee ByteString ByteString m b
+ Data.Enumerator.NetLines: netLinesEmpty :: Monad m => Int -> Enumeratee ByteString ByteString m b
+ Data.Enumerator.NetLines: netSplitBy :: Monad m => (Word8 -> Bool) -> (Word8 -> Bool) -> Int -> Iteratee ByteString m (Maybe ByteString)
+ Data.Enumerator.NetLines: netSplitsBy :: Monad m => Iteratee ByteString m (Maybe ByteString) -> Enumeratee ByteString ByteString m b
+ Data.Enumerator.NetLines: netWord :: Monad m => Int -> Iteratee ByteString m (Maybe ByteString)
+ Data.Enumerator.NetLines: netWordEmpty :: Monad m => Int -> Iteratee ByteString m (Maybe ByteString)
+ Data.Enumerator.NetLines: netWords :: Monad m => Int -> Enumeratee ByteString ByteString m b
+ Data.Enumerator.NetLines: netWordsEmpty :: Monad m => Int -> Enumeratee ByteString ByteString m b

Files

+ Data/Enumerator/NetLines.hs view
@@ -0,0 +1,192 @@+-- |+-- Module:     Data.Enumerator.NetLines+-- Copyright:  (c) 2010 Ertugrul Soeylemez+-- License:    BSD3+-- Maintainer: Ertugrul Soeylemez <es@ertes.de>+-- Stability:  beta+--+-- Enumerator tools for working with text-based network protocols.++{-# LANGUAGE ScopedTypeVariables #-}++module Data.Enumerator.NetLines+    ( -- * Iteratees+      netLine,+      netLineEmpty,+      netWord,+      netWordEmpty,++      -- * Enumeratees+      netLines,+      netLinesEmpty,+      netWords,+      netWordsEmpty,++      -- * General stream splitters+      netSplitBy,+      netSplitsBy,++      -- * Enumerators+      enumHandleTimeout+    )+    where++import qualified Data.ByteString as B+import Control.Arrow+import Control.ContStuff as Monad+import Data.ByteString (ByteString)+import Data.Enumerator as E+import Data.Word+import System.IO+import System.IO.Error as IOErr+++-- | Enumerate from a handle with the given buffer size (first argument)+-- and timeout in milliseconds (second argument).  If the timeout is+-- exceeded an exception is thrown via 'throwError'.++enumHandleTimeout :: forall b m. MonadIO m =>+                     Int -> Int -> Handle -> Enumerator ByteString m b+enumHandleTimeout bufSize timeout h = loop+    where+    loop :: Enumerator ByteString m b+    loop (Continue k) = do+          mHaveInput <- liftIO $ IOErr.try (hWaitForInput h timeout)+          case mHaveInput of+            Left err+                | isEOFError err -> continue k+                | otherwise      -> throwError err+            Right False -> throwError $ userError "Handle timed out"+            Right True  -> do+                mStr <- liftIO $ IOErr.try (B.hGetNonBlocking h bufSize)+                str <- either throwError return mStr+                if B.null str+                  then continue k+                  else k (Chunks [str]) >>== loop+    loop step = returnI step+++-- | Predicate for ASCII vertical whitespace.++isSpace :: Word8 -> Bool+isSpace n = n == 32 || (n >= 9 && n <= 13)+++-- | Get the next nonempty line from the stream using 'netLineEmpty'.++netLine :: forall m. Monad m => Int -> Iteratee ByteString m (Maybe ByteString)+netLine = nonEmpty . netLineEmpty++-- | Get the next line from the stream, length-limited by the given+-- 'Int'.  This iteratee is error-tolerant by using LF as the line+-- terminator and simply ignoring all CR characters.++netLineEmpty :: Monad m => Int -> Iteratee ByteString m (Maybe ByteString)+netLineEmpty = netSplitBy (== 10) (/= 13)+++-- | Convert a raw byte stream to a stream of lines based on 'netLine'.++netLines :: Monad m => Int -> Enumeratee ByteString ByteString m b+netLines = netSplitsBy . netLine+++-- | Convert a raw byte stream to a stream of lines based on+-- 'netLineEmpty'.++netLinesEmpty :: Monad m => Int -> Enumeratee ByteString ByteString m b+netLinesEmpty = netSplitsBy . netLineEmpty+++-- | Get the next token, where tokens are splitted by the first given+-- predicate and filtered by the second.  Tokens are length-limited by+-- the given 'Int' and are truncated safely in constant space.++netSplitBy ::+    forall m. Monad m =>+    (Word8 -> Bool) ->+    (Word8 -> Bool) ->+    Int ->+    Iteratee ByteString m (Maybe ByteString)+netSplitBy breakP filterP n =+    continue (loop n)++    where+    loop :: Int -> Stream ByteString -> Iteratee ByteString m (Maybe ByteString)+    loop _ EOF = return Nothing+    loop n (Chunks []) = continue (loop n)+    loop n (Chunks strs)+        | B.null str = continue (loop n)+        | otherwise = do+            case (B.null line1, B.null line2') of+              (True, True) -> yield Nothing EOF+              (False, True) ->+                  case n of+                    0 -> continue (loop 0)+                    _ -> seq pfx $+                         continue (loop (n - B.length pfx) >=>+                                   maybe (yield (Just pfx) EOF)+                                         (return . Just . B.append pfx))+              (_, False) -> yield (Just pfx) (Chunks [line2])++        where+        str             = B.concat strs+        (line1, line2') = B.break breakP str+        (pfx, _)        = first (B.filter filterP) $ B.splitAt n line1+        line2           = B.tail line2'+++-- | Split the stream using the supplied iteratee.++netSplitsBy ::+    forall b m. Monad m =>+    Iteratee ByteString m (Maybe ByteString) -> Enumeratee ByteString ByteString m b+netSplitsBy getLine = loop+    where+    loop :: Enumeratee ByteString ByteString m b+    loop (Continue k) = do+        mLine <- getLine+        case mLine of+          Just line -> k (Chunks [line]) >>== loop+          Nothing   -> k EOF >>== loop+    loop step = return step+++-- | Get the next nonempty word from the stream with the given maximum+-- length.  Based on 'netWordEmpty'.++netWord :: Monad m => Int -> Iteratee ByteString m (Maybe ByteString)+netWord = nonEmpty . netWordEmpty+++-- | Get the next word from the stream with the given maximum length.+-- This iteratee is error-tolerant by using ASCII whitespace as+-- splitting characters.++netWordEmpty :: Monad m => Int -> Iteratee ByteString m (Maybe ByteString)+netWordEmpty = netSplitBy isSpace (const True)+++-- | Split the raw byte stream into words based on 'netWord'.++netWords :: Monad m => Int -> Enumeratee ByteString ByteString m b+netWords = netSplitsBy . netWord+++-- | Split the raw byte stream into words based on 'netWords'.++netWordsEmpty :: Monad m => Int -> Enumeratee ByteString ByteString m b+netWordsEmpty = netSplitsBy . netWordEmpty+++-- | Apply the given iteratee, until it returns a nonempty line.++nonEmpty ::+    forall a m. Monad m =>+    Iteratee a m (Maybe ByteString) -> Iteratee a m (Maybe ByteString)+nonEmpty getStr = evalMaybeT loop+    where+    loop :: MaybeT r (Iteratee a m) ByteString+    loop = do+        line <- liftF getStr+        if B.null line then loop else return line
− Network/NetLines.hs
@@ -1,139 +0,0 @@--- |--- Module:     Network.NetLines--- Copyright:  (c) 2010 Ertugrul Soeylemez--- License:    BSD3--- Maintainer: Ertugrul Soeylemez <es@ertes.de>--- Stability:  experimental------ Enumerator tools for working with text-based network protocols.--{-# LANGUAGE ScopedTypeVariables #-}--module Network.NetLines-    ( -- * Conversion to lines-      netLine,-      netLines,--      -- * Conversion to sparse lines-      netLineEmpty,-      netLinesEmpty,--      -- * Enumerators-      enumHandleTimeout-    )-    where--import qualified Data.ByteString as B-import Control.ContStuff as Monad-import Data.ByteString (ByteString)-import Data.Enumerator as E-import Data.Enumerator.Binary as EB-import Data.Word-import System.IO-import System.IO.Error as IOErr----- | Enumerate from a handle with the given buffer size (first argument)--- and timeout in milliseconds (second argument).  If the timeout is--- exceeded an exception is thrown via 'throwError'.--enumHandleTimeout :: forall b m. MonadIO m =>-                     Int -> Int -> Handle -> Enumerator ByteString m b-enumHandleTimeout bufSize timeout h = loop-    where-    loop :: Enumerator ByteString m b-    loop (Continue k) = do-          mHaveInput <- liftIO $ IOErr.try (hWaitForInput h timeout)-          case mHaveInput of-            Left err-                | isEOFError err -> continue k-                | otherwise      -> throwError err-            Right False -> throwError $ userError "Handle timed out"-            Right True  -> do-                mStr <- liftIO $ IOErr.try (B.hGetNonBlocking h bufSize)-                str <- either throwError return mStr-                if B.null str-                  then continue k-                  else k (Chunks [str]) >>== loop-    loop step = returnI step----- | Predicate whether the given byte is a line terminator (includes CR--- and LF).--isEol :: Word8 -> Bool-isEol c = c == 10 || c == 13----- | Predicate whether the given byte is an LF line terminator.--isNotEol :: Word8 -> Bool-isNotEol = not . isEol----- | Savely read a line with the given maximum length.  If a longer line--- is enumerated, the excess data is dropped in constant space.  Returns--- 'Nothing' on EOF.------ Please note that this function is very error-tolerant in the way it--- handles line endings.  Both CR and LF are proper line terminators.--- This function ignores empty lines.--netLine :: forall m r. Monad m => Int -> MaybeT r (Iteratee ByteString m) ByteString-netLine n =-    lift (EB.dropWhile isEol) >> netLine' n--    where-    netLine' :: Int -> MaybeT r (Iteratee ByteString m) ByteString-    netLine' 0 = B.empty <$ lift (EB.dropWhile isNotEol)-    netLine' n = do-        c <- liftF EB.head-        if isNotEol c-          then B.cons c <$> netLine' (n-1)-          else return B.empty----- | Variant of 'netLine', which supports empty lines, useful for--- protocols like HTTP, in which empty lines have a special meaning.--- This function splits the input stream by LF characters while ignoring--- CR characters.--netLineEmpty :: Monad m => Int -> MaybeT r (Iteratee ByteString m) ByteString-netLineEmpty 0 = B.empty <$ lift (EB.dropWhile (/= 10) >> EB.head)-netLineEmpty n = do-    c <- liftF EB.head-    case c of-      10 -> return B.empty-      13 -> netLineEmpty (n-1)-      _  -> B.cons c <$> netLineEmpty (n-1)----- | Convert a stream of bytes to a stream of lines with the given--- maximum length.  Longer lines are silently truncated in constant--- space.--netLines :: forall b m. Monad m => Int -> Enumeratee ByteString ByteString m b-netLines maxLen = loop-    where-    loop :: Enumeratee ByteString ByteString m b-    loop (Continue k) = do-        mLine <- evalMaybeT $ netLine maxLen-        case mLine of-          Just line -> k (Chunks [line]) >>== loop-          Nothing   -> k EOF >>== loop-    loop step = return step----- | This is the same like 'netLines', but is based on 'netLinesEmpty'--- to support empty lines.--netLinesEmpty :: forall b m. Monad m => Int -> Enumeratee ByteString ByteString m b-netLinesEmpty maxLen = loop-    where-    loop :: Enumeratee ByteString ByteString m b-    loop (Continue k) = do-        mLine <- evalMaybeT (netLineEmpty maxLen)-        case mLine of-          Just line -> k (Chunks [line]) >>== loop-          Nothing   -> k EOF >>== loop-    loop step = return step
netlines.cabal view
@@ -1,5 +1,5 @@ Name:          netlines-Version:       0.2.1+Version:       0.3.0 Category:      Network Synopsis:      Enumerator tools for text-based network protocols Maintainer:    Ertugrul Söylemez <es@ertes.de>@@ -8,7 +8,7 @@ License:       BSD3 License-file:  LICENSE Build-type:    Simple-Stability:     experimental+Stability:     beta Cabal-version: >= 1.6 Description: @@ -25,7 +25,7 @@         enumerator >= 0.4.7     GHC-Options: -W     Exposed-modules:-        Network.NetLines+        Data.Enumerator.NetLines  -- Executable netlines-test --     Build-depends: