module Utils where
import Prelude ( (+), (), (^)
, Enum, toEnum, fromEnum
, Integral, fromIntegral
)
#if __GLASGOW_HASKELL__ < 700
import Prelude ( fromInteger )
import Control.Monad ( (>>) )
#endif
import Control.Monad ( Monad, (>>=), mapM )
import Foreign.Ptr ( Ptr )
import Foreign.Storable ( Storable, )
import Foreign.Marshal.Array ( peekArray )
import Data.Bool ( Bool, otherwise )
import Data.Ord ( Ord, (<) )
import Data.Bits ( Bits, shiftL, shiftR, bitSize, (.&.) )
import Data.Int ( Int )
import Data.Functor ( Functor, (<$))
import System.IO ( IO )
import Data.Function.Unicode ( (∘) )
import Data.Ord.Unicode ( (≥), (≤) )
import Data.Bool.Unicode ( (∧) )
bits ∷ Bits α ⇒ Int → Int → α → α
bits s e b = (2 ^ (e s + 1) 1) .&. (b `shiftR` s)
between ∷ Ord α ⇒ α → α → α → Bool
between n b e = n ≥ b ∧ n ≤ e
void ∷ Functor m ⇒ m α → m ()
void = (() <$)
genToEnum ∷ (Integral i, Enum e) ⇒ i → e
genToEnum = toEnum ∘ fromIntegral
genFromEnum ∷ (Integral i, Enum e) ⇒ e → i
genFromEnum = fromIntegral ∘ fromEnum
mapPeekArray ∷ Storable α ⇒ (α → IO β) → Int → Ptr α → IO [β]
mapPeekArray f n a = peekArray n a >>= mapM f
ifM ∷ Monad m ⇒ m Bool → m α → m α → m α
ifM cM tM eM = cM >>= \c → if c then tM else eM
decodeBCD ∷ Bits α ⇒ Int → α → [α]
decodeBCD bitsInDigit abcd = go shftR []
where
shftR = bitSize abcd bitsInDigit
go shftL ds | shftL < 0 = ds
| otherwise = let !d = (abcd `shiftL` shftL) `shiftR` shftR
in go (shftL bitsInDigit) (d : ds)