1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
------------------------------------------------------------------------------
--- Library to support reading/writing binary files.
---
--- @author Michael Hanus
--- @version June 2018
------------------------------------------------------------------------------

module BinaryFile
  ( IOMode, Handle -- from IO
  , openBinaryFile, hGetByte, hPutByte, hGetBinaryContents
  )
 where

import IO ( IOMode, Handle, hIsEOF, hClose )

--- `Byte` is an alias for `Int`. Could be changed for a more
--- space efficient representation.
type Byte = Int

--- Like 'openFile', but open the file in binary mode.
--- Thus, no translation of character is performed when reading
--- or writing a file.
--- Returns a handle to read and write the binary stream
--- (e.g., with operations 'hGetByte' and 'hPutByte').
openBinaryFile :: String -> IOMode -> IO Handle
openBinaryFile filename mode = (prim_openBinaryFile $## filename) $# mode

prim_openBinaryFile :: String -> IOMode -> IO Handle
prim_openBinaryFile external

--- Reads a byte from an input handle associated to a _binary_ stream
--- and returns it.
--- Throws an error if the end of file has been reached or the stream
--- is not binary.
hGetByte    :: Handle -> IO Byte
hGetByte h = prim_hGetByte $# h

prim_hGetByte :: Handle -> IO Byte
prim_hGetByte external

--- Puts a byte to an output handle associated to a _binary_ stream.
hPutByte    :: Handle -> Byte -> IO ()
hPutByte h c = (prim_hPutByte $# h)  $## c

prim_hPutByte :: Handle -> Byte -> IO ()
prim_hPutByte external

--- Reads the complete contents from an input handle and closes the input handle
--- before returning the contents.
hGetBinaryContents  :: Handle -> IO [Byte]
hGetBinaryContents h = do
  eof <- hIsEOF h
  if eof then hClose h >> return []
         else do b <- hGetByte h
                 bs <- hGetBinaryContents h
                 return (b:bs)