{-# LANGUAGE CPP, BangPatterns, OverloadedStrings #-}
#ifdef USE_MONO_PAT_BINDS
{-# LANGUAGE MonoPatBinds #-}
#endif
{-# OPTIONS_GHC -fno-warn-unused-imports #-}
module Blaze.ByteString.Builder.ByteString
(
writeByteString
, fromByteString
, fromByteStringWith
, copyByteString
, insertByteString
, fromLazyByteString
, fromLazyByteStringWith
, copyLazyByteString
, insertLazyByteString
) where
import Blaze.ByteString.Builder.Internal hiding (insertByteString)
import qualified Blaze.ByteString.Builder.Internal as I (insertByteString)
#ifdef HAS_FOREIGN_UNSAFE_MODULE
import Foreign (withForeignPtr, touchForeignPtr, copyBytes, plusPtr, minusPtr)
import Foreign.ForeignPtr.Unsafe (unsafeForeignPtrToPtr)
#else
import Foreign (unsafeForeignPtrToPtr, withForeignPtr, touchForeignPtr, copyBytes, plusPtr, minusPtr)
#endif
import Data.Monoid
import qualified Data.ByteString as S
import qualified Data.ByteString.Lazy as L
#ifdef BYTESTRING_IN_BASE
import qualified Data.ByteString.Base as S
import qualified Data.ByteString.Lazy.Base as L
#else
import qualified Data.ByteString.Internal as S
import qualified Data.ByteString.Lazy.Internal as L
#endif
writeByteString :: S.ByteString -> Write
writeByteString bs = exactWrite l io
where
(fptr, o, l) = S.toForeignPtr bs
io pf = withForeignPtr fptr $ \p -> copyBytes pf (p `plusPtr` o) l
{-# INLINE writeByteString #-}
fromByteString :: S.ByteString -> Builder
fromByteString = fromByteStringWith defaultMaximalCopySize
{-# INLINE fromByteString #-}
fromByteStringWith :: Int
-> S.ByteString
-> Builder
fromByteStringWith maxCopySize =
\bs -> fromBuildStepCont $ step bs
where
step !bs !k br@(BufRange !op _)
| maxCopySize < S.length bs = return $ I.insertByteString op bs k
| otherwise = copyByteStringStep bs k br
{-# INLINE fromByteStringWith #-}
copyByteString :: S.ByteString -> Builder
copyByteString = \bs -> fromBuildStepCont $ copyByteStringStep bs
{-# INLINE copyByteString #-}
copyByteStringStep :: S.ByteString
-> (BufRange -> IO (BuildSignal a))
-> (BufRange -> IO (BuildSignal a))
copyByteStringStep (S.PS ifp ioff isize) !k =
goBS (unsafeForeignPtrToPtr ifp `plusPtr` ioff)
where
!ipe = unsafeForeignPtrToPtr ifp `plusPtr` (ioff + isize)
goBS !ip !(BufRange op ope)
| inpRemaining <= outRemaining = do
copyBytes op ip inpRemaining
touchForeignPtr ifp
let !br' = BufRange (op `plusPtr` inpRemaining) ope
k br'
| otherwise = do
copyBytes op ip outRemaining
let !ip' = ip `plusPtr` outRemaining
return $ bufferFull 1 ope (goBS ip')
where
outRemaining = ope `minusPtr` op
inpRemaining = ipe `minusPtr` ip
{-# INLINE copyByteStringStep #-}
insertByteString :: S.ByteString -> Builder
insertByteString =
\bs -> fromBuildStepCont $ step bs
where
step !bs !k !(BufRange op _) = return $ I.insertByteString op bs k
{-# INLINE insertByteString #-}
fromLazyByteString :: L.ByteString -> Builder
fromLazyByteString = fromLazyByteStringWith defaultMaximalCopySize
{-# INLINE fromLazyByteString #-}
fromLazyByteStringWith :: Int
-> L.ByteString
-> Builder
fromLazyByteStringWith maxCopySize =
L.foldrChunks (\bs b -> fromByteStringWith maxCopySize bs `mappend` b) mempty
{-# INLINE fromLazyByteStringWith #-}
copyLazyByteString :: L.ByteString -> Builder
copyLazyByteString =
L.foldrChunks (\bs b -> copyByteString bs `mappend` b) mempty
{-# INLINE copyLazyByteString #-}
insertLazyByteString :: L.ByteString -> Builder
insertLazyByteString =
L.foldrChunks (\bs b -> insertByteString bs `mappend` b) mempty
{-# INLINE insertLazyByteString #-}