{-# OPTIONS_JHC -fffi -funboxed-values #-}
module System.IO.Binary(readBinaryFile,putWord8,getWord8) where

import Jhc.IO
import Foreign.C.Types
import Foreign.C.String
import Foreign.Ptr
import Foreign.C.Error

-- | Lazily read a file as a sequence of bytes.

readBinaryFile :: FilePath -> IO [Word8]
readBinaryFile fn = do
    file <- withCString fn $ \fnc -> c_fopen fnc "rb"#
    if  (file == nullPtr) then getErrno >>= \errno -> (ioError $ errnoToIOError "readBinaryFile" errno Nothing (Just fn)) else do
        let gc = do
                ch <- c_getc file
                case ch of
                    -1 -> c_fclose file >> return []
                    _ -> do
                        xs <- unsafeInterleaveIO gc
                        return (cintToWord8 ch:xs)
        unsafeInterleaveIO gc

foreign import primitive "Lobits" cintToWord8 :: CInt -> Word8
--foreign import primitive "const.\"rb\"" read_str :: Ptr CChar

foreign import ccall "stdio.h getc_unlocked" c_getc :: Ptr () -> IO CInt
foreign import ccall "stdio.h fopen" c_fopen :: CString -> BitsPtr_ -> IO (Ptr ())
foreign import ccall "stdio.h fclose" c_fclose :: Ptr () -> IO CInt

-- Int translates to CInt in the calling conventions so this is safe.
foreign import ccall "stdio.h putchar_unlocked" c_putchar :: Int -> IO Int
foreign import ccall "stdio.h getchar_unlocked" c_getchar :: IO Int

putWord8 :: Word8 -> IO ()
putWord8 w = c_putchar (fromIntegral w) >> return ()

getWord8 :: IO Word8
getWord8 = do
    c <- c_getchar
    case c of
        -1 -> fail "EOF"
        _ -> return $ fromIntegral c
