regex-pcre 0.82 → 0.91
raw patch · 9 files changed
+339/−513 lines, 9 filesdep ~regex-basesetup-changed
Dependency ranges changed: regex-base
Files
- Setup.hs +5/−7
- Text/Regex/PCRE.hs +20/−5
- Text/Regex/PCRE/ByteString.hs +12/−15
- Text/Regex/PCRE/ByteString/Lazy.hs +132/−0
- Text/Regex/PCRE/Sequence.hs +150/−0
- Text/Regex/PCRE/String.hs +3/−0
- Text/Regex/PCRE/Wrap.hs +0/−464
- Text/Regex/PCRE/Wrap.hsc +7/−6
- regex-pcre.cabal +10/−16
Setup.hs view
@@ -3,11 +3,9 @@ -- I usually compile this with "ghc --make -o setup Setup.hs" import Distribution.Simple(defaultMain)--warning = "\nThis is a message from the regex-pcre author.\n\- \You may need to edit regex-pcre.cabal to have\n\- \Include-Dirs: and Extra-Lib-Dirs point to where\n\- \the regex.h and libpcre can be found.\n\n"--main = do putStr warning+main = do putStrLn msg defaultMain++msg = "regex-pcre needs to compile against the libpcre libary from http://www.pcre.org/\n\+ \You might also need to edit the end of the regex-pcre.cabal file to point at\n\+ \the directories where libpcre 'include' and 'lib' have been installed.\n"
Text/Regex/PCRE.hs view
@@ -5,7 +5,7 @@ you should do so with qualified imports, perhaps renamed for convenience. -You will need to have libpcre, from <http://www.pcre.org/>, to use+You will need to have libpcre, from www.pcre.org, to use this module. The haskell must be compiled with -DHAVE_PCRE_H and linked with pcre. This is the default in the cabal file. @@ -34,14 +34,19 @@ exported by this module and medium- and low-level interfaces that returns error using Either structures. -}--module Text.Regex.PCRE(+{- Copyright : (c) Chris Kuklewicz 2007 -}+module Text.Regex.PCRE(getVersion_Text_Regex_PCRE+ ,module Text.Regex.Base -- ** Wrap, for '=~' and '=~~', types and constants- module Text.Regex.PCRE.Wrap+ ,module Text.Regex.PCRE.Wrap -- ** String, instances only ,module Text.Regex.PCRE.String+ -- ** Seq Char, instances only+ ,module Text.Regex.PCRE.Sequence -- ** ByteString, instances only- ,module Text.Regex.PCRE.ByteString) where+ ,module Text.Regex.PCRE.ByteString+ -- ** Lazy ByteString, instances only+ ,module Text.Regex.PCRE.ByteString.Lazy) where import Text.Regex.PCRE.Wrap(Regex, CompOption(CompOption), ExecOption(ExecOption), (=~), (=~~), unusedOffset, getNumSubs, configUTF8, getVersion,@@ -52,4 +57,14 @@ execBlank, execAnchored, execNotBOL, execNotEOL, execNotEmpty, execNoUTF8Check, execPartial) import Text.Regex.PCRE.String()+import Text.Regex.PCRE.Sequence() import Text.Regex.PCRE.ByteString()+import Text.Regex.PCRE.ByteString.Lazy()+import Data.Version(Version(..))+import Text.Regex.Base++getVersion_Text_Regex_PCRE :: Version+getVersion_Text_Regex_PCRE =+ Version { versionBranch = [0,91]+ , versionTags = ["unstable"]+ }
Text/Regex/PCRE/ByteString.hs view
@@ -3,6 +3,7 @@ This exports instances of the high level API and the medium level API of 'compile','execute', and 'regexec'. -}+{- Copyright : (c) Chris Kuklewicz 2007 -} module Text.Regex.PCRE.ByteString( -- ** Types Regex,@@ -47,12 +48,11 @@ import Text.Regex.PCRE.Wrap -- all import Data.Array(Array,listArray) import Data.ByteString(ByteString)-import qualified Data.ByteString as B(empty,useAsCString,last,null,take,drop,pack)+import qualified Data.ByteString as B(empty,useAsCString,last,take,drop) import qualified Data.ByteString.Base 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(nullPtr) import Foreign.C.String(CStringLen) instance RegexContext Regex ByteString ByteString where@@ -63,26 +63,23 @@ unwrap x = case x of Left err -> fail ("Text.Regex.PCRE.ByteString died: "++ show err) Right v -> return v -{-# INLINE asCStringLen #-} asCStringLen :: ByteString -> (CStringLen -> IO a) -> IO a-asCStringLen s op = B.unsafeUseAsCStringLen s checked- where checked cs@(ptr,_) | ptr == nullPtr = B.unsafeUseAsCStringLen myEmpty (op . trim)- | otherwise = op cs- myEmpty = B.pack [0]- trim (ptr,_) = (ptr,0)+asCStringLen = B.unsafeUseAsCStringLen instance RegexMaker Regex CompOption ExecOption ByteString where makeRegexOpts c e pattern = unsafePerformIO $ compile c e pattern >>= unwrap+ makeRegexOptsM c e pattern = either (fail.show) return $ unsafePerformIO $+ compile c e pattern instance RegexLike Regex ByteString where matchTest regex bs = unsafePerformIO $ asCStringLen bs (wrapTest 0 regex) >>= unwrap matchOnce regex bs = unsafePerformIO $ execute regex bs >>= unwrap- matchAll regex bs = unsafePerformIO $+ matchAll regex bs = unsafePerformIO $ asCStringLen bs (wrapMatchAll regex) >>= unwrap- matchCount regex bs = unsafePerformIO $+ matchCount regex bs = unsafePerformIO $ asCStringLen bs (wrapCount regex) >>= unwrap -- ---------------------------------------------------------------------@@ -93,9 +90,9 @@ -> ByteString -- ^ The regular expression to compile -> IO (Either (MatchOffset,String) Regex) -- ^ Returns: the compiled regular expression compile c e pattern = do- let asCString bs = if (not (B.null bs)) && (0==B.last bs)- then B.unsafeUseAsCString bs- else B.useAsCString bs+ let asCString = if (0==B.last pattern)+ then B.unsafeUseAsCString+ else B.useAsCString asCString pattern (wrapCompile c e) -- ---------------------------------------------------------------------@@ -113,7 +110,7 @@ maybeStartEnd <- asCStringLen bs (wrapMatch 0 regex) case maybeStartEnd of Right Nothing -> return (Right Nothing)- Right (Just parts) ->+ Right (Just parts) -> return . Right . Just . listArray (0,pred (length parts)) . map (\(s,e)->(fromIntegral s, fromIntegral (e-s))) $ parts Left err -> return (Left err)@@ -125,7 +122,7 @@ let getSub (start,stop) | start == unusedOffset = B.empty | otherwise = B.take (stop-start) . B.drop start $ bs matchedParts [] = (B.empty,B.empty,bs,[]) -- no information- matchedParts (matchedStartStop@(start,stop):subStartStop) =+ matchedParts (matchedStartStop@(start,stop):subStartStop) = (B.take start bs ,getSub matchedStartStop ,B.drop stop bs
+ Text/Regex/PCRE/ByteString/Lazy.hs view
@@ -0,0 +1,132 @@+{-# OPTIONS_GHC -fglasgow-exts -fno-warn-orphans #-}+{-|+This exports instances of the high level API and the medium level+API of 'compile','execute', and 'regexec'.+-}+{- Copyright : (c) Chris Kuklewicz 2007 -}+module Text.Regex.PCRE.ByteString.Lazy(+ -- ** Types+ Regex,+ MatchOffset,+ MatchLength,+ CompOption(CompOption),+ ExecOption(ExecOption),+ ReturnCode,+ WrapError,+ -- ** Miscellaneous+ unusedOffset,+ getVersion,+ -- ** Medium level API functions+ compile,+ execute,+ regexec,+ -- ** CompOption flags+ compBlank,+ compAnchored,+ compAutoCallout,+ compCaseless,+ compDollarEndOnly,+ compDotAll,+ compExtended,+ compExtra,+ compFirstLine,+ compMultiline,+ compNoAutoCapture,+ compUngreedy,+ compUTF8,+ compNoUTF8Check,+ -- ** ExecOption flags+ execBlank,+ execAnchored,+ execNotBOL,+ execNotEOL,+ execNotEmpty,+ execNoUTF8Check,+ execPartial+ ) where++import Text.Regex.PCRE.Wrap -- all+import Data.Array(Array)+import qualified Data.ByteString.Lazy as L(ByteString,toChunks,fromChunks,last,snoc)+import qualified Data.ByteString as B(ByteString,concat)+import qualified Data.ByteString.Base 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 qualified Text.Regex.PCRE.ByteString as BS(execute,regexec)+import Foreign.C.String(CString,CStringLen)++instance RegexContext Regex L.ByteString L.ByteString where+ match = polymatch+ matchM = polymatchM++{-# INLINE fromLazy #-}+fromLazy :: L.ByteString -> B.ByteString+fromLazy = B.concat . L.toChunks++{-# INLINE toLazy #-}+toLazy :: B.ByteString -> L.ByteString+toLazy = L.fromChunks . return++unwrap :: (Show e) => Either e v -> IO v+unwrap x = case x of Left err -> fail ("Text.Regex.PCRE.ByteString.Lazy died: "++ show err)+ Right v -> return v++{-# INLINE asCString #-}+asCString :: L.ByteString -> (CString -> IO a) -> IO a+asCString s = if (0==L.last s)+ then B.unsafeUseAsCString (fromLazy s)+ else B.unsafeUseAsCString (fromLazy (L.snoc s 0))++{-# INLINE asCStringLen #-}+asCStringLen :: L.ByteString -> (CStringLen -> IO a) -> IO a+asCStringLen s = B.unsafeUseAsCStringLen (fromLazy s)++instance RegexMaker Regex CompOption ExecOption L.ByteString where+ makeRegexOpts c e pattern = unsafePerformIO $+ compile c e pattern >>= unwrap+ makeRegexOptsM c e pattern = either (fail.show) return $ unsafePerformIO $+ compile c e pattern++instance RegexLike Regex L.ByteString where+ matchTest regex bs = unsafePerformIO $+ asCStringLen bs (wrapTest 0 regex) >>= unwrap+ matchOnce regex bs = unsafePerformIO $+ execute regex bs >>= unwrap+ matchAll regex bs = unsafePerformIO $ + asCStringLen bs (wrapMatchAll regex) >>= unwrap+ matchCount regex bs = unsafePerformIO $ + asCStringLen bs (wrapCount regex) >>= unwrap++-- ---------------------------------------------------------------------+-- | Compiles a regular expression+--+compile :: CompOption -- ^ (summed together)+ -> ExecOption -- ^ (summed together)+ -> L.ByteString -- ^ The regular expression to compile+ -> IO (Either (MatchOffset,String) Regex) -- ^ Returns: the compiled regular expression+compile c e pattern = do+ asCString pattern (wrapCompile c e)++-- ---------------------------------------------------------------------+-- | Matches a regular expression against a buffer, returning the buffer+-- indicies of the match, and any submatches+--+-- | Matches a regular expression against a string+execute :: Regex -- ^ Compiled regular expression+ -> L.ByteString -- ^ String to match against+ -> IO (Either WrapError (Maybe (Array Int (MatchOffset,MatchLength))))+ -- ^ Returns: 'Nothing' if the regex did not match the+ -- string, or:+ -- 'Just' an array of (offset,length) pairs where index 0 is whole match, and the rest are the captured subexpressions.+execute regex bs = BS.execute regex (fromLazy bs)++regexec :: Regex -- ^ Compiled regular expression+ -> L.ByteString -- ^ String to match against+ -> IO (Either WrapError (Maybe (L.ByteString, L.ByteString, L.ByteString, [L.ByteString])))+regexec regex bs = do+ x <- BS.regexec regex (fromLazy bs)+ return $ case x of+ Left e -> Left e+ Right Nothing -> Right Nothing+ Right (Just (a,b,c,ds)) -> Right (Just (toLazy a,toLazy b,toLazy c,map toLazy ds))
+ Text/Regex/PCRE/Sequence.hs view
@@ -0,0 +1,150 @@+{-# OPTIONS_GHC -fglasgow-exts -fno-warn-orphans -fbang-patterns #-}+{-|+This exports instances of the high level API and the medium level+API of 'compile','execute', and 'regexec'.+-}+{- Copyright : (c) Chris Kuklewicz 2007 -}+module Text.Regex.PCRE.Sequence(+ -- ** Types+ Regex,+ MatchOffset,+ MatchLength,+ CompOption(CompOption),+ ExecOption(ExecOption),+ ReturnCode,+ WrapError,+ -- ** Miscellaneous+ unusedOffset,+ getVersion,+ -- ** Medium level API functions+ compile,+ execute,+ regexec,+ -- ** Constants for CompOption+ compBlank,+ compAnchored,+ compAutoCallout,+ compCaseless,+ compDollarEndOnly,+ compDotAll,+ compExtended,+ compExtra,+ compFirstLine,+ compMultiline,+ compNoAutoCapture,+ compUngreedy,+ compUTF8,+ compNoUTF8Check,+ -- ** Constants for ExecOption+ execBlank,+ execAnchored,+ execNotBOL,+ execNotEOL,+ execNotEmpty,+ execNoUTF8Check,+ execPartial+ ) where++import Text.Regex.PCRE.Wrap -- all+--import Foreign.C.String(withCStringLen,withCString)+import Data.Array(Array,listArray)+import System.IO.Unsafe(unsafePerformIO)+import Text.Regex.Base.RegexLike(RegexMaker(..),RegexLike(..),RegexContext(..),MatchLength,MatchOffset,Extract(..))+import Text.Regex.Base.Impl(polymatch,polymatchM)+import Data.Sequence as S hiding (length)+import qualified Data.Sequence as S (length)+import Foreign.C.String+import Foreign.Marshal.Array+import Foreign.Marshal.Alloc+import Foreign.Storable++instance RegexContext Regex (Seq Char) (Seq Char) where+ match = polymatch+ matchM = polymatchM++unwrap :: (Show e) => Either e v -> IO v+unwrap x = case x of Left err -> fail ("Text.Regex.PCRE.Sequence died: "++ show err)+ Right v -> return v++instance RegexMaker Regex CompOption ExecOption (Seq Char) where+ makeRegexOpts c e pattern = unsafePerformIO $+ compile c e pattern >>= unwrap+ makeRegexOptsM c e pattern = either (fail.show) return $ unsafePerformIO $+ compile c e pattern++instance RegexLike Regex (Seq Char) where+ matchTest regex str = unsafePerformIO $+ withSeq str (wrapTest 0 regex) >>= unwrap+ matchOnce regex str = unsafePerformIO $+ execute regex str >>= unwrap+ matchAll regex str = unsafePerformIO $ + withSeq str (wrapMatchAll regex) >>= unwrap+ matchCount regex str = unsafePerformIO $ + withSeq str (wrapCount regex) >>= unwrap++-- | Compiles a regular expression+compile :: CompOption -- ^ Flags (summed together)+ -> ExecOption -- ^ Flags (summed together)+ -> (Seq Char) -- ^ The regular expression to compile+ -> IO (Either (MatchOffset,String) Regex) -- ^ Returns: an error string and offset or the compiled regular expression+compile c e pattern = withSeq0 pattern (wrapCompile c e)++-- | Matches a regular expression against a string+execute :: Regex -- ^ Compiled regular expression+ -> (Seq Char) -- ^ (Seq Char) to match against+ -> IO (Either WrapError (Maybe (Array Int (MatchOffset,MatchLength))))+ -- ^ Returns: 'Nothing' if the regex did not match the+ -- string, or:+ -- 'Just' an array of (offset,length) pairs where index 0 is whole match, and the rest are the captured subexpressions.+execute regex str = do+ maybeStartEnd <- withSeq str (wrapMatch 0 regex)+ case maybeStartEnd of+ Right Nothing -> return (Right Nothing)+-- Right (Just []) -> fail "got [] back!" -- should never happen+ Right (Just parts) -> + return . Right . Just . listArray (0,pred (length parts))+ . map (\(s,e)->(fromIntegral s, fromIntegral (e-s))) $ parts+ Left err -> return (Left err)++-- | execute match and extract substrings rather than just offsets+regexec :: Regex -- ^ compiled regular expression+ -> (Seq Char) -- ^ string to match+ -> IO (Either WrapError (Maybe ((Seq Char), (Seq Char),(Seq Char), [(Seq Char)])))+ -- ^ Returns: Nothing if no match, else+ -- (text before match, text after match, array of matches with 0 being the whole match)+regexec regex str = do+ let getSub (start,stop) | start == unusedOffset = S.empty+ | otherwise = extract (start,stop-start) str+ matchedParts [] = (S.empty,S.empty,str,[]) -- no information+ matchedParts (matchedStartStop@(start,stop):subStartStop) = + (before start str+ ,getSub matchedStartStop+ ,after stop str+ ,map getSub subStartStop)+ maybeStartEnd <- withSeq str (wrapMatch 0 regex)+ case maybeStartEnd of+ Right Nothing -> return (Right Nothing)+-- Right (Just []) -> fail "got [] back!" -- should never happen+ Right (Just parts) -> return . Right . Just . matchedParts $ parts+ Left err -> return (Left err)++withSeq :: Seq Char -> (CStringLen -> IO a) -> IO a+withSeq s f =+ let -- Ensure null at end of s+ len = S.length s+ pokes !p !a = case viewl a of+ EmptyL -> return ()+ c :< a' -> poke p (castCharToCChar c) >> pokes (advancePtr p 1) a'+ in allocaBytes (S.length s) (\ptr -> pokes ptr s >> f (ptr,len))++withSeq0 :: Seq Char -> (CString -> IO a) -> IO a+withSeq0 s f =+ let -- Ensure null at end of s+ s' = case viewr s of -- bang !s'+ EmptyR -> singleton '\0'+ _ :> '\0' -> s+ _ -> s |> '\0'+ pokes p a = case viewl a of -- bang pokes !p !a+ EmptyL -> return ()+ c :< a' -> poke p (castCharToCChar c) >> pokes (advancePtr p 1) a'+ in allocaBytes (S.length s') (\ptr -> pokes ptr s' >> f ptr)
Text/Regex/PCRE/String.hs view
@@ -3,6 +3,7 @@ This exports instances of the high level API and the medium level API of 'compile','execute', and 'regexec'. -}+{- Copyright : (c) Chris Kuklewicz 2007 -} module Text.Regex.PCRE.String( -- ** Types Regex,@@ -62,6 +63,8 @@ instance RegexMaker Regex CompOption ExecOption String where makeRegexOpts c e pattern = unsafePerformIO $ compile c e pattern >>= unwrap+ makeRegexOptsM c e pattern = either (fail.show) return $ unsafePerformIO $+ compile c e pattern instance RegexLike Regex String where matchTest regex str = unsafePerformIO $
− Text/Regex/PCRE/Wrap.hs
@@ -1,464 +0,0 @@-{-# OPTIONS_GHC -optc-D__GLASGOW_HASKELL__=606 #-}-{-# OPTIONS_GHC -optc-DHAVE_PCRE_H #-}-{-# INCLUDE <sys/types.h> #-}-{-# INCLUDE <pcre.h> #-}-{-# LINE 1 "Text/Regex/PCRE/Wrap.hsc" #-}-{-# OPTIONS_GHC -fglasgow-exts -fffi #-}-{-# LINE 2 "Text/Regex/PCRE/Wrap.hsc" #-}--- | This will fail or error only if allocation fails or a nullPtr is passed in.--- TODO :: Consider wrapMatchAll using list of start/end offsets and not MatchArray------ The exported symbols are the same whether HAVE_PCRE_H is defined,--- but when if it is not defined then @getVersion == Nothing@ and all--- other exported values will call error or fail.-module Text.Regex.PCRE.Wrap(- -- ** High-level interface- Regex,- CompOption(CompOption),- ExecOption(ExecOption),- (=~),- (=~~),-- -- ** Low-level interface- StartOffset,- EndOffset,- ReturnCode(ReturnCode),- WrapError,- wrapCompile,- wrapTest,- wrapMatch,- wrapMatchAll,- wrapCount,-- -- ** Miscellaneous- getVersion,- configUTF8,- getNumSubs,- unusedOffset,-- -- ** CompOption values- compBlank,- compAnchored,- compAutoCallout,- compCaseless,- compDollarEndOnly,- compDotAll,- compExtended,- compExtra,- compFirstLine,- compMultiline,- compNoAutoCapture,- compUngreedy,- compUTF8,- compNoUTF8Check,-- -- ** ExecOption values- execBlank,- execAnchored,- execNotBOL,- execNotEOL,- execNotEmpty,- execNoUTF8Check,- execPartial,-- -- ** ReturnCode values- retOk,- retNoMatch,- retNull,- retBadOption,- retBadMagic,- retUnknownNode,- retNoMemory,- retNoSubstring- ) where---{-# LINE 70 "Text/Regex/PCRE/Wrap.hsc" #-}-import Control.Monad(when)-import Data.Array(Array,accumArray)-import Data.Bits(Bits((.|.))) -- ((.&.),(.|.),complement))-import Foreign(unsafePerformIO- ,Ptr,ForeignPtr,FinalizerPtr -- ,FunPtr- ,alloca,allocaBytes,nullPtr- ,peek,peekElemOff- ,newForeignPtr,withForeignPtr)-import Foreign.C(CInt,CChar)-import Foreign.C.String(CString,CStringLen,peekCString)-import Text.Regex.Base.RegexLike(RegexOptions(..),RegexMaker(..),RegexContext(..),MatchArray,MatchOffset)--{-# LINE 89 "Text/Regex/PCRE/Wrap.hsc" #-}----- | return version of pcre used or Nothing if pcre is not available.-getVersion :: Maybe String--type PCRE = ()-type StartOffset = MatchOffset-type EndOffset = MatchOffset-type WrapError = (ReturnCode,String)--newtype CompOption = CompOption CInt deriving (Eq,Show,Num,Bits)-newtype ExecOption = ExecOption CInt deriving (Eq,Show,Num,Bits)-newtype ReturnCode = ReturnCode CInt deriving (Eq,Show)---- | A compiled regular expression-data Regex = Regex (ForeignPtr PCRE) CompOption ExecOption--compBlank :: CompOption-execBlank :: ExecOption-unusedOffset :: MatchOffset-retOk :: ReturnCode--wrapCompile :: CompOption -- ^ Flags (summed together)- -> ExecOption -- ^ Flags (summed together)- -> CString -- ^ The regular expression to compile- -> IO (Either (MatchOffset,String) Regex) -- ^ Returns: an error offset and string or the compiled regular expression-wrapTest :: StartOffset -- ^ Starting index in CStringLen- -> Regex -- ^ Compiled regular expression- -> CStringLen -- ^ String to match against and length in bytes- -> IO (Either WrapError Bool)-wrapMatch :: StartOffset -- ^ Starting index in CStringLen- -> Regex -- ^ Compiled regular expression- -> CStringLen -- ^ String to match against and length in bytes- -> IO (Either WrapError (Maybe [(StartOffset,EndOffset)]))- -- ^ Returns: 'Right Nothing' if the regex did not match the- -- string, or:- -- 'Right Just' an array of (offset,length) pairs where index 0 is whole match, and the rest are the captured subexpressions, or:- -- 'Left ReturnCode' if there is some strange error-wrapMatchAll :: Regex -> CStringLen -> IO (Either WrapError [ MatchArray ])-wrapCount :: Regex -> CStringLen -> IO (Either WrapError Int)--getNumSubs :: Regex -> Int-configUTF8 :: Bool--(=~) :: (RegexMaker Regex CompOption ExecOption source,RegexContext Regex source1 target)- => source1 -> source -> target-(=~~) :: (RegexMaker Regex CompOption ExecOption source,RegexContext Regex source1 target,Monad m)- => source1 -> source -> m target---{-# LINE 139 "Text/Regex/PCRE/Wrap.hsc" #-}--{-# LINE 140 "Text/Regex/PCRE/Wrap.hsc" #-}--{-# LINE 141 "Text/Regex/PCRE/Wrap.hsc" #-}--instance RegexOptions Regex CompOption ExecOption where- blankCompOpt = compBlank- blankExecOpt = execBlank- defaultCompOpt = compMultiline- defaultExecOpt = execBlank- setExecOpts e' (Regex r c _) = Regex r c e'- getExecOpts (Regex _ _ e) = e---- (=~) :: (RegexMaker Regex CompOption ExecOption source,RegexContext Regex source1 target) => source1 -> source -> target-(=~) x r = let q :: Regex- q = makeRegex r- in match q x---- (=~~) ::(RegexMaker Regex CompOption ExecOption source,RegexContext Regex source1 target,Monad m) => source1 -> source -> m target-(=~~) x r = let q :: Regex- q = makeRegex r- in matchM q x--type PCRE_Extra = ()--fi :: (Integral i,Num n ) => i -> n-fi x = fromIntegral x--compBlank = CompOption 0-execBlank = ExecOption 0-unusedOffset = (-1)-retOk = ReturnCode 0--retNeededMoreSpace :: ReturnCode-retNeededMoreSpace = ReturnCode 0--newtype InfoWhat = InfoWhat CInt deriving (Eq,Show)-newtype ConfigWhat = ConfigWhat CInt deriving (Eq,Show)--nullTest' :: Ptr a -> String -> IO (Either (MatchOffset,String) b) -> IO (Either (MatchOffset,String) b)-{-# INLINE nullTest' #-}-nullTest' ptr msg io = do- if nullPtr == ptr- then return (Left (0,"Ptr parameter was nullPtr in Text.Regex.PCRE.Wrap."++msg)) - else io--nullTest :: Ptr a -> String -> IO (Either WrapError b) -> IO (Either WrapError b)-{-# INLINE nullTest #-}-nullTest ptr msg io = do- if nullPtr == ptr- then return (Left (retOk,"Ptr parameter was nullPtr in Text.Regex.PCRE.Wrap."++msg)) - else io--wrapRC :: ReturnCode -> IO (Either WrapError b)-{-# INLINE wrapRC #-}-wrapRC r = return (Left (r,"Error in Text.Regex.PCRE.Wrap: "++show r))---- | Compiles a regular expression-wrapCompile flags e pattern = do- nullTest' pattern "wrapCompile pattern" $ do- alloca $ \errOffset -> alloca $ \errPtr -> do- nullTest' errPtr "wrapCompile errPtr" $ do- pcre_ptr <- c_pcre_compile pattern flags errPtr errOffset nullPtr- if pcre_ptr == nullPtr- then do- -- No need to use c_ptr_free in the error case (e.g. pcredemo.c)- offset <- peek errOffset- string <- peekCString =<< peek errPtr- return (Left (fi offset,string))- else do regex <- newForeignPtr c_ptr_free pcre_ptr- return . Right $ Regex regex flags e--getNumSubs (Regex pcre_fptr _ _) = fi . unsafePerformIO $ withForeignPtr pcre_fptr getNumSubs'--getNumSubs' :: Ptr PCRE -> IO CInt-{-# INLINE getNumSubs' #-}-getNumSubs' pcre_ptr =- alloca $ \st -> do -- (st :: Ptr CInt)- when (st == nullPtr) (fail "Text.Regex.PCRE.Wrap.getNumSubs' could not allocate a CInt!!!")- c_pcre_fullinfo pcre_ptr nullPtr pcreInfoCapturecount st- peek st--wrapTest startOffset (Regex pcre_fptr _ flags) (cstr,len) = do- nullTest cstr "wrapTest cstr" $ do- withForeignPtr pcre_fptr $ \pcre_ptr -> do- r@(ReturnCode r') <- c_pcre_exec pcre_ptr nullPtr cstr (fi len) (fi startOffset) flags nullPtr 0- if r == retNoMatch- then return (Right False)- else if r' < 0- then wrapRC r- else return (Right True)---- | Matches a regular expression against a string------ Should never return (Right (Just []))-wrapMatch startOffset (Regex pcre_fptr _ flags) (cstr,len) = do- nullTest cstr "wrapMatch cstr" $ do- withForeignPtr pcre_fptr $ \pcre_ptr -> do- nsub <- getNumSubs' pcre_ptr- let nsub_int :: Int- nsub_int = fi nsub- ovec_size :: CInt- ovec_size = ((nsub + 1) * 3) -- "man pcreapi" for explanation- ovec_bytes :: Int- ovec_bytes = (fi ovec_size) * (4)-{-# LINE 242 "Text/Regex/PCRE/Wrap.hsc" #-}- allocaBytes ovec_bytes $ \ovec -> do- nullTest ovec "wrapMatch ovec" $ do- r@(ReturnCode r') <- c_pcre_exec pcre_ptr nullPtr cstr (fi len) (fi startOffset) flags ovec ovec_size- if r == retNoMatch- then return (Right Nothing)- else if r' < 0- then wrapRC r- else do- let pairsSet :: Int- pairsSet = if r == retNeededMoreSpace -- if r == ReturnCode 0- then nsub_int + 1 -- should not happen- else fi r' -- implies pairsSet > 0- extraPairs :: [(Int,Int)]- extraPairs = replicate (nsub_int + 1 - pairsSet)- (unusedOffset,unusedOffset)- pairs <- return . toPairs =<< mapM (peekElemOff ovec) [0 .. ((pairsSet*2)-1)]- return . Right . Just $ (pairs ++ extraPairs)---- | wrapMatchAll is an improvement over wrapMatch since it only--- allocates memory with allocaBytes once at the start.--- --- -wrapMatchAll (Regex pcre_fptr _ flags) (cstr,len) = do- nullTest cstr "wrapMatchAll cstr" $ do- withForeignPtr pcre_fptr $ \regex -> do- nsub <- getNumSubs' regex- let nsub_int :: Int- nsub_int = fi nsub- ovec_size :: CInt- ovec_size = ((nsub + 1) * 3) -- "man pcreapi" for explanation- ovec_bytes :: Int- ovec_bytes = (fi ovec_size) * (4)-{-# LINE 274 "Text/Regex/PCRE/Wrap.hsc" #-}- clen = fi len- flags' = (execNotEmpty .|. execAnchored .|. flags)- allocaBytes ovec_bytes $ \ovec ->- nullTest ovec "wrapMatchAll ovec" $- let loop acc flags_in_use pos = do- r@(ReturnCode r') <- c_pcre_exec regex nullPtr cstr clen (fi pos) flags_in_use ovec ovec_size- if r == retNoMatch- then return (Right (acc []))- else if r' < 0- then wrapRC r- else do- let pairsSet = if r == retNeededMoreSpace then nsub_int+1 else fi r'- pairs <- return . toPairs =<< mapM (peekElemOff ovec) [0 .. ((pairsSet*2)-1)]- let acc' = acc . (toMatchArray nsub_int pairs:)- case pairs of- [] -> return (Right (acc' []))- ((s,e):_) | s==e -> if s == len - then return (Right (acc' []))- else loop acc' flags' e- | otherwise -> loop acc' flags e- in loop id flags 0-toMatchArray :: Int -> [(Int,Int)] -> Array Int (Int,Int)-toMatchArray n pairs = accumArray (\_ (s,e) -> (s,(e-s))) (-1,0) (0,n) (zip [0..] pairs)--toPairs :: [CInt] -> [(Int,Int)]-toPairs [] = []-toPairs (a:b:rest) = (fi a,fi b):toPairs rest-toPairs [_] = error "Should not have just one element in WrapPCRE.wrapMatchAll.toPairs"--wrapCount (Regex pcre_fptr _ flags) (cstr,len) = do- nullTest cstr "wrapCount cstr" $ do- withForeignPtr pcre_fptr $ \pcre_ptr -> do- nsub <- getNumSubs' pcre_ptr- let ovec_size :: CInt- ovec_size = ((nsub + 1) * 3) -- "man pcreapi" for explanation- ovec_bytes :: Int- ovec_bytes = (fi ovec_size) * (4)-{-# LINE 311 "Text/Regex/PCRE/Wrap.hsc" #-}- clen = fi len- allocaBytes ovec_bytes $ \ovec ->- nullTest ovec "wrapCount ovec" $- let act pos = c_pcre_exec pcre_ptr nullPtr cstr clen (fi pos) flags ovec ovec_size- loop acc pos | acc `seq` pos `seq` False = undefined- | otherwise = do- r@(ReturnCode r') <- act pos- if r == retNoMatch- then return (Right acc)- else if r' < 0- then wrapRC r- else do- pairs <- return . toPairs =<< mapM (peekElemOff ovec) [0,1]- case pairs of- [] -> return (Right (succ acc))- ((s,e):_) | s==e -> return (Right (succ acc))- | otherwise -> loop (succ acc) e- in loop 0 0--getVersion = unsafePerformIO $ do- version <- c_pcre_version- if version == nullPtr- then return (Just "pcre_version was null")- else return . Just =<< peekCString version--configUTF8 = unsafePerformIO $- alloca $ \ptrVal -> do -- (ptrVal :: Ptr CInt)- when (ptrVal == nullPtr) (fail "Text.Regex.PCRE.Wrap.configUTF8 could not alloca CInt!!!")- c_pcre_config pcreConfigUtf8 ptrVal- val <- peek ptrVal- case val of- (1 :: CInt) -> return True- 0 -> return False- _ -> return False -- should not happen--foreign import ccall unsafe "pcre.h pcre_compile"- c_pcre_compile :: CString -> CompOption -> Ptr CString -> Ptr CInt -> CString -> IO (Ptr PCRE)-foreign import ccall unsafe "&free"- c_ptr_free :: FinalizerPtr a -- FunPtr (Ptr a -> IO ())-foreign import ccall unsafe "pcre.h pcre_exec"- c_pcre_exec :: Ptr PCRE -> Ptr PCRE_Extra -> CString -> CInt -> CInt -> ExecOption -> Ptr CInt -> CInt -> IO ReturnCode-foreign import ccall unsafe "pcre.h pcre_fullinfo"- c_pcre_fullinfo :: Ptr PCRE -> Ptr PCRE_Extra -> InfoWhat -> Ptr a -> IO CInt-foreign import ccall unsafe "pcre.h pcre_version"- c_pcre_version :: IO (Ptr CChar)-foreign import ccall unsafe "pcre.h pcre_config"- c_pcre_config :: ConfigWhat -> Ptr a -> IO CInt---compAnchored :: CompOption-compAnchored = CompOption 16-compAutoCallout :: CompOption-compAutoCallout = CompOption 16384-compCaseless :: CompOption-compCaseless = CompOption 1-compDollarEndOnly :: CompOption-compDollarEndOnly = CompOption 32-compDotAll :: CompOption-compDotAll = CompOption 4-compExtended :: CompOption-compExtended = CompOption 8-compExtra :: CompOption-compExtra = CompOption 64-compFirstLine :: CompOption-compFirstLine = CompOption 262144-compMultiline :: CompOption-compMultiline = CompOption 2-compNoAutoCapture :: CompOption-compNoAutoCapture = CompOption 4096-compUngreedy :: CompOption-compUngreedy = CompOption 512-compUTF8 :: CompOption-compUTF8 = CompOption 2048-compNoUTF8Check :: CompOption-compNoUTF8Check = CompOption 8192--{-# LINE 374 "Text/Regex/PCRE/Wrap.hsc" #-}--execAnchored :: ExecOption-execAnchored = ExecOption 16-execNotBOL :: ExecOption-execNotBOL = ExecOption 128-execNotEOL :: ExecOption-execNotEOL = ExecOption 256-execNotEmpty :: ExecOption-execNotEmpty = ExecOption 1024-execNoUTF8Check :: ExecOption-execNoUTF8Check = ExecOption 8192-execPartial :: ExecOption-execPartial = ExecOption 32768--{-# LINE 382 "Text/Regex/PCRE/Wrap.hsc" #-}--retNoMatch :: ReturnCode-retNoMatch = ReturnCode (-1)-retNull :: ReturnCode-retNull = ReturnCode (-2)-retBadOption :: ReturnCode-retBadOption = ReturnCode (-3)-retBadMagic :: ReturnCode-retBadMagic = ReturnCode (-4)-retUnknownNode :: ReturnCode-retUnknownNode = ReturnCode (-5)-retNoMemory :: ReturnCode-retNoMemory = ReturnCode (-6)-retNoSubstring :: ReturnCode-retNoSubstring = ReturnCode (-7)--{-# LINE 391 "Text/Regex/PCRE/Wrap.hsc" #-}---- Comment out most of these to avoid unused binding warnings---- PCRE_INFO_FIRSTCHAR is deprecated, use PCRE_INFO_FIRSTBYTE instead.-pcreInfoCapturecount :: InfoWhat-pcreInfoCapturecount = InfoWhat 2--{-# LINE 397 "Text/Regex/PCRE/Wrap.hsc" #-}-{-- PCRE_INFO_BACKREFMAX, \- PCRE_INFO_DEFAULT_TABLES, \- PCRE_INFO_FIRSTBYTE, \- PCRE_INFO_FIRSTCHAR, \- PCRE_INFO_FIRSTTABLE, \- PCRE_INFO_LASTLITERAL, \- PCRE_INFO_NAMECOUNT, \- PCRE_INFO_NAMEENTRYSIZE, \- PCRE_INFO_NAMETABLE, \- PCRE_INFO_OPTIONS, \- PCRE_INFO_SIZE, \- PCRE_INFO_STUDYSIZE--}-pcreConfigUtf8 :: ConfigWhat-pcreConfigUtf8 = ConfigWhat 0--{-# LINE 413 "Text/Regex/PCRE/Wrap.hsc" #-}-{-- PCRE_CONFIG_UNICODE_PROPERTIES, \- PCRE_CONFIG_NEWLINE, \- PCRE_CONFIG_LINK_SIZE, \- PCRE_CONFIG_POSIX_MALLOC_THRESHOLD, \- PCRE_CONFIG_MATCH_LIMIT, \- PCRE_CONFIG_MATCH_LIMIT_RECURSION, \- PCRE_CONFIG_STACKRECURSE--}---{-# LINE 489 "Text/Regex/PCRE/Wrap.hsc" #-}
Text/Regex/PCRE/Wrap.hsc view
@@ -1,10 +1,12 @@ {-# OPTIONS_GHC -fglasgow-exts -fffi #-}+-- The exported symbols are the same whether HAVE_PCRE_H is defined,+-- but when if it is not defined then 'getVersion == Nothing' and all+-- other exported values will call error or fail.+ -- | This will fail or error only if allocation fails or a nullPtr is passed in. -- TODO :: Consider wrapMatchAll using list of start/end offsets and not MatchArray ----- The exported symbols are the same whether HAVE_PCRE_H is defined,--- but when if it is not defined then @getVersion == Nothing@ and all--- other exported values will call error or fail.+{- Copyright : (c) Chris Kuklewicz 2007 -} module Text.Regex.PCRE.Wrap( -- ** High-level interface Regex,@@ -153,9 +155,8 @@ in match q x -- (=~~) ::(RegexMaker Regex CompOption ExecOption source,RegexContext Regex source1 target,Monad m) => source1 -> source -> m target-(=~~) x r = let q :: Regex- q = makeRegex r- in matchM q x+(=~~) x r = do (q :: Regex) <- makeRegexM r+ matchM q x type PCRE_Extra = ()
regex-pcre.cabal view
@@ -1,10 +1,5 @@--- ****************************************************************--- To fix for cabal < 1.1.4 comment out the Extra-Source-Files line--- You may need to edit the Extra-Lib-Dirs entry near the bottom to find libpcre--- You may need to edit the Include-Dirs entry at the bottom to find regex.h--- **************************************************************** Name: regex-pcre-Version: 0.82+Version: 0.91 -- Cabal-Version: >=1.1.4 License: BSD3 License-File: LICENSE@@ -13,37 +8,36 @@ Maintainer: TextRegexLazy@personal.mightyreason.com Stability: Seems to work, passes a few tests Homepage: http://sourceforge.net/projects/lazy-regex--- Package-URL:+Package-URL: http://darcs.haskell.org/packages/regex-unstable/regex-pcre/ Synopsis: Replaces/Enhances Text.Regex-Description: The PCRE backend to accompany regex-base+Description: The PCRE backend to accompany regex-base, see www.pcre.org Category: Text Tested-With: GHC--- The base >=0 2.0 is for the upcoming GHC 6.6-Build-Depends: base >= 2.0, regex-base--- Build-Depends: regex-base, base, fps >= 0.7+Build-Depends: base >= 2.0, regex-base >= 0.80 -- Data-Files: -- Extra-Source-Files: -- Extra-Tmp-Files: Exposed-Modules: Text.Regex.PCRE Text.Regex.PCRE.Wrap Text.Regex.PCRE.String+ Text.Regex.PCRE.Sequence Text.Regex.PCRE.ByteString+ Text.Regex.PCRE.ByteString.Lazy Buildable: True -- Other-Modules:--- be backward compatible until 6.4.2 is futher deployed -- HS-Source-Dirs: "." Extensions: MultiParamTypeClasses, FunctionalDependencies -- GHC-Options: -Wall -Werror GHC-Options: -Wall -Werror -O2 -- GHC-Options: -Wall -ddump-minimal-imports--- GHC-Prog-Options:+-- GHC-Prof-Options: -- Hugs-Options: -- NHC-Options:--- Includes: -- C-Sources:+-- Includes: -- LD-Options: -- Frameworks: CC-Options: -DHAVE_PCRE_H Extra-Libraries: pcre---Extra-Lib-Dirs: /opt/local/lib---Include-Dirs: /opt/local/include+-- Include-Dirs: /opt/local/include+-- Extra-Lib-Dirs: /opt/local/lib