1 {-# OPTIONS_GHC -XNoImplicitPrelude -funbox-strict-fields #-}
2 -----------------------------------------------------------------------------
4 -- Module : GHC.IO.BufferedIO
5 -- Copyright : (c) The University of Glasgow 2008
6 -- License : see libraries/base/LICENSE
8 -- Maintainer : cvs-ghc@haskell.org
9 -- Stability : internal
10 -- Portability : non-portable (GHC Extensions)
12 -- Class of buffered IO devices
14 -----------------------------------------------------------------------------
16 module GHC.IO.BufferedIO (
18 readBuf, readBufNonBlocking, writeBuf, writeBufNonBlocking
27 import GHC.IO.Device as IODevice
28 import GHC.IO.Device as RawIO
31 -- | The purpose of 'BufferedIO' is to provide a common interface for I/O
32 -- devices that can read and write data through a buffer. Devices that
33 -- implement 'BufferedIO' include ordinary files, memory-mapped files,
34 -- and bytestrings. The underlying device implementing a 'Handle' must
35 -- provide 'BufferedIO'.
37 class BufferedIO dev where
38 -- | allocate a new buffer. The size of the buffer is at the
39 -- discretion of the device; e.g. for a memory-mapped file the
40 -- buffer will probably cover the entire file.
41 newBuffer :: dev -> BufferState -> IO (Buffer Word8)
43 -- | reads bytes into the buffer, blocking if there are no bytes
44 -- available. Returns the number of bytes read (zero indicates
45 -- end-of-file), and the new buffer.
46 fillReadBuffer :: dev -> Buffer Word8 -> IO (Int, Buffer Word8)
48 -- | reads bytes into the buffer without blocking. Returns the
49 -- number of bytes read (Nothing indicates end-of-file), and the new
51 fillReadBuffer0 :: dev -> Buffer Word8 -> IO (Maybe Int, Buffer Word8)
53 -- | Prepares an empty write buffer. This lets the device decide
54 -- how to set up a write buffer: the buffer may need to point to a
55 -- specific location in memory, for example. This is typically used
56 -- by the client when switching from reading to writing on a
57 -- buffered read/write device.
59 -- There is no corresponding operation for read buffers, because before
60 -- reading the client will always call 'fillReadBuffer'.
61 emptyWriteBuffer :: dev -> Buffer Word8 -> IO (Buffer Word8)
62 emptyWriteBuffer _dev buf
63 = return buf{ bufL=0, bufR=0, bufState = WriteBuffer }
65 -- | Flush all the data from the supplied write buffer out to the device.
66 -- The returned buffer should be empty, and ready for writing.
67 flushWriteBuffer :: dev -> Buffer Word8 -> IO (Buffer Word8)
69 -- | Flush data from the supplied write buffer out to the device
70 -- without blocking. Returns the number of bytes written and the
72 flushWriteBuffer0 :: dev -> Buffer Word8 -> IO (Int, Buffer Word8)
74 -- for an I/O device, these operations will perform reading/writing
75 -- to/from the device.
77 -- for a memory-mapped file, the buffer will be the whole file in
78 -- memory. fillReadBuffer sets the pointers to encompass the whole
79 -- file, and flushWriteBuffer needs to do no I/O. A memory-mapped
80 -- file has to maintain its own file pointer.
82 -- for a bytestring, again the buffer should match the bytestring in
85 -- ---------------------------------------------------------------------------
86 -- Low-level read/write to/from buffers
88 -- These operations make it easy to implement an instance of 'BufferedIO'
89 -- for an object that supports 'RawIO'.
91 readBuf :: RawIO dev => dev -> Buffer Word8 -> IO (Int, Buffer Word8)
93 let bytes = bufferAvailable bbuf
94 res <- withBuffer bbuf $ \ptr ->
95 RawIO.read dev (ptr `plusPtr` bufR bbuf) bytes
96 return (res, bbuf{ bufR = bufR bbuf + res })
97 -- zero indicates end of file
99 readBufNonBlocking :: RawIO dev => dev -> Buffer Word8
100 -> IO (Maybe Int, -- Nothing ==> end of file
101 -- Just n ==> n bytes were read (n>=0)
103 readBufNonBlocking dev bbuf = do
104 let bytes = bufferAvailable bbuf
105 res <- withBuffer bbuf $ \ptr ->
106 IODevice.readNonBlocking dev (ptr `plusPtr` bufR bbuf) bytes
108 Nothing -> return (Nothing, bbuf)
109 Just n -> return (Just n, bbuf{ bufR = bufR bbuf + n })
111 writeBuf :: RawIO dev => dev -> Buffer Word8 -> IO (Buffer Word8)
112 writeBuf dev bbuf = do
113 let bytes = bufferElems bbuf
114 withBuffer bbuf $ \ptr ->
115 IODevice.write dev (ptr `plusPtr` bufL bbuf) bytes
116 return bbuf{ bufL=0, bufR=0 }
119 writeBufNonBlocking :: RawIO dev => dev -> Buffer Word8 -> IO (Int, Buffer Word8)
120 writeBufNonBlocking dev bbuf = do
121 let bytes = bufferElems bbuf
122 res <- withBuffer bbuf $ \ptr ->
123 IODevice.writeNonBlocking dev (ptr `plusPtr` bufL bbuf) bytes
124 return (res, bufferAdjustL res bbuf)