packages feed

machines-bytestring (empty) → 0.1.0.0

raw patch · 5 files changed

+224/−0 lines, 5 filesdep +basedep +bytestringdep +machinessetup-changed

Dependencies added: base, bytestring, machines

Files

+ ChangeLog.md view
@@ -0,0 +1,5 @@+# Revision history for machines-bitestring++## 0.1.0.0++* initial release
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2017, Claudio Zanasi++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * Redistributions in binary form must reproduce the above+      copyright notice, this list of conditions and the following+      disclaimer in the documentation and/or other materials provided+      with the distribution.++    * Neither the name of Claudio Zanasi nor the names of other+      contributors may be used to endorse or promote products derived+      from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ machines-bytestring.cabal view
@@ -0,0 +1,25 @@+name:                machines-bytestring+version:             0.1.0.0+cabal-version:       >=1.10+build-type:          Simple+synopsis:            ByteString support for machines+description:         @machines@ utilities to work with @ByteString@+license:             BSD3+license-file:        LICENSE+author:              Claudio Zanasi+maintainer:          claudio.zan@outlook.com+copyright:           2017 Claudio Zanasi+category:            Control, Machines+extra-source-files:  ChangeLog.md+Source-Repository head+    Type: git+    Location: https://github.com/zclod/machines-bytestring++library+  exposed-modules:     Data.Machine.ByteString+  hs-source-dirs:      src+  default-language:    Haskell2010+  GHC-Options:         -Wall -O2+  build-depends:       base       >= 4    && < 5,+                       bytestring >= 0.10 && < 0.11,+                       machines   >= 0.6  && < 0.7
+ src/Data/Machine/ByteString.hs view
@@ -0,0 +1,162 @@+{-# LANGUAGE Rank2Types #-}+module Data.Machine.ByteString (+  -- * Sources+  fromLazy,+  fromStrict,+  fromHandle,+  hGet,+  hGetSome,+  hGetNonBlocking,+  -- * Sinks+  stdin,+  stdout,+  stderr,+  toHandle,+  interact,+  -- * Processes+  mapping,+  filtered,+  taking,+  takingWhile,+  scan,+  -- Stream Transformation+  pack,+  unpack+  ) where++import           Data.Word (Word8)+import           Data.Machine hiding (filtered, mapping, taking, takingWhile, scan)+import           Data.ByteString (ByteString)+import qualified Data.ByteString as B+import           Data.ByteString.Unsafe (unsafeTake)+import           Data.ByteString.Lazy.Builder.Extras (defaultChunkSize)+import qualified Data.ByteString.Lazy as BL+import qualified System.IO as IO+import           Control.Monad.IO.Class (MonadIO(..))+import           Prelude hiding (interact)++-- | Transform a lazy ByteString into a 'Source' of strict 'ByteString'.+fromLazy :: BL.ByteString -> Source ByteString+fromLazy bs = construct $ BL.foldrChunks (\e a -> yield e >> a) (pure ()) bs++-- | Use a strict ByteString as Source+fromStrict :: ByteString -> Source ByteString+fromStrict bs = construct $ yield bs++-- | Use an 'Handle' to create a 'Source' of strict 'ByteString'.+fromHandle :: MonadIO m => IO.Handle -> SourceT m ByteString+fromHandle = hGetSome defaultChunkSize++-- | Read chunks of strict 'ByteString' of fixed size.+hGet :: MonadIO m => Int -> IO.Handle -> SourceT m ByteString+hGet size h = repeatedly $ do+  bs <- liftIO (B.hGet h size)+  if B.null bs+     then pure ()+     else yield bs++-- | Like 'hGet' but may be returned smaller chunks if there are not enough+-- data immediately available.+hGetSome :: MonadIO m => Int -> IO.Handle -> SourceT m ByteString+hGetSome size h = repeatedly $ do+  bs <- liftIO (B.hGetSome h size)+  if B.null bs+     then pure ()+     else yield bs++-- | Similar to 'hGet' but it will never block waiting for data.+hGetNonBlocking :: MonadIO m => Int -> IO.Handle -> SourceT m ByteString+hGetNonBlocking size h = repeatedly $ do+  eof <- liftIO (IO.hIsEOF h)+  if eof+     then pure ()+     else liftIO (B.hGetNonBlocking h size)>>= yield++-- | Source that stream bytes from 'stdin'+stdin :: MonadIO m => SourceT m ByteString+stdin = fromHandle IO.stdin++-- | Create a 'Machine' that stream its input to the given 'Handle'+toHandle :: MonadIO m => IO.Handle -> MachineT m (Is ByteString) ()+toHandle h = autoM (liftIO . B.hPut h)++-- | Stream data to 'stdout'+stdout :: MonadIO m => MachineT m (Is ByteString) ()+stdout = toHandle IO.stdout++-- | Stream data to 'stderr'+stderr :: MonadIO m => MachineT m (Is ByteString) ()+stderr = toHandle IO.stderr++-- | Use a @Process ByteString ByteString@ to transform the input from+-- 'stdin' and output to 'stdout'+interact :: Process ByteString ByteString -> IO ()+interact p = runT_ $ stdin ~> p ~> stdout++-- | Transform every byte of a 'ByteString'+mapping :: (Word8 -> Word8) -> Process ByteString ByteString+mapping f = auto $ B.map f++-- | Allow to pass only the bytes that satisfy the predicate+filtered :: (Word8 -> Bool) -> Process ByteString ByteString+filtered p = auto $ B.filter p++-- | Stream only the first n bytes+taking :: Integral n => n -> Process ByteString ByteString+taking n0 = construct $ go n0+  where+    go n+        | n <= 0 = pure ()+        | otherwise = do+          bs <- await+          let len = fromIntegral (B.length bs)+          if len > n+             then yield (unsafeTake (fromIntegral n) bs)+             else yield bs >> go (n - len)++-- | Stream bytes until they fail the predicate+takingWhile :: (Word8 -> Bool) -> Process ByteString ByteString+takingWhile p = construct go+  where+    go = do+      bs <- await+      let (prefix, suffix) = B.span p bs+      if B.null suffix+         then yield bs >> go+         else yield prefix++-- Drop the first n bytes+-- dropping :: Integral n => n -> Process ByteString ByteString+-- dropping n = loop n+--   where+--     loop cnt+--       | cnt <= 0  = echo+--       | otherwise = do+--                       bs <- await+--                       let l = B.length bs+--                       if l <= cnt+--                          then loop (cnt - l)+--                          else pure . B.drop l >>= yield >> loop (cnt - l)+++-- | Strict left scan over the bytes+scan :: (Word8 -> Word8 -> Word8) -> Word8 -> Process ByteString ByteString+scan step begin = construct $ do+    yield (B.singleton begin)+    go begin+  where+    go w8 = do+        bs <- await+        let bs' = B.scanl step w8 bs+            w8' = B.last bs'+        yield (B.tail bs')+        go w8'++-- | Convert a stream of strict 'ByteString' into a stream of Bytes+unpack :: Process ByteString Word8+unpack = auto B.unpack ~> asParts++-- | Convert a stream of Bytes into a stream of strict 'ByteString' of+-- size equal to 'defaultChunkSize'+pack :: Process Word8 ByteString+pack = buffered defaultChunkSize ~> auto B.pack