text-latin1 0.1 → 0.2
raw patch · 3 files changed
+319/−131 lines, 3 filesdep +case-insensitivedep +hashabledep ~basedep ~data-checked
Dependencies added: case-insensitive, hashable
Dependency ranges changed: base, data-checked
Files
- src/Text/Ascii.hs +257/−126
- src/Text/Latin1.hs +58/−3
- text-latin1.cabal +4/−2
src/Text/Ascii.hs view
@@ -1,5 +1,8 @@ {-# LANGUAGE UnicodeSyntax #-}+{-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE TypeSynonymInstances #-} {-# LANGUAGE MultiParamTypeClasses #-} -- | ASCII utility functions.@@ -21,12 +24,17 @@ , toLower , toUpper , isAlpha- , isDigit- , isNzDigit , isAlphaNum- , fromDigit- , fromNzDigit- , unsafeFromDigit+ , isDecDigit+ , isNzDecDigit+ , fromDecDigit+ , fromNzDecDigit+ , unsafeFromDecDigit+ , isBinDigit+ , isNzBinDigit+ , fromBinDigit+ , fromNzBinDigit+ , unsafeFromBinDigit , isOctDigit , isNzOctDigit , fromOctDigit@@ -57,12 +65,17 @@ , toLower8 , toUpper8 , isAlpha8- , isDigit8- , isNzDigit8 , isAlphaNum8- , fromDigit8- , fromNzDigit8- , unsafeFromDigit8+ , isDecDigit8+ , isNzDecDigit8+ , fromDecDigit8+ , fromNzDecDigit8+ , unsafeFromDecDigit8+ , isBinDigit8+ , isNzBinDigit8+ , fromBinDigit8+ , fromNzBinDigit8+ , unsafeFromBinDigit8 , isOctDigit8 , isNzOctDigit8 , fromOctDigit8@@ -86,12 +99,17 @@ ) where import Data.Checked+import Data.Function (on) import Data.Char (ord, chr)+import Data.String (IsString(..)) import Data.Word (Word8) import qualified Data.ByteString as BS import qualified Data.ByteString.Lazy as BL import qualified Data.Text as TS import qualified Data.Text.Lazy as TL+import Data.Monoid (Monoid(..))+import Data.CaseInsensitive (FoldCase(..))+import Data.Hashable (Hashable(..)) data IsAscii = IsAscii @@ -129,6 +147,61 @@ type Ascii α = Checked IsAscii α +instance Eq α ⇒ Eq (Ascii α) where+ (==) = (==) `on` checked+ {-# INLINE (==) #-}++instance Ord α ⇒ Ord (Ascii α) where+ compare = compare `on` checked+ {-# INLINE compare #-}++instance Show α ⇒ Show (Ascii α) where+ showsPrec p = showsPrec p . checked++instance Monoid α ⇒ Monoid (Ascii α) where+ mempty = trustMe mempty+ {-# INLINE mempty #-}+ mappend x y = trustMe $ mappend (checked x) (checked y)+ {-# INLINE mappend #-}++instance IsString α ⇒ IsString (Ascii α) where+ fromString s | isAscii s = trustMe $ fromString s+ | otherwise = error $ "Not an ASCII string: " ++ show s+ {-# INLINE fromString #-}++instance Hashable α ⇒ Hashable (Ascii α) where+#if MIN_VERSION_hashable(1,2,0)+ hashWithSalt s = hashWithSalt s . checked+ {-# INLINE hashWithSalt #-}+#else+ hash = hash . checked+ {-# INLINE hash #-}+#endif++instance FoldCase (Ascii Char) where+ foldCase = trustMap toLower+ {-# INLINE foldCase #-}++instance FoldCase (Ascii α) ⇒ FoldCase (Ascii [α]) where+ foldCase = trustMap $ map $ checked . foldCase . trustThat IsAscii+ {-# INLINE foldCase #-}++instance FoldCase (Ascii BS.ByteString) where+ foldCase = trustMap $ BS.map toLower8+ {-# INLINE foldCase #-}++instance FoldCase (Ascii BL.ByteString) where+ foldCase = trustMap $ BL.map toLower8+ {-# INLINE foldCase #-}++instance FoldCase (Ascii TS.Text) where+ foldCase = trustMap $ TS.map toLower+ {-# INLINE foldCase #-}++instance FoldCase (Ascii TL.Text) where+ foldCase = trustMap $ TL.map toLower+ {-# INLINE foldCase #-}+ -- | Map a character to its ASCII encoding if possible, otherwise -- return 'Nothing'. maybeAscii ∷ Char → Maybe Word8@@ -136,7 +209,7 @@ | otherwise = Nothing {-# INLINABLE maybeAscii #-} --- | Encode an ASCII character. No checks is performed.+-- | Encode an ASCII character. No checks are performed. ascii ∷ Char → Word8 ascii = fromIntegral . ord {-# INLINE ascii #-}@@ -193,40 +266,68 @@ isAlpha c = isUpper c || isLower c {-# INLINABLE isAlpha #-} --- | Test if a character is a decimal digit (/'0' ... '9'/).-isDigit ∷ Char → Bool-isDigit c = c >= '0' && c <= '9'-{-# INLINE isDigit #-}---- | Test if a character is a non-zero decimal digit (/'1' ... '9'/).-isNzDigit ∷ Char → Bool-isNzDigit c = c >= '1' && c <= '9'-{-# INLINE isNzDigit #-}- -- | Test if a character is either an ASCII letter or a decimal digit. isAlphaNum ∷ Char → Bool-isAlphaNum c = isDigit c || isAlpha c+isAlphaNum c = isDecDigit c || isAlpha c {-# INLINABLE isAlphaNum #-} +-- | Test if a character is a decimal digit (/'0' ... '9'/).+isDecDigit ∷ Char → Bool+isDecDigit c = c >= '0' && c <= '9'+{-# INLINE isDecDigit #-}++-- | Test if a character is a non-zero decimal digit (/'1' ... '9'/).+isNzDecDigit ∷ Char → Bool+isNzDecDigit c = c >= '1' && c <= '9'+{-# INLINE isNzDecDigit #-}+ -- | Map a decimal digit to the corresponding number. Return 'Nothing' on -- other inputs.-fromDigit ∷ Num a ⇒ Char → Maybe a-fromDigit c | isDigit c = Just $ unsafeFromDigit c- | otherwise = Nothing-{-# INLINABLE fromDigit #-}+fromDecDigit ∷ Num a ⇒ Char → Maybe a+fromDecDigit c | isDecDigit c = Just $ unsafeFromDecDigit c+ | otherwise = Nothing+{-# INLINABLE fromDecDigit #-} -- | Map non-zero decimal digits to the corresponding numbers. Return -- 'Nothing' on other inputs.-fromNzDigit ∷ Num a ⇒ Char → Maybe a-fromNzDigit c | isNzDigit c = Just $ unsafeFromDigit c- | otherwise = Nothing-{-# INLINABLE fromNzDigit #-}+fromNzDecDigit ∷ Num a ⇒ Char → Maybe a+fromNzDecDigit c | isNzDecDigit c = Just $ unsafeFromDecDigit c+ | otherwise = Nothing+{-# INLINABLE fromNzDecDigit #-} --- | Map decimal digits to the corresponding numbers. No checks is performed.-unsafeFromDigit ∷ Num a ⇒ Char → a-unsafeFromDigit c = fromIntegral (ord c - ord '0')-{-# INLINE unsafeFromDigit #-}+-- | Map decimal digits to the corresponding numbers. No checks are performed.+unsafeFromDecDigit ∷ Num a ⇒ Char → a+unsafeFromDecDigit c = fromIntegral (ord c - ord '0')+{-# INLINE unsafeFromDecDigit #-} +-- | Test if a character is a binary digit (/'0'/ or /'1'/).+isBinDigit ∷ Char → Bool+isBinDigit c = c == '0' || c == '1'+{-# INLINE isBinDigit #-}++-- | Test if a character is the non-zero binary digit (/'1'/).+isNzBinDigit ∷ Char → Bool+isNzBinDigit c = c == '1'+{-# INLINE isNzBinDigit #-}++-- | Map binary digits to the corresponding numbers. Return 'Nothing' on+-- other inputs.+fromBinDigit ∷ Num a ⇒ Char → Maybe a+fromBinDigit c | isBinDigit c = Just $ unsafeFromBinDigit c+ | otherwise = Nothing+{-# INLINABLE fromBinDigit #-}++-- | Map the digit /'1'/ to the number /1/. Return 'Nothing' on other inputs.+fromNzBinDigit ∷ Num a ⇒ Char → Maybe a+fromNzBinDigit c | isNzBinDigit c = Just 1+ | otherwise = Nothing+{-# INLINABLE fromNzBinDigit #-}++-- | Map binary digits to the corresponding numbers. No checks are performed.+unsafeFromBinDigit ∷ Num a ⇒ Char → a+unsafeFromBinDigit = unsafeFromDecDigit+{-# INLINE unsafeFromBinDigit #-}+ -- | Test if a character is an octal digit (/'0' ... '7'/). isOctDigit ∷ Char → Bool isOctDigit c = c >= '0' && c <= '7'@@ -251,9 +352,9 @@ | otherwise = Nothing {-# INLINABLE fromNzOctDigit #-} --- | Map octal digits to the corresponding numbers. No checks is performed.+-- | Map octal digits to the corresponding numbers. No checks are performed. unsafeFromOctDigit ∷ Num a ⇒ Char → a-unsafeFromOctDigit = unsafeFromDigit+unsafeFromOctDigit = unsafeFromDecDigit {-# INLINE unsafeFromOctDigit #-} isLowAF ∷ Char → Bool@@ -267,35 +368,35 @@ -- | Test if a character is a lower-case hexadecimal digit -- (/'0' ... '9'/ or /'a' ... 'f'/). isLowHexDigit ∷ Char → Bool-isLowHexDigit c = isDigit c || isLowAF c+isLowHexDigit c = isDecDigit c || isLowAF c {-# INLINABLE isLowHexDigit #-} -- | Test if a character is a non-zero lower-case hexadecimal digit -- (/'1' ... '9'/ or /'a' ... 'f'/). isNzLowHexDigit ∷ Char → Bool-isNzLowHexDigit c = isNzDigit c || isLowAF c+isNzLowHexDigit c = isNzDecDigit c || isLowAF c {-# INLINABLE isNzLowHexDigit #-} -- | Map lower-case hexadecimal digits to the corresponding numbers. -- Return 'Nothing' on other inputs. fromLowHexDigit ∷ Num a ⇒ Char → Maybe a-fromLowHexDigit c | isDigit c = Just $ unsafeFromDigit c- | isLowAF c = Just $ fromLowAF c- | otherwise = Nothing+fromLowHexDigit c | isDecDigit c = Just $ unsafeFromDecDigit c+ | isLowAF c = Just $ fromLowAF c+ | otherwise = Nothing {-# INLINABLE fromLowHexDigit #-} -- | Map non-zero lower-case hexadecimal digits to the corresponding numbers. -- Return 'Nothing' on other inputs. fromNzLowHexDigit ∷ Num a ⇒ Char → Maybe a-fromNzLowHexDigit c | isNzDigit c = Just $ unsafeFromDigit c- | isLowAF c = Just $ fromLowAF c- | otherwise = Nothing+fromNzLowHexDigit c | isNzDecDigit c = Just $ unsafeFromDecDigit c+ | isLowAF c = Just $ fromLowAF c+ | otherwise = Nothing {-# INLINABLE fromNzLowHexDigit #-} -- | Map lower-case hexadecimal digits to the corresponding numbers.--- No checks is performed.+-- No checks are performed. unsafeFromLowHexDigit ∷ Num a ⇒ Char → a-unsafeFromLowHexDigit c | c < 'a' = unsafeFromDigit c+unsafeFromLowHexDigit c | c < 'a' = unsafeFromDecDigit c | otherwise = fromLowAF c {-# INLINE unsafeFromLowHexDigit #-} @@ -310,72 +411,72 @@ -- | Test if a character is an upper-case hexadecimal digit -- (/'0' ... '9'/ or /'A' ... 'F'/). isUpHexDigit ∷ Char → Bool-isUpHexDigit c = isDigit c || isUpAF c+isUpHexDigit c = isDecDigit c || isUpAF c {-# INLINABLE isUpHexDigit #-} -- | Test if a character is a non-zero upper-case hexadecimal digit -- (/'1' ... '9'/ or /'A' ... 'F'/). isNzUpHexDigit ∷ Char → Bool-isNzUpHexDigit c = isNzDigit c || isUpAF c+isNzUpHexDigit c = isNzDecDigit c || isUpAF c {-# INLINABLE isNzUpHexDigit #-} -- | Map upper-case hexadecimal digits to the corresponding numbers. -- Return 'Nothing' on other inputs. fromUpHexDigit ∷ Num a ⇒ Char → Maybe a-fromUpHexDigit c | isDigit c = Just $ unsafeFromDigit c- | isUpAF c = Just $ fromUpAF c- | otherwise = Nothing+fromUpHexDigit c | isDecDigit c = Just $ unsafeFromDecDigit c+ | isUpAF c = Just $ fromUpAF c+ | otherwise = Nothing {-# INLINABLE fromUpHexDigit #-} -- | Map non-zero upper-case hexadecimal digits to the corresponding numbers. -- Return 'Nothing' on other inputs. fromNzUpHexDigit ∷ Num a ⇒ Char → Maybe a-fromNzUpHexDigit c | isNzDigit c = Just $ unsafeFromDigit c- | isUpAF c = Just $ fromUpAF c- | otherwise = Nothing+fromNzUpHexDigit c | isNzDecDigit c = Just $ unsafeFromDecDigit c+ | isUpAF c = Just $ fromUpAF c+ | otherwise = Nothing {-# INLINABLE fromNzUpHexDigit #-} -- | Map upper-case hexadecimal digits to the corresponding numbers.--- No checks is performed.+-- No checks are performed. unsafeFromUpHexDigit ∷ Num a ⇒ Char → a-unsafeFromUpHexDigit c | c < 'A' = unsafeFromDigit c+unsafeFromUpHexDigit c | c < 'A' = unsafeFromDecDigit c | otherwise = fromUpAF c {-# INLINE unsafeFromUpHexDigit #-} -- | Test if a character is a hexadecimal digit -- (/'0' ... '9'/ or /'a' ... 'f'/ or /'A' ... 'F'/). isHexDigit ∷ Char → Bool-isHexDigit c = isDigit c || isUpAF c || isLowAF c+isHexDigit c = isDecDigit c || isUpAF c || isLowAF c {-# INLINABLE isHexDigit #-} -- | Test if a character is a non-zero hexadecimal digit -- (/'1' ... '9'/ or /'a' ... 'f'/ or /'A' ... 'F'/). isNzHexDigit ∷ Char → Bool-isNzHexDigit c = isNzDigit c || isUpAF c || isLowAF c+isNzHexDigit c = isNzDecDigit c || isUpAF c || isLowAF c {-# INLINABLE isNzHexDigit #-} -- | Map hexadecimal digits to the corresponding numbers. -- Return 'Nothing' on other inputs. fromHexDigit ∷ Num a ⇒ Char → Maybe a-fromHexDigit c | isDigit c = Just $ unsafeFromDigit c- | isUpAF c = Just $ fromUpAF c- | isLowAF c = Just $ fromLowAF c- | otherwise = Nothing+fromHexDigit c | isDecDigit c = Just $ unsafeFromDecDigit c+ | isUpAF c = Just $ fromUpAF c+ | isLowAF c = Just $ fromLowAF c+ | otherwise = Nothing {-# INLINABLE fromHexDigit #-} -- | Map non-zero hexadecimal digits to the corresponding numbers. -- Return 'Nothing' on other inputs. fromNzHexDigit ∷ Num a ⇒ Char → Maybe a-fromNzHexDigit c | isNzDigit c = Just $ unsafeFromDigit c- | isUpAF c = Just $ fromUpAF c- | isLowAF c = Just $ fromLowAF c- | otherwise = Nothing+fromNzHexDigit c | isNzDecDigit c = Just $ unsafeFromDecDigit c+ | isUpAF c = Just $ fromUpAF c+ | isLowAF c = Just $ fromLowAF c+ | otherwise = Nothing {-# INLINABLE fromNzHexDigit #-} --- | Map hexadecimal digits to the corresponding numbers. No checks is+-- | Map hexadecimal digits to the corresponding numbers. No checks are -- performed. unsafeFromHexDigit ∷ Num a ⇒ Char → a-unsafeFromHexDigit c | c < 'A' = unsafeFromDigit c+unsafeFromHexDigit c | c < 'A' = unsafeFromDecDigit c | c < 'a' = fromUpAF c | otherwise = fromLowAF c {-# INLINE unsafeFromHexDigit #-}@@ -429,43 +530,73 @@ isAlpha8 w = isUpper8 w || isLower8 w {-# INLINABLE isAlpha8 #-} --- | Test if a byte is the encoding of a decimal digit (/'0' ... '9'/).-isDigit8 ∷ Word8 → Bool-isDigit8 w = w >= ascii '0' && w <= ascii '9'-{-# INLINE isDigit8 #-}---- | Test if a byte is the encoding of a non-zero decimal digit--- (/'1' ... '9'/).-isNzDigit8 ∷ Word8 → Bool-isNzDigit8 w = w >= ascii '1' && w <= ascii '9'-{-# INLINE isNzDigit8 #-}- -- | Test if a byte is the encoding of either an ASCII letter -- or a decimal digit. isAlphaNum8 ∷ Word8 → Bool-isAlphaNum8 w = isDigit8 w || isAlpha8 w+isAlphaNum8 w = isDecDigit8 w || isAlpha8 w {-# INLINABLE isAlphaNum8 #-} +-- | Test if a byte is the encoding of a decimal digit (/'0' ... '9'/).+isDecDigit8 ∷ Word8 → Bool+isDecDigit8 w = w >= ascii '0' && w <= ascii '9'+{-# INLINE isDecDigit8 #-}++-- | Test if a byte is the encoding of a non-zero decimal digit+-- (/'1' ... '9'/).+isNzDecDigit8 ∷ Word8 → Bool+isNzDecDigit8 w = w >= ascii '1' && w <= ascii '9'+{-# INLINE isNzDecDigit8 #-}+ -- | Map the encoding of a decimal digit to the corresponding number. -- Return 'Nothing' on other inputs.-fromDigit8 ∷ Num a ⇒ Word8 → Maybe a-fromDigit8 w | isDigit8 w = Just $ unsafeFromDigit8 w- | otherwise = Nothing-{-# INLINABLE fromDigit8 #-}+fromDecDigit8 ∷ Num a ⇒ Word8 → Maybe a+fromDecDigit8 w | isDecDigit8 w = Just $ unsafeFromDecDigit8 w+ | otherwise = Nothing+{-# INLINABLE fromDecDigit8 #-} -- | Map the encoding of a non-zero decimal digit to the corresponding number. -- Return 'Nothing' on other inputs.-fromNzDigit8 ∷ Num a ⇒ Word8 → Maybe a-fromNzDigit8 w | isNzDigit8 w = Just $ unsafeFromDigit8 w- | otherwise = Nothing-{-# INLINABLE fromNzDigit8 #-}+fromNzDecDigit8 ∷ Num a ⇒ Word8 → Maybe a+fromNzDecDigit8 w | isNzDecDigit8 w = Just $ unsafeFromDecDigit8 w+ | otherwise = Nothing+{-# INLINABLE fromNzDecDigit8 #-} -- | Map the encoding of a decimal digit to the corresponding number.--- No checks is performed.-unsafeFromDigit8 ∷ Num a ⇒ Word8 → a-unsafeFromDigit8 w = fromIntegral (w - ascii '0')-{-# INLINE unsafeFromDigit8 #-}+-- No checks are performed.+unsafeFromDecDigit8 ∷ Num a ⇒ Word8 → a+unsafeFromDecDigit8 w = fromIntegral (w - ascii '0')+{-# INLINE unsafeFromDecDigit8 #-} +-- | Test if a byte is the encoding of a binary digit (/'0'/ or /'1'/).+isBinDigit8 ∷ Word8 → Bool+isBinDigit8 w = w == ascii '0' || w == ascii '1'+{-# INLINE isBinDigit8 #-}++-- | Test if a byte is the encoding of the non-zero binary digit (/'1'/).+isNzBinDigit8 ∷ Word8 → Bool+isNzBinDigit8 w = w == ascii '1'+{-# INLINE isNzBinDigit8 #-}++-- | Map the encoding of a binary digit to the corresponding number.+-- Return 'Nothing' on other inputs.+fromBinDigit8 ∷ Num a ⇒ Word8 → Maybe a+fromBinDigit8 w | isBinDigit8 w = Just $ unsafeFromBinDigit8 w+ | otherwise = Nothing+{-# INLINABLE fromBinDigit8 #-}++-- | Map the encoding of the digit /'1'/ to the number /1/.+-- Return 'Nothing' on other inputs.+fromNzBinDigit8 ∷ Num a ⇒ Word8 → Maybe a+fromNzBinDigit8 w | isNzBinDigit8 w = Just 1+ | otherwise = Nothing+{-# INLINABLE fromNzBinDigit8 #-}++-- | Map the encoding of a binary digit to the corresponding number.+-- No checks are performed.+unsafeFromBinDigit8 ∷ Num a ⇒ Word8 → a+unsafeFromBinDigit8 = unsafeFromDecDigit8+{-# INLINE unsafeFromBinDigit8 #-}+ -- | Test if a byte is the encoding of an octal digit (/'0' ... '7'/). isOctDigit8 ∷ Word8 → Bool isOctDigit8 w = w >= ascii '0' && w <= ascii '7'@@ -492,9 +623,9 @@ {-# INLINABLE fromNzOctDigit8 #-} -- | Map the encoding of an octal digit to the corresponding number.--- No checks is performed.+-- No checks are performed. unsafeFromOctDigit8 ∷ Num a ⇒ Word8 → a-unsafeFromOctDigit8 = unsafeFromDigit8+unsafeFromOctDigit8 = unsafeFromDecDigit8 {-# INLINE unsafeFromOctDigit8 #-} isLowAF8 ∷ Word8 → Bool@@ -508,35 +639,35 @@ -- | Test if a byte is the encoding of a lower-case hexadecimal digit -- (/'0' ... '9'/ or /'a' ... 'f'/). isLowHexDigit8 ∷ Word8 → Bool-isLowHexDigit8 w = isDigit8 w || isLowAF8 w+isLowHexDigit8 w = isDecDigit8 w || isLowAF8 w {-# INLINABLE isLowHexDigit8 #-} -- | Test if a byte is the encoding of a non-zero lower-case hexadecimal digit -- (/'1' ... '9'/ or /'a' ... 'f'/). isNzLowHexDigit8 ∷ Word8 → Bool-isNzLowHexDigit8 w = isNzDigit8 w || isLowAF8 w+isNzLowHexDigit8 w = isNzDecDigit8 w || isLowAF8 w {-# INLINABLE isNzLowHexDigit8 #-} -- | Map the encoding of a lower-case hexadecimal digit to the corresponding -- number. Return 'Nothing' on other inputs. fromLowHexDigit8 ∷ Num a ⇒ Word8 → Maybe a-fromLowHexDigit8 w | isDigit8 w = Just $ unsafeFromDigit8 w- | isLowAF8 w = Just $ fromLowAF8 w- | otherwise = Nothing+fromLowHexDigit8 w | isDecDigit8 w = Just $ unsafeFromDecDigit8 w+ | isLowAF8 w = Just $ fromLowAF8 w+ | otherwise = Nothing {-# INLINABLE fromLowHexDigit8 #-} -- | Map the encoding of a non-zero lower-case hexadecimal digit to -- the corresponding number. Return 'Nothing' on other inputs. fromNzLowHexDigit8 ∷ Num a ⇒ Word8 → Maybe a-fromNzLowHexDigit8 w | isNzDigit8 w = Just $ unsafeFromDigit8 w- | isLowAF8 w = Just $ fromLowAF8 w- | otherwise = Nothing+fromNzLowHexDigit8 w | isNzDecDigit8 w = Just $ unsafeFromDecDigit8 w+ | isLowAF8 w = Just $ fromLowAF8 w+ | otherwise = Nothing {-# INLINABLE fromNzLowHexDigit8 #-} -- | Map the encoding of a lower-case hexadecimal digit to the corresponding--- number. No checks is performed.+-- number. No checks are performed. unsafeFromLowHexDigit8 ∷ Num a ⇒ Word8 → a-unsafeFromLowHexDigit8 w | w < ascii 'a' = unsafeFromDigit8 w+unsafeFromLowHexDigit8 w | w < ascii 'a' = unsafeFromDecDigit8 w | otherwise = fromLowAF8 w {-# INLINE unsafeFromLowHexDigit8 #-} @@ -551,72 +682,72 @@ -- | Test if a byte is the encoding of an upper-case hexadecimal digit -- (/'0' ... '9'/ or /'A' ... 'F'/). isUpHexDigit8 ∷ Word8 → Bool-isUpHexDigit8 w = isDigit8 w || isUpAF8 w+isUpHexDigit8 w = isDecDigit8 w || isUpAF8 w {-# INLINABLE isUpHexDigit8 #-} -- | Test if a byte is the encoding of a non-zero upper-case hexadecimal digit -- (/'1' ... '9'/ or /'A' ... 'F'/). isNzUpHexDigit8 ∷ Word8 → Bool-isNzUpHexDigit8 w = isNzDigit8 w || isUpAF8 w+isNzUpHexDigit8 w = isNzDecDigit8 w || isUpAF8 w {-# INLINABLE isNzUpHexDigit8 #-} -- | Map the encoding of an upper-case hexadecimal digit to the corresponding -- number. Return 'Nothing' on other inputs. fromUpHexDigit8 ∷ Num a ⇒ Word8 → Maybe a-fromUpHexDigit8 w | isDigit8 w = Just $ unsafeFromDigit8 w- | isUpAF8 w = Just $ fromUpAF8 w- | otherwise = Nothing+fromUpHexDigit8 w | isDecDigit8 w = Just $ unsafeFromDecDigit8 w+ | isUpAF8 w = Just $ fromUpAF8 w+ | otherwise = Nothing {-# INLINABLE fromUpHexDigit8 #-} -- | Map the encoding of a non-zero upper-case hexadecimal digit to -- the corresponding number. Return 'Nothing' on other inputs. fromNzUpHexDigit8 ∷ Num a ⇒ Word8 → Maybe a-fromNzUpHexDigit8 w | isNzDigit8 w = Just $ unsafeFromDigit8 w- | isUpAF8 w = Just $ fromUpAF8 w- | otherwise = Nothing+fromNzUpHexDigit8 w | isNzDecDigit8 w = Just $ unsafeFromDecDigit8 w+ | isUpAF8 w = Just $ fromUpAF8 w+ | otherwise = Nothing {-# INLINABLE fromNzUpHexDigit8 #-} -- | Map the encoding of an upper-case hexadecimal digit to the corresponding--- number. No checks is performed.+-- number. No checks are performed. unsafeFromUpHexDigit8 ∷ Num a ⇒ Word8 → a-unsafeFromUpHexDigit8 w | w < ascii 'A' = unsafeFromDigit8 w+unsafeFromUpHexDigit8 w | w < ascii 'A' = unsafeFromDecDigit8 w | otherwise = fromUpAF8 w {-# INLINE unsafeFromUpHexDigit8 #-} -- | Test if a byte is the encoding of a hexadecimal digit -- (/'0' ... '9'/ or /'a' ... 'f'/ or /'A' ... 'F'/). isHexDigit8 ∷ Word8 → Bool-isHexDigit8 w = isDigit8 w || isUpAF8 w || isLowAF8 w+isHexDigit8 w = isDecDigit8 w || isUpAF8 w || isLowAF8 w {-# INLINABLE isHexDigit8 #-} -- | Test if a byte is the encoding of a non-zero hexadecimal digit -- (/'1' ... '9'/ or /'a' ... 'f'/ or /'A' ... 'F'/). isNzHexDigit8 ∷ Word8 → Bool-isNzHexDigit8 w = isNzDigit8 w || isUpAF8 w || isLowAF8 w+isNzHexDigit8 w = isNzDecDigit8 w || isUpAF8 w || isLowAF8 w {-# INLINABLE isNzHexDigit8 #-} -- | Map the encoding of a hexadecimal digit to the corresponding -- number. Return 'Nothing' on other inputs. fromHexDigit8 ∷ Num a ⇒ Word8 → Maybe a-fromHexDigit8 w | isDigit8 w = Just $ unsafeFromDigit8 w- | isUpAF8 w = Just $ fromUpAF8 w- | isLowAF8 w = Just $ fromLowAF8 w- | otherwise = Nothing+fromHexDigit8 w | isDecDigit8 w = Just $ unsafeFromDecDigit8 w+ | isUpAF8 w = Just $ fromUpAF8 w+ | isLowAF8 w = Just $ fromLowAF8 w+ | otherwise = Nothing {-# INLINABLE fromHexDigit8 #-} -- | Map the encoding of a non-zero hexadecimal digit to the corresponding -- number. Return 'Nothing' on other inputs. fromNzHexDigit8 ∷ Num a ⇒ Word8 → Maybe a-fromNzHexDigit8 w | isNzDigit8 w = Just $ unsafeFromDigit8 w- | isUpAF8 w = Just $ fromUpAF8 w- | isLowAF8 w = Just $ fromLowAF8 w- | otherwise = Nothing+fromNzHexDigit8 w | isNzDecDigit8 w = Just $ unsafeFromDecDigit8 w+ | isUpAF8 w = Just $ fromUpAF8 w+ | isLowAF8 w = Just $ fromLowAF8 w+ | otherwise = Nothing {-# INLINABLE fromNzHexDigit8 #-} -- | Map the encoding of a hexadecimal digit to the corresponding--- number. No checks is performed.+-- number. No checks are performed. unsafeFromHexDigit8 ∷ Num a ⇒ Word8 → a-unsafeFromHexDigit8 w | w < ascii 'A' = unsafeFromDigit8 w+unsafeFromHexDigit8 w | w < ascii 'A' = unsafeFromDecDigit8 w | w < ascii 'a' = fromUpAF8 w | otherwise = fromLowAF8 w {-# INLINE unsafeFromHexDigit8 #-}
src/Text/Latin1.hs view
@@ -1,6 +1,9 @@ {-# LANGUAGE UnicodeSyntax #-}+{-# LANGUAGE CPP #-} {-# LANGUAGE PatternGuards #-} {-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE TypeSynonymInstances #-} {-# LANGUAGE MultiParamTypeClasses #-} -- | Latin-1 utility functions.@@ -36,12 +39,17 @@ ) where import Data.Checked+import Data.Function (on) import Data.Char (ord, chr)+import Data.String (IsString(..)) import Data.Word (Word8) import qualified Data.Text as TS import qualified Data.Text.Lazy as TL import Text.Ascii (Ascii) import qualified Text.Ascii as A+import Data.Monoid (Monoid(..))+import Data.CaseInsensitive (FoldCase(..))+import Data.Hashable (Hashable(..)) data IsLatin1 = IsLatin1 @@ -67,6 +75,53 @@ type Latin1 α = Checked IsLatin1 α +instance Eq α ⇒ Eq (Latin1 α) where+ (==) = (==) `on` checked+ {-# INLINE (==) #-}++instance Ord α ⇒ Ord (Latin1 α) where+ compare = compare `on` checked+ {-# INLINE compare #-}++instance Show α ⇒ Show (Latin1 α) where+ showsPrec p = showsPrec p . checked++instance Monoid α ⇒ Monoid (Latin1 α) where+ mempty = trustMe mempty+ {-# INLINE mempty #-}+ mappend x y = trustMe $ mappend (checked x) (checked y)+ {-# INLINE mappend #-}++instance IsString α ⇒ IsString (Latin1 α) where+ fromString s | isLatin1 s = trustMe $ fromString s+ | otherwise = error $ "Not a Latin-1 string: " ++ show s+ {-# INLINE fromString #-}++instance Hashable α ⇒ Hashable (Latin1 α) where+#if MIN_VERSION_hashable(1,2,0)+ hashWithSalt s = hashWithSalt s . checked+ {-# INLINE hashWithSalt #-}+#else+ hash = hash . checked+ {-# INLINE hash #-}+#endif++instance FoldCase (Latin1 Char) where+ foldCase = trustMap toLower+ {-# INLINE foldCase #-}++instance FoldCase (Latin1 α) ⇒ FoldCase (Latin1 [α]) where+ foldCase = trustMap $ map $ checked . foldCase . trustThat IsLatin1+ {-# INLINE foldCase #-}++instance FoldCase (Latin1 TS.Text) where+ foldCase = trustMap $ TS.map toLower+ {-# INLINE foldCase #-}++instance FoldCase (Latin1 TL.Text) where+ foldCase = trustMap $ TL.map toLower+ {-# INLINE foldCase #-}+ -- | ASCII values are Latin-1 values. asciiIsLatin1 ∷ Ascii α → Latin1 α asciiIsLatin1 = trustMe . checked@@ -79,7 +134,7 @@ | otherwise = Nothing {-# INLINABLE maybeLatin1 #-} --- | Encode a Latin-1 character. No checks is performed.+-- | Encode a Latin-1 character. No checks are performed. latin1 ∷ Char → Word8 latin1 = fromIntegral . ord {-# INLINE latin1 #-}@@ -138,7 +193,7 @@ -- | Test if a character is either a Latin-1 letter or a decimal digit. isAlphaNum ∷ Char → Bool-isAlphaNum c = A.isDigit c || isAlpha c+isAlphaNum c = A.isDecDigit c || isAlpha c {-# INLINABLE isAlphaNum #-} -- | Test if a byte is the encoding of a Latin-1 control character.@@ -188,6 +243,6 @@ -- | Test if a byte is the encoding of either a Latin-1 letter -- or a decimal digit. isAlphaNum8 ∷ Word8 → Bool-isAlphaNum8 w = A.isDigit8 w || isAlpha8 w+isAlphaNum8 w = A.isDecDigit8 w || isAlpha8 w {-# INLINABLE isAlphaNum8 #-}
text-latin1.cabal view
@@ -1,5 +1,5 @@ Name: text-latin1-Version: 0.1+Version: 0.2 Category: Text Stability: experimental Synopsis: Latin-1 (including ASCII) utility functions@@ -25,9 +25,11 @@ Library Build-Depends: base >= 4 && < 5- , data-checked+ , data-checked >= 0.2 , bytestring , text+ , case-insensitive >= 1.0+ , hashable >= 1.1 Hs-Source-Dirs: src GHC-Options: -Wall Exposed-Modules: