case-insensitive 1.0.0.2 → 1.1
raw patch · 4 files changed
+214/−157 lines, 4 filesdep ~basePVP ok
version bump matches the API change (PVP)
Dependency ranges changed: base
API changes (from Hackage documentation)
- Data.CaseInsensitive: instance (IsString s, FoldCase s) => IsString (CI s)
- Data.CaseInsensitive: instance (Read s, FoldCase s) => Read (CI s)
- Data.CaseInsensitive: instance Eq s => Eq (CI s)
- Data.CaseInsensitive: instance FoldCase (CI s)
- Data.CaseInsensitive: instance FoldCase ByteString
- Data.CaseInsensitive: instance FoldCase Char
- Data.CaseInsensitive: instance FoldCase Text
- Data.CaseInsensitive: instance FoldCase a => FoldCase [a]
- Data.CaseInsensitive: instance Hashable s => Hashable (CI s)
- Data.CaseInsensitive: instance Monoid s => Monoid (CI s)
- Data.CaseInsensitive: instance NFData s => NFData (CI s)
- Data.CaseInsensitive: instance Ord s => Ord (CI s)
- Data.CaseInsensitive: instance Show s => Show (CI s)
- Data.CaseInsensitive: instance Typeable1 CI
+ Data.CaseInsensitive.Unsafe: unsafeMk :: FoldCase s => s -> CI s
Files
- Data/CaseInsensitive.hs +2/−155
- Data/CaseInsensitive/Internal.hs +190/−0
- Data/CaseInsensitive/Unsafe.hs +19/−0
- case-insensitive.cabal +3/−2
Data/CaseInsensitive.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE CPP, NoImplicitPrelude, DeriveDataTypeable #-}+{-# LANGUAGE CPP, NoImplicitPrelude #-} #if __GLASGOW_HASKELL__ >= 702 {-# LANGUAGE Trustworthy #-}@@ -30,157 +30,4 @@ , map , FoldCase(foldCase) ) where------------------------------------------------------------------------------------- Imports------------------------------------------------------------------------------------- from base:-import Data.Bool ( (||) )-import Data.Char ( Char, toLower )-import Data.Eq ( Eq, (==) )-import Data.Function ( on )-import Data.Monoid ( Monoid, mempty, mappend )-import Data.Ord ( Ord, compare )-import Data.String ( IsString, fromString )-import Data.Typeable ( Typeable )-import Data.Word ( Word8 )-import Prelude ( String, (.), fmap, (&&), (+), (<=), (>=), otherwise )-import Text.Read ( Read, readPrec )-import Text.Show ( Show, showsPrec )--import qualified Data.List as L ( map )--#if __GLASGOW_HASKELL__ < 700-import Control.Monad ( (>>) )-import Prelude ( fromInteger )-#endif---- from bytestring:-import qualified Data.ByteString as B ( ByteString, map )-import qualified Data.ByteString.Lazy as BL ( ByteString, map )---- from text:-import qualified Data.Text as T ( Text, toCaseFold )-import qualified Data.Text.Lazy as TL ( Text, toCaseFold, pack, unpack )---- from deepseq:-import Control.DeepSeq ( NFData, rnf, deepseq )---- from hashable:-import Data.Hashable ( Hashable, hashWithSalt )------------------------------------------------------------------------------------- Case Insensitive Strings-----------------------------------------------------------------------------------{-| A @CI s@ provides /C/ase /I/nsensitive comparison for the string-like type-@s@ (for example: 'String', 'T.Text', 'B.ByteString', etc.).--Note that @CI s@ has an instance for 'IsString' which together with the-@OverloadedStrings@ language extension allows you to write case insensitive-string literals as in:--@-\> (\"Content-Type\" :: 'CI' 'T.Text') == (\"CONTENT-TYPE\" :: 'CI' 'T.Text')-True-@---}-data CI s = CI { original :: !s -- ^ Retrieve the original string-like value.- , foldedCase :: !s -- ^ Retrieve the case folded string-like value.- -- (Also see 'foldCase').- }- deriving Typeable---- | Make the given string-like value case insensitive.-mk :: FoldCase s => s -> CI s-mk s = CI s (foldCase s)---- | Transform the original string-like value but keep it case insensitive.-map :: FoldCase s2 => (s1 -> s2) -> (CI s1 -> CI s2)-map f = mk . f . original--instance (IsString s, FoldCase s) => IsString (CI s) where- fromString = mk . fromString--instance Monoid s => Monoid (CI s) where- mempty = CI mempty mempty- CI o1 l1 `mappend` CI o2 l2 = CI (o1 `mappend` o2) (l1 `mappend` l2)--instance Eq s => Eq (CI s) where- (==) = (==) `on` foldedCase--instance Ord s => Ord (CI s) where- compare = compare `on` foldedCase--instance (Read s, FoldCase s) => Read (CI s) where- readPrec = fmap mk readPrec--instance Show s => Show (CI s) where- showsPrec prec = showsPrec prec . original--instance Hashable s => Hashable (CI s) where- hashWithSalt salt = hashWithSalt salt . foldedCase--instance NFData s => NFData (CI s) where- rnf (CI o f) = o `deepseq` f `deepseq` ()------------------------------------------------------------------------------------- Folding (lowering) cases------------------------------------------------------------------------------------- | Class of string-like types that support folding cases.------ /Note/: In some languages, case conversion is a locale- and context-dependent--- operation. The @foldCase@ method is /not/ intended to be locale sensitive.--- Programs that require locale sensitivity should use appropriate versions of--- the case mapping functions from the @text-icu@ package:--- <http://hackage.haskell.org/package/text-icu>-class FoldCase s where- foldCase :: s -> s-- foldCaseList :: [s] -> [s]- foldCaseList = L.map foldCase--instance FoldCase a => FoldCase [a] where- foldCase = foldCaseList---- | Note that @foldCase@ on @'B.ByteString's@ is only guaranteed to be correct for ISO-8859-1 encoded strings!-instance FoldCase B.ByteString where foldCase = B.map toLower8---- | Note that @foldCase@ on @'BL.ByteString's@ is only guaranteed to be correct for ISO-8859-1 encoded strings!-instance FoldCase BL.ByteString where foldCase = BL.map toLower8--instance FoldCase Char where- foldCase = toLower- foldCaseList = TL.unpack . TL.toCaseFold . TL.pack--instance FoldCase T.Text where foldCase = T.toCaseFold-instance FoldCase TL.Text where foldCase = TL.toCaseFold-instance FoldCase (CI s) where foldCase (CI _ l) = CI l l--toLower8 :: Word8 -> Word8-toLower8 w- | 65 <= w && w <= 90 ||- 192 <= w && w <= 214 ||- 216 <= w && w <= 222 = w + 32- | otherwise = w------------------------------------------------------------------------------------- Rewrite RULES-----------------------------------------------------------------------------------{-# RULES- "mk/ByteString" forall (bs :: B.ByteString). mk bs = CI bs (foldCaseBS bs)- #-}--foldCaseBS :: B.ByteString -> B.ByteString-foldCaseBS bs = B.map toLower8' bs- where- toLower8' :: Word8 -> Word8- toLower8' w- | 65 <= w && w <= 90 ||- 192 <= w && w <= 214 ||- 216 <= w && w <= 222 = w + 32- | otherwise = w+import Data.CaseInsensitive.Internal
+ Data/CaseInsensitive/Internal.hs view
@@ -0,0 +1,190 @@+{-# LANGUAGE CPP, NoImplicitPrelude, DeriveDataTypeable #-}++#if __GLASGOW_HASKELL__ >= 702+{-# LANGUAGE Unsafe #-}+#endif++-----------------------------------------------------------------------------+-- |+-- Module : Data.CaseInsensitive.Internal+-- Copyright : (c) 2011-2013 Bas van Dijk+-- License : BSD-style (see the file LICENSE)+-- Maintainer : Bas van Dijk <v.dijk.bas@gmail.com>+--+-- Internal module which exports the 'CI' type, constructor,+-- associated instances and the 'FoldCase' class and instances.+--+-----------------------------------------------------------------------------++module Data.CaseInsensitive.Internal ( CI+ , mk+ , unsafeMk+ , original+ , foldedCase+ , map+ , FoldCase(foldCase)+ ) where++--------------------------------------------------------------------------------+-- Imports+--------------------------------------------------------------------------------++-- from base:+import Data.Bool ( (||) )+import Data.Char ( Char, toLower )+import Data.Eq ( Eq, (==) )+import Data.Function ( on )+import Data.Monoid ( Monoid, mempty, mappend )+import Data.Ord ( Ord, compare )+import Data.String ( IsString, fromString )+import Data.Typeable ( Typeable )+import Data.Word ( Word8 )+import Prelude ( String, (.), fmap, (&&), (+), (<=), (>=), otherwise )+import Text.Read ( Read, readPrec )+import Text.Show ( Show, showsPrec )++import qualified Data.List as L ( map )++#if __GLASGOW_HASKELL__ < 700+import Control.Monad ( (>>) )+import Prelude ( fromInteger )+#endif++-- from bytestring:+import qualified Data.ByteString as B ( ByteString, map )+import qualified Data.ByteString.Lazy as BL ( ByteString, map )++-- from text:+import qualified Data.Text as T ( Text, toCaseFold )+import qualified Data.Text.Lazy as TL ( Text, toCaseFold, pack, unpack )++-- from deepseq:+import Control.DeepSeq ( NFData, rnf, deepseq )++-- from hashable:+import Data.Hashable ( Hashable, hashWithSalt )+++--------------------------------------------------------------------------------+-- Case Insensitive Strings+--------------------------------------------------------------------------------++{-| A @CI s@ provides /C/ase /I/nsensitive comparison for the string-like type+@s@ (for example: 'String', 'T.Text', 'B.ByteString', etc.).++Note that @CI s@ has an instance for 'IsString' which together with the+@OverloadedStrings@ language extension allows you to write case insensitive+string literals as in:++@+\> (\"Content-Type\" :: 'CI' 'T.Text') == (\"CONTENT-TYPE\" :: 'CI' 'T.Text')+True+@++-}+data CI s = CI { original :: !s -- ^ Retrieve the original string-like value.+ , foldedCase :: !s -- ^ Retrieve the case folded string-like value.+ -- (Also see 'foldCase').+ }+ deriving Typeable++-- | Make the given string-like value case insensitive.+mk :: FoldCase s => s -> CI s+mk s = CI s (foldCase s)++-- | Constructs a 'CI' from an already case folded string-like+-- value. The given string is used both as the 'original' as well as+-- the 'foldedCase'.+--+-- This function is unsafe since the compiler can't guarantee that the+-- provided string is case folded.+unsafeMk :: FoldCase s => s -> CI s+unsafeMk s = CI s s++-- | Transform the original string-like value but keep it case insensitive.+map :: FoldCase s2 => (s1 -> s2) -> (CI s1 -> CI s2)+map f = mk . f . original++instance (IsString s, FoldCase s) => IsString (CI s) where+ fromString = mk . fromString++instance Monoid s => Monoid (CI s) where+ mempty = CI mempty mempty+ CI o1 l1 `mappend` CI o2 l2 = CI (o1 `mappend` o2) (l1 `mappend` l2)++instance Eq s => Eq (CI s) where+ (==) = (==) `on` foldedCase++instance Ord s => Ord (CI s) where+ compare = compare `on` foldedCase++instance (Read s, FoldCase s) => Read (CI s) where+ readPrec = fmap mk readPrec++instance Show s => Show (CI s) where+ showsPrec prec = showsPrec prec . original++instance Hashable s => Hashable (CI s) where+ hashWithSalt salt = hashWithSalt salt . foldedCase++instance NFData s => NFData (CI s) where+ rnf (CI o f) = o `deepseq` f `deepseq` ()++--------------------------------------------------------------------------------+-- Folding (lowering) cases+--------------------------------------------------------------------------------++-- | Class of string-like types that support folding cases.+--+-- /Note/: In some languages, case conversion is a locale- and context-dependent+-- operation. The @foldCase@ method is /not/ intended to be locale sensitive.+-- Programs that require locale sensitivity should use appropriate versions of+-- the case mapping functions from the @text-icu@ package:+-- <http://hackage.haskell.org/package/text-icu>+class FoldCase s where+ foldCase :: s -> s++ foldCaseList :: [s] -> [s]+ foldCaseList = L.map foldCase++instance FoldCase a => FoldCase [a] where+ foldCase = foldCaseList++-- | Note that @foldCase@ on @'B.ByteString's@ is only guaranteed to be correct for ISO-8859-1 encoded strings!+instance FoldCase B.ByteString where foldCase = B.map toLower8++-- | Note that @foldCase@ on @'BL.ByteString's@ is only guaranteed to be correct for ISO-8859-1 encoded strings!+instance FoldCase BL.ByteString where foldCase = BL.map toLower8++instance FoldCase Char where+ foldCase = toLower+ foldCaseList = TL.unpack . TL.toCaseFold . TL.pack++instance FoldCase T.Text where foldCase = T.toCaseFold+instance FoldCase TL.Text where foldCase = TL.toCaseFold+instance FoldCase (CI s) where foldCase (CI _ l) = CI l l++toLower8 :: Word8 -> Word8+toLower8 w+ | 65 <= w && w <= 90 ||+ 192 <= w && w <= 214 ||+ 216 <= w && w <= 222 = w + 32+ | otherwise = w++--------------------------------------------------------------------------------+-- Rewrite RULES+--------------------------------------------------------------------------------++{-# RULES+ "mk/ByteString" forall (bs :: B.ByteString). mk bs = CI bs (foldCaseBS bs)+ #-}++foldCaseBS :: B.ByteString -> B.ByteString+foldCaseBS bs = B.map toLower8' bs+ where+ toLower8' :: Word8 -> Word8+ toLower8' w+ | 65 <= w && w <= 90 ||+ 192 <= w && w <= 214 ||+ 216 <= w && w <= 222 = w + 32+ | otherwise = w
+ Data/CaseInsensitive/Unsafe.hs view
@@ -0,0 +1,19 @@+{-# LANGUAGE CPP, NoImplicitPrelude #-}++#if __GLASGOW_HASKELL__ >= 702+{-# LANGUAGE Unsafe #-}+#endif++-----------------------------------------------------------------------------+-- |+-- Module : Data.CaseInsensitive.Unsafe+-- Copyright : (c) 2011-2013 Bas van Dijk+-- License : BSD-style (see the file LICENSE)+-- Maintainer : Bas van Dijk <v.dijk.bas@gmail.com>+--+-- Provides an unsafe way to create a case insensitive string-like value.+--+-----------------------------------------------------------------------------++module Data.CaseInsensitive.Unsafe ( unsafeMk ) where+import Data.CaseInsensitive.Internal ( unsafeMk )
case-insensitive.cabal view
@@ -1,5 +1,5 @@ name: case-insensitive-version: 1.0.0.2+version: 1.1 cabal-version: >=1.8 build-type: Simple license: BSD3@@ -30,7 +30,8 @@ , text >= 0.3 && < 0.12 , deepseq >= 1.1 && < 1.4 , hashable >= 1.0 && < 1.3- exposed-modules: Data.CaseInsensitive+ exposed-modules: Data.CaseInsensitive, Data.CaseInsensitive.Unsafe+ other-modules: Data.CaseInsensitive.Internal test-suite test-case-insensitive type: exitcode-stdio-1.0