{-|
Module      : Hapstone.Internal.Util
Description : Utility functions
Copyright   : (c) Inokentiy Babushkin, 2016
License     : BSD3
Maintainer  : Inokentiy Babushkin <inokentiy.babushkin@googlemail.com>
Stability   : experimental

This module contains various utility functions used to perform common actions
when sanitizing data passed to and from the C functions exposed by capstone.
-}
module Hapstone.Internal.Util where

import Foreign
import Foreign.C.String
import Foreign.C.Types
import Foreign.Ptr

import System.IO.Unsafe (unsafePerformIO)

-- | peeking with number conversion
peekNum :: (Integral a, Num b, Storable a) => Ptr a -> IO b
peekNum :: Ptr a -> IO b
peekNum Ptr a
a = a -> b
forall a b. (Integral a, Num b) => a -> b
fromIntegral (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Ptr a -> IO a
forall a. Storable a => Ptr a -> IO a
peek Ptr a
a

-- | number conversion and enum casting
getCULongFromEnum :: Enum e => e -> CULong
getCULongFromEnum :: e -> CULong
getCULongFromEnum = Int -> CULong
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> CULong) -> (e -> Int) -> e -> CULong
forall b c a. (b -> c) -> (a -> b) -> a -> c
. e -> Int
forall a. Enum a => a -> Int
fromEnum

-- | cast a pointer before using with
withCast :: Storable a => a -> (Ptr b -> IO c) -> IO c
withCast :: a -> (Ptr b -> IO c) -> IO c
withCast a
a Ptr b -> IO c
f = a -> (Ptr a -> IO c) -> IO c
forall a b. Storable a => a -> (Ptr a -> IO b) -> IO b
with a
a (Ptr b -> IO c
f (Ptr b -> IO c) -> (Ptr a -> Ptr b) -> Ptr a -> IO c
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Ptr a -> Ptr b
forall a b. Ptr a -> Ptr b
castPtr)

-- | bitwise OR a list of symbolic constants from an enumeration
combine :: (Enum e, Num n, Bits n) => [e] -> n
combine :: [e] -> n
combine = (e -> n -> n) -> n -> [e] -> n
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (n -> n -> n
forall a. Bits a => a -> a -> a
(.|.) (n -> n -> n) -> (e -> n) -> e -> n -> n
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> n
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> n) -> (e -> Int) -> e -> n
forall b c a. (b -> c) -> (a -> b) -> a -> c
. e -> Int
forall a. Enum a => a -> Int
fromEnum) n
0

-- | lookup a possibly NULL-valued char *
stringLookup :: CString -> Maybe String
stringLookup :: CString -> Maybe String
stringLookup CString
s
    | CString
s CString -> CString -> Bool
forall a. Eq a => a -> a -> Bool
== CString
forall a. Ptr a
nullPtr = Maybe String
forall a. Maybe a
Nothing
    | Bool
otherwise = String -> Maybe String
forall a. a -> Maybe a
Just (String -> Maybe String)
-> (IO String -> String) -> IO String -> Maybe String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IO String -> String
forall a. IO a -> a
unsafePerformIO (IO String -> Maybe String) -> IO String -> Maybe String
forall a b. (a -> b) -> a -> b
$ CString -> IO String
peekCString CString
s

-- | convert between Maybe and zero/nonzero Num
fromZero :: (Eq a, Num a) => a -> Maybe a
fromZero :: a -> Maybe a
fromZero a
0 = Maybe a
forall a. Maybe a
Nothing
fromZero a
v = a -> Maybe a
forall a. a -> Maybe a
Just a
v

-- | peek if given pointer is not NULL
peekFunMaybe :: Storable a => (Ptr a -> IO a) -> Ptr a -> IO (Maybe a)
peekFunMaybe :: (Ptr a -> IO a) -> Ptr a -> IO (Maybe a)
peekFunMaybe Ptr a -> IO a
peekFun Ptr a
ptr
    | Ptr a
ptr Ptr a -> Ptr a -> Bool
forall a. Eq a => a -> a -> Bool
== Ptr a
forall a. Ptr a
nullPtr = Maybe a -> IO (Maybe a)
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe a
forall a. Maybe a
Nothing
    | Bool
otherwise = a -> Maybe a
forall a. a -> Maybe a
Just (a -> Maybe a) -> IO a -> IO (Maybe a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Ptr a -> IO a
peekFun Ptr a
ptr