{-# LANGUAGE BangPatterns #-}
module Data.Attoparsec.ByteString.Buffer
(
Buffer
, buffer
, unbuffer
, pappend
, length
, unsafeIndex
, substring
, unsafeDrop
) where
import Control.Exception (assert)
import Data.ByteString.Internal (ByteString(..), memcpy, nullForeignPtr)
import Data.Attoparsec.Internal.Fhthagn (inlinePerformIO)
import Data.Attoparsec.Internal.Compat
import Data.List (foldl1')
import Data.Monoid as Mon (Monoid(..))
import Data.Semigroup (Semigroup(..))
import Data.Word (Word8)
import Foreign.ForeignPtr (ForeignPtr, withForeignPtr)
import Foreign.Ptr (castPtr, plusPtr)
import Foreign.Storable (peek, peekByteOff, poke, sizeOf)
import GHC.ForeignPtr (mallocPlainForeignPtrBytes)
import Prelude hiding (length)
data Buffer = Buf {
Buffer -> ForeignPtr Word8
_fp :: {-# UNPACK #-} !(ForeignPtr Word8)
, Buffer -> Int
_off :: {-# UNPACK #-} !Int
, Buffer -> Int
_len :: {-# UNPACK #-} !Int
, Buffer -> Int
_cap :: {-# UNPACK #-} !Int
, Buffer -> Int
_gen :: {-# UNPACK #-} !Int
}
instance Show Buffer where
showsPrec :: Int -> Buffer -> ShowS
showsPrec Int
p = forall a. Show a => Int -> a -> ShowS
showsPrec Int
p forall b c a. (b -> c) -> (a -> b) -> a -> c
. Buffer -> ByteString
unbuffer
buffer :: ByteString -> Buffer
buffer :: ByteString -> Buffer
buffer ByteString
bs = forall r. ByteString -> (ForeignPtr Word8 -> Int -> Int -> r) -> r
withPS ByteString
bs forall a b. (a -> b) -> a -> b
$ \ForeignPtr Word8
fp Int
off Int
len -> ForeignPtr Word8 -> Int -> Int -> Int -> Int -> Buffer
Buf ForeignPtr Word8
fp Int
off Int
len Int
len Int
0
unbuffer :: Buffer -> ByteString
unbuffer :: Buffer -> ByteString
unbuffer (Buf ForeignPtr Word8
fp Int
off Int
len Int
_ Int
_) = ForeignPtr Word8 -> Int -> Int -> ByteString
mkPS ForeignPtr Word8
fp Int
off Int
len
instance Semigroup Buffer where
(Buf ForeignPtr Word8
_ Int
_ Int
_ Int
0 Int
_) <> :: Buffer -> Buffer -> Buffer
<> Buffer
b = Buffer
b
Buffer
a <> (Buf ForeignPtr Word8
_ Int
_ Int
_ Int
0 Int
_) = Buffer
a
Buffer
buf <> (Buf ForeignPtr Word8
fp Int
off Int
len Int
_ Int
_) = forall a. Buffer -> ForeignPtr a -> Int -> Int -> Buffer
append Buffer
buf ForeignPtr Word8
fp Int
off Int
len
instance Monoid Buffer where
mempty :: Buffer
mempty = ForeignPtr Word8 -> Int -> Int -> Int -> Int -> Buffer
Buf ForeignPtr Word8
nullForeignPtr Int
0 Int
0 Int
0 Int
0
mappend :: Buffer -> Buffer -> Buffer
mappend = forall a. Semigroup a => a -> a -> a
(<>)
mconcat :: [Buffer] -> Buffer
mconcat [] = forall a. Monoid a => a
Mon.mempty
mconcat [Buffer]
xs = forall a. (a -> a -> a) -> [a] -> a
foldl1' forall a. Monoid a => a -> a -> a
mappend [Buffer]
xs
pappend :: Buffer -> ByteString -> Buffer
pappend :: Buffer -> ByteString -> Buffer
pappend (Buf ForeignPtr Word8
_ Int
_ Int
_ Int
0 Int
_) ByteString
bs = ByteString -> Buffer
buffer ByteString
bs
pappend Buffer
buf ByteString
bs = forall r. ByteString -> (ForeignPtr Word8 -> Int -> Int -> r) -> r
withPS ByteString
bs forall a b. (a -> b) -> a -> b
$ \ForeignPtr Word8
fp Int
off Int
len -> forall a. Buffer -> ForeignPtr a -> Int -> Int -> Buffer
append Buffer
buf ForeignPtr Word8
fp Int
off Int
len
append :: Buffer -> ForeignPtr a -> Int -> Int -> Buffer
append :: forall a. Buffer -> ForeignPtr a -> Int -> Int -> Buffer
append (Buf ForeignPtr Word8
fp0 Int
off0 Int
len0 Int
cap0 Int
gen0) !ForeignPtr a
fp1 !Int
off1 !Int
len1 =
forall a. IO a -> a
inlinePerformIO forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr Word8
fp0 forall a b. (a -> b) -> a -> b
$ \Ptr Word8
ptr0 ->
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr a
fp1 forall a b. (a -> b) -> a -> b
$ \Ptr a
ptr1 -> do
let genSize :: Int
genSize = forall a. Storable a => a -> Int
sizeOf (Int
0::Int)
newlen :: Int
newlen = Int
len0 forall a. Num a => a -> a -> a
+ Int
len1
Int
gen <- if Int
gen0 forall a. Eq a => a -> a -> Bool
== Int
0
then forall (m :: * -> *) a. Monad m => a -> m a
return Int
0
else forall a. Storable a => Ptr a -> IO a
peek (forall a b. Ptr a -> Ptr b
castPtr Ptr Word8
ptr0)
if Int
gen forall a. Eq a => a -> a -> Bool
== Int
gen0 Bool -> Bool -> Bool
&& Int
newlen forall a. Ord a => a -> a -> Bool
<= Int
cap0
then do
let newgen :: Int
newgen = Int
gen forall a. Num a => a -> a -> a
+ Int
1
forall a. Storable a => Ptr a -> a -> IO ()
poke (forall a b. Ptr a -> Ptr b
castPtr Ptr Word8
ptr0) Int
newgen
Ptr Word8 -> Ptr Word8 -> Int -> IO ()
memcpy (Ptr Word8
ptr0 forall a b. Ptr a -> Int -> Ptr b
`plusPtr` (Int
off0forall a. Num a => a -> a -> a
+Int
len0))
(Ptr a
ptr1 forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
off1)
(forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len1)
forall (m :: * -> *) a. Monad m => a -> m a
return (ForeignPtr Word8 -> Int -> Int -> Int -> Int -> Buffer
Buf ForeignPtr Word8
fp0 Int
off0 Int
newlen Int
cap0 Int
newgen)
else do
let newcap :: Int
newcap = Int
newlen forall a. Num a => a -> a -> a
* Int
2
ForeignPtr Word8
fp <- forall a. Int -> IO (ForeignPtr a)
mallocPlainForeignPtrBytes (Int
newcap forall a. Num a => a -> a -> a
+ Int
genSize)
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr Word8
fp forall a b. (a -> b) -> a -> b
$ \Ptr Word8
ptr_ -> do
let ptr :: Ptr b
ptr = Ptr Word8
ptr_ forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
genSize
newgen :: Int
newgen = Int
1
forall a. Storable a => Ptr a -> a -> IO ()
poke (forall a b. Ptr a -> Ptr b
castPtr Ptr Word8
ptr_) Int
newgen
Ptr Word8 -> Ptr Word8 -> Int -> IO ()
memcpy forall {b}. Ptr b
ptr (Ptr Word8
ptr0 forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
off0) (forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len0)
Ptr Word8 -> Ptr Word8 -> Int -> IO ()
memcpy (forall {b}. Ptr b
ptr forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
len0) (Ptr a
ptr1 forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
off1)
(forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len1)
forall (m :: * -> *) a. Monad m => a -> m a
return (ForeignPtr Word8 -> Int -> Int -> Int -> Int -> Buffer
Buf ForeignPtr Word8
fp Int
genSize Int
newlen Int
newcap Int
newgen)
length :: Buffer -> Int
length :: Buffer -> Int
length (Buf ForeignPtr Word8
_ Int
_ Int
len Int
_ Int
_) = Int
len
{-# INLINE length #-}
unsafeIndex :: Buffer -> Int -> Word8
unsafeIndex :: Buffer -> Int -> Word8
unsafeIndex (Buf ForeignPtr Word8
fp Int
off Int
len Int
_ Int
_) Int
i = forall a. (?callStack::CallStack) => Bool -> a -> a
assert (Int
i forall a. Ord a => a -> a -> Bool
>= Int
0 Bool -> Bool -> Bool
&& Int
i forall a. Ord a => a -> a -> Bool
< Int
len) forall b c a. (b -> c) -> (a -> b) -> a -> c
.
forall a. IO a -> a
inlinePerformIO forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr Word8
fp forall a b. (a -> b) -> a -> b
$ forall a b c. (a -> b -> c) -> b -> a -> c
flip forall a b. Storable a => Ptr b -> Int -> IO a
peekByteOff (Int
offforall a. Num a => a -> a -> a
+Int
i)
{-# INLINE unsafeIndex #-}
substring :: Int -> Int -> Buffer -> ByteString
substring :: Int -> Int -> Buffer -> ByteString
substring Int
s Int
l (Buf ForeignPtr Word8
fp Int
off Int
len Int
_ Int
_) =
forall a. (?callStack::CallStack) => Bool -> a -> a
assert (Int
s forall a. Ord a => a -> a -> Bool
>= Int
0 Bool -> Bool -> Bool
&& Int
s forall a. Ord a => a -> a -> Bool
<= Int
len) forall b c a. (b -> c) -> (a -> b) -> a -> c
.
forall a. (?callStack::CallStack) => Bool -> a -> a
assert (Int
l forall a. Ord a => a -> a -> Bool
>= Int
0 Bool -> Bool -> Bool
&& Int
l forall a. Ord a => a -> a -> Bool
<= Int
lenforall a. Num a => a -> a -> a
-Int
s) forall a b. (a -> b) -> a -> b
$
ForeignPtr Word8 -> Int -> Int -> ByteString
mkPS ForeignPtr Word8
fp (Int
offforall a. Num a => a -> a -> a
+Int
s) Int
l
{-# INLINE substring #-}
unsafeDrop :: Int -> Buffer -> ByteString
unsafeDrop :: Int -> Buffer -> ByteString
unsafeDrop Int
s (Buf ForeignPtr Word8
fp Int
off Int
len Int
_ Int
_) =
forall a. (?callStack::CallStack) => Bool -> a -> a
assert (Int
s forall a. Ord a => a -> a -> Bool
>= Int
0 Bool -> Bool -> Bool
&& Int
s forall a. Ord a => a -> a -> Bool
<= Int
len) forall a b. (a -> b) -> a -> b
$
ForeignPtr Word8 -> Int -> Int -> ByteString
mkPS ForeignPtr Word8
fp (Int
offforall a. Num a => a -> a -> a
+Int
s) (Int
lenforall a. Num a => a -> a -> a
-Int
s)
{-# INLINE unsafeDrop #-}