{-# LANGUAGE CPP, Safe #-}
module Data.Char.Small (
toSub, toSup
, fromSubSup
, asSub, asSub', asSubPlus
, asSup, asSup', asSupPlus
, ratioToUnicode, ratioToUnicode', ratioPartsToUnicode, ratioPartsToUnicode'
, unicodeToRatio, unicodeToRatioParts
) where
import Data.Bits((.&.), (.|.))
import Data.Char(chr, isDigit, ord)
import Data.Char.Core(PlusStyle(WithPlus, WithoutPlus), positionalNumberSystem10)
import Data.Default(Default(def))
import Data.Ratio(Ratio, denominator, numerator, (%))
#if __GLASGOW_HASKELL__ < 803
import Data.Semigroup((<>))
#endif
import qualified Data.Text as T
import Data.Text(Text, cons, snoc, singleton, unpack)
import Text.Read(readMaybe)
toSup
:: Char
-> Maybe Char
toSup :: Char -> Maybe Char
toSup Char
'i' = forall a. a -> Maybe a
Just Char
'\x2071'
toSup Char
'+' = forall a. a -> Maybe a
Just Char
'\x207a'
toSup Char
'-' = forall a. a -> Maybe a
Just Char
'\x207b'
toSup Char
'\x2212' = forall a. a -> Maybe a
Just Char
'\x207b'
toSup Char
'=' = forall a. a -> Maybe a
Just Char
'\x207c'
toSup Char
'(' = forall a. a -> Maybe a
Just Char
'\x207d'
toSup Char
')' = forall a. a -> Maybe a
Just Char
'\x207e'
toSup Char
'n' = forall a. a -> Maybe a
Just Char
'\x207f'
toSup Char
c | Char -> Bool
isDigit Char
c = forall a. a -> Maybe a
Just (Int -> Char
_digitToSub (Char -> Int
ord Char
c forall a. Num a => a -> a -> a
- Char -> Int
ord Char
'0'))
| Bool
otherwise = forall a. Maybe a
Nothing
toSub
:: Char
-> Maybe Char
toSub :: Char -> Maybe Char
toSub Char
'+' = forall a. a -> Maybe a
Just Char
'\x208a'
toSub Char
'-' = forall a. a -> Maybe a
Just Char
'\x208b'
toSub Char
'\x2212' = forall a. a -> Maybe a
Just Char
'\x208b'
toSub Char
'=' = forall a. a -> Maybe a
Just Char
'\x208c'
toSub Char
'(' = forall a. a -> Maybe a
Just Char
'\x208d'
toSub Char
')' = forall a. a -> Maybe a
Just Char
'\x208e'
toSub Char
'a' = forall a. a -> Maybe a
Just Char
'\x2090'
toSub Char
'e' = forall a. a -> Maybe a
Just Char
'\x2091'
toSub Char
'o' = forall a. a -> Maybe a
Just Char
'\x2092'
toSub Char
'x' = forall a. a -> Maybe a
Just Char
'\x2093'
toSub Char
'\x259' = forall a. a -> Maybe a
Just Char
'\x2094'
toSub Char
'h' = forall a. a -> Maybe a
Just Char
'\x2095'
toSub Char
'k' = forall a. a -> Maybe a
Just Char
'\x2096'
toSub Char
'l' = forall a. a -> Maybe a
Just Char
'\x2097'
toSub Char
'm' = forall a. a -> Maybe a
Just Char
'\x2098'
toSub Char
'n' = forall a. a -> Maybe a
Just Char
'\x2099'
toSub Char
'p' = forall a. a -> Maybe a
Just Char
'\x209a'
toSub Char
's' = forall a. a -> Maybe a
Just Char
'\x209b'
toSub Char
't' = forall a. a -> Maybe a
Just Char
'\x209c'
toSub Char
c | Char -> Bool
isDigit Char
c = forall a. a -> Maybe a
Just (Int -> Char
_digitToSub (Char -> Int
ord Char
c forall a. Num a => a -> a -> a
- Char -> Int
ord Char
'0'))
| Bool
otherwise = forall a. Maybe a
Nothing
_fromSubSup :: Int -> Char
_fromSubSup :: Int -> Char
_fromSubSup Int
0xa = Char
'+'
_fromSubSup Int
0xb = Char
'-'
_fromSubSup Int
0xc = Char
'='
_fromSubSup Int
0xd = Char
'('
_fromSubSup Int
0xe = Char
')'
_fromSubSup Int
_ = forall a. HasCallStack => [Char] -> a
error [Char]
"Should not happen!"
fromSubSup
:: Char
-> Char
fromSubSup :: Char -> Char
fromSubSup Char
'\x2070' = Char
'0'
fromSubSup Char
'\xb2' = Char
'2'
fromSubSup Char
'\xb3' = Char
'3'
fromSubSup Char
'\xb9' = Char
'1'
fromSubSup Char
'\x2071' = Char
'i'
fromSubSup Char
'\x207f' = Char
'n'
fromSubSup Char
'\x2090' = Char
'a'
fromSubSup Char
'\x2091' = Char
'e'
fromSubSup Char
'\x2092' = Char
'o'
fromSubSup Char
'\x2093' = Char
'x'
fromSubSup Char
'\x2094' = Char
'\x259'
fromSubSup Char
'\x2095' = Char
'h'
fromSubSup Char
'\x2096' = Char
'k'
fromSubSup Char
'\x2097' = Char
'l'
fromSubSup Char
'\x2098' = Char
'm'
fromSubSup Char
'\x2099' = Char
'n'
fromSubSup Char
'\x209a' = Char
'p'
fromSubSup Char
'\x209b' = Char
's'
fromSubSup Char
'\x209c' = Char
't'
fromSubSup Char
x
| Char
'\x207a' forall a. Ord a => a -> a -> Bool
<= Char
x Bool -> Bool -> Bool
&& Char
xforall a. Ord a => a -> a -> Bool
<= Char
'\x208e' Bool -> Bool -> Bool
&& Int
0x0a forall a. Ord a => a -> a -> Bool
<= Int
m Bool -> Bool -> Bool
&& Int
m forall a. Ord a => a -> a -> Bool
<= Int
0x0e = Int -> Char
_fromSubSup Int
m
| Char
'\x2074' forall a. Ord a => a -> a -> Bool
<= Char
x Bool -> Bool -> Bool
&& Char
x forall a. Ord a => a -> a -> Bool
<= Char
'\x2089' = Int -> Char
chr (Int
0x30 forall a. Bits a => a -> a -> a
.|. (Char -> Int
ord Char
x forall a. Bits a => a -> a -> a
.&. Int
0xf))
| Bool
otherwise = Char
x
where m :: Int
m = Char -> Int
ord Char
x forall a. Bits a => a -> a -> a
.&. Int
0xf
_value :: Integral i => (Int -> Char) -> i -> Text
_value :: forall i. Integral i => (Int -> Char) -> i -> Text
_value Int -> Char
f = i -> Text
go
where f' :: i -> Char
f' = Int -> Char
f forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral
go :: i -> Text
go i
n | i
n forall a. Ord a => a -> a -> Bool
<= i
9 = Char -> Text
singleton (i -> Char
f' i
n)
| Bool
otherwise = Text -> Char -> Text
snoc (i -> Text
go i
q) (i -> Char
f' i
r)
where (i
q,i
r) = forall a. Integral a => a -> a -> (a, a)
quotRem i
n i
10
_prefixSign :: Integral i => Char -> (Int -> Char) -> i -> Text
_prefixSign :: forall i. Integral i => Char -> (Int -> Char) -> i -> Text
_prefixSign Char
c Int -> Char
f i
v
| i
v forall a. Ord a => a -> a -> Bool
< i
0 = Char -> Text -> Text
cons Char
c (i -> Text
f' (-i
v))
| Bool
otherwise = i -> Text
f' i
v
where f' :: i -> Text
f' = forall i. Integral i => (Int -> Char) -> i -> Text
_value Int -> Char
f
_prefixSignPlus :: Integral i => Char -> Char -> (Int -> Char) -> i -> Text
_prefixSignPlus :: forall i. Integral i => Char -> Char -> (Int -> Char) -> i -> Text
_prefixSignPlus Char
cp Char
cn Int -> Char
f i
v
| i
v forall a. Ord a => a -> a -> Bool
< i
0 = Char -> i -> Text
c' Char
cn (-i
v)
| Bool
otherwise = Char -> i -> Text
c' Char
cp i
v
where c' :: Char -> i -> Text
c' = (forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall i. Integral i => (Int -> Char) -> i -> Text
_value Int -> Char
f) forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Text -> Text
cons
ratioPartsToUnicode :: (Integral i, Integral j)
=> PlusStyle
-> i
-> j
-> Text
ratioPartsToUnicode :: forall i j. (Integral i, Integral j) => PlusStyle -> i -> j -> Text
ratioPartsToUnicode PlusStyle
ps i
num j
den
| j
den forall a. Ord a => a -> a -> Bool
< j
0 = forall i j. (Integral i, Integral j) => PlusStyle -> i -> j -> Text
ratioPartsToUnicode PlusStyle
ps (-i
num) (-j
den)
| Bool
otherwise = forall i. Integral i => PlusStyle -> i -> Text
asSup PlusStyle
ps i
num forall a. Semigroup a => a -> a -> a
<> Char -> Text -> Text
cons Char
'\x2044' (forall i. Integral i => i -> Text
asSub' j
den)
ratioPartsToUnicode' :: (Integral i, Integral j)
=> i
-> j
-> Text
ratioPartsToUnicode' :: forall i j. (Integral i, Integral j) => i -> j -> Text
ratioPartsToUnicode' = forall i j. (Integral i, Integral j) => PlusStyle -> i -> j -> Text
ratioPartsToUnicode forall a. Default a => a
def
unicodeToRatioParts :: (Read i, Read j)
=> Text
-> Maybe (i, j)
unicodeToRatioParts :: forall i j. (Read i, Read j) => Text -> Maybe (i, j)
unicodeToRatioParts Text
t = (,) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall i. Read i => [Char] -> Maybe i
_parseInt (Text -> [Char]
unpack Text
n) forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall i. Read i => [Char] -> Maybe i
_parseInt (forall a. Int -> [a] -> [a]
drop Int
1 (Text -> [Char]
unpack Text
d))
where ~(Text
n, Text
d) = (Char -> Bool) -> Text -> (Text, Text)
T.break Char -> Bool
_isFrac ((Char -> Char) -> Text -> Text
T.map Char -> Char
fromSubSup Text
t)
unicodeToRatio :: (Integral i, Read i)
=> Text
-> Maybe (Ratio i)
unicodeToRatio :: forall i. (Integral i, Read i) => Text -> Maybe (Ratio i)
unicodeToRatio = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry forall a. Integral a => a -> a -> Ratio a
(%)) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall i j. (Read i, Read j) => Text -> Maybe (i, j)
unicodeToRatioParts
ratioToUnicode :: Integral i
=> PlusStyle
-> Ratio i
-> Text
ratioToUnicode :: forall i. Integral i => PlusStyle -> Ratio i -> Text
ratioToUnicode PlusStyle
ps Ratio i
dn = forall i j. (Integral i, Integral j) => PlusStyle -> i -> j -> Text
ratioPartsToUnicode PlusStyle
ps (forall a. Ratio a -> a
numerator Ratio i
dn) (forall a. Ratio a -> a
denominator Ratio i
dn)
ratioToUnicode' :: Integral i
=> Ratio i
-> Text
ratioToUnicode' :: forall i. Integral i => Ratio i -> Text
ratioToUnicode' = forall i. Integral i => PlusStyle -> Ratio i -> Text
ratioToUnicode forall a. Default a => a
def
asSup :: Integral i
=> PlusStyle
-> i
-> Text
asSup :: forall i. Integral i => PlusStyle -> i -> Text
asSup = forall i.
Integral i =>
(Int -> Char) -> Char -> Char -> PlusStyle -> i -> Text
positionalNumberSystem10 Int -> Char
_digitToSup Char
'\x207a' Char
'\x207b'
asSup' :: Integral i
=> i
-> Text
asSup' :: forall i. Integral i => i -> Text
asSup' = forall i. Integral i => PlusStyle -> i -> Text
asSup PlusStyle
WithoutPlus
asSupPlus :: Integral i
=> i
-> Text
asSupPlus :: forall i. Integral i => i -> Text
asSupPlus = forall i. Integral i => PlusStyle -> i -> Text
asSup PlusStyle
WithPlus
asSub :: Integral i
=> PlusStyle
-> i
-> Text
asSub :: forall i. Integral i => PlusStyle -> i -> Text
asSub = forall i.
Integral i =>
(Int -> Char) -> Char -> Char -> PlusStyle -> i -> Text
positionalNumberSystem10 Int -> Char
_digitToSub Char
'\x208a' Char
'\x208b'
asSub' :: Integral i
=> i
-> Text
asSub' :: forall i. Integral i => i -> Text
asSub' = forall i. Integral i => PlusStyle -> i -> Text
asSub PlusStyle
WithoutPlus
asSubPlus :: Integral i
=> i
-> Text
asSubPlus :: forall i. Integral i => i -> Text
asSubPlus = forall i. Integral i => PlusStyle -> i -> Text
asSub PlusStyle
WithPlus
_digitToSub :: Int -> Char
_digitToSub :: Int -> Char
_digitToSub = Int -> Char
chr forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int
8320forall a. Num a => a -> a -> a
+)
_digitToSup :: Int -> Char
_digitToSup :: Int -> Char
_digitToSup Int
0 = Char
'\x2070'
_digitToSup Int
1 = Char
'\xb9'
_digitToSup Int
n | Int
n forall a. Ord a => a -> a -> Bool
<= Int
3 = Int -> Char
chr (Int
176forall a. Num a => a -> a -> a
+Int
n)
| Bool
otherwise = Int -> Char
chr (Int
8304forall a. Num a => a -> a -> a
+Int
n)
_parseInt :: Read i => String -> Maybe i
_parseInt :: forall i. Read i => [Char] -> Maybe i
_parseInt (Char
'+':[Char]
d) = forall i. Read i => [Char] -> Maybe i
readMaybe [Char]
d
_parseInt [Char]
d = forall i. Read i => [Char] -> Maybe i
readMaybe [Char]
d
_isFrac :: Char -> Bool
_isFrac :: Char -> Bool
_isFrac Char
'/' = Bool
True
_isFrac Char
'\x2044' = Bool
True
_isFrac Char
_ = Bool
False