1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
|
-- |
-- Module : Data.ByteString.Search.Substitution
-- Copyright : Daniel Fischer
-- Licence : BSD3
-- Maintainer : Daniel Fischer <daniel.is.fischer@googlemail.com>
-- 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
|