{-# LANGUAGE MagicHash, BangPatterns #-}
module Text.Regex.PCRE.Precompile where
import Control.Monad (liftM)
import Data.ByteString.Char8 (ByteString, packCStringLen)
import Data.ByteString.Internal (toForeignPtr)
import Foreign.C.Types (CSize)
import Foreign.ForeignPtr (withForeignPtr)
import Foreign.Ptr (nullPtr, castPtr)
import Foreign.Marshal (alloca)
import Foreign.Storable (peek)
import GHC.Exts (Int(..), plusAddr#)
import GHC.ForeignPtr (ForeignPtr(..))
import Text.Regex.PCRE.Light
import Text.Regex.PCRE.Light.Base
type CompiledBytes = ByteString
precompile :: ByteString -> [PCREOption] -> IO (Maybe CompiledBytes)
precompile :: ByteString -> [PCREOption] -> IO (Maybe ByteString)
precompile ByteString
pat [PCREOption]
opts = Regex -> IO (Maybe ByteString)
regexToTable (Regex -> IO (Maybe ByteString)) -> Regex -> IO (Maybe ByteString)
forall a b. (a -> b) -> a -> b
$ ByteString -> [PCREOption] -> Regex
compile ByteString
pat [PCREOption]
opts
regexToTable :: Regex -> IO (Maybe CompiledBytes)
regexToTable :: Regex -> IO (Maybe ByteString)
regexToTable (Regex ForeignPtr PCRE
p ByteString
_) =
ForeignPtr PCRE
-> (Ptr PCRE -> IO (Maybe ByteString)) -> IO (Maybe ByteString)
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr PCRE
p ((Ptr PCRE -> IO (Maybe ByteString)) -> IO (Maybe ByteString))
-> (Ptr PCRE -> IO (Maybe ByteString)) -> IO (Maybe ByteString)
forall a b. (a -> b) -> a -> b
$ \Ptr PCRE
pcre -> (Ptr CSize -> IO (Maybe ByteString)) -> IO (Maybe ByteString)
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr CSize -> IO (Maybe ByteString)) -> IO (Maybe ByteString))
-> (Ptr CSize -> IO (Maybe ByteString)) -> IO (Maybe ByteString)
forall a b. (a -> b) -> a -> b
$ \Ptr CSize
res -> do
CInt
success <- Ptr PCRE -> Ptr PCRE -> CInt -> Ptr CSize -> IO CInt
forall a. Ptr PCRE -> Ptr PCRE -> CInt -> Ptr a -> IO CInt
c_pcre_fullinfo Ptr PCRE
pcre Ptr PCRE
forall a. Ptr a
nullPtr CInt
info_size Ptr CSize
res
Int
len <- Int -> IO Int
forall (m :: * -> *) a. Monad m => a -> m a
return (Int -> IO Int) -> (CSize -> Int) -> CSize -> IO Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CSize -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (CSize -> IO Int) -> IO CSize -> IO Int
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< (Ptr CSize -> IO CSize
forall a. Storable a => Ptr a -> IO a
peek Ptr CSize
res :: IO CSize)
if CInt
success CInt -> CInt -> Bool
forall a. Ord a => a -> a -> Bool
>= CInt
0
then (ByteString -> Maybe ByteString)
-> IO ByteString -> IO (Maybe ByteString)
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM ByteString -> Maybe ByteString
forall a. a -> Maybe a
Just (IO ByteString -> IO (Maybe ByteString))
-> IO ByteString -> IO (Maybe ByteString)
forall a b. (a -> b) -> a -> b
$ CStringLen -> IO ByteString
packCStringLen (Ptr PCRE -> Ptr CChar
forall a b. Ptr a -> Ptr b
castPtr Ptr PCRE
pcre, Int
len)
else Maybe ByteString -> IO (Maybe ByteString)
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe ByteString
forall a. Maybe a
Nothing
regexFromTable :: CompiledBytes -> IO Regex
regexFromTable :: ByteString -> IO Regex
regexFromTable ByteString
bytes =
Regex -> IO Regex
forall (m :: * -> *) a. Monad m => a -> m a
return (Regex -> IO Regex) -> Regex -> IO Regex
forall a b. (a -> b) -> a -> b
$ ForeignPtr PCRE -> ByteString -> Regex
Regex (Addr# -> ForeignPtrContents -> ForeignPtr PCRE
forall a. Addr# -> ForeignPtrContents -> ForeignPtr a
ForeignPtr (Addr# -> Int# -> Addr#
plusAddr# Addr#
addr Int#
offset) ForeignPtrContents
content) ByteString
bytes
where
!(ForeignPtr Addr#
addr ForeignPtrContents
content, I# Int#
offset, Int
_) = ByteString -> (ForeignPtr Word8, Int, Int)
toForeignPtr ByteString
bytes