{-|
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 = 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

instance RegexMaker Regex CompOption ExecOption B.ByteString where
  makeRegexOptsM :: CompOption -> ExecOption -> ByteString -> m Regex
makeRegexOptsM c :: CompOption
c e :: ExecOption
e source :: ByteString
source = CompOption -> ExecOption -> [Char] -> m Regex
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 r :: Regex
r s :: ByteString
s = [MatchArray] -> Maybe MatchArray
forall a. [a] -> Maybe a
listToMaybe (Regex -> ByteString -> [MatchArray]
forall regex source.
RegexLike regex source =>
regex -> source -> [MatchArray]
matchAll Regex
r ByteString
s)
  matchAll :: Regex -> ByteString -> [MatchArray]
matchAll r :: Regex
r s :: ByteString
s = Regex -> Int -> Char -> ByteString -> [MatchArray]
forall text.
Uncons text =>
Regex -> Int -> Char -> text -> [MatchArray]
execMatch Regex
r 0 '\n' ByteString
s
  matchCount :: Regex -> ByteString -> Int
matchCount r :: Regex
r s :: ByteString
s = [MatchArray] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length (Regex -> ByteString -> [MatchArray]
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 = Regex -> ByteString -> Bool
forall text. Uncons text => Regex -> text -> Bool
Tester.matchTest
  matchOnceText :: Regex
-> ByteString
-> Maybe (ByteString, MatchText ByteString, ByteString)
matchOnceText regex :: Regex
regex source :: ByteString
source =
    (MatchArray -> (ByteString, MatchText ByteString, ByteString))
-> Maybe MatchArray
-> Maybe (ByteString, MatchText ByteString, ByteString)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\ma :: MatchArray
ma -> let (o :: Int
o,l :: Int
l) = MatchArray
maMatchArray -> Int -> (Int, Int)
forall i e. Ix i => Array i e -> i -> e
!0
                 in (Int -> ByteString -> ByteString
B.take Int
o ByteString
source
                    ,((Int, Int) -> (ByteString, (Int, Int)))
-> MatchArray -> MatchText ByteString
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\ol :: (Int, Int)
ol@(off :: Int
off,len :: 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
oInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
l) ByteString
source))
         (Regex -> ByteString -> Maybe MatchArray
forall regex source.
RegexLike regex source =>
regex -> source -> Maybe MatchArray
matchOnce Regex
regex ByteString
source)
  matchAllText :: Regex -> ByteString -> [MatchText ByteString]
matchAllText regex :: Regex
regex source :: ByteString
source =
    (MatchArray -> MatchText ByteString)
-> [MatchArray] -> [MatchText ByteString]
forall a b. (a -> b) -> [a] -> [b]
map (((Int, Int) -> (ByteString, (Int, Int)))
-> MatchArray -> MatchText ByteString
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\ol :: (Int, Int)
ol@(off :: Int
off,len :: Int
len) -> (Int -> ByteString -> ByteString
B.take Int
len (Int -> ByteString -> ByteString
B.drop Int
off ByteString
source),(Int, Int)
ol)))
        (Regex -> ByteString -> [MatchArray]
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 compOpt :: CompOption
compOpt execOpt :: ExecOption
execOpt bs :: ByteString
bs =
  case [Char] -> Either ParseError (Pattern, (Int, DoPa))
parseRegex (ByteString -> [Char]
B.unpack ByteString
bs) of
    Left err :: ParseError
err -> [Char] -> Either [Char] Regex
forall a b. a -> Either a b
Left ("parseRegex for Text.Regex.TDFA.ByteString failed:"[Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ParseError -> [Char]
forall a. Show a => a -> [Char]
show ParseError
err)
    Right pattern :: (Pattern, (Int, DoPa))
pattern -> Regex -> Either [Char] Regex
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 r :: Regex
r bs :: ByteString
bs = Maybe MatchArray -> Either [Char] (Maybe MatchArray)
forall a b. b -> Either a b
Right (Regex -> ByteString -> Maybe MatchArray
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 r :: Regex
r bs :: ByteString
bs =
  case Regex
-> ByteString
-> Maybe (ByteString, MatchText ByteString, ByteString)
forall regex source.
RegexLike regex source =>
regex -> source -> Maybe (source, MatchText source, source)
matchOnceText Regex
r ByteString
bs of
    Nothing -> Maybe (ByteString, ByteString, ByteString, [ByteString])
-> Either
     [Char] (Maybe (ByteString, ByteString, ByteString, [ByteString]))
forall a b. b -> Either a b
Right (Maybe (ByteString, ByteString, ByteString, [ByteString])
forall a. Maybe a
Nothing)
    Just (pre :: ByteString
pre,mt :: MatchText ByteString
mt,post :: ByteString
post) ->
      let main :: ByteString
main = (ByteString, (Int, Int)) -> ByteString
forall a b. (a, b) -> a
fst (MatchText ByteString
mtMatchText ByteString -> Int -> (ByteString, (Int, Int))
forall i e. Ix i => Array i e -> i -> e
!0)
          rest :: [ByteString]
rest = ((ByteString, (Int, Int)) -> ByteString)
-> [(ByteString, (Int, Int))] -> [ByteString]
forall a b. (a -> b) -> [a] -> [b]
map (ByteString, (Int, Int)) -> ByteString
forall a b. (a, b) -> a
fst ([(ByteString, (Int, Int))] -> [(ByteString, (Int, Int))]
forall a. [a] -> [a]
tail (MatchText ByteString -> [(ByteString, (Int, Int))]
forall i e. Array i e -> [e]
elems MatchText ByteString
mt)) -- will be []
      in Maybe (ByteString, ByteString, ByteString, [ByteString])
-> Either
     [Char] (Maybe (ByteString, ByteString, ByteString, [ByteString]))
forall a b. b -> Either a b
Right ((ByteString, ByteString, ByteString, [ByteString])
-> Maybe (ByteString, ByteString, ByteString, [ByteString])
forall a. a -> Maybe a
Just (ByteString
pre,ByteString
main,ByteString
post,[ByteString]
rest))