{-# LANGUAGE Safe #-}

-- |
-- Module      : Data.Char.Math.Internal
-- Description : A module to write math unicode alphanumerical characters.
-- Maintainer  : hapytexeu+gh@gmail.com
-- Stability   : experimental
-- Portability : POSIX
--
-- Internal functions for the Math module.
module Data.Char.Math.Internal
  ( _shiftC,
    _ordc,
    _baseUpperLower,
    _baseUpperLowerNum,
    _isValidInt,
    _withCondition,
    _dispatchLatinGreekDigit,
    _dispatchLatinGreekDigit',
  )
where

import Data.Char (chr, isAsciiUpper, isDigit, ord)
import Data.Char.Core (isAsciiAlpha, isGreek)

_shiftC :: Int -> Char -> Char
_shiftC :: Int -> Char -> Char
_shiftC = (Int -> Char
chr (Int -> Char) -> (Char -> Int) -> Char -> Char
forall b c a. (b -> c) -> (a -> b) -> a -> c
.) ((Char -> Int) -> Char -> Char)
-> (Int -> Char -> Int) -> Int -> Char -> Char
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((Int -> Int) -> (Char -> Int) -> Char -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Int
ord) ((Int -> Int) -> Char -> Int)
-> (Int -> Int -> Int) -> Int -> Char -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Int -> Int
forall a. Num a => a -> a -> a
(+)

_ordc :: Char -> Int -> Char
_ordc :: Char -> Int -> Char
_ordc = (Int -> Char
chr (Int -> Char) -> (Int -> Int) -> Int -> Char
forall b c a. (b -> c) -> (a -> b) -> a -> c
.) ((Int -> Int) -> Int -> Char)
-> (Char -> Int -> Int) -> Char -> Int -> Char
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Int -> Int
forall a. Num a => a -> a -> a
(+) (Int -> Int -> Int) -> (Char -> Int) -> Char -> Int -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Int
ord

_baseUpperLower :: Int -> Char -> Char
_baseUpperLower :: Int -> Char -> Char
_baseUpperLower Int
b Char
c
  | Char -> Bool
isAsciiUpper Char
c = Int -> Char
oc (Int
b Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
6)
  | Bool
otherwise = Int -> Char
oc Int
b
  where
    oc :: Int -> Char
oc = Char -> Int -> Char
_ordc Char
c

_baseUpperLowerNum :: Int -> Int -> Char -> Char
_baseUpperLowerNum :: Int -> Int -> Char -> Char
_baseUpperLowerNum Int
n Int
b Char
c
  | Char -> Bool
isDigit Char
c = Int -> Char
oc Int
n
  | Char -> Bool
isAsciiUpper Char
c = Int -> Char
oc (Int
b Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
6)
  | Bool
otherwise = Int -> Char
oc Int
b
  where
    oc :: Int -> Char
oc = Char -> Int -> Char
_ordc Char
c

_isValidInt :: Int -> Bool
_isValidInt :: Int -> Bool
_isValidInt Int
x = Int
x Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
10 Bool -> Bool -> Bool
&& Int
x Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
0

_withCondition :: (a -> Bool) -> (a -> b) -> a -> Maybe b
_withCondition :: forall a b. (a -> Bool) -> (a -> b) -> a -> Maybe b
_withCondition a -> Bool
p a -> b
f = a -> Maybe b
go
  where
    go :: a -> Maybe b
go a
x
      | a -> Bool
p a
x = b -> Maybe b
forall a. a -> Maybe a
Just (a -> b
f a
x)
      | Bool
otherwise = Maybe b
forall a. Maybe a
Nothing

-- | Unsafe dispatch to a conversion function according to the character
_dispatchLatinGreekDigit' ::
  -- | Latin
  (Char -> Char) ->
  -- | Greek
  (Char -> Char) ->
  -- | Digit
  (Char -> Char) ->
  -- | Character to transform
  Char ->
  Char
_dispatchLatinGreekDigit' :: (Char -> Char) -> (Char -> Char) -> (Char -> Char) -> Char -> Char
_dispatchLatinGreekDigit' Char -> Char
l Char -> Char
g Char -> Char
d Char
c
  | Char -> Bool
isDigit Char
c = Char -> Char
d Char
c
  | Char -> Bool
isAsciiAlpha Char
c = Char -> Char
l Char
c
  | Char -> Bool
isGreek Char
c = Char -> Char
g Char
c
  | Bool
otherwise = Char
c -- Keep the character unchanged

-- | Safe dispatch to a conversion function according to the character
_dispatchLatinGreekDigit ::
  -- | Latin
  (Char -> Char) ->
  -- | Greek
  (Char -> Char) ->
  -- | Digit
  (Char -> Char) ->
  -- | Character to transform
  Char ->
  Maybe Char
_dispatchLatinGreekDigit :: (Char -> Char)
-> (Char -> Char) -> (Char -> Char) -> Char -> Maybe Char
_dispatchLatinGreekDigit Char -> Char
l Char -> Char
g Char -> Char
d Char
c
  | Char -> Bool
isDigit Char
c = Char -> Maybe Char
forall a. a -> Maybe a
Just (Char -> Char
d Char
c)
  | Char -> Bool
isAsciiAlpha Char
c = Char -> Maybe Char
forall a. a -> Maybe a
Just (Char -> Char
l Char
c)
  | Char -> Bool
isGreek Char
c = Char -> Maybe Char
forall a. a -> Maybe a
Just (Char -> Char
g Char
c)
  | Bool
otherwise = Maybe Char
forall a. Maybe a
Nothing