{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE MagicHash #-}

module Country.Unexposed.Util
  ( mapTextArray
  , charToWord16
  , word16ToChar
  , word16ToInt
  , timesTwo
  , timesThree
  , half
  ) where

import Data.Bits (unsafeShiftL,unsafeShiftR)
import Data.Char (chr,ord)
import Data.Word (Word16)
import GHC.Exts (sizeofByteArray#)
import GHC.Int (Int(I#))

import qualified Data.Text.Array as TA


mapTextArray :: (Char -> Char) -> TA.Array -> TA.Array
mapTextArray :: (Char -> Char) -> Array -> Array
mapTextArray Char -> Char
f a :: Array
a@(TA.Array ByteArray#
inner) = (forall s. ST s (MArray s)) -> Array
TA.run ((forall s. ST s (MArray s)) -> Array)
-> (forall s. ST s (MArray s)) -> Array
forall a b. (a -> b) -> a -> b
$ do
  let len :: Int
len = Int -> Int
half (Int# -> Int
I# (ByteArray# -> Int#
sizeofByteArray# ByteArray#
inner))
  MArray s
m <- Int -> ST s (MArray s)
forall s. Int -> ST s (MArray s)
TA.new Int
len
  MArray s -> Int -> Array -> Int -> Int -> ST s ()
forall s. MArray s -> Int -> Array -> Int -> Int -> ST s ()
TA.copyI MArray s
m Int
0 Array
a Int
0 Int
len
  let go :: Int -> ST s ()
go !Int
ix = if Int
ix Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
len
        then do
          MArray s -> Int -> Word16 -> ST s ()
forall s. MArray s -> Int -> Word16 -> ST s ()
TA.unsafeWrite MArray s
m Int
ix (Char -> Word16
charToWord16 (Char -> Char
f (Word16 -> Char
word16ToChar (Array -> Int -> Word16
TA.unsafeIndex Array
a Int
ix))))
          Int -> ST s ()
go (Int
ix Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
        else () -> ST s ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
  Int -> ST s ()
go Int
0
  MArray s -> ST s (MArray s)
forall (m :: * -> *) a. Monad m => a -> m a
return MArray s
m
{-# INLINE mapTextArray #-}

word16ToChar :: Word16 -> Char
word16ToChar :: Word16 -> Char
word16ToChar = Int -> Char
chr (Int -> Char) -> (Word16 -> Int) -> Word16 -> Char
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word16 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral
{-# INLINE word16ToChar #-}

charToWord16 :: Char -> Word16
charToWord16 :: Char -> Word16
charToWord16 = Int -> Word16
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Word16) -> (Char -> Int) -> Char -> Word16
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Int
ord
{-# INLINE charToWord16 #-}

word16ToInt :: Word16 -> Int
word16ToInt :: Word16 -> Int
word16ToInt = Word16 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral
{-# INLINE word16ToInt #-}

timesTwo :: Int -> Int
timesTwo :: Int -> Int
timesTwo Int
x = Int -> Int -> Int
forall a. Bits a => a -> Int -> a
unsafeShiftL Int
x Int
1
{-# INLINE timesTwo #-}

timesThree :: Int -> Int
timesThree :: Int -> Int
timesThree Int
x = Int
x Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int -> Int
timesTwo Int
x
{-# INLINE timesThree #-}

half :: Int -> Int
half :: Int -> Int
half Int
x = Int -> Int -> Int
forall a. Bits a => a -> Int -> a
unsafeShiftR Int
x Int
1
{-# INLINE half #-}