{-# LINE 1 "src/Bio/Util/Regex.hsc" #-}
{-# LANGUAGE CPP, ForeignFunctionInterface #-}
{-# LINE 2 "src/Bio/Util/Regex.hsc" #-}
-- | The absolute minimum necessary for regex matching using POSIX regexec.
module Bio.Util.Regex ( Regex, regComp, regMatch )where


{-# LINE 6 "src/Bio/Util/Regex.hsc" #-}

{-# LINE 7 "src/Bio/Util/Regex.hsc" #-}

import Control.Applicative
import Control.Monad
import Foreign.Ptr
import Foreign.ForeignPtr
import Foreign.Marshal.Alloc
import Foreign.C.String
import Foreign.C.Types
import System.IO.Unsafe

newtype Regex = Regex (ForeignPtr Regex)

regComp :: String -> Regex
regComp re = unsafePerformIO $ do
    fp <- mallocForeignPtrBytes (64)
{-# LINE 22 "src/Bio/Util/Regex.hsc" #-}
    withForeignPtr fp $ \p -> do
        withCString re $ \pre -> do
            ec <- regcomp p pre (1 + 8)
{-# LINE 25 "src/Bio/Util/Regex.hsc" #-}
            when (ec /= 0) $ do
                sz <- regerror ec p nullPtr 0
                allocaBytes (fromIntegral sz) $ \err -> do
                    _ <- regerror ec p err sz
                    peekCString err >>= error . (++) "regexec: "
    addForeignPtrFinalizer regfree fp
    return $ Regex fp

regMatch :: Regex -> String -> Bool
regMatch (Regex fp) str =
    unsafePerformIO $
        withForeignPtr fp $ \p ->
            withCString str $ \s ->
                (==) 0 <$> regexec p s 0 nullPtr 0


foreign import ccall unsafe            regcomp :: Ptr Regex -> CString -> CInt -> IO CInt
foreign import ccall unsafe            regexec :: Ptr Regex -> CString -> CSize -> Ptr () -> CInt -> IO CInt
foreign import ccall unsafe           regerror :: CInt -> Ptr Regex -> CString -> CSize -> IO CSize
foreign import ccall unsafe "&regfree" regfree :: FunPtr (Ptr Regex -> IO ())