module Data.Text.Builder.Common.Internal where
import Data.Text (Text)
import Control.Monad.ST
import Data.Monoid
import Text.Printf
import Data.Char (ord)
import Data.Foldable (fold)
import qualified Data.Text as Text
import qualified Data.Text.Array as A
import qualified Data.Text.Internal.Unsafe.Char as TC
portableTextArray :: Text -> A.Array
portableTextArray = fst . portableUntext
{-# INLINE portableTextArray #-}
portableTextLength :: Text -> Int
portableTextLength = snd . portableUntext
{-# INLINE portableTextLength #-}
portableUntext :: Text -> (A.Array,Int)
portableUntext t =
let str = Text.unpack t
Sum len = foldMap (Sum . charUtf16Size) str
arr = A.run $ do
marr <- A.new len
writeString marr str
return marr
in (arr,len)
{-# NOINLINE portableUntext #-}
writeString :: A.MArray s -> String -> ST s ()
writeString marr = go 0 where
go i s = case s of
c : cs -> do
n <- TC.unsafeWrite marr i c
go (i + n) cs
[] -> return ()
charUtf16Size :: Char -> Int
charUtf16Size c = if ord c < 0x10000 then 1 else 2
hexValuesWord12Upper :: A.Array
hexValuesWord12Upper = portableTextArray $ fold
$ map (Text.pack . printf "%03X") [0 :: Int ..4096]
{-# NOINLINE hexValuesWord12Upper #-}
hexValuesWord12Lower :: A.Array
hexValuesWord12Lower = portableTextArray $ fold
$ map (Text.pack . printf "%03x") [0 :: Int ..4096]
{-# NOINLINE hexValuesWord12Lower #-}
hexValuesWord8Upper :: A.Array
hexValuesWord8Upper = portableTextArray $ fold
$ map (Text.pack . printf "%02X") [0 :: Int ..255]
{-# NOINLINE hexValuesWord8Upper #-}
hexValuesWord8Lower :: A.Array
hexValuesWord8Lower = portableTextArray $ fold
$ map (Text.pack . printf "%02x") [0 :: Int ..255]
{-# NOINLINE hexValuesWord8Lower #-}
twoDecimalDigits :: A.Array
twoDecimalDigits = portableTextArray
$ foldMap (Text.pack . printf "%02d") [0 :: Int ..99]
{-# NOINLINE twoDecimalDigits #-}
threeDecimalDigits :: A.Array
threeDecimalDigits = portableTextArray
$ foldMap (Text.pack . printf "%03d") [0 :: Int ..255]
{-# NOINLINE threeDecimalDigits #-}