module LLVM.Internal.MemoryBuffer where
import LLVM.Prelude
import Control.Exception
import Control.Monad.AnyCont
import Control.Monad.Error.Class
import Control.Monad.IO.Class
import qualified Data.ByteString as BS
import qualified Data.ByteString.Unsafe as BS
import Foreign.Ptr
import LLVM.Internal.Coding
import LLVM.Internal.String
import LLVM.Internal.Inject
import qualified LLVM.Internal.FFI.LLVMCTypes as FFI
import qualified LLVM.Internal.FFI.MemoryBuffer as FFI
data Specification
= Bytes { name :: String, content :: BS.ByteString }
| File { pathName :: String }
instance (Inject String e, MonadError e m, Monad m, MonadIO m, MonadAnyCont IO m) => EncodeM m Specification (FFI.OwnerTransfered (Ptr FFI.MemoryBuffer)) where
encodeM spec = liftM FFI.OwnerTransfered $ do
case spec of
Bytes name content -> do
(s,l) <- anyContToM $ BS.unsafeUseAsCStringLen (BS.snoc content 0)
name <- encodeM name
nullTerminate <- encodeM True
liftIO $ FFI.createMemoryBufferWithMemoryRange s (fromIntegral (l1)) name nullTerminate
File pathName -> do
pathName <- encodeM pathName
mbPtr <- alloca
msgPtr <- alloca
result <- decodeM =<< (liftIO $ FFI.createMemoryBufferWithContentsOfFile pathName mbPtr msgPtr)
when result $ do
msg <- decodeM msgPtr
throwError (inject (msg :: String))
peek mbPtr
instance (Inject String e, MonadError e m, Monad m, MonadIO m, MonadAnyCont IO m) => EncodeM m Specification (Ptr FFI.MemoryBuffer) where
encodeM spec = do
FFI.OwnerTransfered mb <- encodeM spec
anyContToM $ bracket (return mb) FFI.disposeMemoryBuffer
instance MonadIO d => DecodeM d BS.ByteString (Ptr FFI.MemoryBuffer) where
decodeM p = do
s <- liftIO $ FFI.getBufferStart p
l <- liftIO $ FFI.getBufferSize p
liftIO $ BS.packCStringLen (s, fromIntegral l)
instance MonadIO d => DecodeM d String (Ptr FFI.MemoryBuffer) where
decodeM = decodeM . UTF8ByteString <=< decodeM