text-latin1 (empty) → 0.1
raw patch · 5 files changed
+881/−0 lines, 5 filesdep +basedep +bytestringdep +data-checkedsetup-changed
Dependencies added: base, bytestring, data-checked, text
Files
- LICENSE +27/−0
- Setup.hs +2/−0
- src/Text/Ascii.hs +623/−0
- src/Text/Latin1.hs +193/−0
- text-latin1.cabal +36/−0
+ LICENSE view
@@ -0,0 +1,27 @@+Copyright (c) 2013 Mikhail Vorozhtsov+All rights reserved.++Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met:++- Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer.+- Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution.+- Neither the names of the copyright owners nor the names of the + contributors may be used to endorse or promote products derived + from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ src/Text/Ascii.hs view
@@ -0,0 +1,623 @@+{-# LANGUAGE UnicodeSyntax #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE MultiParamTypeClasses #-}++-- | ASCII utility functions.+module Text.Ascii+ (+ -- * ASCII checks+ IsAscii(..)+ , isAscii+ , Ascii+ , maybeAscii+ , ascii+ -- * Character properties+ , isControl+ , isPrintable+ , isWhiteSpace+ , isSpaceOrTab+ , isLower+ , isUpper+ , toLower+ , toUpper+ , isAlpha+ , isDigit+ , isNzDigit+ , isAlphaNum+ , fromDigit+ , fromNzDigit+ , unsafeFromDigit+ , isOctDigit+ , isNzOctDigit+ , fromOctDigit+ , fromNzOctDigit+ , unsafeFromOctDigit+ , isUpHexDigit+ , isNzUpHexDigit+ , fromUpHexDigit+ , fromNzUpHexDigit+ , unsafeFromUpHexDigit+ , isLowHexDigit+ , isNzLowHexDigit+ , fromLowHexDigit+ , fromNzLowHexDigit+ , unsafeFromLowHexDigit+ , isHexDigit+ , isNzHexDigit+ , fromHexDigit+ , fromNzHexDigit+ , unsafeFromHexDigit+ -- * Byte properties+ , isControl8+ , isPrintable8+ , isWhiteSpace8+ , isSpaceOrTab8+ , isLower8+ , isUpper8+ , toLower8+ , toUpper8+ , isAlpha8+ , isDigit8+ , isNzDigit8+ , isAlphaNum8+ , fromDigit8+ , fromNzDigit8+ , unsafeFromDigit8+ , isOctDigit8+ , isNzOctDigit8+ , fromOctDigit8+ , fromNzOctDigit8+ , unsafeFromOctDigit8+ , isUpHexDigit8+ , isNzUpHexDigit8+ , fromUpHexDigit8+ , fromNzUpHexDigit8+ , unsafeFromUpHexDigit8+ , isLowHexDigit8+ , isNzLowHexDigit8+ , fromLowHexDigit8+ , fromNzLowHexDigit8+ , unsafeFromLowHexDigit8+ , isHexDigit8+ , isNzHexDigit8+ , fromHexDigit8+ , fromNzHexDigit8+ , unsafeFromHexDigit8+ ) where++import Data.Checked+import Data.Char (ord, chr)+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++data IsAscii = IsAscii++instance Property IsAscii Word8 where+ holds _ = (< 128)+ {-# INLINE holds #-}++instance Property IsAscii BS.ByteString where+ holds _ = BS.all isAscii+ {-# INLINE holds #-}++instance Property IsAscii BL.ByteString where+ holds _ = BL.all isAscii+ {-# INLINE holds #-}++instance Property IsAscii Char where+ holds _ = (< 128) . ord+ {-# INLINE holds #-}++instance Property IsAscii α ⇒ Property IsAscii [α] where+ holds _ = all isAscii+ {-# INLINE holds #-}++instance Property IsAscii TS.Text where+ holds _ = TS.all isAscii+ {-# INLINE holds #-}++instance Property IsAscii TL.Text where+ holds _ = TL.all isAscii+ {-# INLINE holds #-}++isAscii ∷ Property IsAscii v ⇒ v → Bool +isAscii = holds IsAscii+{-# INLINE isAscii #-}++type Ascii α = Checked IsAscii α++-- | Map a character to its ASCII encoding if possible, otherwise+-- return 'Nothing'.+maybeAscii ∷ Char → Maybe Word8+maybeAscii c | isAscii c = Just $ ascii c+ | otherwise = Nothing+{-# INLINABLE maybeAscii #-}++-- | Encode an ASCII character. No checks is performed.+ascii ∷ Char → Word8+ascii = fromIntegral . ord+{-# INLINE ascii #-}++-- | Test if a character is an ASCII control character.+isControl ∷ Char → Bool+isControl c = w < 32 || w == 127+ where w = ord c+{-# INLINE isControl #-}++-- | Test if a character is an ASCII printable character.+isPrintable ∷ Char → Bool+isPrintable c = w >= 32 && w < 127+ where w = ord c+{-# INLINE isPrintable #-}++-- | Test if a character is an ASCII whitespace character.+isWhiteSpace ∷ Char → Bool+isWhiteSpace c = c == ' ' || (w >= 9 && w <= 13)+ where w = ord c+{-# INLINE isWhiteSpace #-}++-- | Test if a character is the SPACE or the TAB character.+isSpaceOrTab ∷ Char → Bool+isSpaceOrTab c = c == ' ' || c == '\t'+{-# INLINE isSpaceOrTab #-}++-- | Test if a character is an ASCII lower-case letter.+isLower ∷ Char → Bool+isLower c = c >= 'a' && c <= 'z'+{-# INLINE isLower #-}++-- | Test if a character is an ASCII upper-case letter.+isUpper ∷ Char → Bool+isUpper c = c >= 'A' && c <= 'Z'+{-# INLINE isUpper #-}++-- | Map lower-case ASCII letters to the corresponding upper-case letters,+-- leaving other characters as is.+toLower ∷ Char → Char+toLower c | isUpper c = chr (ord c + 32)+ | otherwise = c+{-# INLINABLE toLower #-}++-- | Map upper-case ASCII letters to the corresponding lower-case letters,+-- leaving other characters as is.+toUpper ∷ Char → Char+toUpper c | isLower c = chr (ord c - 32)+ | otherwise = c+{-# INLINABLE toUpper #-}++-- | Test if a character is an ASCII letter.+isAlpha ∷ Char → Bool+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+{-# INLINABLE isAlphaNum #-}++-- | 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 #-}++-- | 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 #-}++-- | 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 #-}++-- | Test if a character is an octal digit (/'0' ... '7'/).+isOctDigit ∷ Char → Bool+isOctDigit c = c >= '0' && c <= '7'+{-# INLINE isOctDigit #-}++-- | Test if a character is a non-zero octal digit (/'1' ... '7'/).+isNzOctDigit ∷ Char → Bool+isNzOctDigit c = c >= '1' && c <= '7'+{-# INLINE isNzOctDigit #-}++-- | Map octal digits to the corresponding numbers. Return 'Nothing' on+-- other inputs.+fromOctDigit ∷ Num a ⇒ Char → Maybe a+fromOctDigit c | isOctDigit c = Just $ unsafeFromOctDigit c+ | otherwise = Nothing+{-# INLINABLE fromOctDigit #-}++-- | Map non-zero octal digits to the corresponding numbers. Return+-- 'Nothing' on other inputs.+fromNzOctDigit ∷ Num a ⇒ Char → Maybe a+fromNzOctDigit c | isNzOctDigit c = Just $ unsafeFromOctDigit c+ | otherwise = Nothing+{-# INLINABLE fromNzOctDigit #-}++-- | Map octal digits to the corresponding numbers. No checks is performed.+unsafeFromOctDigit ∷ Num a ⇒ Char → a+unsafeFromOctDigit = unsafeFromDigit+{-# INLINE unsafeFromOctDigit #-}++isLowAF ∷ Char → Bool+isLowAF c = c >= 'a' && c <= 'f'+{-# INLINE isLowAF #-}++fromLowAF ∷ Num a ⇒ Char → a+fromLowAF c = fromIntegral (ord c - ord 'a' + 10)+{-# INLINE fromLowAF #-}++-- | Test if a character is a lower-case hexadecimal digit+-- (/'0' ... '9'/ or /'a' ... 'f'/).+isLowHexDigit ∷ Char → Bool+isLowHexDigit c = isDigit 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+{-# 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+{-# 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+{-# INLINABLE fromNzLowHexDigit #-}++-- | Map lower-case hexadecimal digits to the corresponding numbers.+-- No checks is performed.+unsafeFromLowHexDigit ∷ Num a ⇒ Char → a+unsafeFromLowHexDigit c | c < 'a' = unsafeFromDigit c+ | otherwise = fromLowAF c+{-# INLINE unsafeFromLowHexDigit #-}++isUpAF ∷ Char → Bool+isUpAF c = c >= 'A' && c <= 'F'+{-# INLINE isUpAF #-}++fromUpAF ∷ Num a ⇒ Char → a+fromUpAF c = fromIntegral (ord c - ord 'A' + 10)+{-# INLINE fromUpAF #-}++-- | Test if a character is an upper-case hexadecimal digit+-- (/'0' ... '9'/ or /'A' ... 'F'/).+isUpHexDigit ∷ Char → Bool+isUpHexDigit c = isDigit 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+{-# 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+{-# 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+{-# INLINABLE fromNzUpHexDigit #-}++-- | Map upper-case hexadecimal digits to the corresponding numbers.+-- No checks is performed.+unsafeFromUpHexDigit ∷ Num a ⇒ Char → a+unsafeFromUpHexDigit c | c < 'A' = unsafeFromDigit 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+{-# 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+{-# 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+{-# 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+{-# INLINABLE fromNzHexDigit #-}++-- | Map hexadecimal digits to the corresponding numbers. No checks is+-- performed.+unsafeFromHexDigit ∷ Num a ⇒ Char → a+unsafeFromHexDigit c | c < 'A' = unsafeFromDigit c+ | c < 'a' = fromUpAF c+ | otherwise = fromLowAF c+{-# INLINE unsafeFromHexDigit #-}++-- | Test if a byte is the encoding of an ASCII control character.+isControl8 ∷ Word8 → Bool+isControl8 w = w < 32 || w == 127+{-# INLINE isControl8 #-}++-- | Test if a byte is the encoding of an ASCII printable character.+isPrintable8 ∷ Word8 → Bool+isPrintable8 w = w >= 32 && w < 127+{-# INLINE isPrintable8 #-}++-- | Test if a byte is the encoding of an ASCII whitespace character.+isWhiteSpace8 ∷ Word8 → Bool+isWhiteSpace8 w = w == ascii ' ' || w >= 9 && w <= 13+{-# INLINE isWhiteSpace8 #-}++-- | Test if a byte is the encoding of the SPACE or the TAB character.+isSpaceOrTab8 ∷ Word8 → Bool+isSpaceOrTab8 w = w == ascii ' ' || w == ascii '\t'+{-# INLINE isSpaceOrTab8 #-}++-- | Test if a byte is the encoding of an ASCII lower-case letter.+isLower8 ∷ Word8 → Bool+isLower8 w = w >= ascii 'a' && w <= ascii 'z'+{-# INLINE isLower8 #-}++-- | Test if a byte is the encoding of an ASCII upper-case letter.+isUpper8 ∷ Word8 → Bool+isUpper8 w = w >= ascii 'A' && w <= ascii 'Z'+{-# INLINE isUpper8 #-}++-- | Map the encodings of lower-case ASCII letters to the encodings of+-- the corresponding upper-case letters, leaving other bytes as is.+toLower8 ∷ Word8 → Word8+toLower8 w | isUpper8 w = w + 32+ | otherwise = w+{-# INLINABLE toLower8 #-}++-- | Map the encodings of upper-case ASCII letters to the encodings of+-- the corresponding lower-case letters, leaving other bytes as is.+toUpper8 ∷ Word8 → Word8+toUpper8 w | isLower8 w = w - 32+ | otherwise = w+{-# INLINABLE toUpper8 #-}++-- | Test if a byte is the encoding of an ASCII letter.+isAlpha8 ∷ Word8 → Bool+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+{-# INLINABLE isAlphaNum8 #-}++-- | 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 #-}++-- | 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 #-}++-- | 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 #-}++-- | Test if a byte is the encoding of an octal digit (/'0' ... '7'/).+isOctDigit8 ∷ Word8 → Bool+isOctDigit8 w = w >= ascii '0' && w <= ascii '7'+{-# INLINE isOctDigit8 #-}++-- | Test if a byte is the encoding of a non-zero octal digit+-- (/'1' ... '7'/).+isNzOctDigit8 ∷ Word8 → Bool+isNzOctDigit8 w = w >= ascii '1' && w <= ascii '7'+{-# INLINE isNzOctDigit8 #-}++-- | Map the encoding of an octal digit to the corresponding number.+-- Return 'Nothing' on other inputs.+fromOctDigit8 ∷ Num a ⇒ Word8 → Maybe a+fromOctDigit8 w | isOctDigit8 w = Just $ unsafeFromOctDigit8 w+ | otherwise = Nothing+{-# INLINABLE fromOctDigit8 #-}++-- | Map the encoding of a non-zero octal digit to the corresponding number.+-- Return 'Nothing' on other inputs.+fromNzOctDigit8 ∷ Num a ⇒ Word8 → Maybe a+fromNzOctDigit8 w | isNzOctDigit8 w = Just $ unsafeFromOctDigit8 w+ | otherwise = Nothing+{-# INLINABLE fromNzOctDigit8 #-}++-- | Map the encoding of an octal digit to the corresponding number.+-- No checks is performed.+unsafeFromOctDigit8 ∷ Num a ⇒ Word8 → a+unsafeFromOctDigit8 = unsafeFromDigit8+{-# INLINE unsafeFromOctDigit8 #-}++isLowAF8 ∷ Word8 → Bool+isLowAF8 w = w >= ascii 'a' && w <= ascii 'f'+{-# INLINE isLowAF8 #-}++fromLowAF8 ∷ Num a ⇒ Word8 → a+fromLowAF8 w = fromIntegral (w - ascii 'a' + 10)+{-# INLINE fromLowAF8 #-}++-- | 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+{-# 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+{-# 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+{-# 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+{-# INLINABLE fromNzLowHexDigit8 #-}++-- | Map the encoding of a lower-case hexadecimal digit to the corresponding+-- number. No checks is performed.+unsafeFromLowHexDigit8 ∷ Num a ⇒ Word8 → a+unsafeFromLowHexDigit8 w | w < ascii 'a' = unsafeFromDigit8 w+ | otherwise = fromLowAF8 w+{-# INLINE unsafeFromLowHexDigit8 #-}++isUpAF8 ∷ Word8 → Bool+isUpAF8 w = w >= ascii 'A' && w <= ascii 'F'+{-# INLINE isUpAF8 #-}++fromUpAF8 ∷ Num a ⇒ Word8 → a+fromUpAF8 w = fromIntegral (w - ascii 'A' + 10)+{-# INLINE fromUpAF8 #-}++-- | 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+{-# 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+{-# 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+{-# 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+{-# INLINABLE fromNzUpHexDigit8 #-}++-- | Map the encoding of an upper-case hexadecimal digit to the corresponding+-- number. No checks is performed.+unsafeFromUpHexDigit8 ∷ Num a ⇒ Word8 → a+unsafeFromUpHexDigit8 w | w < ascii 'A' = unsafeFromDigit8 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+{-# 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+{-# 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+{-# 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+{-# INLINABLE fromNzHexDigit8 #-}++-- | Map the encoding of a hexadecimal digit to the corresponding+-- number. No checks is performed.+unsafeFromHexDigit8 ∷ Num a ⇒ Word8 → a+unsafeFromHexDigit8 w | w < ascii 'A' = unsafeFromDigit8 w+ | w < ascii 'a' = fromUpAF8 w+ | otherwise = fromLowAF8 w+{-# INLINE unsafeFromHexDigit8 #-}+
+ src/Text/Latin1.hs view
@@ -0,0 +1,193 @@+{-# LANGUAGE UnicodeSyntax #-}+{-# LANGUAGE PatternGuards #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE MultiParamTypeClasses #-}++-- | Latin-1 utility functions.+module Text.Latin1+ (+ -- * Latin-1 checks + IsLatin1(..)+ , isLatin1+ , Latin1+ , asciiIsLatin1+ , maybeLatin1+ , latin1+ -- * Character properties+ , isControl+ , isPrintable+ , isWhiteSpace+ , isLower+ , isUpper+ , toLower+ , toUpper+ , isAlpha+ , isAlphaNum+ -- * Byte properties+ , isControl8+ , isPrintable8+ , isWhiteSpace8+ , isLower8+ , isUpper8+ , toLower8+ , toUpper8+ , isAlpha8+ , isAlphaNum8+ ) where++import Data.Checked+import Data.Char (ord, chr)+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++data IsLatin1 = IsLatin1++instance Property IsLatin1 Char where+ holds _ = (< 256) . ord+ {-# INLINE holds #-}++instance Property IsLatin1 α ⇒ Property IsLatin1 [α] where+ holds _ = all isLatin1+ {-# INLINE holds #-}++instance Property IsLatin1 TS.Text where+ holds _ = TS.all isLatin1+ {-# INLINE holds #-}++instance Property IsLatin1 TL.Text where+ holds _ = TL.all isLatin1+ {-# INLINE holds #-}++isLatin1 ∷ Property IsLatin1 v ⇒ v → Bool +isLatin1 = holds IsLatin1+{-# INLINE isLatin1 #-}++type Latin1 α = Checked IsLatin1 α++-- | ASCII values are Latin-1 values.+asciiIsLatin1 ∷ Ascii α → Latin1 α+asciiIsLatin1 = trustMe . checked+{-# INLINE asciiIsLatin1 #-}++-- | Map a character to its Latin-1 encoding if possible, otherwise+-- return 'Nothing'.+maybeLatin1 ∷ Char → Maybe Word8+maybeLatin1 c | isLatin1 c = Just $ latin1 c+ | otherwise = Nothing+{-# INLINABLE maybeLatin1 #-}++-- | Encode a Latin-1 character. No checks is performed.+latin1 ∷ Char → Word8+latin1 = fromIntegral . ord+{-# INLINE latin1 #-}++-- | Test if a character is a Latin-1 control character.+isControl ∷ Char → Bool+isControl c = w < 32 || (w >= 127 && w <= 159)+ where w = ord c+{-# INLINE isControl #-}++-- | Test if a character is a Latin-1 printable character.+isPrintable ∷ Char → Bool+isPrintable c = A.isPrintable c || (w >= 160 && w < 256)+ where w = ord c+{-# INLINE isPrintable #-}++-- | Test if a character is a Latin-1 whitespace character.+isWhiteSpace ∷ Char → Bool+isWhiteSpace c = A.isWhiteSpace c || w == 133 || w == 160+ where w = ord c+{-# INLINE isWhiteSpace #-}++-- | Test if a character is a Latin-1 lower-case letter.+isLower ∷ Char → Bool+isLower c = A.isLower c || (w >= 223 && w < 256 && w /= 247)+ where w = ord c+{-# INLINE isLower #-}++-- | Test if a character is a Latin-1 upper-case letter.+isUpper ∷ Char → Bool+isUpper c = A.isUpper c || (w >= 192 && w <= 222 && w /= 215)+ where w = ord c+{-# INLINE isUpper #-}++-- | Map lower-case Latin-1 letters to the corresponding upper-case letters,+-- leaving other characters as is.+toLower ∷ Char → Char+toLower c | isUpper c = chr (ord c + 32)+ | otherwise = c+{-# INLINABLE toLower #-}++-- | Map upper-case Latin-1 letters to the corresponding lower-case letters,+-- leaving other characters as is.+toUpper ∷ Char → Char+toUpper c | w ← ord c+ , A.isLower c || (w >= 224 && w <= 254 && w /= 247)+ = chr (ord c - 32)+ | otherwise+ = c+{-# INLINABLE toUpper #-}++-- | Test if a character is a Latin-1 letter.+isAlpha ∷ Char → Bool+isAlpha c = isUpper c || isLower c+{-# INLINABLE isAlpha #-}++-- | Test if a character is either a Latin-1 letter or a decimal digit.+isAlphaNum ∷ Char → Bool+isAlphaNum c = A.isDigit c || isAlpha c+{-# INLINABLE isAlphaNum #-}++-- | Test if a byte is the encoding of a Latin-1 control character.+isControl8 ∷ Word8 → Bool+isControl8 w = w < 32 || (w >= 127 && w <= 159)+{-# INLINE isControl8 #-}++-- | Test if a byte is the encoding of a Latin-1 printable character.+isPrintable8 ∷ Word8 → Bool+isPrintable8 w = A.isPrintable8 w || w >= 160+{-# INLINE isPrintable8 #-}++-- | Test if a byte is the encoding of a Latin-1 whitespace character.+isWhiteSpace8 ∷ Word8 → Bool+isWhiteSpace8 w = A.isWhiteSpace8 w || w == 133 || w == 160+{-# INLINE isWhiteSpace8 #-}++-- | Test if a byte is the encoding of a Latin-1 lower-case letter.+isLower8 ∷ Word8 → Bool+isLower8 w = A.isLower8 w || (w >= 223 && w /= 247)+{-# INLINE isLower8 #-}++-- | Test if a byte is the encoding of a Latin-1 upper-case letter.+isUpper8 ∷ Word8 → Bool+isUpper8 w = A.isUpper8 w || (w >= 192 && w <= 222 && w /= 215)+{-# INLINE isUpper8 #-}++-- | Map the encodings of lower-case Latin-1 letters to the encodings of+-- the corresponding upper-case letters, leaving other bytes as is.+toLower8 ∷ Word8 → Word8+toLower8 w | isUpper8 w = w + 32+ | otherwise = w+{-# INLINABLE toLower8 #-}++-- | Map the encodings of upper-case Latin-1 letters to the encodings of+-- the corresponding lower-case letters, leaving other bytes as is.+toUpper8 ∷ Word8 → Word8+toUpper8 w | A.isLower8 w || (w >= 224 && w /= 247 && w /= 255) = w - 32+ | otherwise = w+{-# INLINABLE toUpper8 #-}++-- | Test if a byte is the encoding of a Latin-1 letter.+isAlpha8 ∷ Word8 → Bool+isAlpha8 w = isUpper8 w || isLower8 w+{-# INLINABLE isAlpha8 #-}++-- | 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+{-# INLINABLE isAlphaNum8 #-}+
+ text-latin1.cabal view
@@ -0,0 +1,36 @@+Name: text-latin1+Version: 0.1+Category: Text+Stability: experimental+Synopsis: Latin-1 (including ASCII) utility functions+Description:+ This package provides various functions over the ASCII ang Latin-1+ portions of the 'Char' and 'Word8' data types.++Homepage: https://github.com/mvv/text-latin1+Bug-Reports: https://github.com/mvv/text-latin1/issues++Author: Mikhail Vorozhtsov <mikhail.vorozhtsov@gmail.com>+Maintainer: Mikhail Vorozhtsov <mikhail.vorozhtsov@gmail.com>+Copyright: 2013 Mikhail Vorozhtsov <mikhail.vorozhtsov@gmail.com>+License: BSD3+License-File: LICENSE++Cabal-Version: >= 1.6.0+Build-Type: Simple++Source-Repository head+ Type: git+ Location: https://github.com/mvv/text-latin1.git++Library+ Build-Depends: base >= 4 && < 5+ , data-checked+ , bytestring+ , text+ Hs-Source-Dirs: src+ GHC-Options: -Wall+ Exposed-Modules:+ Text.Ascii+ Text.Latin1+