-- GENERATED by C->Haskell Compiler, version 0.23.1 Snowbounder, 31 Oct 2014 (Haskell)
-- Edit the ORIGNAL .chs file instead!


{-# LINE 1 "./Cudd/File.chs" #-}
{-# LANGUAGE ForeignFunctionInterface, CPP, FlexibleContexts, RankNTypes #-}

module Cudd.File (
    DddmpVarInfoType(..),
    DddmpMode(..),
    DddmpVarMatchType(..),
    cuddBddStore,
    cuddBddLoad
    ) where

import Foreign.Storable
import Foreign.Ptr
import Foreign.C.Types
import Foreign.C.String
import Foreign.ForeignPtr
import Foreign.Marshal.Array
import Control.Monad

import Cudd.Cudd
import Cudd.C



data DddmpVarInfoType = DddmpVarids
                      | DddmpVarpermids
                      | DddmpVarauxids
                      | DddmpVarnames
                      | DddmpVardefault
  deriving (Enum)

{-# LINE 24 "./Cudd/File.chs" #-}


--Hard coded values are needed because of limitations of c2hs

data DddmpMode = DddmpModeText
               | DddmpModeBinary
               | DddmpModeDefault
instance Enum DddmpMode where
  succ DddmpModeText = DddmpModeBinary
  succ DddmpModeBinary = DddmpModeDefault
  succ DddmpModeDefault = error "DddmpMode.succ: DddmpModeDefault has no successor"

  pred DddmpModeBinary = DddmpModeText
  pred DddmpModeDefault = DddmpModeBinary
  pred DddmpModeText = error "DddmpMode.pred: DddmpModeText has no predecessor"

  enumFromTo from to = go from
    where
      end = fromEnum to
      go v = case compare (fromEnum v) end of
                 LT -> v : go (succ v)
                 EQ -> [v]
                 GT -> []

  enumFrom from = enumFromTo from DddmpModeDefault

  fromEnum DddmpModeText = 65
  fromEnum DddmpModeBinary = 66
  fromEnum DddmpModeDefault = 68

  toEnum 65 = DddmpModeText
  toEnum 66 = DddmpModeBinary
  toEnum 68 = DddmpModeDefault
  toEnum unmatched = error ("DddmpMode.toEnum: Cannot match " ++ show unmatched)

{-# LINE 36 "./Cudd/File.chs" #-}


foreign import ccall safe "Dddmp_cuddBddStore"
    c_dddmpBddStore :: Ptr CDDManager -> CString -> Ptr CDDNode -> Ptr CString -> Ptr CInt -> CInt -> CInt -> CString -> Ptr CFile -> IO CInt

nullOnEmpty :: Storable a => [a] -> (Ptr a -> IO b) -> IO b
nullOnEmpty lst act = 
    case lst of
        [] -> act nullPtr
        _  -> withArray lst act

cuddBddStore :: DDManager -> String -> DDNode -> [Int] -> DddmpMode -> DddmpVarInfoType -> String -> IO Bool
cuddBddStore (DDManager m) name (DDNode node) auxids mode varinfo fname = liftM (/= 0) $ 
    withCString name                      $ \pname ->
    withForeignPtr node                   $ \dp ->
    nullOnEmpty (map fromIntegral auxids) $ \pauxids -> 
    withCString fname                     $ \pfname -> 
        c_dddmpBddStore m pname dp nullPtr pauxids (fromIntegral $ fromEnum mode) (fromIntegral $ fromEnum varinfo) pfname nullPtr

data DddmpVarMatchType = DddmpVarMatchids
                       | DddmpVarMatchpermids
                       | DddmpVarMatchauxids
                       | DddmpVarMatchnames
                       | DddmpVarComposeids
  deriving (Enum)

{-# LINE 55 "./Cudd/File.chs" #-}


foreign import ccall safe "Dddmp_cuddBddLoad_s"
    c_dddmpBddLoad :: Ptr CDDManager -> CInt -> Ptr CString -> Ptr CInt -> Ptr CInt -> CInt -> CString -> Ptr CFile -> IO (Ptr CDDNode)

cuddBddLoad :: DDManager -> DddmpVarMatchType -> [Int] -> [Int] -> DddmpMode -> String -> IO (Maybe DDNode)
cuddBddLoad (DDManager m) matchtype auxids composeids mode fname = 
    nullOnEmpty (map fromIntegral auxids)     $ \pauxids -> 
    nullOnEmpty (map fromIntegral composeids) $ \pcomposeids -> 
    withCString fname                         $ \pfname -> do
        node <- c_dddmpBddLoad m (fromIntegral $ fromEnum matchtype) nullPtr pauxids pcomposeids (fromIntegral $ fromEnum mode) pfname nullPtr
        case node == nullPtr of
            True  -> return Nothing
            False -> do
                fp <- newForeignPtrEnv deref m node
                return $ Just $ DDNode fp