{-# LANGUAGE CPP #-}
module Text.Regex.PCRE.Light (
Regex
, compile, compileM
, match
, captureCount
, PCREOption
, anchored
, auto_callout
, caseless
, dollar_endonly
, dotall
, dupnames
, extended
, extra
, firstline
, multiline
, newline_cr
, newline_crlf
, newline_lf
, no_auto_capture
, ungreedy
, utf8
, no_utf8_check
, PCREExecOption
, exec_anchored
, exec_newline_cr
, exec_newline_crlf
, exec_newline_lf
, exec_notbol
, exec_noteol
, exec_notempty
, exec_no_utf8_check
, exec_partial
) where
import Text.Regex.PCRE.Light.Base
import qualified Data.ByteString as S
#if __GLASGOW_HASKELL__ >= 608
import qualified Data.ByteString.Internal as S
import qualified Data.ByteString.Unsafe as S
#else
import qualified Data.ByteString.Base as S
#endif
import System.IO.Unsafe (unsafePerformIO)
import Foreign (newForeignPtr, withForeignPtr)
import Foreign.Ptr
import Foreign.C.Types
import Foreign.C.String
import Foreign.Storable
import Foreign.Marshal.Alloc
compile :: S.ByteString -> [PCREOption] -> Regex
compile :: ByteString -> [PCREOption] -> Regex
compile ByteString
s [PCREOption]
o = case ByteString -> [PCREOption] -> Either String Regex
compileM ByteString
s [PCREOption]
o of
Right Regex
r -> Regex
r
Left String
e -> String -> Regex
forall a. HasCallStack => String -> a
error (String
"Text.Regex.PCRE.Light: Error in regex: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
e)
compileM :: S.ByteString -> [PCREOption] -> Either String Regex
compileM :: ByteString -> [PCREOption] -> Either String Regex
compileM ByteString
str [PCREOption]
os = IO (Either String Regex) -> Either String Regex
forall a. IO a -> a
unsafePerformIO (IO (Either String Regex) -> Either String Regex)
-> IO (Either String Regex) -> Either String Regex
forall a b. (a -> b) -> a -> b
$
ByteString
-> (CString -> IO (Either String Regex))
-> IO (Either String Regex)
forall a. ByteString -> (CString -> IO a) -> IO a
S.useAsCString ByteString
str ((CString -> IO (Either String Regex)) -> IO (Either String Regex))
-> (CString -> IO (Either String Regex))
-> IO (Either String Regex)
forall a b. (a -> b) -> a -> b
$ \CString
pattern -> do
(Ptr CString -> IO (Either String Regex))
-> IO (Either String Regex)
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr CString -> IO (Either String Regex))
-> IO (Either String Regex))
-> (Ptr CString -> IO (Either String Regex))
-> IO (Either String Regex)
forall a b. (a -> b) -> a -> b
$ \Ptr CString
errptr -> do
(Ptr CInt -> IO (Either String Regex)) -> IO (Either String Regex)
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr CInt -> IO (Either String Regex))
-> IO (Either String Regex))
-> (Ptr CInt -> IO (Either String Regex))
-> IO (Either String Regex)
forall a b. (a -> b) -> a -> b
$ \Ptr CInt
erroffset -> do
Ptr PCRE
pcre_ptr <- CString
-> PCREOption
-> Ptr CString
-> Ptr CInt
-> Ptr Word8
-> IO (Ptr PCRE)
c_pcre_compile CString
pattern ([PCREOption] -> PCREOption
combineOptions [PCREOption]
os) Ptr CString
errptr Ptr CInt
erroffset Ptr Word8
forall a. Ptr a
nullPtr
if Ptr PCRE
pcre_ptr Ptr PCRE -> Ptr PCRE -> Bool
forall a. Eq a => a -> a -> Bool
== Ptr PCRE
forall a. Ptr a
nullPtr
then do
String
err <- CString -> IO String
peekCString (CString -> IO String) -> IO CString -> IO String
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Ptr CString -> IO CString
forall a. Storable a => Ptr a -> IO a
peek Ptr CString
errptr
Either String Regex -> IO (Either String Regex)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (String -> Either String Regex
forall a b. a -> Either a b
Left String
err)
else do
ForeignPtr PCRE
reg <- FinalizerPtr PCRE -> Ptr PCRE -> IO (ForeignPtr PCRE)
forall a. FinalizerPtr a -> Ptr a -> IO (ForeignPtr a)
newForeignPtr FinalizerPtr PCRE
forall a. FinalizerPtr a
finalizerFree Ptr PCRE
pcre_ptr
Either String Regex -> IO (Either String Regex)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Regex -> Either String Regex
forall a b. b -> Either a b
Right (ForeignPtr PCRE -> ByteString -> Regex
Regex ForeignPtr PCRE
reg ByteString
str))
match :: Regex -> S.ByteString -> [PCREExecOption] -> Maybe [S.ByteString]
match :: Regex -> ByteString -> [PCREExecOption] -> Maybe [ByteString]
match (Regex ForeignPtr PCRE
pcre_fp ByteString
_) ByteString
subject [PCREExecOption]
os = IO (Maybe [ByteString]) -> Maybe [ByteString]
forall a. IO a -> a
unsafePerformIO (IO (Maybe [ByteString]) -> Maybe [ByteString])
-> IO (Maybe [ByteString]) -> Maybe [ByteString]
forall a b. (a -> b) -> a -> b
$ do
ForeignPtr PCRE
-> (Ptr PCRE -> IO (Maybe [ByteString])) -> IO (Maybe [ByteString])
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr PCRE
pcre_fp ((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 -> do
Int
n_capt <- Ptr PCRE -> IO Int
forall {b}. Num b => Ptr PCRE -> IO b
captureCount' Ptr PCRE
pcre_ptr
let ovec_size :: Int
ovec_size = (Int
n_capt Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
3
ovec_bytes :: Int
ovec_bytes = Int
ovec_size Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
size_of_cint
Int
-> (Ptr CInt -> IO (Maybe [ByteString])) -> IO (Maybe [ByteString])
forall a b. Int -> (Ptr a -> IO b) -> IO b
allocaBytes Int
ovec_bytes ((Ptr CInt -> IO (Maybe [ByteString])) -> IO (Maybe [ByteString]))
-> (Ptr CInt -> IO (Maybe [ByteString])) -> IO (Maybe [ByteString])
forall a b. (a -> b) -> a -> b
$ \Ptr CInt
ovec -> do
let (ForeignPtr Word8
str_fp, Int
off, Int
len) = ByteString -> (ForeignPtr Word8, Int, Int)
S.toForeignPtr ByteString
subject
ForeignPtr Word8
-> (Ptr Word8 -> IO (Maybe [ByteString]))
-> IO (Maybe [ByteString])
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr Word8
str_fp ((Ptr Word8 -> IO (Maybe [ByteString])) -> IO (Maybe [ByteString]))
-> (Ptr Word8 -> IO (Maybe [ByteString]))
-> IO (Maybe [ByteString])
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
cstr -> do
CInt
r <- Ptr PCRE
-> Ptr PCRE
-> Ptr Word8
-> CInt
-> CInt
-> PCREExecOption
-> Ptr CInt
-> CInt
-> IO CInt
c_pcre_exec
Ptr PCRE
pcre_ptr
Ptr PCRE
forall a. Ptr a
nullPtr
(Ptr Word8
cstr Ptr Word8 -> Int -> Ptr Word8
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
off)
(Int -> CInt
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len)
CInt
0
([PCREExecOption] -> PCREExecOption
combineExecOptions [PCREExecOption]
os)
Ptr CInt
ovec
(Int -> CInt
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
ovec_size)
if CInt
r CInt -> CInt -> Bool
forall a. Ord a => a -> a -> Bool
< CInt
0
then Maybe [ByteString] -> IO (Maybe [ByteString])
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe [ByteString]
forall a. Maybe a
Nothing
else let loop :: CInt -> Int -> [ByteString] -> IO (Maybe [ByteString])
loop CInt
n Int
o [ByteString]
acc =
if CInt
n CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
== CInt
r
then Maybe [ByteString] -> IO (Maybe [ByteString])
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ([ByteString] -> Maybe [ByteString]
forall a. a -> Maybe a
Just ([ByteString] -> [ByteString]
forall a. [a] -> [a]
reverse [ByteString]
acc))
else do
CInt
i <- Ptr CInt -> Int -> IO CInt
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff Ptr CInt
ovec (Int -> IO CInt) -> Int -> IO CInt
forall a b. (a -> b) -> a -> b
$! Int
o
CInt
j <- Ptr CInt -> Int -> IO CInt
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff Ptr CInt
ovec (Int
oInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1)
let s :: ByteString
s = CInt -> CInt -> ByteString -> ByteString
substring CInt
i CInt
j ByteString
subject
ByteString
s ByteString -> IO (Maybe [ByteString]) -> IO (Maybe [ByteString])
forall a b. a -> b -> b
`seq` CInt -> Int -> [ByteString] -> IO (Maybe [ByteString])
loop (CInt
nCInt -> CInt -> CInt
forall a. Num a => a -> a -> a
+CInt
1) (Int
oInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
2) (ByteString
s ByteString -> [ByteString] -> [ByteString]
forall a. a -> [a] -> [a]
: [ByteString]
acc)
in CInt -> Int -> [ByteString] -> IO (Maybe [ByteString])
loop CInt
0 Int
0 []
where
substring :: CInt -> CInt -> S.ByteString -> S.ByteString
substring :: CInt -> CInt -> ByteString -> ByteString
substring CInt
x CInt
y ByteString
_ | CInt
x CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
== CInt
y = ByteString
S.empty
substring CInt
a CInt
b ByteString
s = ByteString
end
where
start :: ByteString
start = Int -> ByteString -> ByteString
S.unsafeDrop (CInt -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral CInt
a) ByteString
s
end :: ByteString
end = Int -> ByteString -> ByteString
S.unsafeTake (CInt -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (CInt
bCInt -> CInt -> CInt
forall a. Num a => a -> a -> a
-CInt
a)) ByteString
start
captureCount :: Regex -> Int
captureCount :: Regex -> Int
captureCount (Regex ForeignPtr PCRE
pcre_fp ByteString
_) = IO Int -> Int
forall a. IO a -> a
unsafePerformIO (IO Int -> Int) -> IO Int -> Int
forall a b. (a -> b) -> a -> b
$ do
ForeignPtr PCRE -> (Ptr PCRE -> IO Int) -> IO Int
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr PCRE
pcre_fp ((Ptr PCRE -> IO Int) -> IO Int) -> (Ptr PCRE -> IO Int) -> IO Int
forall a b. (a -> b) -> a -> b
$ \Ptr PCRE
pcre_ptr -> do
Ptr PCRE -> IO Int
forall {b}. Num b => Ptr PCRE -> IO b
captureCount' Ptr PCRE
pcre_ptr
captureCount' :: Ptr PCRE -> IO b
captureCount' Ptr PCRE
pcre_fp =
(Ptr CInt -> IO b) -> IO b
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr CInt -> IO b) -> IO b) -> (Ptr CInt -> IO b) -> IO b
forall a b. (a -> b) -> a -> b
$ \Ptr CInt
n_ptr -> do
Ptr PCRE -> Ptr PCRE -> CInt -> Ptr CInt -> IO CInt
forall a. Ptr PCRE -> Ptr PCRE -> CInt -> Ptr a -> IO CInt
c_pcre_fullinfo Ptr PCRE
pcre_fp Ptr PCRE
forall a. Ptr a
nullPtr CInt
info_capturecount Ptr CInt
n_ptr
b -> IO b
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (b -> IO b) -> (CInt -> b) -> CInt -> IO b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CInt -> b
forall a b. (Integral a, Num b) => a -> b
fromIntegral (CInt -> IO b) -> IO CInt -> IO b
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Ptr CInt -> IO CInt
forall a. Storable a => Ptr a -> IO a
peek (Ptr CInt
n_ptr :: Ptr CInt)