module Data.CaseInsensitive.Ord
( CaseInsensitiveOrd(..)
, (^>)
, (^<)
, (^>=)
, (^<=)
, caseInsensitiveComparing
)
where
import Data.Ord
import Data.Char
import Data.Word
import Data.CaseInsensitive.Eq
import qualified Data.ByteString as BS
import qualified Data.ByteString.Lazy as BSL
import qualified Data.Text as T
import qualified Data.Text.Lazy as TL
class CaseInsensitiveOrd a where
caseInsensitiveCompare :: a -> a -> Ordering
(^>) :: (CaseInsensitiveOrd a) => a -> a -> Bool
a ^> b = caseInsensitiveCompare a b == GT
(^<) :: (CaseInsensitiveOrd a) => a -> a -> Bool
a ^< b = caseInsensitiveCompare a b == LT
(^>=) :: (CaseInsensitiveOrd a) => a -> a -> Bool
a ^>= b = caseInsensitiveCompare a b /= LT
(^<=) :: (CaseInsensitiveOrd a) => a -> a -> Bool
a ^<= b = caseInsensitiveCompare a b /= GT
caseInsensitiveComparing :: (CaseInsensitiveOrd a) => (b -> a) -> b -> b -> Ordering
caseInsensitiveComparing f a b = caseInsensitiveCompare (f a) (f b)
instance CaseInsensitiveOrd Char where
caseInsensitiveCompare = compare_char
instance CaseInsensitiveOrd Word8 where
caseInsensitiveCompare = compare_char8
instance (CaseInsensitiveOrd a) => CaseInsensitiveOrd [a] where
caseInsensitiveCompare = compare_list
instance CaseInsensitiveOrd BS.ByteString where
caseInsensitiveCompare = compare_bs
instance CaseInsensitiveOrd BSL.ByteString where
caseInsensitiveCompare = compare_bsl
instance CaseInsensitiveOrd T.Text where
caseInsensitiveCompare = compare_t
instance CaseInsensitiveOrd TL.Text where
caseInsensitiveCompare = compare_tl
instance (CaseInsensitiveOrd a,CaseInsensitiveOrd b) => CaseInsensitiveOrd (a,b) where
caseInsensitiveCompare (a,b) (a',b') =
case caseInsensitiveCompare a a' of
EQ -> caseInsensitiveCompare b b'
ord -> ord
instance (CaseInsensitiveOrd a,CaseInsensitiveOrd b,CaseInsensitiveOrd c) => CaseInsensitiveOrd (a,b,c) where
caseInsensitiveCompare (a,b,c) (a',b',c') =
case caseInsensitiveCompare a a' of
EQ -> caseInsensitiveCompare (b,c) (b',c')
ord -> ord
instance (CaseInsensitiveOrd a,CaseInsensitiveOrd b,CaseInsensitiveOrd c,CaseInsensitiveOrd d) => CaseInsensitiveOrd (a,b,c,d) where
caseInsensitiveCompare (a,b,c,d) (a',b',c',d') =
case caseInsensitiveCompare a a' of
EQ -> caseInsensitiveCompare (b,c,d) (b',c',d')
ord -> ord
compare_char :: Char -> Char -> Ordering
compare_char a b
| caseInsensitiveEq a b = EQ
| otherwise = compare (toUpper a) (toUpper b)
compare_char8 :: Word8 -> Word8 -> Ordering
compare_char8 a b
| a == b = EQ
| a < 65 || b < 65 = compare a b
| a < 97 && b < 97 = compare a b
| a < 91 && b < 123 = compare a (b 32)
| b < 91 && a < 123 = compare (a 32) b
| a < 216 && b < 216 = compare a b
| a == 247 = GT
| b == 247 = LT
| a == 215 = compare a (b 32)
| b == 215 = compare (a 32) b
| a < 224 = compare a (b 32)
| b < 224 = compare (a 32) b
| otherwise = compare a b
compare_list :: (CaseInsensitiveOrd a) => [a] -> [a] -> Ordering
compare_list a b
| null a && null b = EQ
| null a = LT
| null b = GT
| otherwise =
case caseInsensitiveCompare (head a) (head b) of
EQ -> compare_list (tail a) (tail b)
ord -> ord
compare_bs :: BS.ByteString -> BS.ByteString -> Ordering
compare_bs a b
| BS.null a && BS.null b = EQ
| BS.null a = LT
| BS.null b = GT
| otherwise =
case caseInsensitiveCompare (BS.head a) (BS.head b) of
EQ -> compare_bs (BS.tail a) (BS.tail b)
ord -> ord
compare_bsl :: BSL.ByteString -> BSL.ByteString -> Ordering
compare_bsl a b
| BSL.null a && BSL.null b = EQ
| BSL.null a = LT
| BSL.null b = GT
| otherwise =
case caseInsensitiveCompare (BSL.head a) (BSL.head b) of
EQ -> compare_bsl (BSL.tail a) (BSL.tail b)
ord -> ord
compare_t :: T.Text -> T.Text -> Ordering
compare_t a b
| T.null a && T.null b = EQ
| T.null a = LT
| T.null b = GT
| otherwise =
case caseInsensitiveCompare (T.head a) (T.head b) of
EQ -> compare_t (T.tail a) (T.tail b)
ord -> ord
compare_tl :: TL.Text -> TL.Text -> Ordering
compare_tl a b
| TL.null a && TL.null b = EQ
| TL.null a = LT
| TL.null b = GT
| otherwise =
case caseInsensitiveCompare (TL.head a) (TL.head b) of
EQ -> compare_tl (TL.tail a) (TL.tail b)
ord -> ord