584f5a7852347464feec56bf68fde3cf91a87ad5
[ghc-base.git] / GHC / IO / BufferedIO.hs
1 {-# OPTIONS_GHC  -XNoImplicitPrelude -funbox-strict-fields #-}
2 -----------------------------------------------------------------------------
3 -- |
4 -- Module      :  GHC.IO.BufferedIO
5 -- Copyright   :  (c) The University of Glasgow 2008
6 -- License     :  see libraries/base/LICENSE
7 -- 
8 -- Maintainer  :  cvs-ghc@haskell.org
9 -- Stability   :  internal
10 -- Portability :  non-portable (GHC Extensions)
11 --
12 -- Class of buffered IO devices
13 --
14 -----------------------------------------------------------------------------
15
16 module GHC.IO.BufferedIO (
17    BufferedIO(..),
18    readBuf, readBufNonBlocking, writeBuf, writeBufNonBlocking
19  ) where
20
21 import GHC.Base
22 import GHC.Ptr
23 import Data.Word
24 import GHC.Num
25 import Data.Maybe
26 -- import GHC.IO
27 import GHC.IO.Device as IODevice
28 import GHC.IO.Device as RawIO
29 import GHC.IO.Buffer
30
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'.
36 --
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)
42
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)
47
48   -- | reads bytes into the buffer without blocking.  Returns the
49   -- number of bytes read (Nothing indicates end-of-file), and the new
50   -- buffer.
51   fillReadBuffer0   :: dev -> Buffer Word8 -> IO (Maybe Int, Buffer Word8)
52
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.
58   --
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 }
64
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)
68
69   -- | Flush data from the supplied write buffer out to the device
70   -- without blocking.  Returns the number of bytes written and the
71   -- remaining buffer.
72   flushWriteBuffer0 :: dev -> Buffer Word8 -> IO (Int, Buffer Word8)
73
74 -- for an I/O device, these operations will perform reading/writing
75 -- to/from the device.
76
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.
81
82 -- for a bytestring, again the buffer should match the bytestring in
83 -- memory.
84
85 -- ---------------------------------------------------------------------------
86 -- Low-level read/write to/from buffers
87
88 -- These operations make it easy to implement an instance of 'BufferedIO'
89 -- for an object that supports 'RawIO'.
90
91 readBuf :: RawIO dev => dev -> Buffer Word8 -> IO (Int, Buffer Word8)
92 readBuf dev bbuf = do
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
98
99 readBufNonBlocking :: RawIO dev => dev -> Buffer Word8
100                      -> IO (Maybe Int,   -- Nothing ==> end of file
101                                          -- Just n  ==> n bytes were read (n>=0)
102                             Buffer Word8)
103 readBufNonBlocking dev bbuf = do
104   let bytes = bufferAvailable bbuf
105   res <- withBuffer bbuf $ \ptr ->
106            IODevice.readNonBlocking dev (ptr `plusPtr` bufR bbuf) bytes
107   case res of
108      Nothing -> return (Nothing, bbuf)
109      Just n  -> return (Just n, bbuf{ bufR = bufR bbuf + n })
110
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 }
117
118 -- XXX ToDo
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)