1 {-# OPTIONS_GHC -fno-implicit-prelude -funbox-strict-fields #-}
2 {-# OPTIONS_HADDOCK hide #-}
3 -----------------------------------------------------------------------------
5 -- Module : GHC.IO.BufferedIO
6 -- Copyright : (c) The University of Glasgow 2008
7 -- License : see libraries/base/LICENSE
9 -- Maintainer : cvs-ghc@haskell.org
10 -- Stability : internal
11 -- Portability : non-portable (GHC Extensions)
13 -- Class of buffered IO devices
15 -----------------------------------------------------------------------------
17 module GHC.IO.BufferedIO (
19 readBuf, readBufNonBlocking, writeBuf, writeBufNonBlocking
29 import GHC.IO.Device as IODevice
30 import GHC.IO.Device as RawIO
33 -- | The purpose of 'BufferedIO' is to provide a common interface for I/O
34 -- devices that can read and write data through a buffer. Devices that
35 -- implement 'BufferedIO' include ordinary files, memory-mapped files,
36 -- and bytestrings. The underlying device implementing a 'Handle' must
37 -- provide 'BufferedIO'.
39 class BufferedIO dev where
40 -- | allocate a new buffer. The size of the buffer is at the
41 -- discretion of the device; e.g. for a memory-mapped file the
42 -- buffer will probably cover the entire file.
43 newBuffer :: dev -> BufferState -> IO (Buffer Word8)
45 -- | reads bytes into the buffer, blocking if there are no bytes
46 -- available. Returns the number of bytes read (zero indicates
47 -- end-of-file), and the new buffer.
48 fillReadBuffer :: dev -> Buffer Word8 -> IO (Int, Buffer Word8)
50 -- | reads bytes into the buffer without blocking. Returns the
51 -- number of bytes read (Nothing indicates end-of-file), and the new
53 fillReadBuffer0 :: dev -> Buffer Word8 -> IO (Maybe Int, Buffer Word8)
55 -- | Flush all the data from the supplied write buffer out to the device
56 flushWriteBuffer :: dev -> Buffer Word8 -> IO ()
58 -- | Flush data from the supplied write buffer out to the device
59 -- without blocking. Returns the number of bytes written and the
61 flushWriteBuffer0 :: dev -> Buffer Word8 -> IO (Int, Buffer Word8)
63 -- for an I/O device, these operations will perform reading/writing
64 -- to/from the device.
66 -- for a memory-mapped file, the buffer will be the whole file in
67 -- memory. fillReadBuffer sets the pointers to encompass the whole
68 -- file, and flushWriteBuffer will do nothing. A memory-mapped file
69 -- has to maintain its own file pointer.
71 -- for a bytestring, again the buffer should match the bytestring in
74 -- ---------------------------------------------------------------------------
75 -- Low-level read/write to/from buffers
77 -- These operations make it easy to implement an instance of 'BufferedIO'
78 -- for an object that supports 'RawIO'.
80 readBuf :: RawIO dev => dev -> Buffer Word8 -> IO (Int, Buffer Word8)
82 let bytes = bufferAvailable bbuf
83 res <- withBuffer bbuf $ \ptr ->
84 RawIO.read dev (ptr `plusPtr` bufR bbuf) (fromIntegral bytes)
85 let res' = fromIntegral res
86 return (res', bbuf{ bufR = bufR bbuf + res' })
87 -- zero indicates end of file
89 readBufNonBlocking :: RawIO dev => dev -> Buffer Word8
90 -> IO (Maybe Int, -- Nothing ==> end of file
91 -- Just n ==> n bytes were read (n>=0)
93 readBufNonBlocking dev bbuf = do
94 let bytes = bufferAvailable bbuf
95 res <- withBuffer bbuf $ \ptr ->
96 IODevice.readNonBlocking dev (ptr `plusPtr` bufR bbuf) (fromIntegral bytes)
98 Nothing -> return (Nothing, bbuf)
99 Just n -> return (Just n, bbuf{ bufR = bufR bbuf + fromIntegral n })
101 writeBuf :: RawIO dev => dev -> Buffer Word8 -> IO ()
102 writeBuf dev bbuf = do
103 let bytes = bufferElems bbuf
104 withBuffer bbuf $ \ptr ->
105 IODevice.write dev (ptr `plusPtr` bufL bbuf) (fromIntegral bytes)
108 writeBufNonBlocking :: RawIO dev => dev -> Buffer Word8 -> IO (Int, Buffer Word8)
109 writeBufNonBlocking dev bbuf = do
110 let bytes = bufferElems bbuf
111 res <- withBuffer bbuf $ \ptr ->
112 IODevice.writeNonBlocking dev (ptr `plusPtr` bufL bbuf)
114 return (res, bbuf{ bufL = bufL bbuf + res })