blaze-builder 0.4.2.1 → 0.4.2.2
raw patch · 28 files changed
+352/−332 lines, 28 filesdep +ghc-primdep ~basedep ~bytestringdep ~textnew-uploaderPVP ok
version bump matches the API change (PVP)
Dependencies added: ghc-prim
Dependency ranges changed: base, bytestring, text
API changes (from Hackage documentation)
Files
- Blaze/ByteString/Builder.hs +2/−2
- Blaze/ByteString/Builder/ByteString.hs +2/−2
- Blaze/ByteString/Builder/Char/Utf8.hs +2/−2
- Blaze/ByteString/Builder/Char8.hs +2/−2
- Blaze/ByteString/Builder/Compat/Write.hs +2/−2
- Blaze/ByteString/Builder/HTTP.hs +6/−2
- Blaze/ByteString/Builder/Html/Utf8.hs +2/−2
- Blaze/ByteString/Builder/Html/Word.hs +2/−2
- Blaze/ByteString/Builder/Int.hs +2/−2
- Blaze/ByteString/Builder/Internal/Write.hs +4/−2
- Blaze/ByteString/Builder/Word.hs +2/−2
- CHANGES +3/−0
- Makefile +7/−10
- README.markdown +16/−19
- benchmarks/BenchThroughput.hs +23/−24
- benchmarks/BlazeVsBinary.hs +3/−3
- benchmarks/BoundedWrite.hs +8/−9
- benchmarks/BuilderBufferRange.hs +25/−25
- benchmarks/ChunkedWrite.hs +25/−26
- benchmarks/Compression.hs +5/−5
- benchmarks/FastPut.hs +42/−43
- benchmarks/LazyByteString.hs +68/−68
- benchmarks/PlotTest.hs +20/−20
- benchmarks/StringAndText.hs +9/−9
- benchmarks/UnboxedAppend.hs +12/−12
- benchmarks/Utf8IO.hs +7/−8
- blaze-builder.cabal +47/−29
- tests/Tests.hs +4/−0
Blaze/ByteString/Builder.hs view
@@ -6,8 +6,8 @@ -- Module: Blaze.ByteString.Builder -- Copyright: (c) 2013 Leon P Smith -- License: BSD3--- Maintainer: Leon P Smith <leon@melding-monads.com>--- Stability: experimental+-- Maintainer: https://github.com/blaze-builder+-- Stability: stable -- -- "Blaze.ByteString.Builder" is the main module, which you should import as a user -- of the @blaze-builder@ library.
Blaze/ByteString/Builder/ByteString.hs view
@@ -3,8 +3,8 @@ -- Module: Blaze.ByteString.Builder.ByteString -- Copyright: (c) 2013 Leon P Smith -- License: BSD3--- Maintainer: Leon P Smith <leon@melding-monads.com>--- Stability: experimental+-- Maintainer: https://github.com/blaze-builder+-- Stability: stable -- -- 'Write's and 'B.Builder's for strict and lazy bytestrings. --
Blaze/ByteString/Builder/Char/Utf8.hs view
@@ -3,8 +3,8 @@ -- Module: Blaze.ByteString.Builder.Char.Utf8 -- Copyright: (c) 2013 Leon P Smith -- License: BSD3--- Maintainer: Leon P Smith <leon@melding-monads.com>--- Stability: experimental+-- Maintainer: https://github.com/blaze-builder+-- Stability: stable -- -- 'Write's and 'Builder's for serializing Unicode characters using the UTF-8 -- encoding.
Blaze/ByteString/Builder/Char8.hs view
@@ -3,8 +3,8 @@ -- Module: Blaze.ByteString.Builder.Char8 -- Copyright: (c) 2013 Leon P Smith -- License: BSD3--- Maintainer: Leon P Smith <leon@melding-monads.com>--- Stability: experimental+-- Maintainer: https://github.com/blaze-builder+-- Stability: stable -- -- //Note:// This package is intended for low-level use like implementing -- protocols. If you need to //serialize// Unicode characters use one of the
Blaze/ByteString/Builder/Compat/Write.hs view
@@ -3,8 +3,8 @@ -- Module: Blaze.ByteString.Builder.Compat.Write -- Copyright: (c) 2013 Leon P Smith -- License: BSD3--- Maintainer: Leon P Smith <leon@melding-monads.com>--- Stability: experimental+-- Maintainer: https://github.com/blaze-builder+-- Stability: stable -- -- Conversions from the new Prims to the old Writes. --
Blaze/ByteString/Builder/HTTP.hs view
@@ -4,8 +4,8 @@ -- Module: Blaze.ByteString.Builder.HTTP -- Copyright: (c) 2013 Simon Meier -- License: BSD3--- Maintainer: Leon P Smith <leon@melding-monads.com>--- Stability: experimental+-- Maintainer: https://github.com/blaze-builder+-- Stability: stable -- -- Support for HTTP response encoding. --@@ -49,7 +49,11 @@ shiftr_w32 :: Word32 -> Int -> Word32 #if defined(__GLASGOW_HASKELL__) && !defined(__HADDOCK__)+#if MIN_VERSION_ghc_prim(0,8,0)+shiftr_w32 (W32# w) (I# i) = W32# (wordToWord32# ((word32ToWord# w) `uncheckedShiftRL#` i))+#else shiftr_w32 (W32# w) (I# i) = W32# (w `uncheckedShiftRL#` i)+#endif #else shiftr_w32 = shiftR #endif
Blaze/ByteString/Builder/Html/Utf8.hs view
@@ -8,8 +8,8 @@ -- Module: Blaze.ByteString.Builder.Html.Utf8 -- Copyright: (c) 2013 Leon P Smith -- License: BSD3--- Maintainer: Leon P Smith <leon@melding-monads.com>--- Stability: experimental+-- Maintainer: https://github.com/blaze-builder+-- Stability: stable -- -- 'Write's and 'Builder's for serializing HTML escaped and UTF-8 encoded -- characters.
Blaze/ByteString/Builder/Html/Word.hs view
@@ -8,8 +8,8 @@ -- Module: Blaze.ByteString.Builder.Html.Word -- Copyright: (c) 2016 Dylan Simon -- License: BSD3--- Maintainer: Leon P Smith <leon@melding-monads.com>--- Stability: experimental+-- Maintainer: https://github.com/blaze-builder+-- Stability: stable -- -- 'W.Write's and 'B.Builder's for serializing HTML escaped 'Word8' characters -- and 'BS.ByteString's that have already been appropriately encoded into HTML by
Blaze/ByteString/Builder/Int.hs view
@@ -3,8 +3,8 @@ -- Module: Blaze.ByteString.Builder.Int -- Copyright: (c) 2013 Leon P Smith -- License: BSD3--- Maintainer: Leon P Smith <leon@melding-monads.com>--- Stability: experimental+-- Maintainer: https://github.com/blaze-builder+-- Stability: stable -- -- 'Write's and 'Builder's for serializing integers. --
Blaze/ByteString/Builder/Internal/Write.hs view
@@ -6,8 +6,8 @@ -- (c) 2010 Jasper van der Jeugt -- License : BSD3-style (see LICENSE) ----- Maintainer : Leon Smith <leon@melding-monads.com>--- Stability : experimental+-- Maintainer : https://github.com/blaze-builder+-- Stability : stable -- Portability : tested on GHC only -- -- A general and efficient write type that allows for the easy construction of@@ -54,7 +54,9 @@ import Data.ByteString.Builder.Internal +#if !MIN_VERSION_base(4,8,0) import Data.Monoid (Monoid(..))+#endif import Data.Semigroup (Semigroup(..)) ------------------------------------------------------------------------------
Blaze/ByteString/Builder/Word.hs view
@@ -3,8 +3,8 @@ -- Module: Blaze.ByteString.Builder.Word -- Copyright: (c) 2013 Leon P Smith -- License: BSD3--- Maintainer: Leon P Smith <leon@melding-monads.com>--- Stability: experimental+-- Maintainer: https://github.com/blaze-builder+-- Stability: stable -- -- 'Write's and 'Builder's for serializing words. --
CHANGES view
@@ -1,3 +1,6 @@+* 0.4.2.2+ - Support GHC 9.2+ * 0.4.2.1 - Bump cabal file to Cabal >= 1.10
Makefile view
@@ -6,12 +6,9 @@ ## Config ######### -GHC6 = ghc-6.12.3-GHC7 = ghc-7.0.2--GHC = $(GHC7)+GHC = ghc -GHCI = ghci-6.12.3+GHCI = ghci ## All benchmarks@@ -51,7 +48,7 @@ ./benchmarks/BlazeVsBinary --resamples 10000 # throughput benchmarks: interactive development-ghci-throughput: benchmarks/Throughput/CBenchmark.o +ghci-throughput: benchmarks/Throughput/CBenchmark.o $(GHCI) -O2 -fforce-recomp -ibenchmarks -main-is BenchThroughput benchmarks/Throughput/CBenchmark.o benchmarks/BenchThroughput.hs bench-throughput: benchmarks/Throughput/CBenchmark.o@@ -146,11 +143,11 @@ clean-tests: rm -f tests/Tests tests/*.o tests/*.hi -ghci-llvm-segfault: - $(GHCI) -itests -main-is LlvmSegfault tests/LlvmSegfault +ghci-llvm-segfault:+ $(GHCI) -itests -main-is LlvmSegfault tests/LlvmSegfault -test-llvm-segfault: - ghc-7.0.0.20100924 --make -fllvm -itests -main-is LlvmSegfault tests/LlvmSegfault +test-llvm-segfault:+ ghc-7.0.0.20100924 --make -fllvm -itests -main-is LlvmSegfault tests/LlvmSegfault ./tests/LlvmSegfault ##############################################################################
README.markdown view
@@ -1,38 +1,35 @@+[](http://hackage.haskell.org/package/blaze-builder)+[](https://stackage.org/nightly/package/blaze-builder)+[](https://www.stackage.org/package/blaze-builder)+[](https://github.com/blaze-builder/blaze-builder/actions)+ blaze-builder ============= -[![Continuous Integration status][status-png]][status]-[![Hackage page (downloads and API reference)][hackage-png]][hackage]- This library allows to efficiently serialize Haskell values to lazy bytestrings with a large average chunk size. The large average chunk size allows to make good use of cache prefetching in later processing steps (e.g. compression) and reduces the system call overhead when writing the resulting lazy bytestring to a file or sending it over the network. -This library was inspired by the module Data.Binary.Builder provided by the-binary package. It was originally developed with the specific needs of the-blaze-html package in mind. Since then it has been restructured to serve as a-drop-in replacement for Data.Binary.Builder, which it improves upon both in+This library was inspired by the module `Data.Binary.Builder` provided by the+`binary` package. It was originally developed with the specific needs of the+`blaze-html` package in mind. Since then it has been restructured to serve as a+drop-in replacement for `Data.Binary.Builder`, which it improves upon both in speed as well as expressivity. To see the improvements in speed, run the throughput benchmark, which measures-serialization speeds for writing Word8, Word16, Word32 and Word64 in different+serialization speeds for writing `Word8`, `Word16`, `Word32` and `Word64` in different endian formats and different chunk sizes, using the command-+``` make bench-throughput-+``` or run the list serialization comparison benchmark-+``` make bench-blaze-vs-binary--Checkout the combinators in the module "Blaze.ByteString.Builder.Write" to see+```+Checkout the combinators in the module `Blaze.ByteString.Builder.Write` to see the improvements in expressivity. This module allows to incorporate efficient primitive buffer manipulations as parts of a builder. We use this facility-in the 'blaze-html' HTML templating library to allow for the efficient+in the `blaze-html` HTML templating library to allow for the efficient serialization of HTML escaped and UTF-8 encoded characters.-- [status-png]: https://api.travis-ci.org/lpsmith/blaze-builder.svg- [status]: http://travis-ci.org/lpsmith/blaze-builder?branch=master- [hackage-png]: http://img.shields.io/hackage/v/blaze-builder.svg- [hackage]: http://hackage.haskell.org/package/blaze-builder
benchmarks/BenchThroughput.hs view
@@ -3,9 +3,9 @@ -- Module : BenchThroughput -- Copyright : Simon Meier -- License : BSD3-style (see LICENSE)--- --- Maintainer : Leon P Smith <leon@melding-monads.com>--- Stability : experimental+--+-- Maintainer : https://github.com/blaze-builder+-- Stability : stable -- Portability : GHC -- -- This benchmark is based on 'tests/Benchmark.hs' from the 'binary-0.5.0.2'@@ -69,32 +69,32 @@ blazeLineStyle = solidLine 1 . opaque binaryLineStyle = dashedLine 1 [5, 5] . opaque -blazeBuilder = +blazeBuilder = ( "BlazeBuilder" , blazeLineStyle green , supportAllSizes $ BlazeBuilder.serialize) -blazeBuilderDecl = +blazeBuilderDecl = ( "BlazeBuilderDecl" , blazeLineStyle blue , supportAllSizes $ BlazeBuilderDecl.serialize) -blazePut = +blazePut = ( "BlazePut" , blazeLineStyle red , supportAllSizes $ BlazePut.serialize) -binaryBuilder = +binaryBuilder = ( "BinaryBuilder" , binaryLineStyle green , supportAllSizes $ BinaryBuilder.serialize) -binaryBuilderDecl = +binaryBuilderDecl = ( "BinaryBuilderDecl" , binaryLineStyle blue , BinaryBuilderDecl.serialize) -binaryPut = +binaryPut = ( "BinaryPut" , binaryLineStyle red , supportAllSizes $ BinaryPut.serialize)@@ -103,11 +103,11 @@ main :: IO () main = do mb <- getArgs >>= readIO . head- -- memBench (mb*10) + -- memBench (mb*10) putStrLn "" putStrLn "Binary serialisation benchmarks:" - -- do bytewise + -- do bytewise -- sequence_ -- [ test wordSize chunkSize Host mb -- | wordSize <- [1]@@ -116,15 +116,15 @@ -- now Word16 .. Word64 let lift f wS cS e i = return $ f wS cS e i- serializers = + serializers = [ blazeBuilder , blazeBuilderDecl , blazePut , binaryBuilder, binaryBuilderDecl, binaryPut ] wordSizes = [1,2,4,8]- chunkSizes = [1,2,4,8,16] + chunkSizes = [1,2,4,8,16] endians = [Host,Big,Little] - let compares = + let compares = [ compareResults serialize wordSize chunkSize end mb | wordSize <- wordSizes , chunkSize <- chunkSizes@@ -136,7 +136,7 @@ -- sequence_ compares - let serializes = + let serializes = [ [ ( serialize , [ (chunkSize, test serialize wordSize chunkSize end mb) | chunkSize <- [1,2,4,8,16]@@ -160,20 +160,20 @@ let plottedLines = flip map lines $ \ ((name,lineStyle,_), points) -> plot_lines_title ^= name $ plot_lines_style ^= lineStyle $- plot_lines_values ^= [points] $ + plot_lines_values ^= [points] $ defaultPlotLines- let layout = + let layout = defaultLayout1 { layout1_plots_ = map (Right . toPlot) plottedLines } return ()- -- renderableToWindow (toRenderable layout) 640 480 + -- renderableToWindow (toRenderable layout) 640 480 measureSerializer :: (a, [(Int, IO (Maybe Double))]) -> IO (Maybe (a, [(Int,Double)])) measureSerializer (info, tests) = do optPoints <- forM tests $ \ (x, test) -> do optY <- test- case optY of + case optY of Nothing -> return Nothing Just y -> return $ Just (x, y) case catMaybes optPoints of@@ -191,7 +191,7 @@ ------------------------------------------------------------------------ -test :: (String, a, Int -> Int -> Endian -> Int -> Maybe L.ByteString) +test :: (String, a, Int -> Int -> Endian -> Int -> Maybe L.ByteString) -> Int -> Int -> Endian -> Int -> IO (Maybe Double) test (serializeName, _, serialize) wordSize chunkSize end mb = do let bytes :: Int@@ -213,13 +213,13 @@ putThroughput -- getThroughput -- (getThroughput/putThroughput)- + hFlush stdout return $ Just putThroughput ------------------------------------------------------------------------ -compareResults :: (String, a, Int -> Int -> Endian -> Int -> Maybe L.ByteString) +compareResults :: (String, a, Int -> Int -> Endian -> Int -> Maybe L.ByteString) -> Int -> Int -> Endian -> Int -> IO () compareResults (serializeName, _, serialize) wordSize chunkSize end mb0 = do let mb :: Int@@ -233,8 +233,7 @@ Just bs1 -> do _ <- printf "%17s: %dMB of Word%-2d in chunks of %2d (%6s endian):" serializeName (mb :: Int) (8 * wordSize :: Int) (chunkSize :: Int) (show end)- if (bs0 == bs1) + if (bs0 == bs1) then putStrLn " Ok" else putStrLn " Failed" hFlush stdout-
benchmarks/BlazeVsBinary.hs view
@@ -3,9 +3,9 @@ -- Module : BlazeVsBinary -- Copyright : (c) 2010 Jasper Van der Jeught & Simon Meier -- License : BSD3-style (see LICENSE)--- --- Maintainer : Leon P Smith <leon@melding-monads.com>--- Stability : experimental+--+-- Maintainer : https://github.com/blaze-builder+-- Stability : stable -- Portability : tested on GHC only -- -- A comparison between 'blaze-builder' and the Data.Binary.Builder from
benchmarks/BoundedWrite.hs view
@@ -3,9 +3,9 @@ -- Module : BoundedWrite -- Copyright : (c) 2010 Simon Meier -- License : BSD3-style (see LICENSE)--- --- Maintainer : Leon P Smith <leon@melding-monads.com>--- Stability : experimental+--+-- Maintainer : https://github.com/blaze-builder+-- Stability : stable -- Portability : tested on GHC only -- -- A more general/efficient write type.@@ -22,8 +22,8 @@ import qualified Data.ByteString.Lazy as L import Blaze.ByteString.Builder.Internal-import Blaze.ByteString.Builder.Write -import Blaze.ByteString.Builder.Word +import Blaze.ByteString.Builder.Write+import Blaze.ByteString.Builder.Word import Criterion.Main @@ -92,7 +92,7 @@ ------------------------------------------------------------------------------ -- * GRRR* GHC is too 'clever'... code where we branch and each branch should--- execute a few IO actions and then return a value cannot be taught to GHC. +-- execute a few IO actions and then return a value cannot be taught to GHC. -- At least not such that it returns the value of the branches unpacked. -- -- Hmm.. at least he behaves much better for the Monoid instance of BWrite@@ -129,7 +129,7 @@ staticBWrite size io = BWrite size (execWriteSize io size) {-# INLINE staticBWrite #-} -bwriteWord8 :: Word8 -> BWrite +bwriteWord8 :: Word8 -> BWrite bwriteWord8 x = staticBWrite 1 (`poke` x) {-# INLINE bwriteWord8 #-} @@ -145,7 +145,7 @@ {-# INLINE fromBWrite #-} fromBWriteSingleton :: (a -> BWrite) -> a -> Builder-fromBWriteSingleton write = +fromBWriteSingleton write = mkPut where mkPut x = Builder step@@ -238,4 +238,3 @@ x4 = fromIntegral $ (x .&. 0x3F) + 0x80 in f4 x1 x2 x3 x4 {-# INLINE encodeCharUtf8 #-}-
benchmarks/BuilderBufferRange.hs view
@@ -3,9 +3,9 @@ -- Module : BuilderBufferRange -- Copyright : (c) 2010 Simon Meier -- License : BSD3-style (see LICENSE)--- --- Maintainer : Leon P Smith <leon@melding-monads.com>--- Stability : experimental+--+-- Maintainer : https://github.com/blaze-builder+-- Stability : stable -- Portability : tested on GHC only -- -- Benchmark the benefit of using a packed representation for the buffer range.@@ -71,7 +71,7 @@ -- The Builder type ------------------------------------------------------------------------------ -data BufferRange = BR {-# UNPACK #-} !(Ptr Word8) +data BufferRange = BR {-# UNPACK #-} !(Ptr Word8) {-# UNPACK #-} !(Ptr Word8) newtype Put = Put (PutStep -> PutStep)@@ -83,8 +83,8 @@ {-# UNPACK #-} !(Ptr Word8) !PutStep | ModifyChunks- {-# UNPACK #-} !(Ptr Word8) - !(L.ByteString -> L.ByteString) + {-# UNPACK #-} !(Ptr Word8)+ !(L.ByteString -> L.ByteString) !PutStep type PutStep = BufferRange -> IO PutSignal@@ -110,7 +110,7 @@ {-# INLINE putWrite #-} putWriteSingleton :: (a -> Write) -> a -> Put-putWriteSingleton write = +putWriteSingleton write = mkPut where mkPut x = Put step@@ -126,7 +126,7 @@ {-# INLINE putWriteSingleton #-} putBuilder :: B.Builder -> Put-putBuilder (B.Builder b) = +putBuilder (B.Builder b) = Put step where finalStep _ pf = return $ B.Done pf@@ -139,9 +139,9 @@ B.Done pf' -> do let !br' = BR pf' pe k br'- B.BufferFull minSize pf' nextBuildStep -> + B.BufferFull minSize pf' nextBuildStep -> return $ BufferFull minSize pf' (go nextBuildStep)- B.ModifyChunks _ _ _ -> + B.ModifyChunks _ _ _ -> error "putBuilder: ModifyChunks not implemented" putWord8 :: Word8 -> Put@@ -149,7 +149,7 @@ {- m >>= f = GetC $ \done empty pe ->- runGetC m (\pr' x -> runGetC (f x) done empty pe pr') + runGetC m (\pr' x -> runGetC (f x) done empty pe pr') (\m' -> empty (m' >>= f)) pe @@ -165,13 +165,13 @@ instance Functor (GetC r) where fmap f g = GetC $ \done empty ->- runGetC g (\pr' x -> done pr' (f x)) + runGetC g (\pr' x -> done pr' (f x)) (\g' -> empty (fmap f g')) instance Monad (GetC r) where return x = GetC $ \done _ _ pr -> done pr x m >>= f = GetC $ \done empty pe ->- runGetC m (\pr' x -> runGetC (f x) done empty pe pr') + runGetC m (\pr' x -> runGetC (f x) done empty pe pr') (\m' -> empty (m' >>= f)) pe @@ -189,7 +189,7 @@ where overhead = 2 * sizeOf (undefined :: Int) -- | The minimal length (~4kb) a buffer must have before filling it and--- outputting it as a chunk of the output stream. +-- outputting it as a chunk of the output stream. -- -- This size determines when a buffer is spilled after a 'flush' or a direct -- bytestring insertion. It is also the size of the first chunk generated by@@ -199,7 +199,7 @@ where overhead = 2 * sizeOf (undefined :: Int) -- | The default length (64) for the first buffer to be allocated when--- converting a 'Builder' to a lazy bytestring. +-- converting a 'Builder' to a lazy bytestring. -- -- See 'toLazyByteStringWith' for further explanation. defaultFirstBufferSize :: Int@@ -263,7 +263,7 @@ -- @firstBufSize = bufSize@ means that all chunks will use an underlying buffer -- of size @bufSize@. This is recommended, if you know that you always output -- more than @minBufSize@ bytes.-toLazyByteStringWith +toLazyByteStringWith :: Int -- ^ Buffer size (upper-bounds the resulting chunk size). -> Int -- ^ Minimal free buffer space for continuing filling -- the same buffer after a 'flush' or a direct bytestring@@ -275,7 +275,7 @@ -> L.ByteString -- ^ Lazy bytestring to output after the builder is -- finished. -> L.ByteString -- ^ Resulting lazy bytestring-toLazyByteStringWith bufSize minBufSize firstBufSize (Put b) k = +toLazyByteStringWith bufSize minBufSize firstBufSize (Put b) k = inlinePerformIO $ fillFirstBuffer (b finalStep) where finalStep (BR pf _) = return $ Done pf@@ -304,14 +304,14 @@ copyBytes pfNew pf l let !brNew = BR (pfNew `plusPtr` l) peNew nextStep brNew- - ModifyChunks pf' bsk nextStep ++ ModifyChunks pf' bsk nextStep | pf' == pf -> return $ bsk (inlinePerformIO $ fillNewBuffer bufSize nextStep) | otherwise -> return $ L.Chunk (mkbs pf') (bsk (inlinePerformIO $ fillNewBuffer bufSize nextStep))- + -- allocate and fill a new buffer fillNewBuffer !size !step0 = do fpbuf <- S.mallocByteString size@@ -332,9 +332,9 @@ BufferFull newSize pf' nextStep -> return $ L.Chunk (mkbs pf')- (inlinePerformIO $ + (inlinePerformIO $ fillNewBuffer (max newSize bufSize) nextStep)- + ModifyChunks pf' bsk nextStep | pf' == pf -> return $ bsk (inlinePerformIO $ fill pf' nextStep)@@ -361,7 +361,7 @@ -- execute. -- toLazyByteString :: Put -> L.ByteString-toLazyByteString b = toLazyByteStringWith +toLazyByteString b = toLazyByteStringWith defaultBufferSize defaultMinimalBufferSize defaultFirstBufferSize b L.empty {-# INLINE toLazyByteString #-} @@ -415,7 +415,7 @@ -- 'S.ByteString'. -> Builder -- ^ 'Builder' to run. -> IO () -- ^ Resulting 'IO' action.-toByteStringIOWith bufSize io (Builder b) = +toByteStringIOWith bufSize io (Builder b) = fillNewBuffer bufSize (b finalStep) where finalStep pf _ = return $ Done pf@@ -439,7 +439,7 @@ if bufSize < newSize then fillNewBuffer newSize nextStep else fill nextStep- + ModifyChunks pf' bsk nextStep -> do unless (pf' == pf) (io $ S.PS fpbuf 0 (pf' `minusPtr` pf)) -- was: mapM_ io $ L.toChunks (bsk L.empty)
benchmarks/ChunkedWrite.hs view
@@ -3,9 +3,9 @@ -- Module : ChunkedWrite -- Copyright : (c) 2010 Simon Meier -- License : BSD3-style (see LICENSE)--- --- Maintainer : Leon P Smith <leon@melding-monads.com>--- Stability : experimental+--+-- Maintainer : https://github.com/blaze-builder+-- Stability : stable -- Portability : tested on GHC only -- -- Test different strategies for writing lists of simple values:@@ -32,53 +32,53 @@ import qualified Blaze.ByteString.Builder.Char.Utf8 as BB main :: IO ()-main = defaultMain - [ bench "S.pack: [Word8] -> S.ByteString" $ +main = defaultMain+ [ bench "S.pack: [Word8] -> S.ByteString" $ whnf (S.pack) word8s - , bench "toByteString . fromWord8s: [Word8] -> Builder -> S.ByteString" $ + , bench "toByteString . fromWord8s: [Word8] -> Builder -> S.ByteString" $ whnf (BB.toByteString . BB.fromWord8s) word8s - , bench "L.pack: [Word8] -> L.ByteString" $ + , bench "L.pack: [Word8] -> L.ByteString" $ whnf (L.length . L.pack) word8s - , bench "mconcat . map fromByte: [Word8] -> Builder -> L.ByteString" $ + , bench "mconcat . map fromByte: [Word8] -> Builder -> L.ByteString" $ whnf benchMConcatWord8s word8s- , bench "fromWrite1List: [Word8] -> Builder -> L.ByteString" $ + , bench "fromWrite1List: [Word8] -> Builder -> L.ByteString" $ whnf bench1Word8s word8s- , bench "fromWrite2List: [Word8] -> Builder -> L.ByteString" $ + , bench "fromWrite2List: [Word8] -> Builder -> L.ByteString" $ whnf bench2Word8s word8s- , bench "fromWrite4List: [Word8] -> Builder -> L.ByteString" $ + , bench "fromWrite4List: [Word8] -> Builder -> L.ByteString" $ whnf bench4Word8s word8s- , bench "fromWrite8List: [Word8] -> Builder -> L.ByteString" $ + , bench "fromWrite8List: [Word8] -> Builder -> L.ByteString" $ whnf bench8Word8s word8s- , bench "fromWrite16List: [Word8] -> Builder -> L.ByteString" $ + , bench "fromWrite16List: [Word8] -> Builder -> L.ByteString" $ whnf bench16Word8s word8s - , bench "mconcat . map fromByte: [Char] -> Builder -> L.ByteString" $ + , bench "mconcat . map fromByte: [Char] -> Builder -> L.ByteString" $ whnf benchMConcatChars chars- , bench "fromWrite1List: [Char] -> Builder -> L.ByteString" $ + , bench "fromWrite1List: [Char] -> Builder -> L.ByteString" $ whnf bench1Chars chars- , bench "fromWrite2List: [Char] -> Builder -> L.ByteString" $ + , bench "fromWrite2List: [Char] -> Builder -> L.ByteString" $ whnf bench2Chars chars- , bench "fromWrite4List: [Char] -> Builder -> L.ByteString" $ + , bench "fromWrite4List: [Char] -> Builder -> L.ByteString" $ whnf bench4Chars chars- , bench "fromWrite8List: [Char] -> Builder -> L.ByteString" $ + , bench "fromWrite8List: [Char] -> Builder -> L.ByteString" $ whnf bench8Chars chars- , bench "fromWrite16List: [Char] -> Builder -> L.ByteString" $ + , bench "fromWrite16List: [Char] -> Builder -> L.ByteString" $ whnf bench16Chars chars - , bench "mconcat . map fromWord32host: [Word32] -> Builder -> L.ByteString" $ + , bench "mconcat . map fromWord32host: [Word32] -> Builder -> L.ByteString" $ whnf benchMConcatWord32s word32s- , bench "fromWrite1List: [Word32] -> Builder -> L.ByteString" $ + , bench "fromWrite1List: [Word32] -> Builder -> L.ByteString" $ whnf bench1Word32s word32s- , bench "fromWrite2List: [Word32] -> Builder -> L.ByteString" $ + , bench "fromWrite2List: [Word32] -> Builder -> L.ByteString" $ whnf bench2Word32s word32s- , bench "fromWrite4List: [Word32] -> Builder -> L.ByteString" $ + , bench "fromWrite4List: [Word32] -> Builder -> L.ByteString" $ whnf bench4Word32s word32s- , bench "fromWrite8List: [Word32] -> Builder -> L.ByteString" $ + , bench "fromWrite8List: [Word32] -> Builder -> L.ByteString" $ whnf bench8Word32s word32s- , bench "fromWrite16List: [Word32] -> Builder -> L.ByteString" $ + , bench "fromWrite16List: [Word32] -> Builder -> L.ByteString" $ whnf bench16Word32s word32s ] where@@ -155,4 +155,3 @@ bench16Word32s :: [Word32] -> Int64 bench16Word32s = L.length . BB.toLazyByteString . BB.fromWrite16List BB.writeWord32host-
benchmarks/Compression.hs view
@@ -2,9 +2,9 @@ -- Module : Compression -- Copyright : (c) 2010 Simon Meier -- License : BSD3-style (see LICENSE)--- --- Maintainer : Leon P Smith <leon@melding-monads.com>--- Stability : experimental+--+-- Maintainer : https://github.com/blaze-builder+-- Stability : stable -- Portability : tested on GHC only -- -- Benchmark the effect of first compacting the input stream for the 'zlib'@@ -27,7 +27,7 @@ import qualified Blaze.ByteString.Builder as B import Codec.Compression.GZip -main = defaultMain +main = defaultMain [ bench "compress directly (chunksize 10)" $ whnf benchCompressDirectly byteString10 , bench "compress compacted (chunksize 10)" $@@ -51,5 +51,5 @@ benchCompressDirectly = L.length . compress benchCompressCompacted :: L.ByteString -> Int64-benchCompressCompacted = +benchCompressCompacted = L.length . compress . B.toLazyByteString . B.fromLazyByteString
benchmarks/FastPut.hs view
@@ -3,9 +3,9 @@ -- Module : FastPut -- Copyright : (c) 2010 Simon Meier -- License : BSD3-style (see LICENSE)--- --- Maintainer : Leon P Smith <leon@melding-monads.com>--- Stability : experimental+--+-- Maintainer : https://github.com/blaze-builder+-- Stability : stable -- Portability : tested on GHC only -- -- Implementation of a 'Put' monad with similar performance characteristics@@ -88,7 +88,7 @@ {-# UNPACK #-} !(Ptr Word8) !(PutStep a) | InsertByteString- {-# UNPACK #-} !(Ptr Word8) + {-# UNPACK #-} !(Ptr Word8) !S.ByteString !(PutStep a) @@ -135,7 +135,7 @@ {-# INLINE fromWrite #-} fromWriteSingleton :: (a -> Write) -> a -> Builder-fromWriteSingleton write = +fromWriteSingleton write = mkPut where mkPut x = Builder step@@ -174,7 +174,7 @@ {-# INLINE putWrite #-} putWriteSingleton :: (a -> Write) -> a -> Put ()-putWriteSingleton write = +putWriteSingleton write = mkPut where mkPut x = Put step@@ -190,7 +190,7 @@ {-# INLINE putWriteSingleton #-} putBuilder :: B.Builder -> Put ()-putBuilder (B.Builder b) = +putBuilder (B.Builder b) = Put step where finalStep _ pf = return $ B.Done pf@@ -203,14 +203,14 @@ B.Done pf' -> do let !br' = BufRange pf' pe k () br'- B.BufferFull minSize pf' nextBuildStep -> + B.BufferFull minSize pf' nextBuildStep -> return $ BufferFull minSize pf' (go nextBuildStep)- B.ModifyChunks _ _ _ -> + B.ModifyChunks _ _ _ -> error "putBuilder: ModifyChunks not implemented" {- m >>= f = GetC $ \done empty pe ->- runGetC m (\pr' x -> runGetC (f x) done empty pe pr') + runGetC m (\pr' x -> runGetC (f x) done empty pe pr') (\m' -> empty (m' >>= f)) pe @@ -226,13 +226,13 @@ instance Functor (GetC r) where fmap f g = GetC $ \done empty ->- runGetC g (\pr' x -> done pr' (f x)) + runGetC g (\pr' x -> done pr' (f x)) (\g' -> empty (fmap f g')) instance Monad (GetC r) where return x = GetC $ \done _ _ pr -> done pr x m >>= f = GetC $ \done empty pe ->- runGetC m (\pr' x -> runGetC (f x) done empty pe pr') + runGetC m (\pr' x -> runGetC (f x) done empty pe pr') (\m' -> empty (m' >>= f)) pe @@ -250,7 +250,7 @@ where overhead = 2 * sizeOf (undefined :: Int) -- | The minimal length (~4kb) a buffer must have before filling it and--- outputting it as a chunk of the output stream. +-- outputting it as a chunk of the output stream. -- -- This size determines when a buffer is spilled after a 'flush' or a direct -- bytestring insertion. It is also the size of the first chunk generated by@@ -260,7 +260,7 @@ where overhead = 2 * sizeOf (undefined :: Int) -- | The default length (64) for the first buffer to be allocated when--- converting a 'Builder' to a lazy bytestring. +-- converting a 'Builder' to a lazy bytestring. -- -- See 'toLazyByteStringWith' for further explanation. defaultFirstBufferSize :: Int@@ -324,7 +324,7 @@ -- @firstBufSize = bufSize@ means that all chunks will use an underlying buffer -- of size @bufSize@. This is recommended, if you know that you always output -- more than @minBufSize@ bytes.-toLazyByteStringWith +toLazyByteStringWith :: Int -- ^ Buffer size (upper-bounds the resulting chunk size). -> Int -- ^ Minimal free buffer space for continuing filling -- the same buffer after a 'flush' or a direct bytestring@@ -336,7 +336,7 @@ -> L.ByteString -- ^ Lazy bytestring to output after the builder is -- finished. -> L.ByteString -- ^ Resulting lazy bytestring-toLazyByteStringWith bufSize minBufSize firstBufSize (Put b) k = +toLazyByteStringWith bufSize minBufSize firstBufSize (Put b) k = inlinePerformIO $ fillFirstBuffer (b finalStep) where finalStep _ (BufRange pf _) = return $ Done pf undefined@@ -365,17 +365,17 @@ copyBytes pfNew pf l let !brNew = BufRange (pfNew `plusPtr` l) peNew nextStep brNew- + InsertByteString _ _ _ -> error "not yet implemented" {-- ModifyChunks pf' bsk nextStep( + ModifyChunks pf' bsk nextStep( | pf' == pf -> return $ bsk (inlinePerformIO $ fillNewBuffer bufSize nextStep) | otherwise -> return $ L.Chunk (mkbs pf') (bsk (inlinePerformIO $ fillNewBuffer bufSize nextStep)) -}- + -- allocate and fill a new buffer fillNewBuffer !size !step0 = do fpbuf <- S.mallocByteString size@@ -396,9 +396,9 @@ BufferFull newSize pf' nextStep -> return $ L.Chunk (mkbs pf')- (inlinePerformIO $ + (inlinePerformIO $ fillNewBuffer (max newSize bufSize) nextStep)- + InsertByteString _ _ _ -> error "not yet implemented2" {- ModifyChunks pf' bsk nextStep@@ -428,7 +428,7 @@ -- execute. -- toLazyByteString :: Put a -> L.ByteString-toLazyByteString b = toLazyByteStringWith +toLazyByteString b = toLazyByteStringWith defaultBufferSize defaultMinimalBufferSize defaultFirstBufferSize b L.empty {-# INLINE toLazyByteString #-} @@ -436,11 +436,11 @@ -- Builder Enumeration ------------------------------------------------------------------------------ -data BuildStream a = +data BuildStream a = BuildChunk S.ByteString (IO (BuildStream a)) | BuildYield- a - (forall b. Bool -> + a+ (forall b. Bool -> Either (Maybe S.ByteString) (Put b -> IO (BuildStream b))) enumPut :: Int -> Put a -> IO (BuildStream a)@@ -452,16 +452,16 @@ fillBuffer :: forall b. Int -> PutStep b -> IO (BuildStream b) fillBuffer size step = do- fpbuf <- S.mallocByteString bufSize + fpbuf <- S.mallocByteString bufSize let !pbuf = unsafeForeignPtrToPtr fpbuf -- safe due to later reference of fpbuf -- BETTER than withForeignPtr, as we lose a tail call otherwise !br = BufRange pbuf (pbuf `plusPtr` size) fillStep fpbuf br step - fillPut :: ForeignPtr Word8 -> BufRange -> + fillPut :: ForeignPtr Word8 -> BufRange -> Bool -> Either (Maybe S.ByteString) (Put b -> IO (BuildStream b))- fillPut !fpbuf !(BufRange op _) False + fillPut !fpbuf !(BufRange op _) False | pbuf == op = Left Nothing | otherwise = Left $ Just $ S.PS fpbuf 0 (op `minusPtr` pbuf)@@ -481,11 +481,11 @@ let !br' = BufRange op' ope return $ BuildYield x (fillPut fpbuf br') - BufferFull minSize op' nextStep + BufferFull minSize op' nextStep | pbuf == op' -> do -- nothing written, larger buffer required fillBuffer (max bufSize minSize) nextStep | otherwise -> do -- some bytes written, new buffer required- return $ BuildChunk + return $ BuildChunk (S.PS fpbuf 0 (op' `minusPtr` pbuf)) (fillBuffer (max bufSize minSize) nextStep) @@ -501,25 +501,25 @@ toLazyByteString' :: Put () -> L.ByteString-toLazyByteString' put = +toLazyByteString' put = inlinePerformIO (consume `fmap` enumPut defaultBufferSize put) where consume :: BuildStream () -> L.ByteString- consume (BuildYield _ f) = + consume (BuildYield _ f) = case f False of Left Nothing -> L.Empty Left (Just bs) -> L.Chunk bs L.Empty Right _ -> error "toLazyByteString': enumPut violated postcondition" consume (BuildChunk bs ioStream) = L.Chunk bs $ inlinePerformIO (consume `fmap` ioStream)- + {- BufferFull minSize pf' nextStep -> do io $ S.PS fpbuf 0 (pf' `minusPtr` pf) fillBuffer (max bufSize minSize) nextStep- + ModifyChunks pf' bsk nextStep -> do io $ S.PS fpbuf 0 (pf' `minusPtr` pf) L.foldrChunks (\bs -> (io bs >>)) (return ()) (bsk L.empty)@@ -543,11 +543,11 @@ return $! Buffer fpbuf pbuf pbuf (pbuf `plusPtr` size) unsafeFreezeBuffer :: Buffer -> S.ByteString-unsafeFreezeBuffer (Buffer fpbuf p0 op _) = +unsafeFreezeBuffer (Buffer fpbuf p0 op _) = S.PS fpbuf 0 (op `minusPtr` p0) unsafeFreezeNonEmptyBuffer :: Buffer -> Maybe S.ByteString-unsafeFreezeNonEmptyBuffer (Buffer fpbuf p0 op _) +unsafeFreezeNonEmptyBuffer (Buffer fpbuf p0 op _) | p0 == op = Nothing | otherwise = Just $ S.PS fpbuf 0 (op `minusPtr` p0) @@ -556,7 +556,7 @@ | ope `minusPtr` op <= minSize = Nothing | otherwise = Just (Buffer fpbuf op op ope) -runPut :: Monad m +runPut :: Monad m => (IO (PutSignal a) -> m (PutSignal a)) -- lifting of buildsteps -> (Int -> Buffer -> m Buffer) -- output function for a guaranteedly non-empty buffer, the returned buffer will be filled next -> (S.ByteString -> m ()) -- output function for guaranteedly non-empty bytestrings, that are inserted directly into the stream@@ -571,7 +571,7 @@ runStep step buf@(Buffer fpbuf p0 op ope) = do let !br = BufRange op ope signal <- liftIO $ step br- case signal of + case signal of Done op' x -> -- put completed, buffer partially runSteped return (x, Buffer fpbuf p0 op' ope) @@ -590,7 +590,7 @@ outputBS bs runStep nextStep buf' {-# INLINE runPut #-}- + -- | A monad for lazily composing lazy bytestrings using continuations. newtype LBSM a = LBSM { unLBSM :: (a, L.ByteString -> L.ByteString) } @@ -602,7 +602,7 @@ -- | Execute a put and return the written buffers as the chunks of a lazy -- bytestring. toLazyByteString2 :: Put a -> L.ByteString-toLazyByteString2 put = +toLazyByteString2 put = k (bufToLBSCont (snd result) L.empty) where -- initial buffer@@ -622,7 +622,7 @@ outputBS bs = LBSM ((), L.Chunk bs) -- | A Builder that traces a message-traceBuilder :: String -> Builder +traceBuilder :: String -> Builder traceBuilder msg = Builder $ \k br@(BufRange op ope) -> do putStrLn $ "traceBuilder " ++ show (op, ope) ++ ": " ++ msg k br@@ -633,11 +633,10 @@ test2 :: Word8 -> [S.ByteString] test2 x = L.toChunks $ toLazyByteString2 $ fromBuilder $ mconcat- [ traceBuilder "before flush" + [ traceBuilder "before flush" , fromWord8 48 , flushBuilder , flushBuilder , traceBuilder "after flush" , fromWord8 x ]-
benchmarks/LazyByteString.hs view
@@ -3,9 +3,9 @@ -- Module : LazyByteString -- Copyright : (c) 2010 Simon Meier -- License : BSD3-style (see LICENSE)--- --- Maintainer : Leon P Smith <leon@melding-monads.com>--- Stability : experimental+--+-- Maintainer : https://github.com/blaze-builder+-- Stability : stable -- Portability : tested on GHC only -- -- Benchmarking of alternative implementations of functions in@@ -15,14 +15,14 @@ import Data.Char import Data.Word-import Data.Monoid -import Data.List +import Data.Monoid+import Data.List import Control.Monad import Control.Arrow (second) import Criterion.Main -import Foreign +import Foreign import qualified Data.ByteString as S import qualified Data.ByteString.Unsafe as S import qualified Data.ByteString.Internal as S@@ -41,7 +41,7 @@ main :: IO () main = do- let (chunkInfos, benchmarks) = unzip + let (chunkInfos, benchmarks) = unzip {- [ lazyVsBlaze ( "partitionLazy"@@ -97,7 +97,7 @@ , toLazyByteString . concatMapBuilder (fromReplicateWord8 10) , (\i -> L.pack $ take i $ cycle [0..]) , n `div` 10 )- , lazyVsBlaze + , lazyVsBlaze ( "unfoldr countToZero" , L.unfoldr countToZero , unfoldrBlaze countToZero@@ -118,7 +118,7 @@ ( do putStrLn $ cmpName ++ ": " ++ checkResults showChunksize implLazy lazy showChunksize implBlaze blaze- , bgroup cmpName + , bgroup cmpName [ mkBench implBlaze blaze , mkBench implLazy lazy ]@@ -129,7 +129,7 @@ x = prep n nInfo = "for n = " ++ show n- checkResults + checkResults | lazy x == blaze x = "implementations agree " ++ nInfo | otherwise = unlines [ "ERROR: IMPLEMENTATIONS DISAGREE " ++ nInfo , implLazy ++ ": " ++ show (lazy x)@@ -141,7 +141,7 @@ cs = map S.length $ L.toChunks bs putStrLn $ " " ++ implName ++ ": " putStrLn $ " chunks sizes: " ++ show cs- putStrLn $ " avg. chunk size: " ++ + putStrLn $ " avg. chunk size: " ++ show ((fromIntegral (sum cs) :: Double) / fromIntegral (length cs)) mkBench implName impl = bench implName $ whnf (L.length . impl) x@@ -179,7 +179,7 @@ unfoldrBlaze f x = toLazyByteString $ fromWriteUnfoldr writeWord8 f x fromWriteUnfoldr :: (b -> Write) -> (a -> Maybe (b, a)) -> a -> Builder-fromWriteUnfoldr write = +fromWriteUnfoldr write = makeBuilder where makeBuilder f x0 = fromBuildStepCont $ step x0@@ -195,8 +195,8 @@ | pf `plusPtr` bound <= pe0 = do !pf' <- runWrite (write y) pf go (f x') pf'- | otherwise = return $ bufferFull bound pf $ - \(BufRange pfNew peNew) -> do + | otherwise = return $ bufferFull bound pf $+ \(BufRange pfNew peNew) -> do !pfNew' <- runWrite (write y) pfNew fill x' (BufRange pfNew' peNew) where@@ -207,7 +207,7 @@ ------------------------ test :: Int -> (L.ByteString, L.ByteString)-test i = +test i = ((L.filter ((==0) . (`mod` 3)) $ x) , (filterBlaze ((==0) . (`mod` 3)) $ x)) where@@ -237,12 +237,12 @@ mapLazyByteString f = mapFilterMapLazyByteString f (const True) id {-# INLINE mapLazyByteString #-} -mapFilterMapByteString :: (Word8 -> Word8) -> (Word8 -> Bool) -> (Word8 -> Word8) +mapFilterMapByteString :: (Word8 -> Word8) -> (Word8 -> Bool) -> (Word8 -> Word8) -> S.ByteString -> Builder-mapFilterMapByteString f p g = +mapFilterMapByteString f p g = \bs -> fromBuildStepCont $ step bs where- step (S.PS ifp ioff isize) !k = + step (S.PS ifp ioff isize) !k = goBS (unsafeForeignPtrToPtr ifp `plusPtr` ioff) where !ipe = unsafeForeignPtrToPtr ifp `plusPtr` (ioff + isize)@@ -250,7 +250,7 @@ | ip0 >= ipe = do touchForeignPtr ifp -- input buffer consumed k br | op0 < ope = goPartial (ip0 `plusPtr` min outRemaining inpRemaining)- | otherwise = return $ bufferFull 1 op0 (goBS ip0) + | otherwise = return $ bufferFull 1 op0 (goBS ip0) where outRemaining = ope `minusPtr` op0 inpRemaining = ipe `minusPtr` ip0@@ -267,9 +267,9 @@ goBS ip (BufRange op ope) {-# INLINE mapFilterMapByteString #-} -mapFilterMapLazyByteString :: (Word8 -> Word8) -> (Word8 -> Bool) -> (Word8 -> Word8) +mapFilterMapLazyByteString :: (Word8 -> Word8) -> (Word8 -> Bool) -> (Word8 -> Word8) -> L.ByteString -> Builder-mapFilterMapLazyByteString f p g = +mapFilterMapLazyByteString f p g = L.foldrChunks (\c b -> mapFilterMapByteString f p g c `mappend` b) mempty {-# INLINE mapFilterMapLazyByteString #-} @@ -295,10 +295,10 @@ -} fromWriteReplicated :: (a -> Write) -> Int -> a -> Builder-fromWriteReplicated write = +fromWriteReplicated write = makeBuilder where- makeBuilder !n0 x = fromBuildStepCont $ step + makeBuilder !n0 x = fromBuildStepCont $ step where bound = getBound $ write x step !k = fill n0@@ -312,15 +312,15 @@ | pf `plusPtr` bound <= pe0 = do pf' <- runWrite (write x) pf go (n-1) pf'- | otherwise = return $ bufferFull bound pf $ - \(BufRange pfNew peNew) -> do + | otherwise = return $ bufferFull bound pf $+ \(BufRange pfNew peNew) -> do pfNew' <- runWrite (write x) pfNew fill (n-1) (BufRange pfNew' peNew) {-# INLINE fromWriteReplicated #-} -- FIXME: Output repeated bytestrings for large replications. fromReplicateWord8 :: Int -> Word8 -> Builder-fromReplicateWord8 !n0 x = +fromReplicateWord8 !n0 x = fromBuildStepCont $ step where step !k = fill n0@@ -380,7 +380,7 @@ intersperseBlaze :: Word8 -- ^ Byte to intersperse. -> L.ByteString -- ^ Lazy 'L.ByteString' to be "spread". -> Builder -- ^ Resulting 'Builder'.-intersperseBlaze w lbs0 = +intersperseBlaze w lbs0 = Builder $ step lbs0 where step lbs1 k = goChunk lbs1@@ -390,21 +390,21 @@ go touch where- go + go where- !pf' = pf `plusPtr` - - + !pf' = pf `plusPtr`++ goChunk !L.Empty !pf = k pf pe0 goChunk !lbs@(L.Chunk bs' lbs') !pf | pf' <= pe0 = do- withForeignPtr fpbuf $ \pbuf -> + withForeignPtr fpbuf $ \pbuf -> copyBytes pf (pbuf `plusPtr` offset) size go lbs' pf' | otherwise = return $ BufferFull size pf (step lbs k) where- !pf' = pf `plusPtr` + !pf' = pf `plusPtr` !(fpbuf, offset, size) = S.toForeignPtr bs' {-# INLINE intersperseBlaze #-} @@ -455,14 +455,14 @@ -------------------------------------------- intersperseBlocks :: Int -> S.ByteString -> S.ByteString -> Builder-intersperseBlocks blockSize sep (S.PS ifp ioff isize) = +intersperseBlocks blockSize sep (S.PS ifp ioff isize) = fromPut $ do- lastBS <- go (ip0 `plusPtr` ioff) + lastBS <- go (ip0 `plusPtr` ioff) unless (S.null lastBS) (putBuilder $ fromByteString lastBS) where ip0 = unsafeForeignPtrToPtr ifp ipe = ip0 `plusPtr` (ioff + isize)- go !ip + go !ip | ip `plusPtr` blockSize >= ipe = return $ S.PS ifp (ip `minusPtr` ip0) (ipe `minusPtr` ip) | otherwise = do@@ -500,15 +500,15 @@ encodeBase64 = encodeLazyBase64 . L.fromChunks . return encodeLazyBase64 :: L.ByteString -> Builder-encodeLazyBase64 = +encodeLazyBase64 = mkBuilder where mkBuilder bs = fromPut $ do- remainder <- putWriteLazyBlocks 3 writeBase64 bs + remainder <- putWriteLazyBlocks 3 writeBase64 bs putBuilder $ complete remainder {-# INLINE writeBase64 #-}- writeBase64 ip = + writeBase64 ip = exactWrite 4 $ \op -> do b0 <- peekByte 0 b1 <- peekByte 1@@ -519,7 +519,7 @@ where peekByte :: Int -> IO Word32 peekByte off = fmap fromIntegral (peekByteOff ip off :: IO Word8)- + enc = peekElemOff (unsafeForeignPtrToPtr encodeTable) . fromIntegral {-# INLINE complete #-}@@ -532,14 +532,14 @@ pad off = pokeByteOff op off (fromIntegral $ ord '=' :: Word8) poke6Base64 0 18 poke6Base64 1 12- if S.length bs == 1 then pad 2 + if S.length bs == 1 then pad 2 else poke6Base64 2 8 pad 3 where getByte :: Int -> Int -> Word32 getByte i sh = fromIntegral (bs `S.unsafeIndex` i) `shiftL` sh w = getByte 0 16 .|. (if S.length bs == 1 then 0 else getByte 1 8)- + -- Lookup table trick from Data.ByteString.Base64 by Bryan O'Sullivan {-# NOINLINE alphabet #-} alphabet :: S.ByteString@@ -547,7 +547,7 @@ -- FIXME: Check that the implementation of the lookup table aslo works on -- big-endian systems.- {-# NOINLINE encodeTable #-} + {-# NOINLINE encodeTable #-} encodeTable :: ForeignPtr Word16 encodeTable = unsafePerformIO $ do fp <- mallocForeignPtrArray 4096@@ -573,23 +573,23 @@ putWriteBlocks blockSize write = \bs -> putBuildStepCont $ step bs where- step (S.PS ifp ioff isize) !k = + step (S.PS ifp ioff isize) !k = goBS (unsafeForeignPtrToPtr ifp `plusPtr` ioff) where !ipe = unsafeForeignPtrToPtr ifp `plusPtr` (ioff + isize) goBS !ip0 !br@(BufRange op0 ope)- | ip0 `plusPtr` blockSize > ipe = do + | ip0 `plusPtr` blockSize > ipe = do touchForeignPtr ifp -- input buffer consumed- let !bs' = S.PS ifp (ip0 `minusPtr` unsafeForeignPtrToPtr ifp) + let !bs' = S.PS ifp (ip0 `minusPtr` unsafeForeignPtrToPtr ifp) (ipe `minusPtr` ip0) k bs' br - | op0 `plusPtr` writeBound < ope = + | op0 `plusPtr` writeBound < ope = goPartial (ip0 `plusPtr` (blockSize * min outRemaining inpRemaining)) - | otherwise = return $ bufferFull writeBound op0 (goBS ip0) + | otherwise = return $ bufferFull writeBound op0 (goBS ip0) where- writeBound = getBound' "putWriteBlocks" write + writeBound = getBound' "putWriteBlocks" write outRemaining = (ope `minusPtr` op0) `div` writeBound inpRemaining = (ipe `minusPtr` ip0) `div` blockSize @@ -618,36 +618,36 @@ go (L.Chunk bs lbs) = do bsRem <- putWriteBlocks blockSize write bs case S.length bsRem of- lRem + lRem | lRem <= 0 -> go lbs | otherwise -> do- let (lbsPre, lbsSuf) = + let (lbsPre, lbsSuf) = L.splitAt (fromIntegral $ blockSize - lRem) lbs case S.concat $ bsRem : L.toChunks lbsPre of block@(S.PS bfp boff bsize) | bsize < blockSize -> return block | otherwise -> do- putBuilder $ fromWrite $ + putBuilder $ fromWrite $ write (unsafeForeignPtrToPtr bfp `plusPtr` boff) putLiftIO $ touchForeignPtr bfp- go lbsSuf - + go lbsSuf + ------------------------------------------------------------------------------ -- Testing code ------------------------------------------------------------------------------ chunks3 :: [Word8] -> [Word32]-chunks3 (b0 : b1 : b2 : bs) = - ((fromIntegral b0 `shiftL` 16) .|. - (fromIntegral b1 `shiftL` 8) .|. +chunks3 (b0 : b1 : b2 : bs) =+ ((fromIntegral b0 `shiftL` 16) .|.+ (fromIntegral b1 `shiftL` 8) .|. (fromIntegral b2 ) ) : chunks3 bs chunks3 _ = [] cmpWriteToLib :: [Word8] -> (L.ByteString, L.ByteString)-cmpWriteToLib bs = +cmpWriteToLib bs = -- ( toLazyByteString $ fromWriteList write24bitsBase64 $ chunks3 bs ( toLazyByteString $ encodeBase64 $ S.pack bs , (`L.Chunk` L.empty) $ encode $ S.pack bs )@@ -655,11 +655,11 @@ test3 :: Bool test3 = uncurry (==) $ cmpWriteToLib $ [0..] -test2 :: L.ByteString +test2 :: L.ByteString test2 = toLazyByteString $ encodeBase64 $ S.pack [0..] {- OLD code- + {-# INLINE poke8 #-} poke8 :: Word8 -> Ptr Word8 -> IO () poke8 = flip poke@@ -697,7 +697,7 @@ write6bitsBase64 (w `shiftr_w32` 18) `mappend` write6bitsBase64 (w `shiftr_w32` 12) `mappend` writeIf (const only8) (const $ C8.writeChar '=')- (write6bitsBase64 . (`shiftr_w32` 6)) + (write6bitsBase64 . (`shiftr_w32` 6)) w `mappend` C8.writeChar '=' @@ -711,7 +711,7 @@ -- ASSUMES bits 25 - 31 are zero. {-# INLINE write24bitsBase64' #-} write24bitsBase64' :: Word32 -> Write-write24bitsBase64' w = +write24bitsBase64' w = exactWrite 4 $ \p -> do poke (castPtr p ) =<< enc (w `shiftR` 12) poke (castPtr $ p `plusPtr` 2) =<< enc (w .&. 0xfff)@@ -747,12 +747,12 @@ {-# INLINE partitionStrict #-} partitionStrict :: (Word8 -> Bool) -> S.ByteString -> (S.ByteString, S.ByteString)-partitionStrict f (S.PS ifp ioff ilen) = +partitionStrict f (S.PS ifp ioff ilen) = second S.reverse $ S.inlinePerformIO $ do ofp <- S.mallocByteString ilen withForeignPtr ifp $ wrapper ofp where- wrapper !ofp !ip0 = + wrapper !ofp !ip0 = go (ip0 `plusPtr` ioff) op0 (op0 `plusPtr` ilen) where op0 = unsafeForeignPtrToPtr ofp@@ -761,8 +761,8 @@ | oph == opl = return (S.PS ofp 0 olen, S.PS ofp olen (ilen - olen)) | otherwise = do x <- peek ip- if f x - then do poke opl x + if f x+ then do poke opl x go (ip `plusPtr` 1) (opl `plusPtr` 1) oph else do let oph' = oph `plusPtr` (-1) poke oph' x@@ -773,10 +773,10 @@ {-# INLINE partitionLazy #-} partitionLazy :: (Word8 -> Bool) -> L.ByteString -> (L.ByteString, L.ByteString)-partitionLazy f = +partitionLazy f = L.foldrChunks partitionOne (L.empty, L.empty) where- partitionOne bs (ls, rs) = + partitionOne bs (ls, rs) = (L.Chunk l ls, L.Chunk r rs) where (l, r) = partitionStrict f bs
benchmarks/PlotTest.hs view
@@ -3,9 +3,9 @@ -- Module : PlotTest -- Copyright : Simon Meier -- License : BSD3-style (see LICENSE)--- --- Maintainer : Leon P Smith <leon@melding-monads.com>--- Stability : experimental+--+-- Maintainer : https://github.com/blaze-builder+-- Stability : stable -- Portability : GHC -- -- Test plotting for the benchmarks.@@ -67,7 +67,7 @@ -- | A pseudo-random stream of 'Word8' always started from the same initial -- seed. randomWord8s :: [Word8]-randomWord8s = map fromIntegral $ unfoldr (Just . R.next) (R.mkStdGen 666) +randomWord8s = map fromIntegral $ unfoldr (Just . R.next) (R.mkStdGen 666) -- Main function ----------------@@ -83,14 +83,14 @@ -- | Run a list of benchmarks; flattening benchmark groups to a path of strings. runFlattenedBenchmarks :: [Benchmark] -> MyCriterion [([String],Sample)]-runFlattenedBenchmarks = +runFlattenedBenchmarks = (concat `liftM`) . mapM (go id) where go path (Benchmark name b) = do env <- ask sample <- lift $ runBenchmark env b return [(path [name], sample)]- go path (BenchGroup name bs) = + go path (BenchGroup name bs) = concat `liftM` mapM (go (path . (name:))) bs -- | Run a benchmark for a series of data points; e.g. to measure scalability@@ -106,9 +106,9 @@ runMyCriterion config criterion = do env <- withConfig config measureEnvironment withConfig config (runReaderT criterion env)- + -- Plotting Infrastructure -------------------------- @@ -116,7 +116,7 @@ colorPalette = [blue, green, red, yellow, magenta, cyan] lineStylePalette :: [CairoLineStyle]-lineStylePalette = +lineStylePalette = map (solidLine 1 . opaque) colorPalette ++ map (dashedLine 1 [5, 5] . opaque) colorPalette @@ -125,7 +125,7 @@ layoutPlot :: PlotData -> Layout1 Int Double layoutPlot ((title, xName, yName), lines) =- layout1_plots ^= map (Right . toPlot) plots $ + layout1_plots ^= map (Right . toPlot) plots $ layout1_title ^= title $ layout1_bottom_axis ^= mkLinearAxis xName $ layout1_right_axis ^= mkLogAxis yName $@@ -136,18 +136,18 @@ -- | Plot a single named line using the given line style. plotLine :: String -> CairoLineStyle -> [(Int,Double)] -> PlotLines Int Double-plotLine name style points = +plotLine name style points = plot_lines_title ^= name $ plot_lines_style ^= style $- plot_lines_values ^= [points] $ + plot_lines_values ^= [points] $ defaultPlotLines mkLinearAxis :: String -> LayoutAxis Int mkLinearAxis name = laxis_title ^= name $ defaultLayoutAxis mkLogAxis :: String -> LayoutAxis Double-mkLogAxis name = - laxis_title ^= name $ +mkLogAxis name =+ laxis_title ^= name $ laxis_generate ^= autoScaledLogAxis defaultLogAxis $ defaultLayoutAxis @@ -169,12 +169,12 @@ plots :: [PlotLines Int Double]-plots = [ plotLine [c] style testData +plots = [ plotLine [c] style testData | (c, style) <- zip ['a'..] (cycle lineStylePalette) ] -mkLayout xname yname title p = - layout1_plots ^= [Right p] $ +mkLayout xname yname title p =+ layout1_plots ^= [Right p] $ layout1_title ^= title $ layout1_bottom_axis ^= mkLinearAxis xname $ layout1_right_axis ^= mkLogAxis yname $@@ -196,19 +196,19 @@ let plottedLines = flip map lines $ \ ((name,lineStyle,_), points) -> plot_lines_title ^= name $ plot_lines_style ^= lineStyle $- plot_lines_values ^= [points] $ + plot_lines_values ^= [points] $ defaultPlotLines- let layout = + let layout = defaultLayout1 { layout1_plots_ = map (Right . toPlot) plottedLines }- renderableToWindow (toRenderable layout) 640 480 + renderableToWindow (toRenderable layout) 640 480 measureSerializer :: (a, [(Int, IO (Maybe Double))]) -> IO (Maybe (a, [(Int,Double)])) measureSerializer (info, tests) = do optPoints <- forM tests $ \ (x, test) -> do optY <- test- case optY of + case optY of Nothing -> return Nothing Just y -> return $ Just (x, y) case catMaybes optPoints of
benchmarks/StringAndText.hs view
@@ -3,16 +3,16 @@ -- Module : StringAndText -- Copyright : (c) 2010 Simon Meier -- License : BSD3-style (see LICENSE)--- --- Maintainer : Leon P Smith <leon@melding-monads.com>--- Stability : experimental+--+-- Maintainer : https://github.com/blaze-builder+-- Stability : stable -- Portability : tested on GHC only -- -- Benchmarking of String and Text serialization. module StringAndText (main) where import Data.Char (ord)-import Data.Monoid +import Data.Monoid import Criterion.Main @@ -30,19 +30,19 @@ import qualified Blaze.ByteString.Builder.Html.Utf8 as Blaze main :: IO ()-main = defaultMain +main = defaultMain [ bench "TL.unpack :: LazyText -> String" $ nf TL.unpack benchLazyText , bench "TL.foldr :: LazyText -> String" $ nf (TL.foldr (:) []) benchLazyText- + , bench "fromString :: String --[Utf8 encoding]--> L.ByteString" $ whnf (L.length . Blaze.toLazyByteString . Blaze.fromString) benchString , bench "fromStrictTextUnpacked :: StrictText --[Utf8 encoding]--> L.ByteString" $ whnf (L.length . Blaze.toLazyByteString . Blaze.fromText) benchStrictText- + -- , bench "fromStrictTextFolded :: StrictText --[Utf8 encoding]--> L.ByteString" $ whnf -- (L.length . Blaze.toLazyByteString . fromStrictTextFolded) benchStrictText @@ -63,10 +63,10 @@ , bench "fromHtmlEscapedStrictTextUnpacked :: StrictText --[HTML esc. & Utf8 encoding]--> L.ByteString" $ whnf (L.length . Blaze.toLazyByteString . Blaze.fromHtmlEscapedText) benchStrictText- + , bench "fromHtmlEscapedLazyTextUnpacked :: LazyText --[HTML esc. & Utf8 encoding]--> L.ByteString" $ whnf (L.length . Blaze.toLazyByteString . Blaze.fromHtmlEscapedLazyText) benchLazyText- + ] n :: Int
benchmarks/UnboxedAppend.hs view
@@ -3,9 +3,9 @@ -- Module : UnboxedAppend -- Copyright : (c) 2010 Simon Meier -- License : BSD3-style (see LICENSE)--- --- Maintainer : Leon P Smith <leon@melding-monads.com>--- Stability : experimental+--+-- Maintainer : https://github.com/blaze-builder+-- Stability : stable -- Portability : tested on GHC only -- -- Try using unboxed pointers for the continuation calls to make abstract@@ -85,7 +85,7 @@ {-# UNPACK #-} !(Ptr Word8) !(PutStep a) | InsertByteString- {-# UNPACK #-} !(Ptr Word8) + {-# UNPACK #-} !(Ptr Word8) !S.ByteString !(PutStep a) @@ -138,7 +138,7 @@ {-# INLINE unboxBuildStep #-} fromWriteSingleton :: (a -> Write) -> a -> Builder-fromWriteSingleton write = +fromWriteSingleton write = mkBuilder where mkBuilder x = fromBuildStep step@@ -148,7 +148,7 @@ io pf let !br' = BufRange (pf `plusPtr` size) pe callBuildStep k br'- | otherwise = + | otherwise = return $ BufferFull size pf (unboxBuildStep $ step k) where Write size io = write x@@ -175,11 +175,11 @@ return $! Buffer fpbuf pbuf pbuf (pbuf `plusPtr` size) unsafeFreezeBuffer :: Buffer -> S.ByteString-unsafeFreezeBuffer (Buffer fpbuf p0 op _) = +unsafeFreezeBuffer (Buffer fpbuf p0 op _) = S.PS fpbuf 0 (op `minusPtr` p0) unsafeFreezeNonEmptyBuffer :: Buffer -> Maybe S.ByteString-unsafeFreezeNonEmptyBuffer (Buffer fpbuf p0 op _) +unsafeFreezeNonEmptyBuffer (Buffer fpbuf p0 op _) | p0 == op = Nothing | otherwise = Just $ S.PS fpbuf 0 (op `minusPtr` p0) @@ -188,7 +188,7 @@ | ope `minusPtr` op <= minSize = Nothing | otherwise = Just (Buffer fpbuf op op ope) -runPut :: Monad m +runPut :: Monad m => (IO (PutSignal a) -> m (PutSignal a)) -- lifting of buildsteps -> (Int -> Buffer -> m Buffer) -- output function for a guaranteedly non-empty buffer, the returned buffer will be filled next -> (S.ByteString -> m ()) -- output function for guaranteedly non-empty bytestrings, that are inserted directly into the stream@@ -203,7 +203,7 @@ runStep step buf@(Buffer fpbuf p0 op ope) = do let !br = BufRange op ope signal <- liftIO $ callBuildStep step br- case signal of + case signal of Done op' x -> -- put completed, buffer partially runSteped return (x, Buffer fpbuf p0 op' ope) @@ -222,7 +222,7 @@ outputBS bs runStep nextStep buf' {-# INLINE runPut #-}- + -- | A monad for lazily composing lazy bytestrings using continuations. newtype LBSM a = LBSM { unLBSM :: (a, L.ByteString -> L.ByteString) } @@ -234,7 +234,7 @@ -- | Execute a put and return the written buffers as the chunks of a lazy -- bytestring. toLazyByteString2 :: Put a -> L.ByteString-toLazyByteString2 put = +toLazyByteString2 put = k (bufToLBSCont (snd result) L.empty) where -- initial buffer
benchmarks/Utf8IO.hs view
@@ -2,9 +2,9 @@ -- | -- Copyright : (c) 2011 Simon Meier -- License : BSD3-style (see LICENSE)--- --- Maintainer : Leon P Smith <leon@melding-monads.com>--- Stability : experimental+--+-- Maintainer : https://github.com/blaze-builder+-- Stability : stable -- Portability : tested on GHC only -- -- Benchmarking IO output speed of writing a string in Utf8 encoding to a file.@@ -25,14 +25,14 @@ import System.IO import System.Environment -import Blaze.ByteString.Builder +import Blaze.ByteString.Builder import Blaze.ByteString.Builder.Internal (defaultBufferSize) import qualified Blaze.ByteString.Builder.Char.Utf8 as Blaze -- | Write using the standard text utf8 encoding function built into 'base'. writeUtf8_base :: String -> FilePath -> IO ()-writeUtf8_base cs file = +writeUtf8_base cs file = withFile file WriteMode $ \h -> do hSetEncoding h utf8 hPutStr h cs@@ -72,13 +72,13 @@ -- utf8-light is missing support for lazy bytestrings => test 100 times -- writing a 100 times smaller string to avoid out-of-memory errors.- "utf8-light" -> return $ \f -> sequence_ $ replicate 100 $ + "utf8-light" -> return $ \f -> sequence_ $ replicate 100 $ writeUtf8_light (take (n `div` 100) cs) f "via-text" -> do return $ writeUtf8_text tx -- Here, we ensure that the text tx is already packed before timing.- "text" -> do _ <- evaluate (TL.length tx) + "text" -> do _ <- evaluate (TL.length tx) return $ writeUtf8_text tx _ -> error $ "unknown writer '" ++ how ++ "'" t <- timed_ $ writer file@@ -99,4 +99,3 @@ -- | Execute an IO action and return the time it took to execute it. timed_ :: IO a -> IO NominalDiffTime timed_ = (snd `liftM`) . timed-
blaze-builder.cabal view
@@ -1,41 +1,52 @@ Name: blaze-builder-Version: 0.4.2.1+Version: 0.4.2.2 Synopsis: Efficient buffered output. Description:- This library provides an implementation of the older- blaze-builder interface in terms of the new builder that- shipped with bytestring-0.10.4.0- .- This implementation is mostly intended as a bridge to the- new builder, so that code that uses the old interface- can interoperate with code that uses the new- implementation. Note that no attempt has been made- to preserve the old internal modules, so code that- has these dependencies cannot use this interface.- .- New code should, for the most part, use the new- interface. However, this module does implement- a chunked HTTP encoding, which is not otherwise- implemented (yet?) with the new builder.+ This library allows to efficiently serialize Haskell values to lazy bytestrings+ with a large average chunk size. The large average chunk size allows to make+ good use of cache prefetching in later processing steps (e.g. compression) and+ reduces the system call overhead when writing the resulting lazy bytestring to a+ file or sending it over the network.+ .+ This library was inspired by the module Data.Binary.Builder provided by the+ binary package. It was originally developed with the specific needs of the+ blaze-html package in mind. Since then it has been restructured to serve as a+ drop-in replacement for Data.Binary.Builder, which it improves upon both in+ speed as well as expressivity. Author: Jasper Van der Jeugt, Simon Meier, Leon P Smith Copyright: (c) 2010-2014 Simon Meier (c) 2010 Jasper Van der Jeugt (c) 2013-2015 Leon P Smith-Maintainer: Leon Smith <leon@melding-monads.com>+Maintainer: https://github.com/blaze-builder License: BSD3 License-file: LICENSE -Homepage: http://github.com/lpsmith/blaze-builder-Bug-Reports: http://github.com/lpsmith/blaze-builder/issues-Stability: Experimental+Homepage: https://github.com/blaze-builder/blaze-builder+Bug-Reports: https://github.com/blaze-builder/blaze-builder/issues+Stability: Stable Category: Data Build-type: Simple Cabal-version: >= 1.10 +Tested-with:+ GHC == 9.2.0.20210821+ GHC == 9.0.1+ GHC == 8.10.7+ GHC == 8.8.4+ GHC == 8.6.5+ GHC == 8.4.4+ GHC == 8.2.2+ GHC == 8.0.2+ GHC == 7.10.3+ GHC == 7.8.4+ GHC == 7.6.3+ GHC == 7.4.2+ GHC == 7.0.4+ Extra-source-files: Makefile README.markdown@@ -51,10 +62,9 @@ Source-repository head Type: git- Location: https://github.com/lpsmith/blaze-builder.git+ Location: https://github.com/blaze-builder/blaze-builder.git Library- ghc-options: -Wall default-language: Haskell98 exposed-modules: Blaze.ByteString.Builder@@ -70,25 +80,33 @@ Blaze.ByteString.Builder.Internal.Write - build-depends: base == 4.* ,- deepseq,- text >= 0.10 && < 1.3+ build-depends:+ base == 4.*+ , bytestring >= 0.9 && < 1.0+ , deepseq+ , ghc-prim+ , text >= 0.10 && < 1.3 if impl(ghc < 7.8)- build-depends: bytestring >= 0.9 && < 1.0,- bytestring-builder+ build-depends: bytestring-builder else- build-depends: bytestring >= 0.10.4 && < 1.0+ build-depends: bytestring >= 0.10.4 if impl(ghc < 8.0)- build-depends: semigroups >= 0.16 && < 0.20+ build-depends: semigroups >= 0.16 && < 0.20 + ghc-options: -Wall+ if impl(ghc >= 8.0)+ ghc-options: -Wcompat+ test-suite test type: exitcode-stdio-1.0 hs-source-dirs: tests main-is: Tests.hs default-language: Haskell98 ghc-options: -Wall -fno-warn-orphans+ if impl(ghc >= 8.0)+ ghc-options: -Wcompat build-depends: base , blaze-builder
tests/Tests.hs view
@@ -6,8 +6,10 @@ -- module Main where +#if !MIN_VERSION_base(4,8,0) import Control.Applicative ((<$>)) import Data.Monoid (mempty, mappend, mconcat)+#endif import qualified Data.Text as T import qualified Data.ByteString.Lazy as LB@@ -82,8 +84,10 @@ escaping3 :: Assertion escaping3 = fromString ""'" @?= fromHtmlEscapedString "\"'" +#if !MIN_VERSION_bytestring(0,11,1) instance Show Builder where show = show . toLazyByteString+#endif instance Show Write where show = show . fromWrite