{-# LANGUAGE BangPatterns #-} {-# LANGUAGE OverloadedStrings #-} -- | "Data.CIByteString" is a module containing 'CIByteString', a wrapper for -- 'ByteString' which provides case-insensitive (ASCII-wise) 'Ord' and 'Eq' -- instances. -- -- 'CIByteString' also has an 'IsString' instance, so if you use the -- \"OverloadedStrings\" LANGUAGE pragma you can write case-insensitive string -- literals, e.g.: -- -- @ -- \> let a = \"Foo\" in -- putStrLn $ (show $ unCI a) ++ \"==\\\"FoO\\\" is \" ++ show (a == \"FoO\") -- \"Foo\"==\"FoO\" is True -- @ module Data.CIByteString ( CIByteString , toCI , unCI , ciToLower ) where -- for IsString instance import Data.ByteString.Char8 () import Data.ByteString (ByteString) import Data.ByteString.Internal (c2w, w2c) import qualified Data.ByteString as S import Data.Char import Data.String -- | A case-insensitive newtype wrapper for 'ByteString' data CIByteString = CIByteString { unCI :: !ByteString , _lowercased :: !ByteString } toCI :: ByteString -> CIByteString toCI s = CIByteString s t where t = lowercase s ciToLower :: CIByteString -> ByteString ciToLower = _lowercased instance Show CIByteString where show (CIByteString s _) = show s lowercase :: ByteString -> ByteString lowercase = S.map (c2w . toLower . w2c) instance Eq CIByteString where (CIByteString _ a) == (CIByteString _ b) = a == b (CIByteString _ a) /= (CIByteString _ b) = a /= b instance Ord CIByteString where (CIByteString _ a) <= (CIByteString _ b) = a <= b instance IsString CIByteString where fromString = toCI . fromString