{-|
This modules provides 'RegexMaker' and 'RegexLike' instances for using
@ByteString@ with the DFA backend ("Text.Regex.Lib.WrapDFAEngine" and
"Text.Regex.Lazy.DFAEngineFPS").  This module is usually used via
import "Text.Regex.TDFA".

This exports instances of the high level API and the medium level
API of 'compile','execute', and 'regexec'.
-}
{- By Chris Kuklewicz, 2009. BSD License, see the LICENSE file. -}
module Text.Regex.TDFA.ByteString(
  Regex
 ,CompOption
 ,ExecOption
 ,compile
 ,execute
 ,regexec
 ) where

import Data.Array((!),elems)
import qualified Data.ByteString.Char8 as B(ByteString,take,drop,unpack)

import Text.Regex.Base(MatchArray,RegexContext(..),RegexMaker(..),RegexLike(..))
import Text.Regex.Base.Impl(polymatch,polymatchM)
import Text.Regex.TDFA.ReadRegex(parseRegex)
import Text.Regex.TDFA.String() -- piggyback on RegexMaker for String
import Text.Regex.TDFA.TDFA(patternToRegex)
import Text.Regex.TDFA.Common(Regex(..),CompOption,ExecOption(captureGroups))

import Data.Maybe(listToMaybe)
import Text.Regex.TDFA.NewDFA.Engine(execMatch)
import Text.Regex.TDFA.NewDFA.Tester as Tester(matchTest)

instance RegexContext Regex B.ByteString B.ByteString where
  match :: Regex -> ByteString -> ByteString
match = forall a b. RegexLike a b => a -> b -> b
polymatch
  matchM :: forall (m :: * -> *).
MonadFail m =>
Regex -> ByteString -> m ByteString
matchM = forall a b (m :: * -> *).
(RegexLike a b, MonadFail m) =>
a -> b -> m b
polymatchM

instance RegexMaker Regex CompOption ExecOption B.ByteString where
  makeRegexOptsM :: forall (m :: * -> *).
MonadFail m =>
CompOption -> ExecOption -> ByteString -> m Regex
makeRegexOptsM CompOption
c ExecOption
e ByteString
source = forall regex compOpt execOpt source (m :: * -> *).
(RegexMaker regex compOpt execOpt source, MonadFail m) =>
compOpt -> execOpt -> source -> m regex
makeRegexOptsM CompOption
c ExecOption
e (ByteString -> [Char]
B.unpack ByteString
source)

instance RegexLike Regex B.ByteString where
  matchOnce :: Regex -> ByteString -> Maybe MatchArray
matchOnce Regex
r ByteString
s = forall a. [a] -> Maybe a
listToMaybe (forall regex source.
RegexLike regex source =>
regex -> source -> [MatchArray]
matchAll Regex
r ByteString
s)
  matchAll :: Regex -> ByteString -> [MatchArray]
matchAll Regex
r ByteString
s = forall text.
Uncons text =>
Regex -> Int -> Char -> text -> [MatchArray]
execMatch Regex
r Int
0 Char
'\n' ByteString
s
  matchCount :: Regex -> ByteString -> Int
matchCount Regex
r ByteString
s = forall (t :: * -> *) a. Foldable t => t a -> Int
length (forall regex source.
RegexLike regex source =>
regex -> source -> [MatchArray]
matchAll Regex
r' ByteString
s)
    where r' :: Regex
r' = Regex
r { regex_execOptions :: ExecOption
regex_execOptions = (Regex -> ExecOption
regex_execOptions Regex
r) {captureGroups :: Bool
captureGroups = Bool
False} }
  matchTest :: Regex -> ByteString -> Bool
matchTest = forall text. Uncons text => Regex -> text -> Bool
Tester.matchTest
  matchOnceText :: Regex
-> ByteString
-> Maybe (ByteString, MatchText ByteString, ByteString)
matchOnceText Regex
regex ByteString
source =
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\MatchArray
ma -> let (Int
o,Int
l) = MatchArray
maforall i e. Ix i => Array i e -> i -> e
!Int
0
                 in (Int -> ByteString -> ByteString
B.take Int
o ByteString
source
                    ,forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\ol :: (Int, Int)
ol@(Int
off,Int
len) -> (Int -> ByteString -> ByteString
B.take Int
len (Int -> ByteString -> ByteString
B.drop Int
off ByteString
source),(Int, Int)
ol)) MatchArray
ma
                    ,Int -> ByteString -> ByteString
B.drop (Int
oforall a. Num a => a -> a -> a
+Int
l) ByteString
source))
         (forall regex source.
RegexLike regex source =>
regex -> source -> Maybe MatchArray
matchOnce Regex
regex ByteString
source)
  matchAllText :: Regex -> ByteString -> [MatchText ByteString]
matchAllText Regex
regex ByteString
source =
    forall a b. (a -> b) -> [a] -> [b]
map (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\ol :: (Int, Int)
ol@(Int
off,Int
len) -> (Int -> ByteString -> ByteString
B.take Int
len (Int -> ByteString -> ByteString
B.drop Int
off ByteString
source),(Int, Int)
ol)))
        (forall regex source.
RegexLike regex source =>
regex -> source -> [MatchArray]
matchAll Regex
regex ByteString
source)

compile :: CompOption -- ^ Flags (summed together)
        -> ExecOption -- ^ Flags (summed together)
        -> B.ByteString -- ^ The regular expression to compile
        -> Either String Regex -- ^ Returns: the compiled regular expression
compile :: CompOption -> ExecOption -> ByteString -> Either [Char] Regex
compile CompOption
compOpt ExecOption
execOpt ByteString
bs =
  case [Char] -> Either ParseError (Pattern, (Int, DoPa))
parseRegex (ByteString -> [Char]
B.unpack ByteString
bs) of
    Left ParseError
err -> forall a b. a -> Either a b
Left ([Char]
"parseRegex for Text.Regex.TDFA.ByteString failed:"forall a. [a] -> [a] -> [a]
++forall a. Show a => a -> [Char]
show ParseError
err)
    Right (Pattern, (Int, DoPa))
pattern -> forall a b. b -> Either a b
Right ((Pattern, (Int, DoPa)) -> CompOption -> ExecOption -> Regex
patternToRegex (Pattern, (Int, DoPa))
pattern CompOption
compOpt ExecOption
execOpt)

execute :: Regex        -- ^ Compiled regular expression
        -> B.ByteString -- ^ ByteString to match against
        -> Either String (Maybe MatchArray)
execute :: Regex -> ByteString -> Either [Char] (Maybe MatchArray)
execute Regex
r ByteString
bs = forall a b. b -> Either a b
Right (forall regex source.
RegexLike regex source =>
regex -> source -> Maybe MatchArray
matchOnce Regex
r ByteString
bs)

regexec :: Regex        -- ^ Compiled regular expression
        -> B.ByteString -- ^ ByteString to match against
        -> Either String (Maybe (B.ByteString, B.ByteString, B.ByteString, [B.ByteString]))
regexec :: Regex
-> ByteString
-> Either
     [Char] (Maybe (ByteString, ByteString, ByteString, [ByteString]))
regexec Regex
r ByteString
txt = forall a b. b -> Either a b
Right forall a b. (a -> b) -> a -> b
$
  case forall regex source.
RegexLike regex source =>
regex -> source -> Maybe (source, MatchText source, source)
matchOnceText Regex
r ByteString
txt of
    Just (ByteString
pre, MatchText ByteString
mt, ByteString
post) | ByteString
main:[ByteString]
rest <- forall a b. (a -> b) -> [a] -> [b]
map forall a b. (a, b) -> a
fst (forall i e. Array i e -> [e]
elems MatchText ByteString
mt)
      -> forall a. a -> Maybe a
Just (ByteString
pre, ByteString
main, ByteString
post, [ByteString]
rest)
    Maybe (ByteString, MatchText ByteString, ByteString)
_ -> forall a. Maybe a
Nothing