{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE UnboxedTuples #-}
{-# OPTIONS_HADDOCK hide #-}
module Data.ByteString.Short.Extra (
ShortByteString,
take,
takeWhile,
) where
import Data.ByteString.Short ( ShortByteString )
import qualified Data.ByteString.Short as BS
import qualified Data.ByteString.Short.Internal as BI
import Prelude hiding ( take, takeWhile )
import GHC.ST
import GHC.Exts
import GHC.Word
{-# INLINEABLE take #-}
take :: Int -> ShortByteString -> ShortByteString
take n xs
| n >= BS.length xs = xs
| otherwise = runST $ do
mba <- newByteArray n
copyByteArray (asBA xs) 0 mba 0 n
ba <- unsafeFreezeByteArray mba
return (asSBS ba)
{-# INLINEABLE takeWhile #-}
takeWhile :: (Word8 -> Bool) -> ShortByteString -> ShortByteString
takeWhile f ps = take (findIndexOrEnd (not . f) ps) ps
{-# INLINEABLE findIndexOrEnd #-}
findIndexOrEnd :: (Word8 -> Bool) -> ShortByteString -> Int
findIndexOrEnd p xs = go 0
where
!ba = asBA xs
!n = BS.length xs
go !i | i >= n = i
| p (indexWord8Array ba i) = i
| otherwise = go (i+1)
asBA :: ShortByteString -> BA
asBA (BI.SBS ba#) = BA# ba#
asSBS :: BA -> ShortByteString
asSBS (BA# ba#) = BI.SBS ba#
data BA = BA# ByteArray#
data MBA s = MBA# (MutableByteArray# s)
indexWord8Array :: BA -> Int -> Word8
indexWord8Array (BA# ba#) (I# i#) = W8# (indexWord8Array# ba# i#)
newByteArray :: Int -> ST s (MBA s)
newByteArray (I# len#) =
ST $ \s -> case newByteArray# len# s of
(# s', mba# #) -> (# s', MBA# mba# #)
unsafeFreezeByteArray :: MBA s -> ST s BA
unsafeFreezeByteArray (MBA# mba#) =
ST $ \s -> case unsafeFreezeByteArray# mba# s of
(# s', ba# #) -> (# s', BA# ba# #)
copyByteArray :: BA -> Int -> MBA s -> Int -> Int -> ST s ()
copyByteArray (BA# src#) (I# src_off#) (MBA# dst#) (I# dst_off#) (I# len#) =
ST $ \s -> case copyByteArray# src# src_off# dst# dst_off# len# s of
s' -> (# s', () #)