{-# 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 a. (forall s. ST s a) -> a
runST (do
MArray s
dst <- forall s. Int -> ST s (MArray s)
A.new Int
n
forall s. MArray s -> Int -> ST s ()
write MArray s
dst Int
0
Array
arr <- forall s. MArray s -> ST s Array
A.unsafeFreeze MArray s
dst
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Array -> Int -> Int -> Text
Text Array
arr Int
0 Int
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 = 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
_ -> 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 forall a. Num a => a -> a -> a
+ Int
n2) (\MArray s
dst Int
ofs -> do
forall s. MArray s -> Int -> ST s ()
write2 MArray s
dst (Int
ofs forall a. Num a => a -> a -> a
+ Int
n1)
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 = forall r. ByteString -> (ForeignPtr Word8 -> Int -> r) -> r
withBS ByteString
src forall a b. (a -> b) -> a -> b
$ \ ForeignPtr Word8
srcFPtr Int
len ->
forall a s. IO a -> ST s a
unsafeIOToST forall a b. (a -> b) -> a -> b
$ forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
unsafeWithForeignPtr ForeignPtr Word8
srcFPtr forall a b. (a -> b) -> a -> b
$ \ Ptr Word8
srcPtr -> do
forall s a. ST s a -> IO a
unsafeSTToIO forall a b. (a -> b) -> a -> b
$ 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 -> 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 -> forall (f :: * -> *) a. Functor f => f a -> f ()
void (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 -> 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 ->
forall s. Int -> MArray s -> Int -> Array -> Int -> ST s ()
A.copyI Int
n MArray s
dst Int
dstOfs Array
src Int
srcOfs)