packages feed

case-insensitive 0.4.0.4 → 1.0

raw patch · 7 files changed

+208/−40 lines, 7 filesdep +HUnitdep +case-insensitivedep +criterionsetup-changedPVP ok

version bump matches the API change (PVP)

Dependencies added: HUnit, case-insensitive, criterion, deepseq, test-framework, test-framework-hunit

API changes (from Hackage documentation)

- Data.CaseInsensitive: instance FoldCase ShowS
- Data.CaseInsensitive: instance FoldCase String
+ Data.CaseInsensitive: instance FoldCase Char
+ Data.CaseInsensitive: instance FoldCase a => FoldCase [a]
+ Data.CaseInsensitive: instance NFData s => NFData (CI s)
- Data.CaseInsensitive: class FoldCase s
+ Data.CaseInsensitive: class FoldCase s where foldCaseList = map foldCase

Files

Data/CaseInsensitive.hs view
@@ -1,10 +1,4 @@-{-# LANGUAGE CPP-           , NoImplicitPrelude-           , UnicodeSyntax-           , TypeSynonymInstances-           , DeriveDataTypeable-           , FlexibleInstances-  #-}+{-# LANGUAGE CPP, NoImplicitPrelude, DeriveDataTypeable #-}  #if __GLASGOW_HASKELL__ >= 702 {-# LANGUAGE Trustworthy #-}@@ -13,7 +7,7 @@ ----------------------------------------------------------------------------- -- | -- Module      :  Data.CaseInsensitive--- Copyright   :  (c) 2011-2012 Bas van Dijk+-- Copyright   :  (c) 2011-2013 Bas van Dijk -- License     :  BSD-style (see the file LICENSE) -- Maintainer  :  Bas van Dijk <v.dijk.bas@gmail.com> --@@ -24,6 +18,9 @@ -- import qualified Data.CaseInsensitive as CI -- @ --+-- /Note that the FoldCase instance for ByteStrings is only/+-- /guaranteed to be correct for ISO-8859-1 encoded strings!/+-- -----------------------------------------------------------------------------  module Data.CaseInsensitive ( CI@@ -40,25 +37,31 @@  -- from base: import Data.Bool     ( (||) )+import Data.Char     ( Char, toLower ) import Data.Eq       ( Eq, (==) )-import Data.Ord      ( Ord, compare ) 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, ShowS )+import Text.Show     ( Show, showsPrec ) +import qualified Data.List as L ( map )+ -- from bytestring:-import qualified Data.ByteString             as B    ( ByteString, map )-import qualified Data.ByteString.Lazy        as BL   ( ByteString, map )+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 ) @@ -67,7 +70,7 @@ --------------------------------------------------------------------------------  {-| A @CI s@ provides /C/ase /I/nsensitive comparison for the string-like type-@s@ (for example: 'String', 'T.Text', 'B.ByteString', 'ShowS', etc.).+@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@@ -79,42 +82,44 @@ @  -}-data CI s = CI { original   ∷ !s -- ^ Retrieve the original string-like value.-               , foldedCase ∷ !s -- ^ Retrieve the case folded string-like value.-                                 --   (Also see 'foldCase').+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 :: 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 :: FoldCase s2 => (s1 -> s2) -> (CI s1 -> CI s2) map f = mk . f . original -instance (IsString s, FoldCase s) ⇒ IsString (CI s) where+instance (IsString s, FoldCase s) => IsString (CI s) where     fromString = mk . fromString -instance Monoid s ⇒ Monoid (CI s) where+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+instance Eq s => Eq (CI s) where     (==) = (==) `on` foldedCase -instance Ord s ⇒ Ord (CI s) where+instance Ord s => Ord (CI s) where     compare = compare `on` foldedCase -instance (Read s, FoldCase s) ⇒ Read (CI s) where+instance (Read s, FoldCase s) => Read (CI s) where     readPrec = fmap mk readPrec -instance Show s ⇒ Show (CI s) where+instance Show s => Show (CI s) where     showsPrec prec = showsPrec prec . original  instance Hashable s => Hashable (CI s) where-  hashWithSalt salt = hashWithSalt salt . foldedCase+    hashWithSalt salt = hashWithSalt salt . foldedCase +instance NFData s => NFData (CI s) where+    rnf (CI o f) = o `deepseq` f `deepseq` ()  -------------------------------------------------------------------------------- -- Folding (lowering) cases@@ -127,23 +132,50 @@ -- 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+class FoldCase s where+    foldCase :: s -> s --- | Note that @foldCase = 'B.map' toLower@ which is only guaranteed to be correct for ASCII encoded strings!-instance FoldCase B.ByteString where foldCase = B.map toLower+    foldCaseList :: [s] -> [s]+    foldCaseList = L.map foldCase --- | Note that @foldCase = 'BL.map' toLower@ which is only guaranteed to be correct for ASCII encoded strings!-instance FoldCase BL.ByteString where foldCase = BL.map toLower+instance FoldCase a => FoldCase [a] where+    foldCase = foldCaseList -instance FoldCase String  where foldCase = TL.unpack . TL.toCaseFold . TL.pack+-- | 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 ShowS   where foldCase = (foldCase .) instance FoldCase (CI s)  where foldCase (CI _ l) = CI l l -toLower :: Word8 -> Word8-toLower w+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
LICENSE view
@@ -1,4 +1,4 @@-Copyright (c) 2011-2012 Bas van Dijk+Copyright (c) 2011-2013 Bas van Dijk  All rights reserved. 
− Setup.hs
@@ -1,2 +0,0 @@-import Distribution.Simple-main = defaultMain
+ Setup.lhs view
@@ -0,0 +1,3 @@+#!/usr/bin/env runhaskell+> import Distribution.Simple+> main = defaultMain
+ bench/bench.hs view
@@ -0,0 +1,24 @@+{-# LANGUAGE CPP #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}++module Main ( main) where++import           Criterion.Main             ( defaultMain, bcompare, bench, nf )+import qualified Data.ByteString      as B  ( readFile )+import qualified Data.CaseInsensitive as CI ( mk )+import qualified NoClass              as NC ( mk )++#if !MIN_VERSION_bytestring(0,10,0)+import Control.DeepSeq ( NFData )+instance NFData ByteString+#endif++main :: IO ()+main = do+  bs <- B.readFile "data/pg2189.txt"+  defaultMain+    [ bcompare+      [ bench "no-class"         $ nf (\s -> NC.mk s) bs+      , bench "case-insensitive" $ nf (\s -> CI.mk s) bs+      ]+    ]
case-insensitive.cabal view
@@ -1,6 +1,6 @@ name:          case-insensitive-version:       0.4.0.4-cabal-version: >=1.6+version:       1.0+cabal-version: >=1.8 build-type:    Simple license:       BSD3 license-file:  LICENSE@@ -24,9 +24,38 @@   Location: git://github.com/basvandijk/case-insensitive.git  Library-  GHC-Options: -Wall+  ghc-options: -Wall   build-depends: base       >= 3   && < 4.7                , bytestring >= 0.9 && < 0.11                , text       >= 0.3 && < 0.12+               , deepseq    >= 1.1 && < 1.4                , hashable   >= 1.0 && < 1.3   exposed-modules: Data.CaseInsensitive++test-suite test-case-insensitive+  type:           exitcode-stdio-1.0+  main-is:        test.hs+  hs-source-dirs: test++  build-depends: case-insensitive+               , base                 >= 3     && < 4.7+               , bytestring           >= 0.9   && < 0.11+               , text                 >= 0.3   && < 0.12+               , HUnit                >= 1.2.2 && < 1.3+               , test-framework       >= 0.2.4 && < 0.9+               , test-framework-hunit >= 0.2.4 && < 0.4++  ghc-options: -Wall++benchmark bench-case-insensitive+  type:           exitcode-stdio-1.0+  main-is:        bench.hs+  hs-source-dirs: bench++  ghc-options:    -Wall -O2++  build-depends: case-insensitive+               , base                 >= 3     && < 4.7+               , bytestring           >= 0.9   && < 0.11+               , criterion            >= 0.6.1 && < 0.7+               , deepseq              >= 1.1   && < 1.4
+ test/test.hs view
@@ -0,0 +1,82 @@+module Main ( main ) where++import           Data.ByteString                    ( ByteString )+import qualified Data.ByteString.Char8      as BC8  ( pack, map )+import qualified Data.ByteString.Lazy       as Lazy ( ByteString )+import qualified Data.ByteString.Lazy.Char8 as BLC8 ( pack, map )+import qualified Data.CaseInsensitive       as CI   ( mk )+import           Data.Char                          ( toUpper, chr )+import           Data.Text                          ( Text )+import qualified Data.Text                  as T    ( pack, toUpper )+import qualified Data.Text.Lazy             as Lazy ( Text )+import qualified Data.Text.Lazy             as TL   ( pack, toUpper )+import           Test.Framework                     ( defaultMain, testGroup )+import           Test.Framework.Providers.HUnit     ( testCase )+import           Test.HUnit                         ( assertEqual )++main :: IO ()+main = defaultMain+  [ testGroup "ASCII"+    [ testCase "String"          $ assertEqual "" (CI.mk                    asciiStr)+                                                  (CI.mk (     map toUpper  asciiStr))+    , testCase "ByteString"      $ assertEqual "" (CI.mk                    asciiBs)+                                                  (CI.mk ( BC8.map toUpper  asciiBs))+    , testCase "Lazy.ByteString" $ assertEqual "" (CI.mk                    asciiLBs)+                                                  (CI.mk (BLC8.map toUpper  asciiLBs))+    , testCase "Text"            $ assertEqual "" (CI.mk                    asciiTxt)+                                                  (CI.mk (       T.toUpper  asciiTxt))+    , testCase "Lazy.Text"       $ assertEqual "" (CI.mk                    asciiLTxt)+                                                  (CI.mk (      TL.toUpper  asciiLTxt))+    ]+  , testGroup "ISO-8859-1"+    [ testCase "String"          $ assertEqual "" (CI.mk                    iso_8859_1Str)+                                                  (CI.mk (     map toUpper  iso_8859_1Str))+    , testCase "ByteString"      $ assertEqual "" (CI.mk                    iso_8859_1Bs)+                                                  (CI.mk ( BC8.map toUpper' iso_8859_1Bs))+    , testCase "Lazy.ByteString" $ assertEqual "" (CI.mk                    iso_8859_1LBs)+                                                  (CI.mk (BLC8.map toUpper' iso_8859_1LBs))+    , testCase "Text"            $ assertEqual "" (CI.mk                    iso_8859_1Txt)+                                                  (CI.mk (       T.toUpper  iso_8859_1Txt))+    , testCase "Lazy.Text"       $ assertEqual "" (CI.mk                    iso_8859_1LTxt)+                                                  (CI.mk (      TL.toUpper  iso_8859_1LTxt))+    ]+  ]+++asciiLTxt :: Lazy.Text+asciiLTxt = TL.pack asciiStr++asciiTxt :: Text+asciiTxt = T.pack asciiStr++asciiLBs :: Lazy.ByteString+asciiLBs = BLC8.pack asciiStr++asciiBs :: ByteString+asciiBs = BC8.pack asciiStr++asciiStr :: String+asciiStr = map chr [0..127]+++iso_8859_1LTxt :: Lazy.Text+iso_8859_1LTxt = TL.pack iso_8859_1Str++iso_8859_1Txt :: Text+iso_8859_1Txt = T.pack iso_8859_1Str++iso_8859_1LBs :: Lazy.ByteString+iso_8859_1LBs = BLC8.pack iso_8859_1Str++iso_8859_1Bs :: ByteString+iso_8859_1Bs = BC8.pack iso_8859_1Str++iso_8859_1Str :: String+iso_8859_1Str = asciiStr ++ map chr [128..255]+++-- | Upper-casing some characters in ISO 8859-1 move them outside the 0-255 range.+toUpper' :: Char -> Char+toUpper' 'µ' = 'µ'       -- toUpper 'µ' (code point: 181) == 'Μ' (code point: 924)+toUpper' 'ÿ' = 'ÿ'       -- toUpper 'ÿ' (code point: 255) == 'Ÿ' (code point: 376)+toUpper' c   = toUpper c