{-# LANGUAGE MagicHash                  #-}
{-# LANGUAGE BangPatterns               #-}
module Basement.Types.Char7
    ( Char7(..)
    , toChar
    , fromCharMask
    , fromChar
    , fromByteMask
    , fromByte
    -- * individual ASCII Characters
    , c7_LF
    , c7_CR
    , c7_minus
    , c7_a
    , c7_A
    , c7_z
    , c7_Z
    , c7_0
    , c7_1
    , c7_2
    , c7_3
    , c7_4
    , c7_5
    , c7_6
    , c7_7
    , c7_8
    , c7_9
    -- * Upper / Lower With ASCII
    , c7Upper
    , c7Lower
    ) where

import GHC.Prim
import GHC.Word
import GHC.Types
import Data.Bits
import Data.Maybe
import Basement.Compat.Base
import Basement.Compat.Primitive

-- | ASCII value between 0x0 and 0x7f
newtype Char7 = Char7 { Char7 -> Word8
toByte :: Word8 }
    deriving (Int -> Char7 -> ShowS
[Char7] -> ShowS
Char7 -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Char7] -> ShowS
$cshowList :: [Char7] -> ShowS
show :: Char7 -> String
$cshow :: Char7 -> String
showsPrec :: Int -> Char7 -> ShowS
$cshowsPrec :: Int -> Char7 -> ShowS
Show,Char7 -> Char7 -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Char7 -> Char7 -> Bool
$c/= :: Char7 -> Char7 -> Bool
== :: Char7 -> Char7 -> Bool
$c== :: Char7 -> Char7 -> Bool
Eq,Eq Char7
Char7 -> Char7 -> Bool
Char7 -> Char7 -> Ordering
Char7 -> Char7 -> Char7
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Char7 -> Char7 -> Char7
$cmin :: Char7 -> Char7 -> Char7
max :: Char7 -> Char7 -> Char7
$cmax :: Char7 -> Char7 -> Char7
>= :: Char7 -> Char7 -> Bool
$c>= :: Char7 -> Char7 -> Bool
> :: Char7 -> Char7 -> Bool
$c> :: Char7 -> Char7 -> Bool
<= :: Char7 -> Char7 -> Bool
$c<= :: Char7 -> Char7 -> Bool
< :: Char7 -> Char7 -> Bool
$c< :: Char7 -> Char7 -> Bool
compare :: Char7 -> Char7 -> Ordering
$ccompare :: Char7 -> Char7 -> Ordering
Ord,Typeable)

-- | Convert a 'Char7' to a unicode code point 'Char'
toChar :: Char7 -> Char
toChar :: Char7 -> Char
toChar !(Char7 (W8# Word8#
w)) = Char# -> Char
C# (Int# -> Char#
chr# (Word# -> Int#
word2Int# (Word8# -> Word#
word8ToWord# Word8#
w)))

-- | Try to convert a 'Char' to a 'Char7'
-- 
-- If the code point is non ascii, then Nothing is returned.
fromChar :: Char -> Maybe Char7
fromChar :: Char -> Maybe Char7
fromChar !(C# Char#
c#)
    | Int# -> Bool
bool# (Char# -> Char# -> Int#
ltChar# Char#
c# (Int# -> Char#
chr# Int#
0x80#)) = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ Word8 -> Char7
Char7 forall a b. (a -> b) -> a -> b
$ Word8# -> Word8
W8# (Word# -> Word8#
wordToWord8# (Int# -> Word#
int2Word# (Char# -> Int#
ord# Char#
c#)))
    | Bool
otherwise                       = forall a. Maybe a
Nothing

-- | Try to convert 'Word8' to a 'Char7'
--
-- If the byte got higher bit set, then Nothing is returned.
fromByte :: Word8 -> Maybe Char7
fromByte :: Word8 -> Maybe Char7
fromByte !Word8
w
    | (Word8
w forall a. Bits a => a -> a -> a
.&. Word8
0x80) forall a. Eq a => a -> a -> Bool
== Word8
0 = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ Word8 -> Char7
Char7 Word8
w
    | Bool
otherwise         = forall a. Maybe a
Nothing

-- | Convert a 'Char' to a 'Char7' ignoring all higher bits
fromCharMask :: Char -> Char7
fromCharMask :: Char -> Char7
fromCharMask !(C# Char#
c#) = Word8 -> Char7
Char7 forall a b. (a -> b) -> a -> b
$ Word8# -> Word8
W8# (Word# -> Word8#
wordToWord8# (Word# -> Word# -> Word#
and# (Int# -> Word#
int2Word# (Char# -> Int#
ord# Char#
c#)) Word#
0x7f##))

-- | Convert a 'Byte' to a 'Char7' ignoring the higher bit
fromByteMask :: Word8 -> Char7
fromByteMask :: Word8 -> Char7
fromByteMask !Word8
w = Word8 -> Char7
Char7 (Word8
w forall a. Bits a => a -> a -> a
.&. Word8
0x7f)

c7_LF :: Char7
c7_LF :: Char7
c7_LF = Word8 -> Char7
Char7 Word8
0xa

c7_CR :: Char7
c7_CR :: Char7
c7_CR = Word8 -> Char7
Char7 Word8
0xd

c7_minus :: Char7
c7_minus :: Char7
c7_minus = Word8 -> Char7
Char7 Word8
0x2d

c7_a :: Char7
c7_a :: Char7
c7_a = Word8 -> Char7
Char7 Word8
0x61

c7_A :: Char7
c7_A :: Char7
c7_A = Word8 -> Char7
Char7 Word8
0x41

c7_z :: Char7
c7_z :: Char7
c7_z = Word8 -> Char7
Char7 Word8
0x7a

c7_Z :: Char7
c7_Z :: Char7
c7_Z = Word8 -> Char7
Char7 Word8
0x5a

c7_0, c7_1, c7_2, c7_3, c7_4, c7_5, c7_6, c7_7, c7_8, c7_9 :: Char7
c7_0 :: Char7
c7_0 = Word8 -> Char7
Char7 Word8
0x30
c7_1 :: Char7
c7_1 = Word8 -> Char7
Char7 Word8
0x31
c7_2 :: Char7
c7_2 = Word8 -> Char7
Char7 Word8
0x32
c7_3 :: Char7
c7_3 = Word8 -> Char7
Char7 Word8
0x33
c7_4 :: Char7
c7_4 = Word8 -> Char7
Char7 Word8
0x34
c7_5 :: Char7
c7_5 = Word8 -> Char7
Char7 Word8
0x35
c7_6 :: Char7
c7_6 = Word8 -> Char7
Char7 Word8
0x36
c7_7 :: Char7
c7_7 = Word8 -> Char7
Char7 Word8
0x37
c7_8 :: Char7
c7_8 = Word8 -> Char7
Char7 Word8
0x38
c7_9 :: Char7
c7_9 = Word8 -> Char7
Char7 Word8
0x39

c7Lower :: Char7 -> Char7
c7Lower :: Char7 -> Char7
c7Lower c :: Char7
c@(Char7 Word8
w)
    | Char7
c forall a. Ord a => a -> a -> Bool
<  Char7
c7_A = Char7
c
    | Char7
c forall a. Ord a => a -> a -> Bool
<= Char7
c7_Z = Word8 -> Char7
Char7 (Word8
w forall a. Bits a => a -> a -> a
.|. Word8
0x20)
    | Bool
otherwise = Char7
c

c7Upper :: Char7 -> Char7
c7Upper :: Char7 -> Char7
c7Upper c :: Char7
c@(Char7 Word8
w)
    | Char7
c forall a. Ord a => a -> a -> Bool
<  Char7
c7_a = Char7
c
    | Char7
c forall a. Ord a => a -> a -> Bool
<= Char7
c7_z = Word8 -> Char7
Char7 (Word8
w forall a. Bits a => a -> a -> a
.&. Word8
0xdf)
    | Bool
otherwise = Char7
c