|
@@ -5,7 +5,7 @@
|
|
|
-- character tream IO using high performance block IO.
|
|
|
module System.IO.Uniform.Streamline (
|
|
|
Streamline,
|
|
|
- IOScannerState,
|
|
|
+ IOScannerState(..),
|
|
|
withClient,
|
|
|
withServer,
|
|
|
withTarget,
|
|
@@ -28,12 +28,14 @@ module System.IO.Uniform.Streamline (
|
|
|
runScanner,
|
|
|
runScanner',
|
|
|
scan,
|
|
|
- scan'
|
|
|
+ scan',
|
|
|
+ textScanner
|
|
|
) where
|
|
|
|
|
|
import qualified System.IO.Uniform as S
|
|
|
import qualified System.IO.Uniform.Network as N
|
|
|
import System.IO.Uniform (UniformIO, SomeIO(..), TlsSettings)
|
|
|
+import System.IO.Uniform.Streamline.Scanner
|
|
|
|
|
|
import Control.Monad.Trans.Class
|
|
|
import Control.Applicative
|
|
@@ -144,25 +146,9 @@ send' r = Streamline $ \cl -> do
|
|
|
mapM (writeF cl) dd
|
|
|
return ((), cl)
|
|
|
|
|
|
--- | State of an IO scanner.
|
|
|
--- Differently from a parser scanner, an IO scanner
|
|
|
--- must deal with blocking behavior.
|
|
|
-data IOScannerState a =
|
|
|
- -- | A scanner returns Finished when the current input is not
|
|
|
- -- part of the result, and the scanning must stop before this
|
|
|
- -- input.
|
|
|
- Finished |
|
|
|
- -- | A scanner returns LastPass when the current input is the
|
|
|
- -- last one of the result, and the scanning must stop before
|
|
|
- -- after this input, without consuming more data.
|
|
|
- LastPass a |
|
|
|
- -- | A scanner returns Running when the current input is part
|
|
|
- -- of the result, and the scanning must continue.
|
|
|
- Running a
|
|
|
-
|
|
|
-- | Equivalent to runScanner', but returns a strict, completely
|
|
|
-- evaluated ByteString.
|
|
|
-runScanner :: MonadIO m => s -> (s -> Word8 -> IOScannerState s) -> Streamline m (ByteString, s)
|
|
|
+runScanner :: MonadIO m => s -> IOScanner s -> Streamline m (ByteString, s)
|
|
|
runScanner state scanner = do
|
|
|
(rt, st) <- runScanner' state scanner
|
|
|
return (LBS.toStrict rt, st)
|
|
@@ -179,7 +165,7 @@ Nothing.
|
|
|
|
|
|
Returns the scanned ByteString.
|
|
|
-}
|
|
|
-runScanner' :: MonadIO m => s -> (s -> Word8 -> IOScannerState s) -> Streamline m (LBS.ByteString, s)
|
|
|
+runScanner' :: MonadIO m => s -> IOScanner s -> Streamline m (LBS.ByteString, s)
|
|
|
runScanner' state scanner = Streamline $ \d ->
|
|
|
do
|
|
|
(tx, st, d') <- in_scan d state
|
|
@@ -212,11 +198,11 @@ data ScanResult s = SplitAt Int s | AllInput s
|
|
|
|
|
|
|
|
|
-- | Equivalent to runScanner, but dischards the final state
|
|
|
-scan :: MonadIO m => s -> (s -> Word8 -> IOScannerState s) -> Streamline m ByteString
|
|
|
+scan :: MonadIO m => s -> IOScanner s -> Streamline m ByteString
|
|
|
scan state scanner = fst <$> runScanner state scanner
|
|
|
|
|
|
-- | Equivalent to runScanner', but dischards the final state
|
|
|
-scan' :: MonadIO m => s -> (s -> Word8 -> IOScannerState s) -> Streamline m LBS.ByteString
|
|
|
+scan' :: MonadIO m => s -> IOScanner s -> Streamline m LBS.ByteString
|
|
|
scan' state scanner = fst <$> runScanner' state scanner
|
|
|
|
|
|
-- | Recieves data untill the next end of line (\n or \r\n)
|
|
@@ -383,32 +369,11 @@ lineWithEol = do
|
|
|
r <- A.takeByteString
|
|
|
return (l, r)
|
|
|
|
|
|
+eofError :: MonadIO m => String -> m a
|
|
|
+eofError msg = liftIO . ioError $ mkIOError eofErrorType msg Nothing Nothing
|
|
|
+
|
|
|
lineScanner :: Bool -> Word8 -> Maybe Bool
|
|
|
lineScanner False c
|
|
|
| c == (fromIntegral . C.ord $ '\n') = Just True
|
|
|
| otherwise = Just False
|
|
|
lineScanner True _ = Nothing
|
|
|
-
|
|
|
-eofError :: MonadIO m => String -> m a
|
|
|
-eofError msg = liftIO . ioError $ mkIOError eofErrorType msg Nothing Nothing
|
|
|
-
|
|
|
-textScanner :: [Word8] -> ([[Word8]] -> Word8 -> IOScannerState [[Word8]])
|
|
|
-textScanner [] = \_ _ -> Finished
|
|
|
-textScanner t@(c:_) = scanner
|
|
|
- where
|
|
|
- scanner st c'
|
|
|
- | c == c' = popStacks c' $ t:st
|
|
|
- | otherwise = popStacks c' st
|
|
|
- popStacks :: Word8 -> [[Word8]] -> IOScannerState [[Word8]]
|
|
|
- popStacks _ [] = Running []
|
|
|
- popStacks _ ([]:_) = Finished
|
|
|
- popStacks h ((h':hh):ss)
|
|
|
- | h == h' && null hh = case popStacks h ss of
|
|
|
- Finished -> Finished
|
|
|
- LastPass ss' -> LastPass $ ss'
|
|
|
- Running ss' -> LastPass $ ss'
|
|
|
- | h == h' = case popStacks h ss of
|
|
|
- Finished -> Finished
|
|
|
- LastPass ss' -> LastPass $ hh:ss'
|
|
|
- Running ss' -> Running $ hh:ss'
|
|
|
- | otherwise = popStacks h ss
|