{-# LANGUAGE BangPatterns #-} {-# LANGUAGE MagicHash #-} {-# LANGUAGE UnboxedTuples #-} {-# LANGUAGE UnliftedFFITypes #-} module EscapeXML (escapeXML) where import Data.Array.Byte import Data.Text.Internal import Foreign.C.Types import GHC.Exts import GHC.IO (IO(IO)) import System.IO.Unsafe (unsafePerformIO) foreign import ccall unsafe "tirclogv_escapexml_len" c_escapexml_len :: ByteArray# -> CSize -> CSize -> IO CSize foreign import ccall unsafe "tirclogv_escapexml" c_escapexml :: MutableByteArray# RealWorld -> ByteArray# -> CSize -> CSize -> IO () {-# NOINLINE escapeXML #-} escapeXML :: Text -> Text escapeXML (Text (ByteArray src#) off len) = unsafePerformIO $ do let offCS = fromIntegral @Int @CSize off lenCS = fromIntegral @Int @CSize len reslen <- c_escapexml_len src# offCS lenCS let !reslenI@(I# reslen#) = fromIntegral @CSize @Int reslen MutableByteArray dst# <- IO $ \s -> case newByteArray# reslen# s of (# s', mba# #) -> (# s', MutableByteArray mba# #) c_escapexml dst# src# offCS lenCS ba <- IO $ \s -> case unsafeFreezeByteArray# dst# s of (# s', ba# #) -> (# s', ByteArray ba# #) return (Text ba 0 reslenI)