#if !(MIN_VERSION_bytestring(0,10,0))
#endif
module TextShow.Data.ByteString (
showbByteStringStrict
, showbByteStringLazy
, showbByteStringLazyPrec
, showbShortByteString
) where
import qualified Data.ByteString.Internal as BS
import qualified Data.ByteString.Lazy.Internal as BL
import qualified Data.ByteString.Short as SBS
import Data.ByteString.Short.Internal (ShortByteString(..))
import Data.Text.Lazy.Builder (Builder)
import GHC.Exts (ByteArray#, Char(C#), Int(I#), indexCharArray#)
import TextShow.Classes (TextShow(..))
import TextShow.Data.Char ()
import TextShow.Data.List ()
#if !(MIN_VERSION_bytestring(0,10,0))
import Data.Word (Word8)
import Foreign.ForeignPtr (withForeignPtr)
import Foreign.Ptr (plusPtr)
import Foreign.Storable (peek, peekByteOff)
import TextShow.TH.Internal (deriveTextShow)
#endif
#include "inline.h"
showbByteStringStrict :: BS.ByteString -> Builder
#if MIN_VERSION_bytestring(0,10,0)
showbByteStringStrict = showb . BS.unpackChars
#else
showbByteStringStrict = showb . unpackWith BS.w2c
unpackWith :: (Word8 -> a) -> BS.ByteString -> [a]
unpackWith _ (BS.PS _ _ 0) = []
unpackWith k (BS.PS ps s l) = BS.inlinePerformIO $ withForeignPtr ps $ \p ->
go (p `plusPtr` s) (l 1) []
where
go !p !0 !acc = peek p >>= \e -> return (k e : acc)
go !p !n !acc = peekByteOff p n >>= \e -> go p (n1) (k e : acc)
#endif
showbByteStringLazy :: BL.ByteString -> Builder
showbByteStringLazy = showbByteStringLazyPrec 0
showbByteStringLazyPrec :: Int -> BL.ByteString -> Builder
#if MIN_VERSION_bytestring(0,10,0)
showbByteStringLazyPrec _ = showb . BL.unpackChars
#else
showbByteStringLazyPrec = showbPrec
#endif
showbShortByteString :: ShortByteString -> Builder
showbShortByteString = showb . unpackChars
unpackChars :: ShortByteString -> [Char]
unpackChars bs = unpackAppendCharsLazy bs []
unpackAppendCharsLazy :: ShortByteString -> [Char] -> [Char]
unpackAppendCharsLazy sbs cs0 =
go 0 (SBS.length sbs) cs0
where
sz = 100
go off len cs
| len <= sz = unpackAppendCharsStrict sbs off len cs
| otherwise = unpackAppendCharsStrict sbs off sz remainder
where remainder = go (off+sz) (lensz) cs
unpackAppendCharsStrict :: ShortByteString -> Int -> Int -> [Char] -> [Char]
unpackAppendCharsStrict !sbs off len cs =
go (off1) (off1 + len) cs
where
go !sentinal !i !acc
| i == sentinal = acc
| otherwise = let !c = indexCharArray (asBA sbs) i
in go sentinal (i1) (c:acc)
data BA = BA# ByteArray#
indexCharArray :: BA -> Int -> Char
indexCharArray (BA# ba#) (I# i#) = C# (indexCharArray# ba# i#)
asBA :: ShortByteString -> BA
asBA (SBS ba#) = BA# ba#
instance TextShow BS.ByteString where
showb = showbByteStringStrict
INLINE_INST_FUN(showb)
#if MIN_VERSION_bytestring(0,10,0)
instance TextShow BL.ByteString where
showbPrec = showbByteStringLazyPrec
INLINE_INST_FUN(showbPrec)
#else
$(deriveTextShow ''BL.ByteString)
#endif
instance TextShow ShortByteString where
showb = showbShortByteString
INLINE_INST_FUN(showb)