packages feed

AhoCorasick 0.0.3 → 0.0.4

raw patch · 4 files changed

+159/−63 lines, 4 filesdep +AhoCorasickdep +containersdep +tastydep ~basenew-uploaderPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies added: AhoCorasick, containers, tasty, tasty-hunit

Dependency ranges changed: base

API changes (from Hackage documentation)

- Text.AhoCorasick: instance (Eq keySymb, Hashable keySymb, Show keySymb) => Show (SMElem keySymb)
- Text.AhoCorasick: instance (Eq keySymb, Hashable keySymb, Show keySymb, Show val) => Show (SMStepRes keySymb val)
- Text.AhoCorasick: instance (Eq keySymb, Hashable keySymb, Show keySymb, Show val) => Show (StateMachine keySymb val)
- Text.AhoCorasick: instance Show val => Show (Position val)
- Text.AhoCorasick: pIndex :: Position val -> Int
- Text.AhoCorasick: pLength :: Position val -> Int
- Text.AhoCorasick: pVal :: Position val -> val
- Text.AhoCorasick: smsrMatch :: SMStepRes keySymb val -> [(KeyLength, val)]
- Text.AhoCorasick: smsrNextSM :: SMStepRes keySymb val -> StateMachine keySymb val
+ Text.AhoCorasick: [pIndex] :: Position val -> Int
+ Text.AhoCorasick: [pLength] :: Position val -> Int
+ Text.AhoCorasick: [pVal] :: Position val -> val
+ Text.AhoCorasick: [smsrMatch] :: SMStepRes keySymb val -> [(KeyLength, val)]
+ Text.AhoCorasick: [smsrNextSM] :: SMStepRes keySymb val -> StateMachine keySymb val
+ Text.AhoCorasick: instance (GHC.Classes.Eq keySymb, Data.Hashable.Class.Hashable keySymb, GHC.Show.Show keySymb) => GHC.Show.Show (Text.AhoCorasick.SMElem keySymb)
+ Text.AhoCorasick: instance (GHC.Classes.Eq keySymb, Data.Hashable.Class.Hashable keySymb, GHC.Show.Show keySymb, GHC.Show.Show val) => GHC.Show.Show (Text.AhoCorasick.SMStepRes keySymb val)
+ Text.AhoCorasick: instance (GHC.Classes.Eq keySymb, Data.Hashable.Class.Hashable keySymb, GHC.Show.Show keySymb, GHC.Show.Show val) => GHC.Show.Show (Text.AhoCorasick.StateMachine keySymb val)
+ Text.AhoCorasick: instance GHC.Show.Show val => GHC.Show.Show (Text.AhoCorasick.Position val)

Files

AhoCorasick.cabal view
@@ -1,25 +1,26 @@+cabal-version:   3.0 name:            AhoCorasick-version:         0.0.3-license:         BSD3+version:         0.0.4+license:         BSD-3-Clause license-file:    LICENSE category:        Text copyright:       Sergey S Lymar (c) 2012 author:          Sergey S Lymar <sergey.lymar@gmail.com>-maintainer:      Sergey S Lymar <sergey.lymar@gmail.com>+maintainer:      Karl Ostmo <kostmo@gmail.com> stability:       experimental-tested-with:     GHC == 7.0.3+tested-with:     GHC == 9.4.5 synopsis:        Aho-Corasick string matching algorithm-cabal-version:   >= 1.8-homepage:        http://github.com/lymar/AhoCorasick-bug-reports:     http://github.com/lymar/AhoCorasick/issues+homepage:        http://github.com/kostmo/AhoCorasick+bug-reports:     http://github.com/kostmo/AhoCorasick/issues build-type:      Simple description:     Aho-Corasick string matching algorithm.-    .-    See homepage for examples of usage: <http://github.com/lymar/AhoCorasick>+    +    See usage examples in "Text.AhoCorasick". -extra-source-files:+extra-doc-files:     README.md+    CHANGELOG.md  library   exposed-modules:@@ -35,6 +36,21 @@     ,array     ,mtl +  default-language: Haskell2010++test-suite unit-tests+    main-is:          Main.hs+    type:             exitcode-stdio-1.0+    build-depends:    tasty                         >= 0.10 && < 1.5,+                      tasty-hunit                   >= 0.10 && < 0.11,+                      -- Imports shared with the library don't need bounds+                      base,+                      containers,+                      AhoCorasick+    hs-source-dirs:   test/unit+    default-language: Haskell2010+    ghc-options:      -threaded+ source-repository head   type:     git-  location: http://github.com/lymar/AhoCorasick+  location: http://github.com/kostmo/AhoCorasick
+ CHANGELOG.md view
@@ -0,0 +1,20 @@+# Revision history for AhoCorasick++## **0.4** - 2023-10-8+* Compilation fixed by DarinM223+* Updated Cabal version+* Added unit tests++## **0.3** - 2012-11-09++* Export StateMachine datatype+* comment in Deque.hs+* readme fix++## **0.2** - 2012-03-15++* Haddock fixes++## **0.1** - 2012-03-14++* Initial Hackage release
Text/AhoCorasick.hs view
@@ -1,17 +1,17 @@-{-# LANGUAGE RankNTypes, ScopedTypeVariables, ExistentialQuantification #-}--- Module:      Text.Hastache--- Copyright:   Sergey S Lymar (c) 2012--- License:     BSD3--- Maintainer:  Sergey S Lymar <sergey.lymar@gmail.com>--- Stability:   experimental--- Portability: portable------ Aho-Corasick string matching algorithm+{-# LANGUAGE FlexibleContexts, RankNTypes, ScopedTypeVariables, ExistentialQuantification #-}+{- | -{- | Aho-Corasick string matching algorithm+Module:      Text.AhoCorasick+Copyright:   Sergey S Lymar (c) 2012+License:     BSD-3-Clause+Maintainer:  Sergey S Lymar <sergey.lymar@gmail.com>+Stability:   experimental+Portability: portable -Simplest example:+Aho-Corasick string matching algorithm += Simplest example+ @ example1 = mapM_ print $ findAll simpleSM \"ushers\" where     simpleSM = makeSimpleStateMachine [\"he\",\"she\",\"his\",\"hers\"]@@ -23,7 +23,7 @@ Position {pIndex = 2, pLength = 4, pVal = \"hers\"} @ -With data:+= With data  @ example2 = mapM_ print $ findAll sm \"ushers\" where@@ -36,7 +36,7 @@ Position {pIndex = 2, pLength = 4, pVal = 3} @ -Step-by-step state machine evaluation:+= Step-by-step state machine evaluation  @ example3 = mapM_ print $ next sm \"ushers\" where@@ -56,21 +56,25 @@ @ -} module Text.AhoCorasick (-      StateMachine-    , makeStateMachine+      -- ** Basic interface+      makeStateMachine     , makeSimpleStateMachine     , findAll     , Position(..)+      -- ** Low-level interface     , stateMachineStep-    , KeyLength     , SMStepRes(..)     , resetStateMachine+    -- ** Types+    , StateMachine+    , KeyLength     ) where  import Control.Monad.State.Lazy (execStateT, get, put) import Control.Monad.ST.Strict (ST, runST) import Control.Monad.Trans (lift) import Data.Array.IArray (Array, array, (!))+import Data.Functor ((<&>)) import Data.Hashable (Hashable) import Data.Maybe (fromJust) import Data.STRef (STRef, newSTRef, readSTRef, writeSTRef, modifySTRef)@@ -78,7 +82,7 @@  import Text.AhoCorasick.Internal.Deque (mkDQ, pushBack, popFront, dqLength, DQ) -data (Eq keySymb, Hashable keySymb) => TNode keySymb s = +data (Eq keySymb, Hashable keySymb) => TNode keySymb s =     TNode {           tnId          :: Int         , tnLinks       :: M.HashMap keySymb (STRef s (TNode keySymb s))@@ -88,7 +92,7 @@  type KeyLength = Int -data (Eq keySymb, Hashable keySymb) => TTree keySymb val s = +data (Eq keySymb, Hashable keySymb) => TTree keySymb val s =     TTree {           ttRoot        :: STRef s (TNode keySymb s)         , ttLastId      :: STRef s Int@@ -97,21 +101,21 @@  type NodeIndex = Int -data (Eq keySymb, Hashable keySymb) => SMElem keySymb = +data (Eq keySymb, Hashable keySymb) => SMElem keySymb =     SMElem {           smeLinks      :: M.HashMap keySymb NodeIndex         , smeFail       :: NodeIndex         , smeValuesIds  :: [Int]     }-    -data (Eq keySymb, Hashable keySymb) => StateMachine keySymb val = ++data (Eq keySymb, Hashable keySymb) => StateMachine keySymb val =     StateMachine {           smStates      :: Array NodeIndex (SMElem keySymb)         , smValues      :: Array Int (KeyLength, val)         , smState       :: Int     } -data (Eq keySymb, Hashable keySymb) => SMStepRes keySymb val = +data (Eq keySymb, Hashable keySymb) => SMStepRes keySymb val =     SMStepRes {           smsrMatch     :: [(KeyLength, val)]         , smsrNextSM    :: StateMachine keySymb val@@ -124,18 +128,18 @@         , pVal          :: val     } -instance (Eq keySymb, Hashable keySymb, Show keySymb) => +instance (Eq keySymb, Hashable keySymb, Show keySymb) =>                                                     Show (SMElem keySymb) where     show (SMElem l f v) = concat ["SMElem {smeLinks = ", show l,         ", smeFail = ", show f,", smeValuesIds = ", show v, "}"] -instance (Eq keySymb, Hashable keySymb, Show keySymb, Show val) => +instance (Eq keySymb, Hashable keySymb, Show keySymb, Show val) =>                                         Show (StateMachine keySymb val) where     show (StateMachine st vals state) = concat [         "StateMachine {smStates = ", show st,         ", smValues = ", show vals, ", smState = ", show state,"}"] -instance (Eq keySymb, Hashable keySymb, Show keySymb, Show val) => +instance (Eq keySymb, Hashable keySymb, Show keySymb, Show val) =>                                             Show (SMStepRes keySymb val) where     show (SMStepRes f n) = concat [         "StateMachineStepRes {smsrFound = ", show f,@@ -147,6 +151,7 @@         ", pLength = ", show l,         ", pVal = ", show v,"}"] +(~>) :: t1 -> (t1 -> t2) -> t2 x ~> f = f x infixl 9 ~> @@ -157,10 +162,9 @@ initNewTTree = do     root <- newSTRef $ TNode rootNodeId M.empty Nothing []     lid <- newSTRef rootNodeId-    kw <- mkDQ-    return $ TTree root lid kw-    -mkNewTNode :: (Eq keySymb, Hashable keySymb) => +    TTree root lid <$> mkDQ++mkNewTNode :: (Eq keySymb, Hashable keySymb) =>     TTree keySymb a s -> ST s (TNode keySymb s) mkNewTNode tree = do     modifySTRef lid (+1)@@ -169,7 +173,7 @@     where     lid = ttLastId tree -addKeyVal :: forall val s keySymb. (Eq keySymb, Hashable keySymb) => +addKeyVal :: forall val s keySymb. (Eq keySymb, Hashable keySymb) =>     TTree keySymb val s -> [keySymb] -> val -> ST s () addKeyVal tree key val = addSymb (ttRoot tree) key     where@@ -210,10 +214,10 @@             pushBack dq link             fRef <- findParentFail link (tnFail node) symb             f <- readSTRef fRef-            modifySTRef link (\n -> n {tnFail = Just fRef, -                tnValuesIds = (tnValuesIds n) ++ (tnValuesIds f)})+            modifySTRef link (\n -> n {tnFail = Just fRef,+                tnValuesIds = tnValuesIds n ++ tnValuesIds f})             ) $ tnLinks node ~> M.toList-        return ()+     findParentFail link (Just cfRef) symb = do         cf <- readSTRef cfRef         case (M.lookup symb (tnLinks cf), cfRef == root) of@@ -223,19 +227,19 @@             (Nothing, True) -> return root             _ -> findParentFail link (tnFail cf) symb -convertToStateMachine :: forall val s keySymb. (Eq keySymb, Hashable keySymb) => -    TTree keySymb val s -> +convertToStateMachine :: forall val s keySymb. (Eq keySymb, Hashable keySymb) =>+    TTree keySymb val s ->     ST s (StateMachine keySymb val) convertToStateMachine tree = do     size <- readSTRef $ ttLastId tree     nds <- execStateT (convertNode $ ttRoot tree) []-    +     vlsSize <- dqLength $ ttValues tree     vls <- mapM (\i -> do         k <- popFront (ttValues tree)         return (i,fromJust k)         ) [0..(vlsSize-1)]-    +     StateMachine (array (0, size) nds) (array (0, vlsSize-1) vls) rootNodeId         ~> return     where@@ -243,7 +247,7 @@         (n,l,fail) <- lift $ do             n <- readSTRef node             l <- tnLinks n ~> convertLinks-            fail <- tnFail n ~> fromJust ~> readSTRef >>= return . tnId+            fail <- (tnFail n ~> fromJust ~> readSTRef) <&> tnId             return (n,l,fail)         v <- get         put $ (tnId n, SMElem l fail (tnValuesIds n)) : v@@ -254,42 +258,43 @@     convertLinks lnksMap = do         nl <- mapM (\(symb, link) -> do             l <- readSTRef link-            return $ (symb, tnId l)+            return (symb, tnId l)             ) $ M.toList lnksMap         return $ M.fromList nl -resetStateMachine :: (Eq keySymb, Hashable keySymb) => +resetStateMachine :: (Eq keySymb, Hashable keySymb) =>     StateMachine keySymb val -> StateMachine keySymb val resetStateMachine m = m { smState = rootNodeId } -stateMachineStep :: (Eq keySymb, Hashable keySymb) => +stateMachineStep :: (Eq keySymb, Hashable keySymb) =>     StateMachine keySymb val -> keySymb -> SMStepRes keySymb val stateMachineStep sm symb =     case (M.lookup symb links, currentState == rootNodeId) of         (Just nextState, _) -> SMStepRes-            ((smStates sm) ! nextState ~> smeValuesIds ~> convertToVals)+            (smStates sm ! nextState ~> smeValuesIds ~> convertToVals)             (sm { smState = nextState })         (Nothing, True) -> SMStepRes [] sm-        (Nothing, False) -> stateMachineStep -            (sm { smState = smeFail currentNode}) symb            +        (Nothing, False) -> stateMachineStep+            (sm { smState = smeFail currentNode}) symb     where     currentState = smState sm-    currentNode = (smStates sm) ! currentState+    currentNode = smStates sm ! currentState     links = smeLinks currentNode-    convertToVals idx = map (\i -> smValues sm ! i) idx+    convertToVals = map (\i -> smValues sm ! i) -findAll :: (Eq keySymb, Hashable keySymb) => +findAll :: (Eq keySymb, Hashable keySymb) =>     StateMachine keySymb val -> [keySymb] -> [Position val]-findAll sm str = +findAll sm str =     step (resetStateMachine sm) (zip [0..] str) ~> concat     where     step _ [] = []     step csm ((idx,symb):next) = case stateMachineStep csm symb of         SMStepRes [] newsm -> step newsm next-        SMStepRes r newsm -> (map (cnvToPos idx) r) : (step newsm next)      +        SMStepRes r newsm -> map (cnvToPos idx) r : step newsm next     cnvToPos idx (keyLength, val) = Position (idx - keyLength + 1) keyLength val -makeSimpleStateMachine :: (Eq keySymb, Hashable keySymb) => +-- | Returns search keys as values+makeSimpleStateMachine :: (Eq keySymb, Hashable keySymb) =>     [[keySymb]] -> StateMachine keySymb [keySymb] makeSimpleStateMachine keys = runST $ do     tree <- initNewTTree@@ -297,11 +302,12 @@     findFailures tree     convertToStateMachine tree -makeStateMachine :: (Eq keySymb, Hashable keySymb) => +-- | Associate custom values with the search keys+makeStateMachine :: (Eq keySymb, Hashable keySymb) =>     [([keySymb], val)] -> StateMachine keySymb val makeStateMachine kv = runST $ do     tree <- initNewTTree-    mapM_ (\(s,v) -> addKeyVal tree s v) kv+    mapM_ (uncurry (addKeyVal tree)) kv     findFailures tree     convertToStateMachine tree 
+ test/unit/Main.hs view
@@ -0,0 +1,54 @@+{-# LANGUAGE OverloadedStrings #-}++-- |+-- SPDX-License-Identifier: BSD-3-Clause+--+-- BoolExpr unit tests+module Main where++import qualified Data.Map as M+import Data.Either (isRight)+import Data.List (isInfixOf)+import Test.Tasty (TestTree, defaultMain, testGroup)+import Test.Tasty.HUnit++import Text.AhoCorasick++main :: IO ()+main = defaultMain tests++tests :: TestTree+tests = testGroup "Main" [+    testCase "Simplest example" $+        assertEqual "Found strings not equal!"+            ["she", "he", "hers"] example1+    , testCase "With data" $+        assertEqual "Found strings not equal!"+            [1, 0, 3] example2+    , testCase "Step-by-step state machine evaluation" $+        assertEqual "Steps were not equal!"+        [ ('u',[])+        , ('s',[])+        , ('h',[])+        , ('e',[(3,"she"),(2,"he")])+        , ('r',[])+        , ('s',[(4,"hers")])+        ]+        example3+    ]++example1 :: [String]+example1 = map pVal $ findAll simpleSM "ushers"+    where+    simpleSM = makeSimpleStateMachine ["he","she","his","hers"]++example2 :: [Int]+example2 = map pVal $ findAll sm "ushers" where+    sm = makeStateMachine [("he",0),("she",1),("his",2),("hers",3)]++example3 :: [(Char, [(Int, String)])]+example3 = next sm "ushers" where+    sm = makeSimpleStateMachine ["he","she","his","hers"]+    next _ [] = []+    next sm (s:n) = let (SMStepRes match nextSM) = stateMachineStep sm s in+        (s, match) : next nextSM n