packages feed

ascii 0.0.5.2 → 1.7.0.2

raw patch · 12 files changed

Files

− Data/Ascii.hs
@@ -1,61 +0,0 @@-module Data.Ascii-    ( -- * Datatypes-      Ascii-    , CIAscii-    , AsciiBuilder-      -- * Construction-      -- ** Safe-    , fromByteString-    , fromChars-    , fromText-      -- ** Unsafe-    , unsafeFromByteString-    , unsafeFromString-    , unsafeFromText-      -- * Extraction-    , toByteString-    , toString-    , toText-      -- * Case insensitive-    , toCIAscii-    , fromCIAscii-    , ciToByteString-      -- * Builder-    , toAsciiBuilder-    , fromAsciiBuilder-    , unsafeFromBuilder-    , toBuilder-      -- * Character-level functions and predicates-    , fromChar-    , toChar-    , ascii-    , isAscii-    , isControl-    , isPrintable-    , isWhiteSpace-    , isSpaceOrTab-    , isLower-    , isUpper-    , toLower-    , toUpper-    , isAlpha-    , isDigit-    , isAlphaNum-    , fromDigit-    , unsafeFromDigit-    , fromOctDigit-    , unsafeFromOctDigit-    , isUpHexDigit-    , fromUpHexDigit-    , unsafeFromUpHexDigit-    , isLowHexDigit-    , fromLowHexDigit-    , unsafeFromLowHexDigit-    , isHexDigit-    , fromHexDigit-    , unsafeFromHexDigit-    ) where--import Data.Ascii.Blaze-import Data.Ascii.ByteString-import Data.Ascii.Word8
− Data/Ascii/Blaze.hs
@@ -1,27 +0,0 @@-{-# LANGUAGE GeneralizedNewtypeDeriving #-}--module Data.Ascii.Blaze where--import Data.Ascii.ByteString---- base-import Data.Monoid (Monoid)-import Data.Semigroup (Semigroup)---- blaze-builder-import qualified Blaze.ByteString.Builder as Blaze--newtype AsciiBuilder = AsciiBuilder (Blaze.Builder)-    deriving (Semigroup, Monoid)--unsafeFromBuilder :: Blaze.Builder -> AsciiBuilder-unsafeFromBuilder = AsciiBuilder--toBuilder :: AsciiBuilder -> Blaze.Builder-toBuilder (AsciiBuilder b) = b--toAsciiBuilder :: Ascii -> AsciiBuilder-toAsciiBuilder (Ascii bs) = AsciiBuilder $ Blaze.fromByteString bs--fromAsciiBuilder :: AsciiBuilder -> Ascii-fromAsciiBuilder (AsciiBuilder b) = Ascii $ Blaze.toByteString b
− Data/Ascii/ByteString.hs
@@ -1,75 +0,0 @@-{-# LANGUAGE DeriveDataTypeable, GeneralizedNewtypeDeriving #-}--module Data.Ascii.ByteString where---- base-import Data.Data (Data)-import Data.Typeable (Typeable)-import Data.String (IsString (..))-import qualified Data.Char as C-import Data.Monoid (Monoid)-import Data.Semigroup (Semigroup)---- bytestring-import qualified Data.ByteString as S-import qualified Data.ByteString.Char8 as S8-import Data.ByteString (ByteString)---- case-insensitive-import Data.CaseInsensitive (FoldCase, CI, mk, original)---- hashable-import Data.Hashable (Hashable)---- text-import Data.Text (Text)-import qualified Data.Text as T-import qualified Data.Text.Encoding as TE--newtype Ascii = Ascii ByteString-    deriving (Show, Eq, Read, Ord, Data, Typeable, IsString, FoldCase, Hashable, Semigroup, Monoid)--type CIAscii = CI Ascii--fromByteString :: ByteString -> Maybe Ascii-fromByteString bs-    | S.all (< 128) bs = Just $ Ascii bs-    | otherwise = Nothing---- | Renamed to avoid clash with 'fromString'-fromChars :: String -> Maybe Ascii-fromChars s-    | all C.isAscii s = Just $ Ascii $ S8.pack s-    | otherwise = Nothing--fromText :: Text -> Maybe Ascii-fromText t-    | T.all C.isAscii t = Just $ Ascii $ TE.encodeUtf8 t-    | otherwise = Nothing--unsafeFromByteString :: ByteString -> Ascii-unsafeFromByteString = Ascii--unsafeFromString :: String -> Ascii-unsafeFromString = Ascii . S8.pack--unsafeFromText :: Text -> Ascii-unsafeFromText = Ascii . TE.encodeUtf8--toCIAscii :: Ascii -> CIAscii-toCIAscii = mk--fromCIAscii :: CIAscii -> Ascii-fromCIAscii = original--toByteString :: Ascii -> ByteString-toByteString (Ascii bs) = bs--toString :: Ascii -> String-toString (Ascii bs) = S8.unpack bs--toText :: Ascii -> Text-toText (Ascii bs) = TE.decodeUtf8 bs--ciToByteString :: CIAscii -> ByteString-ciToByteString = toByteString . original
− Data/Ascii/Word8.hs
@@ -1,148 +0,0 @@-{-# LANGUAGE CPP #-}--module Data.Ascii.Word8 where---- base-import Data.Word (Word8)-import qualified Data.Char as C--fromChar :: Char -> Maybe Word8-fromChar c = if i < 128 then Just (fromIntegral i) else Nothing-  where i = C.ord c--toChar :: Word8 -> Char-toChar = C.chr . fromIntegral---- | Unsafe version of 'fromChar'-ascii :: Char -> Word8-ascii = fromIntegral . C.ord-{-# INLINE ascii #-}--isAscii :: Word8 -> Bool-isAscii = (< 128)--isControl :: Word8 -> Bool-isControl w = w < 32 || w == 127--isPrintable :: Word8 -> Bool-isPrintable w = w >= 32 && w < 127--isWhiteSpace :: Word8 -> Bool-isWhiteSpace w = w == ascii ' ' || w >= 9 && w <= 13--isSpaceOrTab :: Word8 -> Bool-isSpaceOrTab w = w == ascii ' ' || w == ascii '\t'--isLower :: Word8 -> Bool-isLower w = w >= ascii 'a' && w <= ascii 'z'--isUpper :: Word8 -> Bool-isUpper w = w >= ascii 'A' && w <= ascii 'Z'--toLower :: Word8 -> Word8-toLower w | isUpper w = w + 32-          | otherwise = w--toUpper :: Word8 -> Word8-toUpper w | isLower w = w - 32-          | otherwise = w--isAlpha :: Word8 -> Bool-isAlpha w = isUpper w || isLower w--isDigit :: Word8 -> Bool-isDigit w = w >= ascii '0' && w <= ascii '9'--isAlphaNum :: Word8 -> Bool-isAlphaNum w = isDigit w || isAlpha w--fromDigit :: Num a => Word8 -> Maybe a-fromDigit w | isDigit w = Just $ unsafeFromDigit w-            | otherwise = Nothing-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE fromDigit #-}-#endif--unsafeFromDigit :: Num a => Word8 -> a-unsafeFromDigit w = fromIntegral (w - ascii '0')-{-# INLINE unsafeFromDigit #-}--isOctDigit :: Word8 -> Bool-isOctDigit w = w >= ascii '0' && w <= ascii '7'--fromOctDigit :: Num a => Word8 -> Maybe a-fromOctDigit w | isOctDigit w = Just $ unsafeFromOctDigit w-               | otherwise    = Nothing-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE fromOctDigit #-}-#endif--unsafeFromOctDigit :: Num a => Word8 -> a-unsafeFromOctDigit = unsafeFromDigit-{-# INLINE unsafeFromOctDigit #-}--isLowAF :: Word8 -> Bool-isLowAF w = w >= ascii 'a' && w <= ascii 'f'-{-# INLINE isLowAF #-}--fromLowAF :: Num a => Word8 -> a-fromLowAF w = fromIntegral (w - ascii 'a' + 10)-{-# INLINE fromLowAF #-}--isLowHexDigit :: Word8 -> Bool-isLowHexDigit w = isDigit w || isLowAF w--fromLowHexDigit :: Num a => Word8 -> Maybe a-fromLowHexDigit w | isDigit w = Just $ unsafeFromDigit w-                  | isLowAF w = Just $ fromLowAF w-                  | otherwise = Nothing-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE fromLowHexDigit #-}-#endif--unsafeFromLowHexDigit :: Num a => Word8 -> a-unsafeFromLowHexDigit w | w < ascii 'a' = unsafeFromDigit w-                        | otherwise     = fromLowAF w-{-# INLINE unsafeFromLowHexDigit #-}--isUpAF :: Word8 -> Bool-isUpAF w = w >= ascii 'A' && w <= ascii 'F'-{-# INLINE isUpAF #-}--fromUpAF :: Num a => Word8 -> a-fromUpAF w = fromIntegral (w - ascii 'A' + 10)-{-# INLINE fromUpAF #-}--isUpHexDigit :: Word8 -> Bool-isUpHexDigit w = isDigit w || isUpAF w--fromUpHexDigit :: Num a => Word8 -> Maybe a-fromUpHexDigit w | isDigit w = Just $ unsafeFromDigit w-                 | isUpAF w  = Just $ fromUpAF w-                 | otherwise = Nothing-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE fromUpHexDigit #-}-#endif--unsafeFromUpHexDigit :: Num a => Word8 -> a-unsafeFromUpHexDigit w | w < ascii 'A' = unsafeFromDigit w-                       | otherwise     = fromUpAF w-{-# INLINE unsafeFromUpHexDigit #-}--isHexDigit :: Word8 -> Bool-isHexDigit w = isDigit w || isUpAF w || isLowAF w--fromHexDigit :: Num a => Word8 -> Maybe a-fromHexDigit w | isDigit w = Just $ unsafeFromDigit w-               | isUpAF w  = Just $ fromUpAF w-               | isLowAF w = Just $ fromLowAF w-               | otherwise = Nothing-#if __GLASGOW_HASKELL__ >= 700-{-# INLINABLE fromHexDigit #-}-#endif--unsafeFromHexDigit :: Num a => Word8 -> a-unsafeFromHexDigit w | w < ascii 'A' = unsafeFromDigit w-                     | w < ascii 'a' = fromUpAF w-                     | otherwise     = fromLowAF w-{-# INLINE unsafeFromHexDigit #-}
− LICENSE
@@ -1,30 +0,0 @@-Copyright Michael Snoyman 2011, Typeclass Consulting LLC 2018--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 name of Michael Snoyman nor the names of other-      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
@@ -1,3 +0,0 @@-#!/usr/bin/env runhaskell-import Distribution.Simple-main = defaultMain
ascii.cabal view
@@ -1,40 +1,74 @@-Name:                ascii-Version:             0.0.5.2-Synopsis:            Type-safe, bytestring-based ASCII values-Description:         Type-safe, bytestring-based ASCII values.-License:             BSD3-License-file:        LICENSE-Author:              Michael Snoyman-Maintainer:          Chris Martin, Julie Moronuki-Stability:           Stable-Category:            Data-Homepage:            https://github.com/typeclasses/ascii-Bug-Reports:         https://github.com/typeclasses/ascii/issues-Build-type:          Simple-Cabal-version:       >= 1.6-Tested-with:         GHC == 8.4.3-                   , GHC == 8.2.2-                   , GHC == 7.10.3-                   , GHC == 7.8.4-                   , GHC == 7.6.3-                   , GHC == 7.4.2-                   , GHC == 7.2.2-                   , GHC == 7.0.4+cabal-version: 3.0 -Source-Repository head-    Type:     git-    Location: git://github.com/typeclasses/ascii.git+name: ascii+version: 1.7.0.2+synopsis: The ASCII character set and encoding+category: Data, Text -Library-  Exposed-modules:     Data.Ascii-                     , Data.Ascii.Blaze-                     , Data.Ascii.ByteString-                     , Data.Ascii.Word8-  Build-depends:       base             >= 4             && < 5-                     , bytestring       >= 0.9           && < 0.11-                     , text             >= 0.11          && < 1.3-                     , blaze-builder    >= 0.2.1.4       && < 0.5-                     , case-insensitive >= 0.2           && < 1.3-                     , hashable         >= 1.0           && < 1.3-                     , semigroups-  Ghc-options:         -Wall+description:+    This package provides a variety of ways to work with ASCII text.++license: Apache-2.0+license-file: license.txt++author: Chris Martin+maintainer: Chris Martin, Julie Moronuki++homepage: https://github.com/typeclasses/ascii+bug-reports: https://github.com/typeclasses/ascii/issues++extra-source-files: *.md++source-repository head+    type: git+    location: git://github.com/typeclasses/ascii.git++common base+    default-language: GHC2021+    ghc-options: -Wall+    default-extensions: NoImplicitPrelude+    build-depends:+      , ascii-caseless == 0.0.0.*+      , ascii-char == 1.0.1.*+      , ascii-group == 1.0.0.*+      , ascii-case == 1.0.1.*+      , ascii-numbers == 1.2.0.*+      , ascii-predicates == 1.0.1.*+      , ascii-superset == 1.3.0.*+      , ascii-th == 1.2.0.*+      , base ^>= 4.16 || ^>= 4.17 || ^>= 4.18 || ^>= 4.19+      , bytestring ^>= 0.11.4 || ^>= 0.12+      , text ^>= 1.2.5 || ^>= 2.0 || ^>= 2.1++library+    import: base+    hs-source-dirs: library+    exposed-modules: ASCII+    reexported-modules:+      , ASCII.Case+      , ASCII.Caseless+      , ASCII.CaseRefinement+      , ASCII.Char+      , ASCII.Decimal+      , ASCII.Group+      , ASCII.Hexadecimal+      , ASCII.Isomorphism+      , ASCII.Lists+      , ASCII.ListsAndPredicates+      , ASCII.Predicates+      , ASCII.QuasiQuoters+      , ASCII.Refinement+      , ASCII.Superset+      , ASCII.Superset.Text+      , ASCII.TemplateHaskell+      , ASCII.Word4++test-suite test-ascii+    import: base+    type: exitcode-stdio-1.0+    hs-source-dirs: test+    main-is: Main.hs+    default-extensions: OverloadedStrings QuasiQuotes+    build-depends:+      , ascii+      , hspec ^>= 2.9.7 || ^>= 2.10 || ^>= 2.11
+ changelog.md view
@@ -0,0 +1,305 @@+### 1.7.0.2 (2025-01-20)++Version bumps++### 1.7.0.1 (2023-06-26)++Upgrade language to GHC2021++### 1.7.0.0 (2023-03-01)++Rename `toAsciiCharMaybe` to `toCharMaybe`++Add `toCharListMaybe`++### 1.6.0.0 (2023-02-08)++Raise `ascii-superset` to `1.3`. This removes the `ASCII.Lift` module.++Raise `ascii-numbers` to `1.2`.++From the `ASCII` module, the `Lift` class and `lift` function are removed.++The removed `lift` function is replaced with the `lift` function from+`ASCII.Refinement`. If you were using `lift` specialized as+`ASCII a -> a`, then this is not a breaking change. Otherwise, migrate+by using one the new functions below.++```haskell+fromChar        :: FromChar char               => Char      -> char+fromCharList    :: FromString string           => [Char]    -> string+fromDigit       :: DigitSuperset char          => Digit     -> char+fromDigitList   :: DigitStringSuperset string  => [Digit]   -> string+fromHexChar     :: HexCharSuperset char        => HexChar   -> char+fromHexCharList :: HexStringSuperset string    => [HexChar] -> string++forgetCase      :: ASCII'case letterCase superset -> ASCII superset+```++### 1.5.4.0 (2023-02-08)++Raise `ascii-superset` to `1.2.7`++Adds module `ASCII.Superset.Text`++Added to the `ASCII` module:++- Class `ToText`+- Functions `toStrictText`, `toLazyText`, `toUnicodeCharList`++### 1.5.3.0 (2023-02-07)++Raise `ascii-superset` to `1.2.6`++Added class `StringSupersetConversion` and the following function:++```haskell+convertRefinedString ::+    StringSupersetConversion a b => ASCII a -> ASCII b+```++### 1.5.2.0 (2023-01-25)++New functions: `asciiByteStringToText` and `asciiByteStringToTextLazy`++### 1.5.1.0 (2023-01-06)++Raise `ascii-superset` version to `1.2.5`. This adds a new instance:++```haskell+instance Lift (ASCII'case letterCase superset) (ASCII superset)+```++### 1.5.0.0 (2023-01-06)++Raise `ascii-th` version to `1.2.0`. This changes the constraints on `lower` and+`upper` quasi-quotations in an expression context. Previously, the constraint+was `FromString`. The constraints are now `ToCasefulString 'LowerCase` and+`ToCasefulString 'UpperCase` respectively. This expands the range of types+inhabited by lower/uppercase quotes to include `ASCII'lower` and `ASCII'upper`,+which were previously not able to be expressed using quasi-quotations.++### 1.4.2.0 (2023-01-05)++Raise `ascii-superset` version from `1.2.0` to `1.2.4`. This adds classes+`ToCasefulChar` and `ToCasefulString` to the `ASCII.Superset` module. It also+adds some instances for the various other superset classes.++### 1.4.1.1 (2023-01-05)++Change test suite from `hedgehog` to `hspec`++### 1.4.1.0 (2023-01-05)++Raise `ascii-char` version to `1.0.1`. This adds `Word8` conversions to the+`ASCII.Char` module.++### 1.4.0.0 (2023-01-03)++Additions to the `ASCII` module: `disregardCase`, `ASCII'case`, `ASCII'upper`,+`ASCII'lower`, `KnownCase (..)`, `refineCharToCase`, `refineStringToCase`++Update `ascii-superset` to `1.2.0`. This adds `CharSuperset (toCaseChar)`,+`StringSuperset (toCaseString)`, `refineCharToCase`, and `refineStringToCase`.++The constraint on `toCaseChar` is relaxed from `CharIso` to `CharSuperset`.+The constraint on `toCaseString` is relaxed from `StringIso` to `StringSuperset`.++### 1.3.1.0 (2023-01-03)++Update `ascii-th` to `1.1.1`.++This adds, most notably, to the `ASCII.QuasiQuoters` module.+The new quasi-quoters are `caseless`, `lower`, and `upper`.+These are also re-exported from the `ASCII` module.++### 1.3.0.0 (2023-01-03)++Update `ascii-superset` to `1.1.0`.++This adds several classes to the `ASCII.Superset` module: `ToChar`, `FromChar`,+`ToString`, `FromString`, `ToCaselessChar`, and `ToCaselessString`.++This is a breaking change because these are superclasses of the existing+`CharSuperset` and `StringSuperset` classes, and they take methods from them.++### 1.2.6.0 (2023-01-02)++Update `ascii-superset` to `1.0.2`. This adds the `ASCII.CaseRefinement` module.++### 1.2.5.0 (2023-01-02)++Add the `ASCII.Caseless` module (re-exported from the `ascii-caseless` package)++Additions to the `ASCII` module:++* `CaselessChar`++### 1.2.4.1 (2022-12-30)++Metadata changes only++### 1.2.4.0 (2022-12-23)++Bump version of `ascii-case` to `1.0.1`. This adds the following function to the+`ASCII.Case` module:++```haskell+opposite :: Case -> Case+```++### 1.2.3.0 (2022-05-04)++Add `isVisible :: Char -> Bool`. Visible characters include all print characters+other than `Space`.++### 1.2.2.0 (2022-04-29)++Add `type UnicodeChar = Data.Char.Char` type alias to `ASCII` module++### 1.2.1.0 (2022-04-29)++New polymorphic narrowing functions:++* `toAsciiCharMaybe :: CharSuperset char => char -> Maybe Char`+* `toDigitMaybe :: DigitSuperset char => char -> Maybe Digit`+* `toHexCharMaybe :: HexCharSuperset char => char -> Maybe HexChar`++New monomorphic character conversion functions:++* `digitToWord8 :: Digit -> Word8`+* `word8ToDigitMaybe :: Word8 -> Maybe Digit`+* `word8ToDigitUnsafe :: Word8 -> Digit`+* `digitToChar :: Digit -> Char`+* `charToDigitMaybe :: Char -> Maybe Digit`+* `charToDigitUnsafe :: Char -> Digit`+* `digitToUnicode :: Digit -> Unicode.Char`+* `unicodeToDigitMaybe :: Unicode.Char -> Maybe Digit`+* `unicodeToDigitUnsafe :: Unicode.Char -> Digit`+* `hexCharToWord8 :: HexChar -> Word8`+* `word8ToHexCharMaybe :: Word8 -> Maybe HexChar`+* `word8ToHexCharUnsafe :: Word8 -> HexChar`+* `hexCharToChar :: HexChar -> Char`+* `charToHexCharMaybe :: Char -> Maybe HexChar`+* `charToHexCharUnsafe :: Char -> HexChar`+* `hexCharToUnicode :: HexChar -> Unicode.Char`+* `unicodeToHexCharMaybe :: Unicode.Char -> Maybe HexChar`+* `unicodeToHexCharUnsafe :: Unicode.Char -> HexChar`++### 1.2.0.0 (2022-04-20)++Update to `ascii-numbers` version `1.1.0`. The major change is that there are+now `Lift` instances for `Digit` and `HexChar`.++### 1.1.3.0++Added functions `digitString` and `hexCharString`++### 1.1.2.0++Add dependency on `ascii-numbers`++New modules:++* `ASCII.Decimal`+* `ASCII.Hexadecimal`++New types:++* `Digit`+* `HexChar`++New classes:++* `DigitSuperset`+* `DigitStringSuperset`+* `HexCharSuperset`+* `HexStringSuperset`++New functions:++* `showIntegralDecimal`+* `showIntegralHexadecimal`+* `readIntegralDecimal`+* `readIntegralHexadecimal`++* `showNaturalDigits`+* `readNaturalDigits`+* `showNaturalHexChars`+* `readNaturalHexChars`++* `showNaturalDecimal`+* `showNaturalHexadecimal`+* `readNaturalDecimal`+* `readNaturalHexadecimal`++Dropped support for old versions:++* Drop support for `base` 4.11 (GHC 8.4)+* Drop support for `base` 4.12 (GHC 8.6)++### 1.1.1.4++Switch test-suite over to `hedgehog`++### 1.1.1.2++Support GHC 9.2++### 1.1.1.0++New functions:++  - `isAlphaNum`+  - `isLetter`+  - `isDigit`+  - `isOctDigit`+  - `isHexDigit`+  - `isSpace`+  - `isPunctuation`+  - `isSymbol`++### 1.1.0.0++The dependency on the 'data-ascii' package is removed, and the following modules+are no longer re-exported:++  - `Data.Ascii`+  - `Data.Ascii.Blaze`+  - `Data.Ascii.ByteString`+  - `Data.Ascii.Word8`++### 1.0.1.6++Add a test suite++Raise `text` lower bound to 1.2.3++### 1.0.1.4++Support GHC 9.0++### 1.0.1.2++Support `bytestring-0.11`++### 1.0.1.0++New functions:++  - `byteStringToUnicodeStringMaybe`+  - `unicodeStringToByteStringMaybe`+  - `byteListToUnicodeStringMaybe`+  - `unicodeStringToByteListMaybe`+  - `convertCharMaybe`+  - `convertCharOrFail`+  - `convertStringMaybe`+  - `convertStringOrFail`++### 1.0.0.2++Support GHC 8.10++### 1.0.0.0++Completely redesigned the library
+ library/ASCII.hs view
@@ -0,0 +1,872 @@+{-| The __American Standard Code for Information Interchange__ (ASCII) comprises+a set of 128 characters, each represented by 7 bits. 33 of these characters are+/'Control' codes/; a few of these are still in use, but most are obsolete relics+of the early days of computing. The other 95 are /'Printable' characters/ such+as letters and numbers, mostly corresponding to the keys on an American English+keyboard.++Nowadays instead of ASCII we typically work with text using an encoding such as+UTF-8 that can represent the entire Unicode character set, which includes over a+hundred thousand characters and is not limited to the symbols of any particular+writing system or culture. However, ASCII is still relevant to network+protocols; for example, we can see it in the specification of+<https://www.rfc-editor.org/rfc/rfc9110.html#name-syntax-notation HTTP>.++There is a convenient relationship between ASCII and Unicode: the ASCII+characters are the first 128 characters of the much larger Unicode character set.+The <https://www.unicode.org/charts/PDF/U0000.pdf C0 Controls and Basic Latin>+section of the Unicode standard contains a list of all the ASCII characters.+You may also find this list replicated in the "ASCII.Char" module; each ASCII+character corresponds to a constructor of the 'ASCII.Char' type.++We do not elaborate on the semantics of the control characters here,+because this information is both obsolete and restricted by copyright law.+It is described by a document entitled+/"Coded Character Sets - 7-Bit American National Standard Code for Information Interchange (7-Bit ASCII)"/,+published by American National Standards Institute (ANSI) and available for purchase+<https://webstore.ansi.org/Standards/INCITS/INCITS1986R2012 on their website>.+-}+module ASCII+  (+    {- * @Char@ -}++        {- ** ASCII -}+            {- $char -} Char,++        {- ** Unicode -}+            UnicodeChar,++        {- ** Case-insensitive -}+            {- $caselessChar -} CaselessChar,++    {- * Character classifications -}++        {- ** Print/control groups -}+            {- $groups -} Group (..), charGroup, inGroup,++        {- ** Upper/lower case -}+            {- $case -} Case (..), letterCase, isCase, toCaseChar, toCaseString,+            disregardCase, refineCharToCase, refineStringToCase,++        {- ** Letters -}+            isLetter,++        {- ** Letters and numbers -}+            isAlphaNum,++        {- ** Decimal digits -}+            {- $digit -} isDigit, Digit,++        {- ** Hexadecimal digits -}+            {- $hexchar -} isHexDigit, HexChar,++        {- ** Octal digits -}+            isOctDigit,++        {- ** Spaces and symbols -}+            isSpace, isPunctuation, isSymbol, isVisible,++    {- * Monomorphic character conversions -}++        {- $monomorphicConversions -}++        {- ** @ASCII.Char@ ↔ @Int@ -}+            {- $intConversions -}+            charToInt, intToCharMaybe, intToCharUnsafe,++        {- ** @ASCII.Char@ ↔ @Word8@ -}+            {- $word8Conversions -}+            charToWord8, word8ToCharMaybe, word8ToCharUnsafe,++        {- ** @ASCII.Char@ ↔ @UnicodeChar@ -}+            {- $unicodeCharConversions -}+            charToUnicode, unicodeToCharMaybe, unicodeToCharUnsafe,++    {- * Monomorphic digit conversions -}++        {- ** @Digit@ ↔ @Word8@ -}+            {- $digitWord8Conversions -}+            digitToWord8, word8ToDigitMaybe, word8ToDigitUnsafe,++        {- ** @Digit@ ↔ @ASCII.Char@ -}+            {- $digitCharConversions -}+            digitToChar, charToDigitMaybe, charToDigitUnsafe,++        {- ** @Digit@ ↔ @UnicodeChar@ -}+            {- $digitUnicodeConversions -}+            digitToUnicode, unicodeToDigitMaybe, unicodeToDigitUnsafe,++        {- ** @HexChar@ ↔ @Word8@ -}+            {- $hexCharWord8Conversions -}+            hexCharToWord8, word8ToHexCharMaybe, word8ToHexCharUnsafe,++        {- ** @HexChar@ ↔ @ASCII.Char@ -}+            {- $hexCharCharConversions -}+            hexCharToChar, charToHexCharMaybe, charToHexCharUnsafe,++        {- ** @HexChar@ ↔ @UnicodeChar@ -}+            {- $hexCharUnicodeConversions -}+            hexCharToUnicode, unicodeToHexCharMaybe, unicodeToHexCharUnsafe,++    {- * Monomorphic string conversions -}++        {- ** @ASCII.Char@ ↔ @String@ -}+            {- $unicodeStringConversions -}+            charListToUnicodeString, unicodeStringToCharListMaybe,+            unicodeStringToCharListUnsafe,++        {- ** @ASCII.Char@ ↔ @Text@ -}+            {- $textConversions -}+            charListToText, textToCharListMaybe, textToCharListUnsafe,++        {- ** @ASCII.Char@ ↔ @ByteString@ -}+            {- $byteStringConversions -}+            charListToByteString, byteStringToCharListMaybe,+            byteStringToCharListUnsafe,++        {- ** @ASCII ByteString@ -> @Text@ -}+            asciiByteStringToText, asciiByteStringToTextLazy,++    {- * Monomorphic conversions between ASCII supersets -}++        {- $monoSupersetConversions -}++        {- ** @ByteString@ ↔ @String@ -}+            byteStringToUnicodeStringMaybe, unicodeStringToByteStringMaybe,++        {- ** @[Word8]@ ↔ @String@ -}+            byteListToUnicodeStringMaybe, unicodeStringToByteListMaybe,++    {- * Monomorphic numeric string conversions -}++        {- ** @Natural@ ↔ @[Digit]@ -}+            showNaturalDigits, readNaturalDigits,++        {- ** @Natural@ ↔ @[HexChar]@ -}+            showNaturalHexChars, readNaturalHexChars,++    {- * Refinement types -}+        {- $refinement -} ASCII,+        ASCII'case, ASCII'upper, ASCII'lower, KnownCase (..),++    {- * Polymorphic conversions -}++        {- ** Narrowing -}+            toCharMaybe, toCharListMaybe, toDigitMaybe, toHexCharMaybe,++        {- ** Validate -}+            validateChar, validateString,++        {- ** Widening -}+            {- $lift -} lift,+            {- $toText -} toStrictText, toLazyText, toUnicodeCharList,+            {- $fromChar -} fromChar, fromCharList,+            {- $fromDigit -} fromDigit, fromDigitList,+            {- $fromHexChar -} fromHexChar, fromHexCharList,+            {- $forgetCase -} forgetCase,++        {- ** Convert -}+            {- $supersetConversions -}+            convertCharMaybe, convertCharOrFail, convertStringMaybe,+            convertStringOrFail, convertRefinedString,++        {- ** Integral strings -}+            {- $numbers -}+            showIntegralDecimal, showIntegralHexadecimal,+            readIntegralDecimal, readIntegralHexadecimal,++        {- ** Natural strings -}+            showNaturalDecimal, showNaturalHexadecimal,+            readNaturalDecimal, readNaturalHexadecimal,++        {- ** Single-digit strings -}+            digitString, hexCharString,++    {- * Classes -}++        {- ** Supersets of ASCII -}+            CharSuperset, StringSuperset,+            StringSupersetConversion, ToText,++        {- ** Equivalents to ASCII -}+            CharIso, StringIso,++        {- ** Supersets of numeric characters -}+            DigitSuperset, DigitStringSuperset, HexCharSuperset, HexStringSuperset,++    {- * Quasi-quoters -}+        char, string, caseless, lower, upper,+  )+  where++import ASCII.Case (Case (..))+import ASCII.CaseRefinement (KnownCase (..), ASCII'case, ASCII'upper, ASCII'lower, refineCharToCase, refineStringToCase, forgetCase)+import ASCII.Caseless (CaselessChar)+import ASCII.Char (Char)+import ASCII.Decimal (Digit, DigitStringSuperset, DigitSuperset, fromDigit, fromDigitList)+import ASCII.Group (Group (..))+import ASCII.Hexadecimal (HexChar, HexCharSuperset, HexStringSuperset, fromHexChar, fromHexCharList)+import ASCII.Isomorphism (CharIso, StringIso)+import ASCII.QuasiQuoters (char, string, caseless, lower, upper)+import ASCII.Refinement (ASCII, lift, validateChar, validateString)+import ASCII.Superset (CharSuperset, StringSuperset, toCharMaybe, toCharListMaybe, fromChar, fromCharList)+import ASCII.SupersetConversion (StringSupersetConversion)+import ASCII.Superset.Text (ToText (..))++import Control.Monad ((>=>))+import Control.Monad.Fail (MonadFail)+import Data.Bits (Bits)+import Data.Bool (Bool (..))+import Data.Foldable (any)+import Data.Function ((.))+import Data.Int (Int)+import Data.Maybe (Maybe, maybe)+import Data.Word (Word8)+import Numeric.Natural (Natural)+import Prelude (Integral)++import qualified ASCII.Case+import qualified ASCII.Caseless+import qualified ASCII.Decimal+import qualified ASCII.Group+import qualified ASCII.Hexadecimal+import qualified ASCII.Isomorphism+import qualified ASCII.Predicates+import qualified ASCII.Superset+import qualified ASCII.SupersetConversion as SupersetConversion++import qualified Data.ByteString as BS+import qualified Data.ByteString.Lazy as LBS+import qualified Data.Char as Unicode+import qualified Data.String as Unicode+import qualified Data.Text as Text+import qualified Data.Text.Encoding as Text+import qualified Data.Text.Lazy as LText+import qualified Data.Text.Lazy.Encoding as LText++{- $char++See also: "ASCII.Char" -}++{- $caselessChar++See also: "ASCII.Caseless" -}++{-| A character in the full range of Unicode++ASCII 'Char' is a subset of this type. Convert using 'charToUnicode' and+'unicodeToCharMaybe'. -}+type UnicodeChar = Unicode.Char++{- $groups++ASCII characters are broadly categorized into two groups: /control codes/ and+/printable characters/.++See also: "ASCII.Group" -}++{-| Determine which group a particular character belongs to++@+charGroup CapitalLetterA == Printable++charGroup EndOfTransmission == Control+@ -}+charGroup :: CharIso char => char -> Group+charGroup = ASCII.Group.charGroup . ASCII.Isomorphism.toChar++{-| Test whether a character belongs to a particular ASCII group++@+not (inGroup Printable EndOfTransmission)++inGroup Control EndOfTransmission++map (inGroup Printable) ([-1, 5, 65, 97, 127, 130] :: [Int])+    == [False, False, True, True, False, False]+@ -}+inGroup :: CharSuperset char => Group -> char -> Bool+inGroup g = maybe False (ASCII.Group.inGroup g) . ASCII.Superset.toCharMaybe++{- $case++/Case/ is a property of letters. /A-Z/ are /upper case/ letters, and /a-z/ are+/lower case/ letters. No other ASCII characters have case.++See also: "ASCII.Case" -}++{-| Determines whether a character is an ASCII letter, and if so, whether it is+    upper or lower case++@+map letterCase [SmallLetterA, CapitalLetterA, ExclamationMark]+    == [Just LowerCase, Just UpperCase, Nothing]++map letterCase ([string|Hey!|] :: [ASCII Word8])+    == [Just UpperCase, Just LowerCase, Just LowerCase, Nothing]+@ -}+letterCase :: CharSuperset char => char -> Maybe Case+letterCase = ASCII.Superset.toCharMaybe >=> ASCII.Case.letterCase++{-| Determines whether a character is an ASCII letter of a particular case++@+map (isCase UpperCase) [SmallLetterA, CapitalLetterA, ExclamationMark]+    == [False, True, False]++map (isCase UpperCase) ([string|Hey!|] :: [ASCII Word8])+    == [True, False, False, False]++map (isCase UpperCase) ([-1, 65, 97, 150] :: [Int])+    == [False, True, False, False]+@ -}+isCase :: CharSuperset char => Case -> char -> Bool+isCase c = maybe False (ASCII.Case.isCase c) . ASCII.Superset.toCharMaybe++{-| Maps a letter character to its upper/lower case equivalent++@+toCaseChar UpperCase SmallLetterA == CapitalLetterA++(                     [char|a|] :: ASCII Word8) == asciiUnsafe 97+(toCaseChar UpperCase [char|a|] :: ASCII Word8) == asciiUnsafe 65+@ -}+toCaseChar :: CharSuperset char => Case -> char -> char+toCaseChar = ASCII.Superset.toCaseChar++{-| Maps each of the characters in a string to its upper/lower case equivalent++@+toCaseString UpperCase [CapitalLetterH, SmallLetterE, SmallLetterY, ExclamationMark]+    == [CapitalLetterH, CapitalLetterE, CapitalLetterY, ExclamationMark]++(toCaseString UpperCase [string|Hey!|] :: ASCII Text) == asciiUnsafe "HEY!"+@ -}+toCaseString :: StringSuperset string => Case -> string -> string+toCaseString = ASCII.Superset.toCaseString++{-| Convert from ASCII character to caseless ASCII character, discarding the+    case if the character is a letter -}+disregardCase :: Char -> CaselessChar+disregardCase = ASCII.Caseless.disregardCase++{- $monomorphicConversions++These are a few simple monomorphic functions to convert between ASCII and types+representing some other character set.++This is not intended to be an exhaustive list of all possible conversions. For+more options, see "ASCII.Superset". -}++{- $intConversions++These functions convert between the ASCII 'Char' type and 'Int'. -}++{-|++@+map charToInt [Null, CapitalLetterA, SmallLetterA, Delete] == [0, 65, 97, 127]+@ -}+charToInt :: Char -> Int+charToInt = ASCII.Superset.fromChar++intToCharMaybe :: Int -> Maybe Char+intToCharMaybe = ASCII.Superset.toCharMaybe++intToCharUnsafe :: Int -> Char+intToCharUnsafe = ASCII.Superset.toCharUnsafe++{- $word8Conversions++These functions convert between the ASCII 'Char' type and 'Word8'. -}++{-|++@+map charToWord8 [Null, CapitalLetterA, SmallLetterA, Delete] == [0, 65, 97, 127]+@ -}+charToWord8 :: Char -> Word8+charToWord8 = ASCII.Superset.fromChar++word8ToCharMaybe :: Word8 -> Maybe Char+word8ToCharMaybe = ASCII.Superset.toCharMaybe++word8ToCharUnsafe :: Word8 -> Char+word8ToCharUnsafe = ASCII.Superset.toCharUnsafe++{- $unicodeCharConversions++These functions convert between the ASCII 'Char' type and the 'UnicodeChar'+type. -}++charToUnicode :: Char -> UnicodeChar+charToUnicode = ASCII.Superset.fromChar++unicodeToCharMaybe :: UnicodeChar -> Maybe Char+unicodeToCharMaybe = ASCII.Superset.toCharMaybe++unicodeToCharUnsafe :: UnicodeChar -> Char+unicodeToCharUnsafe = ASCII.Superset.toCharUnsafe++{- $digitWord8Conversions++These functions convert between the ASCII 'Digit' type and ASCII digits in their+byte encoding.++These conversions do /not/ correspond to the numeric interpretations of 'Digit'+and 'Word8'. For example, 'digitToWord8' 'ASCII.Decimal.Digit0' is 48, not 0. -}++digitToWord8 :: Digit -> Word8+digitToWord8 = ASCII.Decimal.fromDigit++word8ToDigitMaybe :: Word8 -> Maybe Digit+word8ToDigitMaybe = ASCII.Decimal.toDigitMaybe++word8ToDigitUnsafe :: Word8 -> Digit+word8ToDigitUnsafe = ASCII.Decimal.toDigitUnsafe++{- $digitCharConversions++These functions convert between the ASCII 'Digit' type and the ASCII 'Char'+type. -}++digitToChar :: Digit -> Char+digitToChar = ASCII.Decimal.fromDigit++charToDigitMaybe :: Char -> Maybe Digit+charToDigitMaybe = ASCII.Decimal.toDigitMaybe++charToDigitUnsafe :: Char -> Digit+charToDigitUnsafe = ASCII.Decimal.toDigitUnsafe++{- $digitUnicodeConversions++These functions convert between the ASCII 'Digit' type and the 'UnicodeChar'+type. -}++digitToUnicode :: Digit -> UnicodeChar+digitToUnicode = ASCII.Decimal.fromDigit++unicodeToDigitMaybe :: UnicodeChar -> Maybe Digit+unicodeToDigitMaybe = ASCII.Decimal.toDigitMaybe++unicodeToDigitUnsafe :: UnicodeChar -> Digit+unicodeToDigitUnsafe = ASCII.Decimal.toDigitUnsafe+++{- $hexCharWord8Conversions++These functions convert between the ASCII 'HexChar' type and ASCII characters in+their byte encoding.++These conversions do /not/ correspond to the numeric interpretations of+'HexChar' and 'Word8'. For example, 'hexCharToWord8'+'ASCII.Hexadecimal.CapitalLetterA' is 65, not 10. -}++hexCharToWord8 :: HexChar -> Word8+hexCharToWord8 = ASCII.Hexadecimal.fromHexChar++word8ToHexCharMaybe :: Word8 -> Maybe HexChar+word8ToHexCharMaybe = ASCII.Hexadecimal.toHexCharMaybe++word8ToHexCharUnsafe :: Word8 -> HexChar+word8ToHexCharUnsafe = ASCII.Hexadecimal.toHexCharUnsafe++{- $hexCharCharConversions++These functions convert between the ASCII 'HexChar' type and the ASCII 'Char'+type. -}++hexCharToChar :: HexChar -> Char+hexCharToChar = ASCII.Hexadecimal.fromHexChar++charToHexCharMaybe :: Char -> Maybe HexChar+charToHexCharMaybe = ASCII.Hexadecimal.toHexCharMaybe++charToHexCharUnsafe :: Char -> HexChar+charToHexCharUnsafe = ASCII.Hexadecimal.toHexCharUnsafe++{- $hexCharUnicodeConversions++These functions convert between the ASCII 'HexChar' type and the 'UnicodeChar'+type. -}++hexCharToUnicode :: HexChar -> UnicodeChar+hexCharToUnicode = ASCII.Hexadecimal.fromHexChar++unicodeToHexCharMaybe :: UnicodeChar -> Maybe HexChar+unicodeToHexCharMaybe = ASCII.Hexadecimal.toHexCharMaybe++unicodeToHexCharUnsafe :: UnicodeChar -> HexChar+unicodeToHexCharUnsafe = ASCII.Hexadecimal.toHexCharUnsafe++{- $unicodeStringConversions++These functions convert between @['Char']@ (a list of ASCII characters) and+'Unicode.String' (a list of Unicode characters). -}++charListToUnicodeString :: [Char] -> Unicode.String+charListToUnicodeString = ASCII.Superset.fromCharList++unicodeStringToCharListMaybe :: Unicode.String -> Maybe [Char]+unicodeStringToCharListMaybe = ASCII.Superset.toCharListMaybe++unicodeStringToCharListUnsafe :: Unicode.String -> [Char]+unicodeStringToCharListUnsafe = ASCII.Superset.toCharListUnsafe++{- $textConversions++These functions convert between @['Char']@ and 'Text.Text'. -}++{-|++@+charListToText [CapitalLetterH, SmallLetterI, ExclamationMark] == "Hi!"+@ -}+charListToText :: [Char] -> Text.Text+charListToText = ASCII.Superset.fromCharList++textToCharListMaybe :: Text.Text -> Maybe [Char]+textToCharListMaybe = ASCII.Superset.toCharListMaybe++textToCharListUnsafe :: Text.Text -> [Char]+textToCharListUnsafe = ASCII.Superset.toCharListUnsafe++{- $byteStringConversions++These functions convert between @['Char']@ and 'BS.ByteString'. -}++charListToByteString :: [Char] -> BS.ByteString+charListToByteString = ASCII.Superset.fromCharList++byteStringToCharListMaybe :: BS.ByteString -> Maybe [Char]+byteStringToCharListMaybe = ASCII.Superset.toCharListMaybe++byteStringToCharListUnsafe :: BS.ByteString -> [Char]+byteStringToCharListUnsafe = ASCII.Superset.toCharListUnsafe++asciiByteStringToText :: ASCII BS.ByteString -> Text.Text+asciiByteStringToText = Text.decodeUtf8 . ASCII.Refinement.lift++asciiByteStringToTextLazy :: ASCII LBS.ByteString -> LText.Text+asciiByteStringToTextLazy = LText.decodeUtf8 . ASCII.Refinement.lift++{- $refinement++See also: "ASCII.Refinement", "ASCII.CaseRefinement" -}++{- $lift++See also: "ASCII.Refinement" -}++{- $toText++See also: "ASCII.Superset.ToText" -}++{- $fromChar++See also: "ASCII.Superset" -}++{- $fromDigit++See also: "ASCII.Decimal" -}++{- $fromHexChar++See also: "ASCII.Hexadecimal" -}++{- $forgetCase++See also: "ASCII.CaseRefinement" -}++{- $supersetConversions++These functions all convert from one ASCII-superset type to another, failing if+any of the characters in the input is outside the ASCII character set. -}++convertCharMaybe :: (CharSuperset char1, CharSuperset char2) => char1 -> Maybe char2+convertCharMaybe = ASCII.Superset.convertCharMaybe++convertCharOrFail :: (CharSuperset char1, CharSuperset char2, MonadFail context) => char1 -> context char2+convertCharOrFail = ASCII.Superset.convertCharOrFail++convertStringMaybe :: (StringSuperset string1, StringSuperset string2) => string1 -> Maybe string2+convertStringMaybe = ASCII.Superset.convertStringMaybe++convertStringOrFail :: (StringSuperset string1, StringSuperset string2, MonadFail context) => string1 -> context string2+convertStringOrFail = ASCII.Superset.convertStringOrFail++{- $monoSupersetConversions++These functions are all specializations of 'convertStringMaybe'.+They convert a string from one ASCII-superset type to another.++@+ASCII.byteListToUnicodeStringMaybe [0x48, 0x54, 0x54, 0x50] == Just \"HTTP"+@++If any of the characters in the input is outside the ASCII character set, the+result is 'Nothing'.++@+ASCII.byteListToUnicodeStringMaybe [0x48, 0x54, 0x54, 0x80] == Nothing+@ -}+byteStringToUnicodeStringMaybe :: BS.ByteString -> Maybe Unicode.String+byteStringToUnicodeStringMaybe = convertStringMaybe++unicodeStringToByteStringMaybe :: Unicode.String -> Maybe BS.ByteString+unicodeStringToByteStringMaybe = convertStringMaybe++byteListToUnicodeStringMaybe :: [Word8] -> Maybe Unicode.String+byteListToUnicodeStringMaybe = convertStringMaybe++unicodeStringToByteListMaybe :: Unicode.String -> Maybe [Word8]+unicodeStringToByteListMaybe = convertStringMaybe++{-| Returns True for ASCII letters:++- 'ASCII.Char.SmallLetterA' to 'ASCII.Char.SmallLetterZ'+- 'ASCII.Char.CapitalLetterA' to 'ASCII.Char.CapitalLetterZ' -}+isLetter :: CharSuperset char => char -> Bool+isLetter x = any ASCII.Predicates.isLetter (convertCharMaybe x)++{-| Returns True for the characters from 'ASCII.Char.Digit0' to+'ASCII.Char.Digit9'. -}+isDigit :: CharSuperset char => char -> Bool+isDigit x = any ASCII.Predicates.isDigit (convertCharMaybe x)++{-| Returns True for the characters from 'ASCII.Char.Digit0' to+'ASCII.Char.Digit7'. -}+isOctDigit :: CharSuperset char => char -> Bool+isOctDigit x = any ASCII.Predicates.isOctDigit (convertCharMaybe x)++{-| Returns True for characters in any of the following ranges:++- 'ASCII.Char.Digit0' to 'ASCII.Char.Digit9'+- 'ASCII.Char.CapitalLetterA' to 'ASCII.Char.CapitalLetterF'+- 'ASCII.Char.SmallLetterA' to 'ASCII.Char.SmallLetterF' -}+isHexDigit :: CharSuperset char => char -> Bool+isHexDigit x = any ASCII.Predicates.isHexDigit (convertCharMaybe x)++{-| Returns True for the following characters:++- 'ASCII.Char.Space'+- 'ASCII.Char.HorizontalTab'+- 'ASCII.Char.LineFeed'+- 'ASCII.Char.VerticalTab'+- 'ASCII.Char.FormFeed'+- 'ASCII.Char.CarriageReturn' -}+isSpace :: CharSuperset char => char -> Bool+isSpace x = any ASCII.Predicates.isSpace (convertCharMaybe x)++{-| Returns True if the character is either an ASCII letter ('isLetter') or an+ASCII digit ('isDigit'). -}+isAlphaNum :: CharSuperset char => char -> Bool+isAlphaNum x = any ASCII.Predicates.isAlphaNum (convertCharMaybe x)++{-| Returns True for the following characters:++- 'ASCII.Char.ExclamationMark'+- 'ASCII.Char.QuotationMark'+- 'ASCII.Char.NumberSign'+- 'ASCII.Char.PercentSign'+- 'ASCII.Char.Ampersand'+- 'ASCII.Char.Apostrophe'+- 'ASCII.Char.LeftParenthesis'+- 'ASCII.Char.RightParenthesis'+- 'ASCII.Char.Asterisk'+- 'ASCII.Char.Comma'+- 'ASCII.Char.HyphenMinus'+- 'ASCII.Char.FullStop'+- 'ASCII.Char.Slash'+- 'ASCII.Char.Colon'+- 'ASCII.Char.Semicolon'+- 'ASCII.Char.QuestionMark'+- 'ASCII.Char.AtSign'+- 'ASCII.Char.LeftSquareBracket'+- 'ASCII.Char.Backslash'+- 'ASCII.Char.RightSquareBracket'+- 'ASCII.Char.Underscore'+- 'ASCII.Char.LeftCurlyBracket'+- 'ASCII.Char.RightCurlyBracket' -}+isPunctuation :: CharSuperset char => char -> Bool+isPunctuation x = any ASCII.Predicates.isPunctuation (convertCharMaybe x)++{-| Returns True for the following characters:++- 'ASCII.Char.DollarSign'+- 'ASCII.Char.PlusSign'+- 'ASCII.Char.LessThanSign'+- 'ASCII.Char.EqualsSign'+- 'ASCII.Char.GreaterThanSign'+- 'ASCII.Char.Caret'+- 'ASCII.Char.GraveAccent'+- 'ASCII.Char.VerticalLine'+- 'ASCII.Char.Tilde' -}+isSymbol :: CharSuperset char => char -> Bool+isSymbol x = any ASCII.Predicates.isSymbol (convertCharMaybe x)++{- |Returns True for visible characters++This includes all print characters except 'ASCII.Char.Space'. -}+isVisible :: CharSuperset char => char -> Bool+isVisible x = any ASCII.Predicates.isVisible (convertCharMaybe x)++{- $numbers++See also: "ASCII.Decimal" and "ASCII.Hexadecimal" -}++{-| Gives the ASCII string representation of an integer in decimal (base 10)+    notation, using digits 'ASCII.Char.Digit0' through 'ASCII.Char.Digit9',+    leading with 'ASCII.Char.HyphenMinus' for negative numbers++For example, @'showIntegralDecimal' (-512 :: 'Prelude.Integer')@ = @"-512"@. -}+showIntegralDecimal :: (Integral n, StringSuperset string) => n -> string+showIntegralDecimal = ASCII.Decimal.showIntegral++{-| Gives the ASCII string representation of an integer in hexadecimal (base 16)+    notation++The characters 'ASCII.Char.Digit0' through 'ASCII.Char.Digit9' represent digits+0 though 9. The representation of digits 10 to 15 is determined by the value of+'Case' parameter: 'UpperCase' means 'ASCII.Char.CapitalLetterA' to+'ASCII.Char.CapitalLetterF', and 'LowerCase' means 'ASCII.Char.SmallLetterA' to+'ASCII.Char.SmallLetterF'. For negative numbers, the resulting string begins+with 'ASCII.Char.HyphenMinus'.++@+'showIntegralHexadecimal' 'UpperCase' ('Prelude.negate' (256 + 12) :: 'Prelude.Integer') == "-10C"+@ -}+showIntegralHexadecimal :: (Integral n, StringSuperset string) =>+    Case -> n -> string+showIntegralHexadecimal = ASCII.Hexadecimal.showIntegral++{-| Roughly the inverse of 'showIntegralDecimal'++* Leading zeroes are accepted, as in @"0074"@ and @"-0074"@++Conditions where the result is 'Data.Maybe.Nothing':++* If the input is empty+* If the input contains any other extraneous characters+* If the resulting number would be outside the range supported by the 'Integral'+  (determined by its 'Bits' instance) -}+readIntegralDecimal :: (StringSuperset string, Integral number, Bits number) =>+    string -> Maybe number+readIntegralDecimal = ASCII.Decimal.readIntegral++{-| Roughly the inverse of 'showIntegralHexadecimal'++* Upper and lower case letters are treated equally+* Leading zeroes are accepted, as in @"006a"@ and @"-006a"@++Conditions where the result is 'Data.Maybe.Nothing':++* If the input is empty+* If the input contains any other extraneous characters+* If the resulting number would be outside the range supported by the 'Integral'+  (determined by its 'Bits' instance) -}+readIntegralHexadecimal :: (StringSuperset string, Integral number, Bits number) =>+    string -> Maybe number+readIntegralHexadecimal = ASCII.Hexadecimal.readIntegral++{-| Gives the ASCII string representation of an natural number in decimal+    (base 10) notation, using digits 'ASCII.Char.Digit0' through 'ASCII.Char.Digit9'++@+'showNaturalDecimal' 512 == @"512"+@ -}+showNaturalDecimal :: DigitStringSuperset string => Natural -> string+showNaturalDecimal = ASCII.Decimal.showNatural++{-| Gives the ASCII string representation of an integer in hexadecimal (base 16)+    notation++Characters 'ASCII.Char.Digit0' through 'ASCII.Char.Digit9' represent digits 0+though 9. The representation of digits 10 to 15 is determined by the value of+'Case' parameter: 'UpperCase' means 'ASCII.Char.CapitalLetterA' to+'ASCII.Char.CapitalLetterF', and 'LowerCase' means 'ASCII.Char.SmallLetterA' to+'ASCII.Char.SmallLetterF'.++@+'showNaturalHexadecimal' 'UpperCase' (256 + 12) == "10C"+@ -}+showNaturalHexadecimal :: HexStringSuperset string => Case -> Natural -> string+showNaturalHexadecimal = ASCII.Hexadecimal.showNatural++{-| Roughly the inverse of 'showNaturalDecimal'++* Leading zeroes are accepted, as in @"0074"@++Conditions where the result is 'Data.Maybe.Nothing':++* If the input is empty+* If the input contains any other extraneous characters -}+readNaturalDecimal :: DigitStringSuperset string => string -> Maybe Natural+readNaturalDecimal = ASCII.Decimal.readNatural++{-| Roughly the inverse of 'showNaturalHexadecimal'++* Upper and lower case letters are treated equally+* Leading zeroes are accepted, as in @"006a"@++Conditions where the result is 'Data.Maybe.Nothing':++* If the input is empty+* If the input contains any other extraneous characters -}+readNaturalHexadecimal :: HexStringSuperset string => string -> Maybe Natural+readNaturalHexadecimal = ASCII.Hexadecimal.readNatural++{- $digit++See also: "ASCII.Decimal" -}++{- $hexchar++See also: "ASCII.Hexadecimal" -}++{-| Specialization of 'showNaturalDecimal'++See also: 'showIntegralDecimal' -}+showNaturalDigits :: Natural -> [Digit]+showNaturalDigits = showNaturalDecimal++{-| Specialization of 'readNaturalDecimal'++See also: 'readIntegralDecimal' -}+readNaturalDigits :: [Digit] -> Maybe Natural+readNaturalDigits = readNaturalDecimal++{-| Specialization of 'showNaturalHexadecimal'++See also: 'showIntegralHexadecimal' -}++showNaturalHexChars :: Case -> Natural -> [HexChar]+showNaturalHexChars = showNaturalHexadecimal++{-| Specialization of 'readNaturalHexadecimal'++See also: 'readIntegralHexadecimal' -}+readNaturalHexChars :: [HexChar] -> Maybe Natural+readNaturalHexChars = readNaturalHexadecimal++{-| A string containing a single digit character 0-9 -}+digitString :: DigitStringSuperset string => Digit -> string+digitString x = ASCII.Decimal.fromDigitList [x]++{-| A string containing a single hexadecimal digit character+    0-9, A-F, or a-f -}+hexCharString :: HexStringSuperset string => HexChar -> string+hexCharString x = ASCII.Hexadecimal.fromHexCharList [x]++toDigitMaybe :: DigitSuperset char => char -> Maybe Digit+toDigitMaybe = ASCII.Decimal.toDigitMaybe++toHexCharMaybe :: HexCharSuperset char => char -> Maybe HexChar+toHexCharMaybe = ASCII.Hexadecimal.toHexCharMaybe++{-| For example, this function can convert @ASCII ByteString@+    to @ASCII Text@ and vice versa -}+convertRefinedString ::+    StringSupersetConversion a b => ASCII a -> ASCII b+convertRefinedString = SupersetConversion.convertRefinedString
+ license.txt view
@@ -0,0 +1,13 @@+Copyright 2021 Mission Valley Software LLC++Licensed under the Apache License, Version 2.0 (the "License");+you may not use this file except in compliance with the License.+You may obtain a copy of the License at++    http://www.apache.org/licenses/LICENSE-2.0++Unless required by applicable law or agreed to in writing, software+distributed under the License is distributed on an "AS IS" BASIS,+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+See the License for the specific language governing permissions and+limitations under the License.
+ readme.md view
@@ -0,0 +1,69 @@+## What is ASCII?++The *American Standard Code for Information Interchange* (ASCII) comprises a set+of 128 characters, each represented by 7 bits. 33 of these characters are+"control codes"; a few of these are still in use, but most are obsolete relics+of the early days of computing. The other 95 are "printable characters" such as+letters and numbers, mostly corresponding to the keys on an American English+keyboard.++Nowadays instead of ASCII we typically work with text using an encoding such as+UTF-8 that can represent the entire Unicode character set, which includes over a+hundred thousand characters and is not limited to the symbols of any particular+writing system or culture. However, ASCII is still relevant to network+protocols; for example, we can see it in the specification of [HTTP].++There is a convenient relationship between ASCII and Unicode: the ASCII+characters are the first 128 characters of the much larger Unicode character+set. The [C0 Controls and Basic Latin][unicode] section of the Unicode standard+contains a list of all the ASCII characters.++## Haskell packages++This repository contains the main API, the [`ASCII`][ascii] module in the+`ascii` package, which is an amalgamation of smaller packages in other+repositories.++  * If you only need the ASCII [`Char`][char] type, you can use the+    `ascii-char` package, which is minimal so that it can be kept stable.++  * The `ascii-group` package defines the [`Group`][group] type (`Control` and+    `Printable`), and the `ascii-case` package defines the [`Case`][case] type+    (`UpperCase` and `LowerCase`). These package are also small and stable.++  * The `ascii-predicates` package provides [additional ways of categorizing+    characters][predicates] similar to what you can find in [the `base`+    package][base].++  * For case-insensitivity, use the `ascii-caseless` package.++  * The `ascii-superset` package defines [`CharSuperset` and+    `StringSuperset`][superset] classes to generalize types that represent+    characters and strings, respectively, in character sets larger than ASCII.+    It also defines the [`ASCII`][refinement] type constructor, which is used+    to indicate that a value from some ASCII superset is confined to ASCII.++  * The `ascii-numbers` package provides utilities for working with numbers+    represented using ASCII digits 0-9, ASCII letters A-F to represent+    hexadecimal digits 10-15, and the `HyphenMinus` character for negation.++  * The `ascii-th` package provides a [quasi-quoter][qq] that allows one to+    safely and conveniently express ASCII string literals. The generated+    expressions are polymorphic and can take the form of any type belonging to+    the `StringSuperset` class, including `[ASCII.Char]`, [`String`][string],+    [`ByteString`][bytestring], and [`Text`][text].++  [HTTP]: https://www.rfc-editor.org/rfc/rfc9110.html#name-syntax-notation+  [unicode]: https://www.unicode.org/charts/PDF/U0000.pdf+  [ascii]: https://hackage.haskell.org/package/ascii/docs/ASCII.html+  [char]: https://hackage.haskell.org/package/ascii-char/docs/ASCII-Char.html+  [group]: https://hackage.haskell.org/package/ascii-group/docs/ASCII-Group.html+  [case]: https://hackage.haskell.org/package/ascii-case/docs/ASCII-Case.html+  [predicates]: https://hackage.haskell.org/package/ascii-predicates/docs/ASCII-ListsAndPredicates.html+  [base]: https://hackage.haskell.org/package/base/docs/Data-Char.html+  [superset]: https://hackage.haskell.org/package/ascii-superset/docs/ASCII-Superset.html+  [refinement]: https://hackage.haskell.org/package/ascii-superset/docs/ASCII-Refinement.html+  [qq]: https://hackage.haskell.org/package/ascii-th/docs/ASCII-QuasiQuoters.html+  [string]: https://hackage.haskell.org/package/base/docs/Data-String.html+  [bytestring]: https://hackage.haskell.org/package/bytestring+  [text]: https://hackage.haskell.org/package/text
+ test/Main.hs view
@@ -0,0 +1,148 @@+module Main (main) where++import ASCII++import ASCII.Char (Char (..))+import ASCII.Refinement (asciiUnsafe)++import Data.Bool (Bool (..))+import Data.Function (($))+import Data.Int (Int)+import Data.List (map)+import Data.Maybe (Maybe (..))+import Data.Text (Text)+import Data.Word (Word8)+import Prelude (enumFromTo, maxBound, minBound)+import System.IO (IO)++import Test.Hspec (describe, hspec, it, shouldBe)++main :: IO ()+main = hspec $ do++    describe "charGroup" $ do+        let c ~> g = charGroup c `shouldBe` g++        it "A is printable"                 $ CapitalLetterA    ~> Printable+        it "end-of-transmission is control" $ EndOfTransmission ~> Control++    describe "inGroup" $ do++        describe "tests Char" $ do+            it "end-of-transmission is not printable" $+                inGroup Printable EndOfTransmission `shouldBe` False+            it "end-of-transmission is control" $+                inGroup Control   EndOfTransmission `shouldBe` True++        describe "tests Int" $ do+            let i ~> b = inGroup Printable (i :: Int) `shouldBe` b++            it "-1 is not printable (isn't anything)"  $ (-1) ~> False+            it "5 is not printable"                    $ 5    ~> False+            it "65 is printable"                       $ 65   ~> True+            it "97 is printable"                       $ 97   ~> True+            it "127 is not printable"                  $ 127  ~> False+            it "128 is not printable (isn't anything)" $ 128  ~> False++    describe "letterCase" $ do+        let ch ~> ca = letterCase ch `shouldBe` ca++        describe "works with Char" $ do+            it "a is lower"    $ SmallLetterA    ~> Just LowerCase+            it "A is upper"    $ CapitalLetterA  ~> Just UpperCase+            it "! has no case" $ ExclamationMark ~> Nothing++        it "works with ASCII Word8" $ do+            map letterCase ([string|Hey!|] :: [ASCII Word8]) `shouldBe`+                [Just UpperCase, Just LowerCase, Just LowerCase, Nothing]++    describe "isCase" $ do++        describe "works with Char" $ do+            let c ~> b = isCase UpperCase c `shouldBe` b++            it "a is not upper" $ SmallLetterA    ~> False+            it "A is upper"     $ CapitalLetterA  ~> True+            it "! is not upper" $ ExclamationMark ~> False++        it "works with ASCII Word8" $ do+            map (isCase UpperCase) ([string|Hey!|] :: [ASCII Word8])+                `shouldBe` [True, False, False, False]++        describe "works with Int" $ do+            let i ~> b = isCase UpperCase (i :: Int) `shouldBe` b++            it "-1 is not upper (isn't anything)"  $ (-1) ~> False+            it "65 is upper"                       $ 65   ~> True+            it "97 is not upper"                   $ 97   ~> False+            it "128 is not upper (isn't anything)" $ 128  ~> False++    describe "toCaseChar" $ do++        describe "works with Char" $ do+            it "a to upper is A" $ toCaseChar UpperCase SmallLetterA+                `shouldBe` CapitalLetterA++        describe "works with ASCII Word8" $ do+            it "a to upper is 65" $ toCaseChar UpperCase ([char|a|] :: ASCII Word8)+                `shouldBe` (asciiUnsafe 65 :: ASCII Word8)++    describe "toCaseString" $ do+        it "converts each Char to a case" $ do+            let check a b = toCaseString UpperCase a `shouldBe` b+            check [ CapitalLetterH, SmallLetterE,   SmallLetterY,   ExclamationMark ]+                  [ CapitalLetterH, CapitalLetterE, CapitalLetterY, ExclamationMark ]++        it "works with ASCII Text" $+            (toCaseString UpperCase [string|Hey!|] :: ASCII Text)+                `shouldBe` asciiUnsafe "HEY!"++    describe "charToInt" $ do+        let c ~> i = charToInt c `shouldBe` i++        it "Null is 0"     $ Null           ~> 0+        it "A is 65"       $ CapitalLetterA ~> 65+        it "a is 97"       $ SmallLetterA   ~> 97+        it "Delete is 127" $ Delete         ~> 127++    describe "charToWord8" $ do+        let c ~> i = charToWord8 c `shouldBe` i++        it "Null is 0"     $ Null           ~> 0+        it "A is 65"       $ CapitalLetterA ~> 65+        it "a is 97"       $ SmallLetterA   ~> 97+        it "Delete is 127" $ Delete         ~> 127++    describe "charListToText" $ do+        it "packs a list of Char into Text" $+            charListToText [CapitalLetterH, SmallLetterI, ExclamationMark]+                `shouldBe` "Hi!"++    describe "fromChar" $ do+        it "converts Char to Word8" $ (fromChar CapitalLetterA :: Word8) `shouldBe` 65++    describe "fromCharList" $ do+        it "converts [Char] to Text" $+            (fromCharList [CapitalLetterH, SmallLetterI, ExclamationMark] :: Text)+                `shouldBe` "Hi!"++    describe "byteListToUnicodeStringMaybe" $ do+        it "converts [Word8] to String" $+            ASCII.byteListToUnicodeStringMaybe [0x48, 0x54, 0x54, 0x50]+                `shouldBe` Just "HTTP"+        it "can fail" $ ASCII.byteListToUnicodeStringMaybe [0x48, 0x54, 0x54, 0x80]+            `shouldBe` Nothing++    describe "digitString" $ do+        it "converts Digit to a single character of Text" $ do+            let f = digitString :: Digit -> Text+            map f (enumFromTo minBound maxBound) `shouldBe`+                ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]++    describe "hexCharString" $ do+        it "converts HexChar to a single character of Text" $ do+            let f = hexCharString :: HexChar -> Text+            map f (enumFromTo minBound maxBound) `shouldBe`+                [ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"+                , "A", "B", "C", "D", "E", "F"+                , "a", "b", "c", "d", "e", "f" ]