-- | -- Module : Data.ByteString.Search.Substitution -- Copyright : Daniel Fischer -- Licence : BSD3 -- Maintainer : Daniel Fischer -- Stability : Provisional -- Portability : portable -- -- Class for values to be substituted into strict and lazy 'S.ByteString's -- by the @replace@ functions defined in this package. -- module Data.ByteString.Search.Substitution ( Substitution(..)) where import qualified Data.ByteString as S import qualified Data.ByteString.Lazy as L import qualified Data.ByteString.Lazy.Internal as LI -- | Type class of meaningful substitutions for replace functions -- on ByteStrings. Instances for strict and lazy ByteStrings are -- provided here. class Substitution a where -- | @'substitution'@ transforms a value to a substitution function. substitution :: a -> ([S.ByteString] -> [S.ByteString]) -- | @'prependCycle' sub lazyBS@ shall prepend infinitely many copies -- of @sub@ to @lazyBS@ without entering an infinite loop in case -- of an empty @sub@, so e.g. -- -- @ -- 'prependCycle' \"\" \"ab\" == \"ab\" -- @ -- -- shall (quickly) evaluate to 'True'. -- For non-empty @sub@, the cycle shall be constructed efficiently. prependCycle :: a -> (L.ByteString -> L.ByteString) instance Substitution S.ByteString where {-# INLINE substitution #-} substitution sub = if S.null sub then id else (sub :) {-# INLINE prependCycle #-} prependCycle sub | S.null sub = id | otherwise = let c = LI.Chunk sub c in const c instance Substitution L.ByteString where {-# INLINE substitution #-} substitution LI.Empty = id substitution (LI.Chunk c t) = (c :) . flip (LI.foldrChunks (:)) t {-# INLINE prependCycle #-} prependCycle sub | L.null sub = id prependCycle sub = let cyc = LI.foldrChunks LI.Chunk cyc sub in const cyc