Browse Source

Ready for version 1.1.1.0

Marcos Dumay de Medeiros 6 years ago
parent
commit
36c7ac4c17
3 changed files with 91 additions and 49 deletions
  1. 11 46
      src/System/IO/Uniform/Streamline.hs
  2. 76 0
      src/System/IO/Uniform/Streamline/Scanner.hs
  3. 4 3
      uniform-io.cabal

+ 11 - 46
src/System/IO/Uniform/Streamline.hs

@@ -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

+ 76 - 0
src/System/IO/Uniform/Streamline/Scanner.hs

@@ -0,0 +1,76 @@
+module System.IO.Uniform.Streamline.Scanner where
+
+import Control.Applicative
+import Data.Default.Class
+import Data.Word8 (Word8)
+
+-- | 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
+
+instance Functor IOScannerState where
+  fmap _ Finished = Finished
+  fmap f (LastPass x) = LastPass $ f x
+  fmap f (Running x) = Running $ f x
+instance Applicative IOScannerState where
+  pure a = Running a
+  Finished <*> _ = Finished
+  _ <*> Finished = Finished
+  (LastPass f) <*> (LastPass x) = LastPass $ f x
+  (LastPass f) <*> (Running x) = LastPass $ f x
+  (Running f) <*> (LastPass x) = LastPass $ f x
+  (Running f) <*> (Running x) = Running $ f x
+instance Monad IOScannerState where
+  return = pure
+  Finished >>= _ = Finished
+  (LastPass x) >>= f = case f x of
+    Finished -> Finished
+    LastPass y -> LastPass y
+    Running y -> LastPass y
+  (Running x) >>= f = f x
+
+type IOScanner a = a -> Word8 -> IOScannerState a
+
+anyScanner :: Default a => [IOScanner a] -> IOScanner [a]
+anyScanner scanners = scan
+  where
+    --scan :: IOScanner [a]
+    scan st c = sequence $ apScanner scanners st c
+    --apScanner :: [IOScanner a] -> [a] -> Word8 -> [IOScannerState a]
+    apScanner [] _ _ = []
+    apScanner (s:ss) [] h = s def h : apScanner ss [] h
+    apScanner (s:ss) (t:tt) h = s t h : apScanner ss tt h
+
+
+textScanner :: [Word8] -> (IOScanner [[Word8]])
+textScanner [] = \_ _ -> Finished
+textScanner t@(c:_) = scanner
+  where
+    scanner st c'
+      | c == c' = popStacks (t:st) c'
+      | otherwise = popStacks st c'
+    popStacks :: IOScanner [[Word8]]
+    popStacks [] _ = Running []
+    popStacks ([]:_) _ = Finished
+    popStacks ((h':hh):ss) h
+      | h == h' && null hh = case popStacks ss h of
+        Finished -> Finished
+        LastPass ss' -> LastPass $ ss'
+        Running ss' -> LastPass $ ss'
+      | h == h' = case popStacks ss h of
+        Finished -> Finished
+        LastPass ss' -> LastPass $ hh:ss'
+        Running ss' -> Running $ hh:ss'
+      | otherwise = popStacks ss h

+ 4 - 3
uniform-io.cabal

@@ -10,7 +10,7 @@ name:                uniform-io
 -- PVP summary:      +-+------- breaking API changes
 --                   | | +----- non-breaking API additions
 --                   | | | +--- code changes with no API change
-version:    1.1.0.0
+version:    1.1.1.0
 
 -- A short (one-line) description of the package.
 synopsis:   Uniform IO over files, network, anything.
@@ -70,7 +70,7 @@ source-repository head
 source-repository this
   type:     git
   location: https://sealgram.com/git/haskell/uniform-io
-  tag:   1.1.0.0
+  tag:   1.1.1.0
 
 library
   -- Modules exported by the library.
@@ -80,7 +80,8 @@ library
       System.IO.Uniform.File,
       System.IO.Uniform.Std,
       System.IO.Uniform.ByteString,
-      System.IO.Uniform.Streamline
+      System.IO.Uniform.Streamline,
+      System.IO.Uniform.Streamline.Scanner
 
   ghc-options: -Wall -fno-warn-unused-do-bind -fwarn-incomplete-patterns -fno-warn-orphans