{-# LINE 1 "Magic/Utils.hsc" #-}
{- -*- Mode: haskell; -*-
Haskell magic Interface
Copyright (C) 2005 John Goerzen <jgoerzen@complete.org>

This code is under a 3-clause BSD license; see COPYING for details.
-}

{- |
   Module     : Magic.Utils
   Copyright  : Copyright (C) 2005 John Goerzen
   License    : BSD

   Maintainer : John Goerzen,
   Maintainer : jgoerzen\@complete.org
   Stability  : provisional
   Portability: portable

Utils

Written by John Goerzen, jgoerzen\@complete.org
-}

module Magic.Utils (flaglist2int, fromMagicPtr, withMagicPtr, checkIntError,
                    throwErrorIfNull)
where

import Foreign
import Foreign.C.Error
import Foreign.C.String
import Foreign.ForeignPtr
import Magic.TypesLL
import Magic.Types
import Data.Bits
import Foreign.C.Types
import Magic.Data

flaglist2int :: [MagicFlag] -> CInt
flaglist2int :: [MagicFlag] -> CInt
flaglist2int [MagicFlag]
mfl =
    (CInt -> MagicFlag -> CInt) -> CInt -> [MagicFlag] -> CInt
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl (\CInt
c MagicFlag
f -> CInt
c CInt -> CInt -> CInt
forall a. Bits a => a -> a -> a
.|. (Int -> CInt
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> CInt) -> (MagicFlag -> Int) -> MagicFlag -> CInt
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MagicFlag -> Int
forall a. Enum a => a -> Int
fromEnum (MagicFlag -> CInt) -> MagicFlag -> CInt
forall a b. (a -> b) -> a -> b
$ MagicFlag
f)) CInt
0 [MagicFlag]
mfl

fromMagicPtr :: String -> IO (Ptr CMagic) -> IO Magic
fromMagicPtr :: String -> IO (Ptr CMagic) -> IO Magic
fromMagicPtr String
caller IO (Ptr CMagic)
action =
    do Ptr CMagic
ptr <- String -> IO (Ptr CMagic) -> IO (Ptr CMagic)
forall a. String -> IO (Ptr a) -> IO (Ptr a)
throwErrnoIfNull String
caller IO (Ptr CMagic)
action
       FinalizerPtr CMagic -> Ptr CMagic -> IO Magic
forall a. FinalizerPtr a -> Ptr a -> IO (ForeignPtr a)
newForeignPtr FinalizerPtr CMagic
magic_close Ptr CMagic
ptr

throwErrorIfNull :: String -> Magic -> IO (Ptr a) -> IO (Ptr a)
throwErrorIfNull :: forall a. String -> Magic -> IO (Ptr a) -> IO (Ptr a)
throwErrorIfNull String
caller Magic
m IO (Ptr a)
action =
    do Ptr a
res <- IO (Ptr a)
action
       if Ptr a
res Ptr a -> Ptr a -> Bool
forall a. Eq a => a -> a -> Bool
== Ptr a
forall a. Ptr a
nullPtr
          then String -> Magic -> IO (Ptr a)
forall a. String -> Magic -> IO a
throwError String
caller Magic
m
          else Ptr a -> IO (Ptr a)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Ptr a
res

withMagicPtr :: Magic -> (Ptr CMagic -> IO a) -> IO a
withMagicPtr :: forall a. Magic -> (Ptr CMagic -> IO a) -> IO a
withMagicPtr Magic
m = Magic -> (Ptr CMagic -> IO a) -> IO a
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr Magic
m

throwError :: String -> Magic -> IO a
throwError :: forall a. String -> Magic -> IO a
throwError String
caller Magic
m = Magic -> (Ptr CMagic -> IO a) -> IO a
forall a. Magic -> (Ptr CMagic -> IO a) -> IO a
withMagicPtr Magic
m (\Ptr CMagic
cmagic ->
               do CString
errormsg <- Ptr CMagic -> IO CString
magic_error Ptr CMagic
cmagic
                  if CString
errormsg CString -> CString -> Bool
forall a. Eq a => a -> a -> Bool
/= CString
forall a. Ptr a
nullPtr
                     then do String
em <- CString -> IO String
peekCString CString
errormsg
                             String -> IO a
forall a. String -> IO a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String -> IO a) -> String -> IO a
forall a b. (a -> b) -> a -> b
$ String
caller String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
": " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
em
                     else String -> IO a
forall a. String -> IO a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String -> IO a) -> String -> IO a
forall a b. (a -> b) -> a -> b
$ String
caller String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
": got error code but no error message"
                                     )

checkIntError :: String -> Magic -> IO CInt -> IO ()
checkIntError :: String -> Magic -> IO CInt -> IO ()
checkIntError String
caller Magic
m IO CInt
action = 
    do CInt
res <- IO CInt
action
       if CInt
res CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
== CInt
0
          then () -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
          else String -> Magic -> IO ()
forall a. String -> Magic -> IO a
throwError String
caller Magic
m


foreign import ccall unsafe "magic.h &magic_close"
  magic_close :: FunPtr (Ptr CMagic -> IO ())

foreign import ccall unsafe "magic.h magic_error"
  magic_error :: Ptr CMagic -> IO CString