packages feed

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 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: