    {-|
    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 :: forall (m :: * -> *).
    MonadFail m =>
    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 :: forall (m :: * -> *).
    MonadFail m =>
    CompOption -> ExecOption -> ByteString -> m Regex
    makeRegexOptsM CompOption
    c ExecOption
    e 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
    forall (m :: * -> *).
    MonadFail m =>
    CompOption -> ExecOption -> [Char] -> 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 = [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 Regex
    r ByteString
    s = Regex -> Int -> Char -> ByteString -> [MatchArray]
    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 = [MatchArray] -> Int
    forall a. [a] -> 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 = (regex_execOptions r) {captureGroups = 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 ByteString
    source =
        (MatchArray -> (ByteString, MatchText ByteString, ByteString))
    -> Maybe MatchArray
    -> Maybe (ByteString, MatchText ByteString, ByteString)
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (\MatchArray
    ma -> let (Int
    o,Int
    l) = MatchArray
    maMatchArray -> Int -> (Int, Int)
    forall i e. Ix i => Array i e -> i -> e
    !Int
    0
                     in (Int -> ByteString -> ByteString
    B.take Int
    o ByteString
    source
                        ,((Int, Int) -> (ByteString, (Int, Int)))
    -> MatchArray -> MatchText ByteString
    forall a b. (a -> b) -> Array Int a -> Array Int b
    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
    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 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 a b. (a -> b) -> Array Int a -> Array Int b
    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)))
            (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 CompOption
    compOpt ExecOption
    execOpt ByteString
    bs =
      case [Char] -> Either ParseError (Pattern, (Int, DoPa))
    parseRegex (ByteString -> [Char]
    B.unpack ByteString
    bs) of
        Left ParseError
    err -> [Char] -> Either [Char] Regex
    forall a b. a -> Either a b
    Left ([Char]
    "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, (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 Regex
    r 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 Regex
    r ByteString
    txt = 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])
     -> Either
          [Char] (Maybe (ByteString, ByteString, ByteString, [ByteString])))
    -> Maybe (ByteString, ByteString, ByteString, [ByteString])
    -> Either
         [Char] (Maybe (ByteString, ByteString, ByteString, [ByteString]))
    forall a b. (a -> b) -> a -> b
    $
      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
    txt of
        Just (ByteString
    pre, MatchText ByteString
    mt, ByteString
    post) | ByteString
    main:[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 (MatchText ByteString -> [(ByteString, (Int, Int))]
    forall i e. Array i e -> [e]
    elems MatchText ByteString
    mt)
          -> (ByteString, ByteString, ByteString, [ByteString])
    -> Maybe (ByteString, ByteString, ByteString, [ByteString])
    forall a. a -> Maybe a
    Just (ByteString
    pre, ByteString
    main, ByteString
    post, [ByteString]
    rest)
        Maybe (ByteString, MatchText ByteString, ByteString)
    _ -> Maybe (ByteString, ByteString, ByteString, [ByteString])
    forall a. Maybe a
    Nothing