{-# OPTIONS_GHC -fno-warn-orphans #-}
module Text.Regex.PCRE.String(
Regex,
MatchOffset,
MatchLength,
CompOption(CompOption),
ExecOption(ExecOption),
ReturnCode,
WrapError,
unusedOffset,
getVersion,
compile,
execute,
regexec,
compBlank,
compAnchored,
compAutoCallout,
compCaseless,
compDollarEndOnly,
compDotAll,
compExtended,
compExtra,
compFirstLine,
compMultiline,
compNoAutoCapture,
compUngreedy,
compUTF8,
compNoUTF8Check,
execBlank,
execAnchored,
execNotBOL,
execNotEOL,
execNotEmpty,
execNoUTF8Check,
execPartial
) where
import Prelude
( Either(Left,Right), either
, Int, (-), fromIntegral, pred
, IO, (>>=), return
, Maybe(Nothing,Just)
, Show(show)
, String
, ($), (.), (==), otherwise
, (++), drop, length, map, take
)
import Control.Monad.Fail (MonadFail(fail))
import Text.Regex.PCRE.Wrap
import Foreign.C.String(withCStringLen,withCString)
import Data.Array(Array,listArray)
import System.IO.Unsafe(unsafePerformIO)
import Text.Regex.Base.RegexLike(RegexMaker(..),RegexLike(..),RegexContext(..),MatchLength,MatchOffset)
import Text.Regex.Base.Impl(polymatch,polymatchM)
instance RegexContext Regex String String where
match :: Regex -> String -> String
match = Regex -> String -> String
forall a b. RegexLike a b => a -> b -> b
polymatch
matchM :: forall (m :: * -> *). MonadFail m => Regex -> String -> m String
matchM = Regex -> String -> m String
forall a b (m :: * -> *).
(RegexLike a b, MonadFail m) =>
a -> b -> m b
polymatchM
unwrap :: (Show e) => Either e v -> IO v
unwrap :: forall e v. Show e => Either e v -> IO v
unwrap Either e v
x = case Either e v
x of Left e
err -> String -> IO v
forall a. String -> IO a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String
"Text.Regex.PCRE.String died: "String -> String -> String
forall a. [a] -> [a] -> [a]
++ e -> String
forall a. Show a => a -> String
show e
err)
Right v
v -> v -> IO v
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return v
v
instance RegexMaker Regex CompOption ExecOption String where
makeRegexOpts :: CompOption -> ExecOption -> String -> Regex
makeRegexOpts CompOption
c ExecOption
e String
pattern = IO Regex -> Regex
forall a. IO a -> a
unsafePerformIO (IO Regex -> Regex) -> IO Regex -> Regex
forall a b. (a -> b) -> a -> b
$
CompOption
-> ExecOption -> String -> IO (Either (Int, String) Regex)
compile CompOption
c ExecOption
e String
pattern IO (Either (Int, String) Regex)
-> (Either (Int, String) Regex -> IO Regex) -> IO Regex
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Either (Int, String) Regex -> IO Regex
forall e v. Show e => Either e v -> IO v
unwrap
makeRegexOptsM :: forall (m :: * -> *).
MonadFail m =>
CompOption -> ExecOption -> String -> m Regex
makeRegexOptsM CompOption
c ExecOption
e String
pattern = ((Int, String) -> m Regex)
-> (Regex -> m Regex) -> Either (Int, String) Regex -> m Regex
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (String -> m Regex
forall a. String -> m a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail(String -> m Regex)
-> ((Int, String) -> String) -> (Int, String) -> m Regex
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(Int, String) -> String
forall a. Show a => a -> String
show) Regex -> m Regex
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Either (Int, String) Regex -> m Regex)
-> Either (Int, String) Regex -> m Regex
forall a b. (a -> b) -> a -> b
$ IO (Either (Int, String) Regex) -> Either (Int, String) Regex
forall a. IO a -> a
unsafePerformIO (IO (Either (Int, String) Regex) -> Either (Int, String) Regex)
-> IO (Either (Int, String) Regex) -> Either (Int, String) Regex
forall a b. (a -> b) -> a -> b
$
CompOption
-> ExecOption -> String -> IO (Either (Int, String) Regex)
compile CompOption
c ExecOption
e String
pattern
instance RegexLike Regex String where
matchTest :: Regex -> String -> Bool
matchTest Regex
regex String
str = IO Bool -> Bool
forall a. IO a -> a
unsafePerformIO (IO Bool -> Bool) -> IO Bool -> Bool
forall a b. (a -> b) -> a -> b
$
String
-> (CStringLen -> IO (Either WrapError Bool))
-> IO (Either WrapError Bool)
forall a. String -> (CStringLen -> IO a) -> IO a
withCStringLen String
str (Int -> Regex -> CStringLen -> IO (Either WrapError Bool)
wrapTest Int
0 Regex
regex) IO (Either WrapError Bool)
-> (Either WrapError Bool -> IO Bool) -> IO Bool
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Either WrapError Bool -> IO Bool
forall e v. Show e => Either e v -> IO v
unwrap
matchOnce :: Regex -> String -> Maybe MatchArray
matchOnce Regex
regex String
str = IO (Maybe MatchArray) -> Maybe MatchArray
forall a. IO a -> a
unsafePerformIO (IO (Maybe MatchArray) -> Maybe MatchArray)
-> IO (Maybe MatchArray) -> Maybe MatchArray
forall a b. (a -> b) -> a -> b
$
Regex -> String -> IO (Either WrapError (Maybe MatchArray))
execute Regex
regex String
str IO (Either WrapError (Maybe MatchArray))
-> (Either WrapError (Maybe MatchArray) -> IO (Maybe MatchArray))
-> IO (Maybe MatchArray)
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Either WrapError (Maybe MatchArray) -> IO (Maybe MatchArray)
forall e v. Show e => Either e v -> IO v
unwrap
matchAll :: Regex -> String -> [MatchArray]
matchAll Regex
regex String
str = IO [MatchArray] -> [MatchArray]
forall a. IO a -> a
unsafePerformIO (IO [MatchArray] -> [MatchArray])
-> IO [MatchArray] -> [MatchArray]
forall a b. (a -> b) -> a -> b
$
String
-> (CStringLen -> IO (Either WrapError [MatchArray]))
-> IO (Either WrapError [MatchArray])
forall a. String -> (CStringLen -> IO a) -> IO a
withCStringLen String
str (Regex -> CStringLen -> IO (Either WrapError [MatchArray])
wrapMatchAll Regex
regex) IO (Either WrapError [MatchArray])
-> (Either WrapError [MatchArray] -> IO [MatchArray])
-> IO [MatchArray]
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Either WrapError [MatchArray] -> IO [MatchArray]
forall e v. Show e => Either e v -> IO v
unwrap
matchCount :: Regex -> String -> Int
matchCount Regex
regex String
str = IO Int -> Int
forall a. IO a -> a
unsafePerformIO (IO Int -> Int) -> IO Int -> Int
forall a b. (a -> b) -> a -> b
$
String
-> (CStringLen -> IO (Either WrapError Int))
-> IO (Either WrapError Int)
forall a. String -> (CStringLen -> IO a) -> IO a
withCStringLen String
str (Regex -> CStringLen -> IO (Either WrapError Int)
wrapCount Regex
regex) IO (Either WrapError Int)
-> (Either WrapError Int -> IO Int) -> IO Int
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Either WrapError Int -> IO Int
forall e v. Show e => Either e v -> IO v
unwrap
compile :: CompOption
-> ExecOption
-> String
-> IO (Either (MatchOffset,String) Regex)
compile :: CompOption
-> ExecOption -> String -> IO (Either (Int, String) Regex)
compile CompOption
c ExecOption
e String
pattern = String
-> (CString -> IO (Either (Int, String) Regex))
-> IO (Either (Int, String) Regex)
forall a. String -> (CString -> IO a) -> IO a
withCString String
pattern (CompOption
-> ExecOption -> CString -> IO (Either (Int, String) Regex)
wrapCompile CompOption
c ExecOption
e)
execute :: Regex
-> String
-> IO (Either WrapError (Maybe (Array Int (MatchOffset,MatchLength))))
execute :: Regex -> String -> IO (Either WrapError (Maybe MatchArray))
execute Regex
regex String
str = do
maybeStartEnd <- String
-> (CStringLen -> IO (Either WrapError (Maybe [(Int, Int)])))
-> IO (Either WrapError (Maybe [(Int, Int)]))
forall a. String -> (CStringLen -> IO a) -> IO a
withCStringLen String
str (Int
-> Regex
-> CStringLen
-> IO (Either WrapError (Maybe [(Int, Int)]))
wrapMatch Int
0 Regex
regex)
case maybeStartEnd of
Right Maybe [(Int, Int)]
Nothing -> Either WrapError (Maybe MatchArray)
-> IO (Either WrapError (Maybe MatchArray))
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe MatchArray -> Either WrapError (Maybe MatchArray)
forall a b. b -> Either a b
Right Maybe MatchArray
forall a. Maybe a
Nothing)
Right (Just [(Int, Int)]
parts) ->
Either WrapError (Maybe MatchArray)
-> IO (Either WrapError (Maybe MatchArray))
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Either WrapError (Maybe MatchArray)
-> IO (Either WrapError (Maybe MatchArray)))
-> ([(Int, Int)] -> Either WrapError (Maybe MatchArray))
-> [(Int, Int)]
-> IO (Either WrapError (Maybe MatchArray))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe MatchArray -> Either WrapError (Maybe MatchArray)
forall a b. b -> Either a b
Right (Maybe MatchArray -> Either WrapError (Maybe MatchArray))
-> ([(Int, Int)] -> Maybe MatchArray)
-> [(Int, Int)]
-> Either WrapError (Maybe MatchArray)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MatchArray -> Maybe MatchArray
forall a. a -> Maybe a
Just (MatchArray -> Maybe MatchArray)
-> ([(Int, Int)] -> MatchArray) -> [(Int, Int)] -> Maybe MatchArray
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int, Int) -> [(Int, Int)] -> MatchArray
forall i e. Ix i => (i, i) -> [e] -> Array i e
listArray (Int
0,Int -> Int
forall a. Enum a => a -> a
pred ([(Int, Int)] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [(Int, Int)]
parts))
([(Int, Int)] -> MatchArray)
-> ([(Int, Int)] -> [(Int, Int)]) -> [(Int, Int)] -> MatchArray
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((Int, Int) -> (Int, Int)) -> [(Int, Int)] -> [(Int, Int)]
forall a b. (a -> b) -> [a] -> [b]
map (\(Int
s,Int
e)->(Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
s, Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int
eInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
s))) ([(Int, Int)] -> IO (Either WrapError (Maybe MatchArray)))
-> [(Int, Int)] -> IO (Either WrapError (Maybe MatchArray))
forall a b. (a -> b) -> a -> b
$ [(Int, Int)]
parts
Left WrapError
err -> Either WrapError (Maybe MatchArray)
-> IO (Either WrapError (Maybe MatchArray))
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (WrapError -> Either WrapError (Maybe MatchArray)
forall a b. a -> Either a b
Left WrapError
err)
regexec :: Regex
-> String
-> IO (Either WrapError (Maybe (String, String,String, [String])))
regexec :: Regex
-> String
-> IO (Either WrapError (Maybe (String, String, String, [String])))
regexec Regex
regex String
str = do
let getSub :: (Int, Int) -> String
getSub (Int
start,Int
stop) | Int
start Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
unusedOffset = String
""
| Bool
otherwise = Int -> String -> String
forall a. Int -> [a] -> [a]
take (Int
stopInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
start) (String -> String) -> (String -> String) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> String -> String
forall a. Int -> [a] -> [a]
drop Int
start (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ String
str
matchedParts :: [(Int, Int)] -> (String, String, String, [String])
matchedParts [] = (String
"",String
"",String
str,[])
matchedParts (matchedStartStop :: (Int, Int)
matchedStartStop@(Int
start,Int
stop):[(Int, Int)]
subStartStop) =
(Int -> String -> String
forall a. Int -> [a] -> [a]
take Int
start String
str
,(Int, Int) -> String
getSub (Int, Int)
matchedStartStop
,Int -> String -> String
forall a. Int -> [a] -> [a]
drop Int
stop String
str
,((Int, Int) -> String) -> [(Int, Int)] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (Int, Int) -> String
getSub [(Int, Int)]
subStartStop)
maybeStartEnd <- String
-> (CStringLen -> IO (Either WrapError (Maybe [(Int, Int)])))
-> IO (Either WrapError (Maybe [(Int, Int)]))
forall a. String -> (CStringLen -> IO a) -> IO a
withCStringLen String
str (Int
-> Regex
-> CStringLen
-> IO (Either WrapError (Maybe [(Int, Int)]))
wrapMatch Int
0 Regex
regex)
case maybeStartEnd of
Right Maybe [(Int, Int)]
Nothing -> Either WrapError (Maybe (String, String, String, [String]))
-> IO (Either WrapError (Maybe (String, String, String, [String])))
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe (String, String, String, [String])
-> Either WrapError (Maybe (String, String, String, [String]))
forall a b. b -> Either a b
Right Maybe (String, String, String, [String])
forall a. Maybe a
Nothing)
Right (Just [(Int, Int)]
parts) -> Either WrapError (Maybe (String, String, String, [String]))
-> IO (Either WrapError (Maybe (String, String, String, [String])))
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Either WrapError (Maybe (String, String, String, [String]))
-> IO
(Either WrapError (Maybe (String, String, String, [String]))))
-> ([(Int, Int)]
-> Either WrapError (Maybe (String, String, String, [String])))
-> [(Int, Int)]
-> IO (Either WrapError (Maybe (String, String, String, [String])))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe (String, String, String, [String])
-> Either WrapError (Maybe (String, String, String, [String]))
forall a b. b -> Either a b
Right (Maybe (String, String, String, [String])
-> Either WrapError (Maybe (String, String, String, [String])))
-> ([(Int, Int)] -> Maybe (String, String, String, [String]))
-> [(Int, Int)]
-> Either WrapError (Maybe (String, String, String, [String]))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String, String, String, [String])
-> Maybe (String, String, String, [String])
forall a. a -> Maybe a
Just ((String, String, String, [String])
-> Maybe (String, String, String, [String]))
-> ([(Int, Int)] -> (String, String, String, [String]))
-> [(Int, Int)]
-> Maybe (String, String, String, [String])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [(Int, Int)] -> (String, String, String, [String])
matchedParts ([(Int, Int)]
-> IO
(Either WrapError (Maybe (String, String, String, [String]))))
-> [(Int, Int)]
-> IO (Either WrapError (Maybe (String, String, String, [String])))
forall a b. (a -> b) -> a -> b
$ [(Int, Int)]
parts
Left WrapError
err -> Either WrapError (Maybe (String, String, String, [String]))
-> IO (Either WrapError (Maybe (String, String, String, [String])))
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (WrapError
-> Either WrapError (Maybe (String, String, String, [String]))
forall a b. a -> Either a b
Left WrapError
err)