module Utils where
import Prelude ( ($)
, Num, (+), (*), ()
, Enum, toEnum, fromEnum
, Integral, fromIntegral, undefined
)
#if __GLASGOW_HASKELL__ < 700
import Prelude ( fromInteger )
#endif
import Control.Monad ( Monad, return, (>>=), (>>) )
import Foreign.Ptr ( Ptr )
import Foreign.ForeignPtr ( withForeignPtr )
import Foreign.Storable ( Storable, peek, sizeOf )
import Foreign.Marshal.Alloc ( alloca )
import Foreign.Marshal.Utils ( copyBytes )
import Data.Bool ( Bool, otherwise )
import Data.Ord ( Ord, (>) )
import Data.Bits ( Bits, shiftL, shiftR, bitSize, (.&.) )
import Data.Int ( Int )
import Data.Maybe ( Maybe(Nothing, Just) )
import System.IO ( IO )
import GHC.ForeignPtr ( mallocPlainForeignPtrBytes )
import Data.Vector ( Vector )
import qualified Data.Vector as V ( null, unsafeHead, unsafeTail )
import qualified Data.Vector.Storable as VS ( Vector, empty, null
, unsafeFromForeignPtr0
, unsafeToForeignPtr0
)
import qualified Data.Vector.Generic as VG ( Vector, mapM, convert )
import Data.Function.Unicode ( (∘) )
import Data.Ord.Unicode ( (≥), (≤) )
import Data.Bool.Unicode ( (∧) )
bits ∷ (Bits α, Num α) ⇒ Int → Int → α → α
bits s e b = ((1 `shiftL` (e s + 1)) 1) .&. (b `shiftR` s)
between ∷ Ord α ⇒ α → α → α → Bool
between n b e = n ≥ b ∧ n ≤ e
genToEnum ∷ (Integral i, Enum e) ⇒ i → e
genToEnum = toEnum ∘ fromIntegral
genFromEnum ∷ (Integral i, Enum e) ⇒ e → i
genFromEnum = fromIntegral ∘ fromEnum
mapPeekArray ∷ (Storable a, VG.Vector v a, VG.Vector v b) ⇒ (a → IO b) → Int → Ptr a → IO (v b)
mapPeekArray f n a = peekVector n a >>= VG.mapM f ∘ VG.convert
peekVector ∷ forall a. (Storable a) ⇒ Int → Ptr a → IO (VS.Vector a)
peekVector size ptr
| size ≤ 0 = return VS.empty
| otherwise = do
let n = (size * sizeOf (undefined ∷ a))
fp ← mallocPlainForeignPtrBytes n
withForeignPtr fp $ \p → copyBytes p ptr n
return $ VS.unsafeFromForeignPtr0 fp size
pokeVector ∷ forall a. Storable a ⇒ Ptr a → VS.Vector a → IO ()
pokeVector ptr v | VS.null v = return ()
| otherwise = withForeignPtr fp $ \p →
copyBytes ptr p (size * sizeOf (undefined ∷ a))
where
(fp, size) = VS.unsafeToForeignPtr0 v
allocaPeek ∷ Storable α ⇒ (Ptr α → IO ()) → IO α
allocaPeek f = alloca $ \ptr → f ptr >> peek ptr
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 0
where
shftR = bitSize abcd bitsInDigit
go !shftL | shftL > shftR = []
| otherwise = let !d = (abcd `shiftL` shftL) `shiftR` shftR
in d : go (shftL + bitsInDigit)
uncons ∷ Vector α → Maybe (α, Vector α)
uncons v | V.null v = Nothing
| otherwise = Just (V.unsafeHead v, V.unsafeTail v)