{-# OPTIONS_GHC -fno-warn-orphans #-}
module Text.Regex.PCRE.ByteString(
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 hiding (fail)
import Control.Monad.Fail (MonadFail(fail))
import Text.Regex.PCRE.Wrap
import Data.Array(Array,listArray)
import Data.ByteString(ByteString)
import qualified Data.ByteString as B(empty,useAsCString,last,take,drop,null,pack)
import qualified Data.ByteString.Unsafe as B(unsafeUseAsCString,unsafeUseAsCStringLen)
import System.IO.Unsafe(unsafePerformIO)
import Text.Regex.Base.RegexLike(RegexContext(..),RegexMaker(..),RegexLike(..),MatchOffset,MatchLength)
import Text.Regex.Base.Impl(polymatch,polymatchM)
import Foreign.C.String(CStringLen)
import Foreign(nullPtr)
instance RegexContext Regex ByteString ByteString where
match :: Regex -> ByteString -> ByteString
match = Regex -> ByteString -> ByteString
forall a b. RegexLike a b => a -> b -> b
polymatch
matchM :: Regex -> ByteString -> m ByteString
matchM = Regex -> ByteString -> m ByteString
forall a b (m :: * -> *).
(RegexLike a b, MonadFail m) =>
a -> b -> m b
polymatchM
unwrap :: (Show e) => Either e v -> IO v
unwrap :: Either e v -> IO v
unwrap x :: Either e v
x = case Either e v
x of Left err :: e
err -> String -> IO v
forall (m :: * -> *) a. MonadFail m => String -> m a
fail ("Text.Regex.PCRE.ByteString died: "String -> String -> String
forall a. [a] -> [a] -> [a]
++ e -> String
forall a. Show a => a -> String
show e
err)
Right v :: v
v -> v -> IO v
forall (m :: * -> *) a. Monad m => a -> m a
return v
v
{-# INLINE asCStringLen #-}
asCStringLen :: ByteString -> (CStringLen -> IO a) -> IO a
asCStringLen :: ByteString -> (CStringLen -> IO a) -> IO a
asCStringLen s :: ByteString
s op :: CStringLen -> IO a
op = ByteString -> (CStringLen -> IO a) -> IO a
forall a. ByteString -> (CStringLen -> IO a) -> IO a
B.unsafeUseAsCStringLen ByteString
s CStringLen -> IO a
checked
where checked :: CStringLen -> IO a
checked cs :: CStringLen
cs@(ptr :: Ptr CChar
ptr,_) | Ptr CChar
ptr Ptr CChar -> Ptr CChar -> Bool
forall a. Eq a => a -> a -> Bool
== Ptr CChar
forall a. Ptr a
nullPtr = ByteString -> (CStringLen -> IO a) -> IO a
forall a. ByteString -> (CStringLen -> IO a) -> IO a
B.unsafeUseAsCStringLen ByteString
myEmpty (CStringLen -> IO a
op (CStringLen -> IO a)
-> (CStringLen -> CStringLen) -> CStringLen -> IO a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CStringLen -> CStringLen
forall b a b. Num b => (a, b) -> (a, b)
trim)
| Bool
otherwise = CStringLen -> IO a
op CStringLen
cs
myEmpty :: ByteString
myEmpty = [Word8] -> ByteString
B.pack [0]
trim :: (a, b) -> (a, b)
trim (ptr :: a
ptr,_) = (a
ptr,0)
instance RegexMaker Regex CompOption ExecOption ByteString where
makeRegexOpts :: CompOption -> ExecOption -> ByteString -> Regex
makeRegexOpts c :: CompOption
c e :: ExecOption
e pattern :: ByteString
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
-> ByteString
-> IO (Either (MatchOffset, String) Regex)
compile CompOption
c ExecOption
e ByteString
pattern IO (Either (MatchOffset, String) Regex)
-> (Either (MatchOffset, String) Regex -> IO Regex) -> IO Regex
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Either (MatchOffset, String) Regex -> IO Regex
forall e v. Show e => Either e v -> IO v
unwrap
makeRegexOptsM :: CompOption -> ExecOption -> ByteString -> m Regex
makeRegexOptsM c :: CompOption
c e :: ExecOption
e pattern :: ByteString
pattern = ((MatchOffset, String) -> m Regex)
-> (Regex -> m Regex)
-> Either (MatchOffset, String) Regex
-> m Regex
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (String -> m Regex
forall (m :: * -> *) a. MonadFail m => String -> m a
fail(String -> m Regex)
-> ((MatchOffset, String) -> String)
-> (MatchOffset, String)
-> m Regex
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(MatchOffset, String) -> String
forall a. Show a => a -> String
show) Regex -> m Regex
forall (m :: * -> *) a. Monad m => a -> m a
return (Either (MatchOffset, String) Regex -> m Regex)
-> Either (MatchOffset, String) Regex -> m Regex
forall a b. (a -> b) -> a -> b
$ IO (Either (MatchOffset, String) Regex)
-> Either (MatchOffset, String) Regex
forall a. IO a -> a
unsafePerformIO (IO (Either (MatchOffset, String) Regex)
-> Either (MatchOffset, String) Regex)
-> IO (Either (MatchOffset, String) Regex)
-> Either (MatchOffset, String) Regex
forall a b. (a -> b) -> a -> b
$
CompOption
-> ExecOption
-> ByteString
-> IO (Either (MatchOffset, String) Regex)
compile CompOption
c ExecOption
e ByteString
pattern
instance RegexLike Regex ByteString where
matchTest :: Regex -> ByteString -> Bool
matchTest regex :: Regex
regex bs :: ByteString
bs = IO Bool -> Bool
forall a. IO a -> a
unsafePerformIO (IO Bool -> Bool) -> IO Bool -> Bool
forall a b. (a -> b) -> a -> b
$
ByteString
-> (CStringLen -> IO (Either WrapError Bool))
-> IO (Either WrapError Bool)
forall a. ByteString -> (CStringLen -> IO a) -> IO a
asCStringLen ByteString
bs (MatchOffset -> Regex -> CStringLen -> IO (Either WrapError Bool)
wrapTest 0 Regex
regex) IO (Either WrapError Bool)
-> (Either WrapError Bool -> IO Bool) -> IO Bool
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 -> ByteString -> Maybe MatchArray
matchOnce regex :: Regex
regex bs :: ByteString
bs = 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 -> ByteString -> IO (Either WrapError (Maybe MatchArray))
execute Regex
regex ByteString
bs IO (Either WrapError (Maybe MatchArray))
-> (Either WrapError (Maybe MatchArray) -> IO (Maybe MatchArray))
-> IO (Maybe MatchArray)
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 -> ByteString -> [MatchArray]
matchAll regex :: Regex
regex bs :: ByteString
bs = IO [MatchArray] -> [MatchArray]
forall a. IO a -> a
unsafePerformIO (IO [MatchArray] -> [MatchArray])
-> IO [MatchArray] -> [MatchArray]
forall a b. (a -> b) -> a -> b
$
ByteString
-> (CStringLen -> IO (Either WrapError [MatchArray]))
-> IO (Either WrapError [MatchArray])
forall a. ByteString -> (CStringLen -> IO a) -> IO a
asCStringLen ByteString
bs (Regex -> CStringLen -> IO (Either WrapError [MatchArray])
wrapMatchAll Regex
regex) IO (Either WrapError [MatchArray])
-> (Either WrapError [MatchArray] -> IO [MatchArray])
-> IO [MatchArray]
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 -> ByteString -> MatchOffset
matchCount regex :: Regex
regex bs :: ByteString
bs = IO MatchOffset -> MatchOffset
forall a. IO a -> a
unsafePerformIO (IO MatchOffset -> MatchOffset) -> IO MatchOffset -> MatchOffset
forall a b. (a -> b) -> a -> b
$
ByteString
-> (CStringLen -> IO (Either WrapError MatchOffset))
-> IO (Either WrapError MatchOffset)
forall a. ByteString -> (CStringLen -> IO a) -> IO a
asCStringLen ByteString
bs (Regex -> CStringLen -> IO (Either WrapError MatchOffset)
wrapCount Regex
regex) IO (Either WrapError MatchOffset)
-> (Either WrapError MatchOffset -> IO MatchOffset)
-> IO MatchOffset
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Either WrapError MatchOffset -> IO MatchOffset
forall e v. Show e => Either e v -> IO v
unwrap
compile :: CompOption
-> ExecOption
-> ByteString
-> IO (Either (MatchOffset,String) Regex)
compile :: CompOption
-> ExecOption
-> ByteString
-> IO (Either (MatchOffset, String) Regex)
compile c :: CompOption
c e :: ExecOption
e pattern :: ByteString
pattern = do
let asCString :: ByteString -> (Ptr CChar -> IO a) -> IO a
asCString bs :: ByteString
bs = if (Bool -> Bool
not (ByteString -> Bool
B.null ByteString
bs)) Bool -> Bool -> Bool
&& (0Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
==ByteString -> Word8
B.last ByteString
bs)
then ByteString -> (Ptr CChar -> IO a) -> IO a
forall a. ByteString -> (Ptr CChar -> IO a) -> IO a
B.unsafeUseAsCString ByteString
bs
else ByteString -> (Ptr CChar -> IO a) -> IO a
forall a. ByteString -> (Ptr CChar -> IO a) -> IO a
B.useAsCString ByteString
bs
ByteString
-> (Ptr CChar -> IO (Either (MatchOffset, String) Regex))
-> IO (Either (MatchOffset, String) Regex)
forall a. ByteString -> (Ptr CChar -> IO a) -> IO a
asCString ByteString
pattern (CompOption
-> ExecOption
-> Ptr CChar
-> IO (Either (MatchOffset, String) Regex)
wrapCompile CompOption
c ExecOption
e)
execute :: Regex
-> ByteString
-> IO (Either WrapError (Maybe (Array Int (MatchOffset,MatchLength))))
execute :: Regex -> ByteString -> IO (Either WrapError (Maybe MatchArray))
execute regex :: Regex
regex bs :: ByteString
bs = do
Either WrapError (Maybe [(MatchOffset, MatchOffset)])
maybeStartEnd <- ByteString
-> (CStringLen
-> IO (Either WrapError (Maybe [(MatchOffset, MatchOffset)])))
-> IO (Either WrapError (Maybe [(MatchOffset, MatchOffset)]))
forall a. ByteString -> (CStringLen -> IO a) -> IO a
asCStringLen ByteString
bs (MatchOffset
-> Regex
-> CStringLen
-> IO (Either WrapError (Maybe [(MatchOffset, MatchOffset)]))
wrapMatch 0 Regex
regex)
case Either WrapError (Maybe [(MatchOffset, MatchOffset)])
maybeStartEnd of
Right Nothing -> Either WrapError (Maybe MatchArray)
-> IO (Either WrapError (Maybe MatchArray))
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 parts :: [(MatchOffset, MatchOffset)]
parts) ->
Either WrapError (Maybe MatchArray)
-> IO (Either WrapError (Maybe MatchArray))
forall (m :: * -> *) a. Monad m => a -> m a
return (Either WrapError (Maybe MatchArray)
-> IO (Either WrapError (Maybe MatchArray)))
-> ([(MatchOffset, MatchOffset)]
-> Either WrapError (Maybe MatchArray))
-> [(MatchOffset, MatchOffset)]
-> 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))
-> ([(MatchOffset, MatchOffset)] -> Maybe MatchArray)
-> [(MatchOffset, MatchOffset)]
-> 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)
-> ([(MatchOffset, MatchOffset)] -> MatchArray)
-> [(MatchOffset, MatchOffset)]
-> Maybe MatchArray
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (MatchOffset, MatchOffset)
-> [(MatchOffset, MatchOffset)] -> MatchArray
forall i e. Ix i => (i, i) -> [e] -> Array i e
listArray (0,MatchOffset -> MatchOffset
forall a. Enum a => a -> a
pred ([(MatchOffset, MatchOffset)] -> MatchOffset
forall (t :: * -> *) a. Foldable t => t a -> MatchOffset
length [(MatchOffset, MatchOffset)]
parts))
([(MatchOffset, MatchOffset)] -> MatchArray)
-> ([(MatchOffset, MatchOffset)] -> [(MatchOffset, MatchOffset)])
-> [(MatchOffset, MatchOffset)]
-> MatchArray
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((MatchOffset, MatchOffset) -> (MatchOffset, MatchOffset))
-> [(MatchOffset, MatchOffset)] -> [(MatchOffset, MatchOffset)]
forall a b. (a -> b) -> [a] -> [b]
map (\(s :: MatchOffset
s,e :: MatchOffset
e)->(MatchOffset -> MatchOffset
forall a b. (Integral a, Num b) => a -> b
fromIntegral MatchOffset
s, MatchOffset -> MatchOffset
forall a b. (Integral a, Num b) => a -> b
fromIntegral (MatchOffset
eMatchOffset -> MatchOffset -> MatchOffset
forall a. Num a => a -> a -> a
-MatchOffset
s))) ([(MatchOffset, MatchOffset)]
-> IO (Either WrapError (Maybe MatchArray)))
-> [(MatchOffset, MatchOffset)]
-> IO (Either WrapError (Maybe MatchArray))
forall a b. (a -> b) -> a -> b
$ [(MatchOffset, MatchOffset)]
parts
Left err :: WrapError
err -> Either WrapError (Maybe MatchArray)
-> IO (Either WrapError (Maybe MatchArray))
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
-> ByteString
-> IO (Either WrapError (Maybe (ByteString, ByteString, ByteString, [ByteString])))
regexec :: Regex
-> ByteString
-> IO
(Either
WrapError
(Maybe (ByteString, ByteString, ByteString, [ByteString])))
regexec regex :: Regex
regex bs :: ByteString
bs = do
let getSub :: (MatchOffset, MatchOffset) -> ByteString
getSub (start :: MatchOffset
start,stop :: MatchOffset
stop) | MatchOffset
start MatchOffset -> MatchOffset -> Bool
forall a. Eq a => a -> a -> Bool
== MatchOffset
unusedOffset = ByteString
B.empty
| Bool
otherwise = MatchOffset -> ByteString -> ByteString
B.take (MatchOffset
stopMatchOffset -> MatchOffset -> MatchOffset
forall a. Num a => a -> a -> a
-MatchOffset
start) (ByteString -> ByteString)
-> (ByteString -> ByteString) -> ByteString -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MatchOffset -> ByteString -> ByteString
B.drop MatchOffset
start (ByteString -> ByteString) -> ByteString -> ByteString
forall a b. (a -> b) -> a -> b
$ ByteString
bs
matchedParts :: [(MatchOffset, MatchOffset)]
-> (ByteString, ByteString, ByteString, [ByteString])
matchedParts [] = (ByteString
B.empty,ByteString
B.empty,ByteString
bs,[])
matchedParts (matchedStartStop :: (MatchOffset, MatchOffset)
matchedStartStop@(start :: MatchOffset
start,stop :: MatchOffset
stop):subStartStop :: [(MatchOffset, MatchOffset)]
subStartStop) =
(MatchOffset -> ByteString -> ByteString
B.take MatchOffset
start ByteString
bs
,(MatchOffset, MatchOffset) -> ByteString
getSub (MatchOffset, MatchOffset)
matchedStartStop
,MatchOffset -> ByteString -> ByteString
B.drop MatchOffset
stop ByteString
bs
,((MatchOffset, MatchOffset) -> ByteString)
-> [(MatchOffset, MatchOffset)] -> [ByteString]
forall a b. (a -> b) -> [a] -> [b]
map (MatchOffset, MatchOffset) -> ByteString
getSub [(MatchOffset, MatchOffset)]
subStartStop)
Either WrapError (Maybe [(MatchOffset, MatchOffset)])
maybeStartEnd <- ByteString
-> (CStringLen
-> IO (Either WrapError (Maybe [(MatchOffset, MatchOffset)])))
-> IO (Either WrapError (Maybe [(MatchOffset, MatchOffset)]))
forall a. ByteString -> (CStringLen -> IO a) -> IO a
asCStringLen ByteString
bs (MatchOffset
-> Regex
-> CStringLen
-> IO (Either WrapError (Maybe [(MatchOffset, MatchOffset)]))
wrapMatch 0 Regex
regex)
case Either WrapError (Maybe [(MatchOffset, MatchOffset)])
maybeStartEnd of
Right Nothing -> Either
WrapError
(Maybe (ByteString, ByteString, ByteString, [ByteString]))
-> IO
(Either
WrapError
(Maybe (ByteString, ByteString, ByteString, [ByteString])))
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe (ByteString, ByteString, ByteString, [ByteString])
-> Either
WrapError
(Maybe (ByteString, ByteString, ByteString, [ByteString]))
forall a b. b -> Either a b
Right Maybe (ByteString, ByteString, ByteString, [ByteString])
forall a. Maybe a
Nothing)
Right (Just parts :: [(MatchOffset, MatchOffset)]
parts) -> Either
WrapError
(Maybe (ByteString, ByteString, ByteString, [ByteString]))
-> IO
(Either
WrapError
(Maybe (ByteString, ByteString, ByteString, [ByteString])))
forall (m :: * -> *) a. Monad m => a -> m a
return (Either
WrapError
(Maybe (ByteString, ByteString, ByteString, [ByteString]))
-> IO
(Either
WrapError
(Maybe (ByteString, ByteString, ByteString, [ByteString]))))
-> ([(MatchOffset, MatchOffset)]
-> Either
WrapError
(Maybe (ByteString, ByteString, ByteString, [ByteString])))
-> [(MatchOffset, MatchOffset)]
-> IO
(Either
WrapError
(Maybe (ByteString, ByteString, ByteString, [ByteString])))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe (ByteString, ByteString, ByteString, [ByteString])
-> Either
WrapError
(Maybe (ByteString, ByteString, ByteString, [ByteString]))
forall a b. b -> Either a b
Right (Maybe (ByteString, ByteString, ByteString, [ByteString])
-> Either
WrapError
(Maybe (ByteString, ByteString, ByteString, [ByteString])))
-> ([(MatchOffset, MatchOffset)]
-> Maybe (ByteString, ByteString, ByteString, [ByteString]))
-> [(MatchOffset, MatchOffset)]
-> Either
WrapError
(Maybe (ByteString, ByteString, ByteString, [ByteString]))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ByteString, ByteString, ByteString, [ByteString])
-> Maybe (ByteString, ByteString, ByteString, [ByteString])
forall a. a -> Maybe a
Just ((ByteString, ByteString, ByteString, [ByteString])
-> Maybe (ByteString, ByteString, ByteString, [ByteString]))
-> ([(MatchOffset, MatchOffset)]
-> (ByteString, ByteString, ByteString, [ByteString]))
-> [(MatchOffset, MatchOffset)]
-> Maybe (ByteString, ByteString, ByteString, [ByteString])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [(MatchOffset, MatchOffset)]
-> (ByteString, ByteString, ByteString, [ByteString])
matchedParts ([(MatchOffset, MatchOffset)]
-> IO
(Either
WrapError
(Maybe (ByteString, ByteString, ByteString, [ByteString]))))
-> [(MatchOffset, MatchOffset)]
-> IO
(Either
WrapError
(Maybe (ByteString, ByteString, ByteString, [ByteString])))
forall a b. (a -> b) -> a -> b
$ [(MatchOffset, MatchOffset)]
parts
Left err :: WrapError
err -> Either
WrapError
(Maybe (ByteString, ByteString, ByteString, [ByteString]))
-> IO
(Either
WrapError
(Maybe (ByteString, ByteString, ByteString, [ByteString])))
forall (m :: * -> *) a. Monad m => a -> m a
return (WrapError
-> Either
WrapError
(Maybe (ByteString, ByteString, ByteString, [ByteString]))
forall a b. a -> Either a b
Left WrapError
err)