summaryrefslogtreecommitdiff
path: root/src/EscapeXML.hs
diff options
context:
space:
mode:
Diffstat (limited to 'src/EscapeXML.hs')
-rw-r--r--src/EscapeXML.hs37
1 files changed, 37 insertions, 0 deletions
diff --git a/src/EscapeXML.hs b/src/EscapeXML.hs
new file mode 100644
index 0000000..662d2ed
--- /dev/null
+++ b/src/EscapeXML.hs
@@ -0,0 +1,37 @@
+{-# 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)