matchers 0.10.0.0 → 0.12.0.0
raw patch · 4 files changed
+173/−26 lines, 4 filesdep −pcre-lightPVP ok
version bump matches the API change (PVP)
Dependencies removed: pcre-light
API changes (from Hackage documentation)
+ Text.Matchers.Pcre: compile :: Caseless -> Text -> Either String Regex
+ Text.Matchers.Pcre: data Regex
+ Text.Matchers.Pcre: exec :: Regex -> Text -> Maybe Bool
+ Text.Matchers.Pcre: reCaseless :: Regex -> Caseless
+ Text.Matchers.Pcre: rePattern :: Regex -> Text
+ Text.Matchers.Pcre: type Caseless = Bool
+ Text.Matchers.Pcre.Base: c_free :: FunPtr (Ptr a -> IO ())
+ Text.Matchers.Pcre.Base: c_pcre_compile :: CString -> CInt -> Ptr CString -> Ptr CInt -> Ptr CUChar -> IO (Ptr PCRE)
+ Text.Matchers.Pcre.Base: c_pcre_exec :: Ptr PCRE -> Ptr PCRE_Extra -> CString -> CInt -> CInt -> CInt -> Ptr CInt -> CInt -> IO CInt
+ Text.Matchers.Pcre.Base: caseless :: CInt
+ Text.Matchers.Pcre.Base: compile :: Caseless -> Text -> IO (Either String Regex)
+ Text.Matchers.Pcre.Base: data PCRE
+ Text.Matchers.Pcre.Base: data PCRE_Extra
+ Text.Matchers.Pcre.Base: data Regex
+ Text.Matchers.Pcre.Base: exec :: Regex -> Text -> IO (Maybe Bool)
+ Text.Matchers.Pcre.Base: instance [safe] Show PCRE
+ Text.Matchers.Pcre.Base: instance [safe] Show PCRE_Extra
+ Text.Matchers.Pcre.Base: instance [safe] Show Regex
+ Text.Matchers.Pcre.Base: pcre_compile :: Caseless -> Text -> IO (Either String (Ptr PCRE))
+ Text.Matchers.Pcre.Base: pcre_exec :: Ptr PCRE -> Text -> IO (Maybe Bool)
+ Text.Matchers.Pcre.Base: reCaseless :: Regex -> Caseless
+ Text.Matchers.Pcre.Base: rePattern :: Regex -> Text
+ Text.Matchers.Pcre.Base: type Caseless = Bool
Files
- Text/Matchers.hs +6/−23
- Text/Matchers/Pcre.hs +26/−0
- Text/Matchers/Pcre/Base.hsc +135/−0
- matchers.cabal +6/−3
Text/Matchers.hs view
@@ -12,16 +12,14 @@ import Control.Applicative ((<$>), (<*>), (<*), (<$), optional, (<|>)) import Control.Monad (replicateM, mzero)-import qualified Data.ByteString as BS import Data.Fixed (Pico)-import Data.Maybe (fromMaybe, isJust)+import Data.Maybe (fromMaybe) import Data.Text (Text, pack, unpack, toCaseFold, isInfixOf)-import Data.Text.Encoding (encodeUtf8)-import qualified Text.Regex.PCRE.Light as PCRE import Text.Parsec (many, satisfy) import qualified Text.Parsec as P import Text.Parsec.Text (Parser) import qualified Data.Time as Time+import Text.Matchers.Pcre as PCRE data CaseSensitive = Sensitive | Insensitive deriving (Eq, Ord, Show) @@ -56,13 +54,13 @@ -- ^ The Matcher if the pattern is good; if the pattern is bad, -- returns an error message. -pcre c t = case pcrePrim c (encodeUtf8 t) of- Left e -> Left $ pack e- Right f ->+pcre c t = case PCRE.compile (c == Insensitive) t of+ Left e -> Left . pack $ e+ Right r -> let sDesc = pack "Perl-compatible regular expression" mrDesc = pack $ "matches the PCRE pattern \"" ++ unpack t ++ "\"" ++ descSensitive c- mr = f . encodeUtf8+ mr = maybe False id . PCRE.exec r in return $ Matcher sDesc mrDesc mr -- | Matcher that succeeds if the pattern text is found anywhere@@ -126,21 +124,6 @@ Just (c, t) -> let cmp = compUTCtoCmp c in return $ subjDT `cmp` t----------------------------------------------------------------- PCRE primitives---------------------------------------------------------------pcrePrim :: CaseSensitive- -> BS.ByteString- -> Either String (BS.ByteString -> Bool)-pcrePrim c bs =- let u8 = [PCRE.utf8]- opts = case c of- Sensitive -> u8- Insensitive -> PCRE.caseless:u8- doMatch rx s = isJust $ PCRE.match rx s []- in fmap doMatch $ PCRE.compileM bs opts ------------------------------------------------------------ -- Date parsers
+ Text/Matchers/Pcre.hs view
@@ -0,0 +1,26 @@+{-# LANGUAGE Trustworthy #-}+module Text.Matchers.Pcre+ ( B.Caseless+ , B.Regex+ , B.reCaseless+ , B.rePattern+ , compile+ , exec+ ) where++import qualified Text.Matchers.Pcre.Base as B+import qualified Data.Text as X+import System.IO.Unsafe (unsafePerformIO)++compile+ :: B.Caseless+ -> X.Text+ -> Either String B.Regex+compile cl x = unsafePerformIO $ B.compile cl x++exec+ :: B.Regex+ -> X.Text+ -> Maybe Bool+exec r x = unsafePerformIO $ B.exec r x+
+ Text/Matchers/Pcre/Base.hsc view
@@ -0,0 +1,135 @@+{-# LANGUAGE ForeignFunctionInterface, EmptyDataDecls, Safe #-}++module Text.Matchers.Pcre.Base+ ( caseless+ , PCRE+ , PCRE_Extra+ , c_free+ , c_pcre_compile+ , c_pcre_exec+ , Caseless+ , pcre_compile+ , pcre_exec+ , Regex+ , reCaseless+ , rePattern+ , compile+ , exec+ ) where++import Foreign.Storable+import Foreign.C+import Foreign.Marshal.Alloc+import Foreign.Marshal.Array+import Foreign.ForeignPtr.Safe+import Foreign.Ptr+import Data.ByteString+import Data.Text+import Data.Text.Encoding++#include <pcre.h>+#include <stdlib.h>++caseless :: CInt+caseless = #const PCRE_CASELESS++data PCRE++instance Show PCRE where+ show _ = "PCRE"++data PCRE_Extra++instance Show PCRE_Extra where+ show _ = "PCRE_Extra"++foreign import ccall unsafe "stdlib.h &free"+ c_free :: FunPtr (Ptr a -> IO ())++foreign import ccall unsafe "pcre.h pcre_compile"+ c_pcre_compile+ :: CString+ -- ^ Pattern+ -> CInt+ -- ^ Options+ -> Ptr CString+ -- ^ OUT error message+ -> Ptr CInt+ -- ^ OUT Error offset+ -> Ptr CUChar+ -- ^ Pointer to character table. Use NULL for default.+ -> IO (Ptr PCRE)++foreign import ccall unsafe "pcre.h pcre_exec"+ c_pcre_exec+ :: Ptr PCRE+ -- ^ Regex+ -> Ptr PCRE_Extra+ -- ^ Result of study+ -> CString+ -- ^ Subject+ -> CInt+ -- ^ Length of subject string. (Apparently it does not have to be+ -- null terminated?)+ -> CInt+ -- ^ Start at this offset in the subject string.+ -> CInt+ -- ^ Options+ -> Ptr CInt+ -- ^ OUT Output vector. Information about matching substrings is+ -- stored in this array.+ -> CInt+ -- ^ Output vector size+ -> IO CInt+ -- ^ One more than the highest numbered pair that has been set.++type Caseless = Bool++pcre_compile+ :: Caseless+ -> Text+ -- ^ Pattern+ -> IO (Either String (Ptr PCRE))+ -- ^ Errors are indicated with a Left with the error message.+pcre_compile cl pat+ = useAsCString (encodeUtf8 pat) $ \patC ->+ alloca $ \ptrMsg ->+ alloca $ \ptrOffset -> do+ let cOpt = if cl then caseless else 0+ ptrPcre <- c_pcre_compile patC cOpt ptrMsg ptrOffset nullPtr+ if ptrPcre == nullPtr+ then do+ ptrErr <- peek ptrMsg+ msg <- peekCAString ptrErr+ return . Left $ msg+ else return . Right $ ptrPcre+ + +pcre_exec :: Ptr PCRE -> Text -> IO (Maybe Bool)+pcre_exec ptr txt+ = useAsCStringLen (encodeUtf8 txt) $ \(ptrSubj, len) ->+ allocaArray 30 $ \array -> do+ r <- c_pcre_exec ptr nullPtr ptrSubj (fromIntegral len)+ 0 0 array 30+ return $ case () of+ _ | r == (-1) -> Just False+ | r < (-1) -> Nothing+ | otherwise -> Just True+ +data Regex = Regex+ { reCaseless :: Caseless+ , rePattern :: Text+ , _rePtr :: ForeignPtr PCRE+ } deriving Show++compile :: Caseless -> Text -> IO (Either String Regex)+compile cl pat = do+ ei <- pcre_compile cl pat+ case ei of+ Left e -> return . Left $ e+ Right ptr -> do+ fp <- newForeignPtr c_free ptr+ return . Right $ Regex cl pat fp++exec :: Regex -> Text -> IO (Maybe Bool)+exec (Regex _ _ fp) s = withForeignPtr fp $ \p -> pcre_exec p s
matchers.cabal view
@@ -1,5 +1,5 @@ Name: matchers-Version: 0.10.0.0+Version: 0.12.0.0 Cabal-version: >=1.8 Build-Type: Simple License: BSD3@@ -24,12 +24,15 @@ base ==4.6.* , bytestring ==0.10.* , parsec >= 3.1.2 && < 3.2- , pcre-light ==0.4.* , text ==0.11.* , time ==1.4.* Exposed-modules: Text.Matchers+ , Text.Matchers.Pcre+ , Text.Matchers.Pcre.Base - ghc-options: -Wall+ extra-libraries: pcre++ ghc-options: -Wall