{-# LANGUAGE CPP #-}
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE RankNTypes #-}
module Data.Text.Internal.StrictBuilder
( StrictBuilder(..)
, toText
, fromChar
, fromText
, unsafeFromByteString
, unsafeFromWord8
) where
import Control.Monad.ST (ST, runST)
import Control.Monad.ST.Unsafe (unsafeIOToST, unsafeSTToIO)
import Data.Functor (void)
import Data.Word (Word8)
import Data.ByteString (ByteString)
#if !MIN_VERSION_base(4,11,0)
import Data.Semigroup (Semigroup(..))
#endif
import Data.Text.Internal (Text(..), empty, safe)
import Data.Text.Internal.ByteStringCompat (withBS)
import Data.Text.Internal.Encoding.Utf8 (utf8Length)
import Data.Text.Internal.Unsafe (unsafeWithForeignPtr)
import qualified Data.ByteString as B
import qualified Data.Text.Array as A
import qualified Data.Text.Internal.Unsafe.Char as Char
data StrictBuilder = StrictBuilder
{ StrictBuilder -> Int
sbLength :: {-# UNPACK #-} !Int
, StrictBuilder -> forall s. MArray s -> Int -> ST s ()
sbWrite :: forall s. A.MArray s -> Int -> ST s ()
}
toText :: StrictBuilder -> Text
toText :: StrictBuilder -> Text
toText (StrictBuilder Int
0 forall s. MArray s -> Int -> ST s ()
_) = Text
empty
toText (StrictBuilder Int
n forall s. MArray s -> Int -> ST s ()
write) = (forall s. ST s Text) -> Text
forall a. (forall s. ST s a) -> a
runST (do
dst <- Int -> ST s (MArray s)
forall s. Int -> ST s (MArray s)
A.new Int
n
write dst 0
arr <- A.unsafeFreeze dst
pure (Text arr 0 n))
instance Semigroup StrictBuilder where
<> :: StrictBuilder -> StrictBuilder -> StrictBuilder
(<>) = StrictBuilder -> StrictBuilder -> StrictBuilder
appendRStrictBuilder
instance Monoid StrictBuilder where
mempty :: StrictBuilder
mempty = StrictBuilder
emptyStrictBuilder
mappend :: StrictBuilder -> StrictBuilder -> StrictBuilder
mappend = StrictBuilder -> StrictBuilder -> StrictBuilder
forall a. Semigroup a => a -> a -> a
(<>)
emptyStrictBuilder :: StrictBuilder
emptyStrictBuilder :: StrictBuilder
emptyStrictBuilder = Int -> (forall s. MArray s -> Int -> ST s ()) -> StrictBuilder
StrictBuilder Int
0 (\MArray s
_ Int
_ -> () -> ST s ()
forall a. a -> ST s a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ())
appendRStrictBuilder :: StrictBuilder -> StrictBuilder -> StrictBuilder
appendRStrictBuilder :: StrictBuilder -> StrictBuilder -> StrictBuilder
appendRStrictBuilder (StrictBuilder Int
0 forall s. MArray s -> Int -> ST s ()
_) StrictBuilder
b2 = StrictBuilder
b2
appendRStrictBuilder StrictBuilder
b1 (StrictBuilder Int
0 forall s. MArray s -> Int -> ST s ()
_) = StrictBuilder
b1
appendRStrictBuilder (StrictBuilder Int
n1 forall s. MArray s -> Int -> ST s ()
write1) (StrictBuilder Int
n2 forall s. MArray s -> Int -> ST s ()
write2) =
Int -> (forall s. MArray s -> Int -> ST s ()) -> StrictBuilder
StrictBuilder (Int
n1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
n2) (\MArray s
dst Int
ofs -> do
MArray s -> Int -> ST s ()
forall s. MArray s -> Int -> ST s ()
write2 MArray s
dst (Int
ofs Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
n1)
MArray s -> Int -> ST s ()
forall s. MArray s -> Int -> ST s ()
write1 MArray s
dst Int
ofs)
copyFromByteString :: A.MArray s -> Int -> ByteString -> ST s ()
copyFromByteString :: forall s. MArray s -> Int -> ByteString -> ST s ()
copyFromByteString MArray s
dst Int
ofs ByteString
src = ByteString -> (ForeignPtr Word8 -> Int -> ST s ()) -> ST s ()
forall r. ByteString -> (ForeignPtr Word8 -> Int -> r) -> r
withBS ByteString
src ((ForeignPtr Word8 -> Int -> ST s ()) -> ST s ())
-> (ForeignPtr Word8 -> Int -> ST s ()) -> ST s ()
forall a b. (a -> b) -> a -> b
$ \ ForeignPtr Word8
srcFPtr Int
len ->
IO () -> ST s ()
forall a s. IO a -> ST s a
unsafeIOToST (IO () -> ST s ()) -> IO () -> ST s ()
forall a b. (a -> b) -> a -> b
$ ForeignPtr Word8 -> (Ptr Word8 -> IO ()) -> IO ()
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
unsafeWithForeignPtr ForeignPtr Word8
srcFPtr ((Ptr Word8 -> IO ()) -> IO ()) -> (Ptr Word8 -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \ Ptr Word8
srcPtr -> do
ST s () -> IO ()
forall s a. ST s a -> IO a
unsafeSTToIO (ST s () -> IO ()) -> ST s () -> IO ()
forall a b. (a -> b) -> a -> b
$ MArray s -> Int -> Ptr Word8 -> Int -> ST s ()
forall s. MArray s -> Int -> Ptr Word8 -> Int -> ST s ()
A.copyFromPointer MArray s
dst Int
ofs Ptr Word8
srcPtr Int
len
unsafeFromByteString :: ByteString -> StrictBuilder
unsafeFromByteString :: ByteString -> StrictBuilder
unsafeFromByteString ByteString
bs =
Int -> (forall s. MArray s -> Int -> ST s ()) -> StrictBuilder
StrictBuilder (ByteString -> Int
B.length ByteString
bs) (\MArray s
dst Int
ofs -> MArray s -> Int -> ByteString -> ST s ()
forall s. MArray s -> Int -> ByteString -> ST s ()
copyFromByteString MArray s
dst Int
ofs ByteString
bs)
{-# INLINE fromChar #-}
fromChar :: Char -> StrictBuilder
fromChar :: Char -> StrictBuilder
fromChar Char
c =
Int -> (forall s. MArray s -> Int -> ST s ()) -> StrictBuilder
StrictBuilder (Char -> Int
utf8Length Char
c) (\MArray s
dst Int
ofs -> ST s Int -> ST s ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (MArray s -> Int -> Char -> ST s Int
forall s. MArray s -> Int -> Char -> ST s Int
Char.unsafeWrite MArray s
dst Int
ofs (Char -> Char
safe Char
c)))
unsafeFromWord8 :: Word8 -> StrictBuilder
unsafeFromWord8 :: Word8 -> StrictBuilder
unsafeFromWord8 !Word8
w =
Int -> (forall s. MArray s -> Int -> ST s ()) -> StrictBuilder
StrictBuilder Int
1 (\MArray s
dst Int
ofs -> MArray s -> Int -> Word8 -> ST s ()
forall s. MArray s -> Int -> Word8 -> ST s ()
A.unsafeWrite MArray s
dst Int
ofs Word8
w)
fromText :: Text -> StrictBuilder
fromText :: Text -> StrictBuilder
fromText (Text Array
src Int
srcOfs Int
n) = Int -> (forall s. MArray s -> Int -> ST s ()) -> StrictBuilder
StrictBuilder Int
n (\MArray s
dst Int
dstOfs ->
Int -> MArray s -> Int -> Array -> Int -> ST s ()
forall s. Int -> MArray s -> Int -> Array -> Int -> ST s ()
A.copyI Int
n MArray s
dst Int
dstOfs Array
src Int
srcOfs)