f5c874e01edb8883611a23abedf00ed3080b0094
[ghc-base.git] / GHC / IO / BufferedIO.hs
1 {-# OPTIONS_GHC  -XNoImplicitPrelude -funbox-strict-fields #-}
2 {-# OPTIONS_HADDOCK hide #-}
3 -----------------------------------------------------------------------------
4 -- |
5 -- Module      :  GHC.IO.BufferedIO
6 -- Copyright   :  (c) The University of Glasgow 2008
7 -- License     :  see libraries/base/LICENSE
8 -- 
9 -- Maintainer  :  cvs-ghc@haskell.org
10 -- Stability   :  internal
11 -- Portability :  non-portable (GHC Extensions)
12 --
13 -- Class of buffered IO devices
14 --
15 -----------------------------------------------------------------------------
16
17 module GHC.IO.BufferedIO (
18    BufferedIO(..),
19    readBuf, readBufNonBlocking, writeBuf, writeBufNonBlocking
20  ) where
21
22 import GHC.Base
23 import GHC.Ptr
24 import Data.Word
25 import GHC.Num
26 import GHC.Real
27 import Data.Maybe
28 -- import GHC.IO
29 import GHC.IO.Device as IODevice
30 import GHC.IO.Device as RawIO
31 import GHC.IO.Buffer
32
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'.
38 --
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)
44
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)
49
50   -- | reads bytes into the buffer without blocking.  Returns the
51   -- number of bytes read (Nothing indicates end-of-file), and the new
52   -- buffer.
53   fillReadBuffer0   :: dev -> Buffer Word8 -> IO (Maybe Int, Buffer Word8)
54
55   -- | Flush all the data from the supplied write buffer out to the device
56   flushWriteBuffer  :: dev -> Buffer Word8 -> IO ()
57
58   -- | Flush data from the supplied write buffer out to the device
59   -- without blocking.  Returns the number of bytes written and the
60   -- remaining buffer.
61   flushWriteBuffer0 :: dev -> Buffer Word8 -> IO (Int, Buffer Word8)
62
63 -- for an I/O device, these operations will perform reading/writing
64 -- to/from the device.
65
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.
70
71 -- for a bytestring, again the buffer should match the bytestring in
72 -- memory.
73
74 -- ---------------------------------------------------------------------------
75 -- Low-level read/write to/from buffers
76
77 -- These operations make it easy to implement an instance of 'BufferedIO'
78 -- for an object that supports 'RawIO'.
79
80 readBuf :: RawIO dev => dev -> Buffer Word8 -> IO (Int, Buffer Word8)
81 readBuf dev bbuf = do
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
88
89 readBufNonBlocking :: RawIO dev => dev -> Buffer Word8
90                      -> IO (Maybe Int,   -- Nothing ==> end of file
91                                          -- Just n  ==> n bytes were read (n>=0)
92                             Buffer Word8)
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)
97   case res of
98      Nothing -> return (Nothing, bbuf)
99      Just n  -> return (Just n, bbuf{ bufR = bufR bbuf + fromIntegral n })
100
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)
106
107 -- XXX ToDo
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)
113                                       (fromIntegral bytes)
114   return (res, bbuf{ bufL = bufL bbuf + res })
115