packages feed

streaming-bytestring 0.1.0.3 → 0.1.0.4

raw patch · 3 files changed

+101/−12 lines, 3 files

Files

Data/ByteString/Streaming.hs view
@@ -109,6 +109,13 @@          , concat          -- concat :: Monad m => Stream (ByteString m) m r -> ByteString m r  +    -- * Builders+    +    , toStreamingByteStringWith+    , toStreamingByteString+    , toBuilder+    , concatBuilders+         -- * Building ByteStrings          -- ** Infinite ByteStrings@@ -177,14 +184,16 @@ import qualified Data.ByteString        as S  -- S for strict (hmm...) import qualified Data.ByteString.Internal as S import qualified Data.ByteString.Unsafe as S+import Data.ByteString.Builder.Internal hiding (hPut, defaultChunkSize, empty, append)  import Data.ByteString.Streaming.Internal  import Streaming hiding (concats, unfold, distribute, wrap) import Streaming.Internal (Stream (..)) import qualified Streaming.Prelude as SP -import Control.Monad            (liftM, forever) +import Control.Monad            (liftM, forever)+import Data.Monoid              (Monoid(..)) import Data.Word                (Word8) import Data.Int                 (Int64) import System.IO                (Handle,openBinaryFile,IOMode(..)@@ -1554,3 +1563,74 @@          case e of             Left stream -> loop stream            Right (bs, qbs) -> Step (chunk bs >> fmap loop qbs)+           +{- Take a builder constructed otherwise and convert it to a genuine+   streaming bytestring.  +           +>>>  Q.putStrLn $ Q.toStreamingByteString $ stringUtf8 "哈斯克尔" <> stringUtf8 " " <> integerDec 98+哈斯克尔 98+           +    <https://gist.github.com/michaelt/6ea89ca95a77b0ef91f3 This benchmark> shows its+    indistinguishable performance is indistinguishable from @toLazyByteString@++           +-}++toStreamingByteString+  :: MonadIO m => Builder -> ByteString m ()+toStreamingByteString = toStreamingByteStringWith+ (safeStrategy BI.smallChunkSize BI.defaultChunkSize)+{-#INLINE toStreamingByteString #-}+{-#SPECIALIZE toStreamingByteString :: Builder -> ByteString IO () #-}++{-| Take a builder and convert it to a genuine+   streaming bytestring, using a specific allocation strategy.+-}+toStreamingByteStringWith+   :: MonadIO m =>+      AllocationStrategy -> Builder -> ByteString m ()+toStreamingByteStringWith strategy builder0 = do+       cios <- liftIO (buildStepToCIOS strategy (runBuilder builder0))+       let loop cios0 = case cios0 of+              Yield1 bs io   -> Chunk bs $ do +                    cios1 <- liftIO io +                    loop cios1 +              Finished buf r -> trimmedChunkFromBuffer buf (Empty r)+           trimmedChunkFromBuffer buffer k +              | S.null bs                            = k+              |  2 * S.length bs < bufferSize buffer = Chunk (S.copy bs) k+              | otherwise                            = Chunk bs          k+              where+                bs = byteStringFromBuffer buffer+       loop cios+{-#INLINABLE toStreamingByteStringWith #-}+{-#SPECIALIZE toStreamingByteStringWith ::  AllocationStrategy -> Builder -> ByteString IO () #-}+           +           +{- Concatenate a stream of builders (not a streaming bytestring!) into a single builder.++>>> let aa = yield (integerDec 10000) >> yield (string8 " is a number.") >> yield (char8 '\n')+>>>  hPutBuilder  IO.stdout $ concatBuilders aa+10000 is a number.++-}+concatBuilders :: Stream (Of Builder) IO () -> Builder+concatBuilders p = builder $ \bstep r -> do +  case p of+    Return _          -> runBuilderWith mempty bstep r+    Step (b :> rest)  -> runBuilderWith (b `mappend` concatBuilders rest) bstep r +    Delay m            -> m >>= \p' -> runBuilderWith (concatBuilders p') bstep r+{-#INLINABLE concatBuilders #-}+++{-| A simple construction of a builder from a byte stream.++>>> let aaa = "10000 is a number\n" :: Q.ByteString IO ()+>>>  hPutBuilder  IO.stdout $ toBuilder  aaa+10000 is a number+++-}+toBuilder :: ByteString IO () -> Builder+toBuilder  =  concatBuilders . SP.map byteString . toChunks+{-#INLINABLE toBuilder #-}
Data/ByteString/Streaming/Char8.hs view
@@ -82,6 +82,13 @@      , concat          -- concat :: Monad m => Stream (ByteString m) m r -> ByteString m r  +    -- * Builders+    +    , toStreamingByteString+    , toStreamingByteStringWith+    , toBuilder+    , concatBuilders+         -- * Building ByteStrings      -- ** Infinite ByteStrings@@ -159,7 +166,8 @@ import Data.ByteString.Streaming     (fromLazy, toLazy, toLazy', nextChunk, unconsChunk,      fromChunks, toChunks, fromStrict, toStrict, toStrict', -    concat, distribute, drain,+    concat, distribute, drain, toStreamingByteStringWith,+    toStreamingByteString, toBuilder, concatBuilders,     empty, null, null', length, length', append, cycle,      take, drop, splitAt, intercalate, group, denull,     appendFile, stdout, stdin, fromHandle, toHandle,
streaming-bytestring.cabal view
@@ -1,5 +1,5 @@ name:                streaming-bytestring-version:             0.1.0.3+version:             0.1.0.4 synopsis:            effectful byte steams, or: lazy bytestring done right description:         This is an implementation of effectful, memory-constrained                       bytestrings (byte streams) and functions for streaming @@ -33,12 +33,13 @@                      .                      > data ByteString     = Empty   | Chunk Strict.ByteString ByteString                      .-                     with the minimal effectful variant+                     with the /minimal/ effectful variant:                      .                      > data ByteString m r = Empty r | Chunk Strict.ByteString (ByteString m r) | Go (m (ByteString m r))                      .                      (Constructors are necessarily hidden in internal modules in both cases.) -                     As a lazy bytestring is implemented internally +                     .+                     That's it. As a lazy bytestring is implemented internally                       by a sort of list of strict bytestring chunks, a streaming bytestring is                       simply implemented as a /producer/ or /generator/ of strict bytestring chunks.                      Most operations are defined by simply adding a line to what we find in@@ -102,17 +103,17 @@                      this library depends the @streaming@ library, which is used in place                       of @free@ to express the (streaming) splitting and division of byte streams.                       Those elementary concepts are catastrophically mishandled in the streaming io libraries -                     other than pipes; already the @enumerator@ and @iteratee@ libraries-                     were completely defeated by it: see e.g. the implementation of +                     other than pipes. Already the @enumerator@ and @iteratee@ libraries+                     were completely defeated by it: see e.g. the @enumerator@ implementation of                       <http://hackage.haskell.org/package/enumerator-0.4.20/docs/Data-Enumerator-Text.html#v:splitWhen splitWhen and lines>.                      This will concatenate strict text forever, if that's what is coming-                     in.+                     in.  It becomes torture to express elementary distinctions.                       .                      Though we barely alter signatures in @Data.ByteString.Lazy@ -                     more than is required-                     by the types, the point of view that emerges is very much that of+                     more than is required  by the types, +                     the point of view that emerges is very much that of                      @pipes-bytestring@ and @pipes-group@. In particular-                     we have the correspondences:+                     we have these correspondences:                      .                      > Lazy.splitAt      :: Int -> ByteString              -> (ByteString, ByteString)                      > Streaming.splitAt :: Int -> ByteString m r          -> ByteString m (ByteString m r)@@ -163,4 +164,4 @@    -- hs-source-dirs:         default-language:    Haskell2010-  -- ghc-options: -Wall+  ghc-options: -O2