{-# LINE 1 "OpenSSL/Objects.hsc" #-}
{-# LANGUAGE EmptyDataDecls           #-}
{-# LANGUAGE ForeignFunctionInterface #-}
module OpenSSL.Objects
    ( ObjNameType(..)
    , getObjNames
    )
    where

import           Data.IORef
import           Foreign
import           Foreign.C


type ObjName  = Ptr OBJ_NAME
data OBJ_NAME

type DoAllCallback = ObjName -> Ptr () -> IO ()


foreign import ccall safe "OBJ_NAME_do_all"
        _NAME_do_all :: CInt -> FunPtr DoAllCallback -> Ptr () -> IO ()

foreign import ccall safe "OBJ_NAME_do_all_sorted"
        _NAME_do_all_sorted :: CInt -> FunPtr DoAllCallback -> Ptr () -> IO ()

foreign import ccall "wrapper"
        mkDoAllCallback :: DoAllCallback -> IO (FunPtr DoAllCallback)


data ObjNameType = MDMethodType
                 | CipherMethodType
                 | PKeyMethodType
                 | CompMethodType

objNameTypeToInt :: ObjNameType -> CInt
objNameTypeToInt MDMethodType     = 1
{-# LINE 37 "OpenSSL/Objects.hsc" #-}
objNameTypeToInt CipherMethodType = 2
{-# LINE 38 "OpenSSL/Objects.hsc" #-}
objNameTypeToInt PKeyMethodType   = 3
{-# LINE 39 "OpenSSL/Objects.hsc" #-}
objNameTypeToInt CompMethodType   = 4
{-# LINE 40 "OpenSSL/Objects.hsc" #-}


iterateObjNames :: ObjNameType -> Bool -> (ObjName -> IO ()) -> IO ()
iterateObjNames nameType wantSorted cb
    = do cbPtr <- mkDoAllCallback $ \ name _ -> cb name
         let action = if wantSorted then
                          _NAME_do_all_sorted
                      else
                          _NAME_do_all
         action (objNameTypeToInt nameType) cbPtr nullPtr
         freeHaskellFunPtr cbPtr


objNameStr :: ObjName -> IO String
objNameStr name
    = ((\hsc_ptr -> peekByteOff hsc_ptr 8)) name >>= peekCString
{-# LINE 56 "OpenSSL/Objects.hsc" #-}


getObjNames :: ObjNameType -> Bool -> IO [String]
getObjNames nameType wantSorted
    = do listRef <- newIORef []
         iterateObjNames nameType wantSorted $ \ name ->
             do nameStr <- objNameStr name
                modifyIORef listRef (++ [nameStr])
         readIORef listRef