add GHC.HetMet.{hetmet_kappa,hetmet_kappa_app}
[ghc-base.git] / GHC / IO / BufferedIO.hs
1 {-# LANGUAGE NoImplicitPrelude #-}
2 {-# OPTIONS_GHC -funbox-strict-fields #-}
3
4 -----------------------------------------------------------------------------
5 -- |
6 -- Module      :  GHC.IO.BufferedIO
7 -- Copyright   :  (c) The University of Glasgow 2008
8 -- License     :  see libraries/base/LICENSE
9 -- 
10 -- Maintainer  :  cvs-ghc@haskell.org
11 -- Stability   :  internal
12 -- Portability :  non-portable (GHC Extensions)
13 --
14 -- Class of buffered IO devices
15 --
16 -----------------------------------------------------------------------------
17
18 module GHC.IO.BufferedIO (
19    BufferedIO(..),
20    readBuf, readBufNonBlocking, writeBuf, writeBufNonBlocking
21  ) where
22
23 import GHC.Base
24 import GHC.Ptr
25 import Data.Word
26 import GHC.Num
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   -- | Prepares an empty write buffer.  This lets the device decide
56   -- how to set up a write buffer: the buffer may need to point to a
57   -- specific location in memory, for example.  This is typically used
58   -- by the client when switching from reading to writing on a
59   -- buffered read/write device.
60   --
61   -- There is no corresponding operation for read buffers, because before
62   -- reading the client will always call 'fillReadBuffer'.
63   emptyWriteBuffer  :: dev -> Buffer Word8 -> IO (Buffer Word8)
64   emptyWriteBuffer _dev buf 
65     = return buf{ bufL=0, bufR=0, bufState = WriteBuffer }
66
67   -- | Flush all the data from the supplied write buffer out to the device.
68   -- The returned buffer should be empty, and ready for writing.
69   flushWriteBuffer  :: dev -> Buffer Word8 -> IO (Buffer Word8)
70
71   -- | Flush data from the supplied write buffer out to the device
72   -- without blocking.  Returns the number of bytes written and the
73   -- remaining buffer.
74   flushWriteBuffer0 :: dev -> Buffer Word8 -> IO (Int, Buffer Word8)
75
76 -- for an I/O device, these operations will perform reading/writing
77 -- to/from the device.
78
79 -- for a memory-mapped file, the buffer will be the whole file in
80 -- memory.  fillReadBuffer sets the pointers to encompass the whole
81 -- file, and flushWriteBuffer needs to do no I/O.  A memory-mapped
82 -- file has to maintain its own file pointer.
83
84 -- for a bytestring, again the buffer should match the bytestring in
85 -- memory.
86
87 -- ---------------------------------------------------------------------------
88 -- Low-level read/write to/from buffers
89
90 -- These operations make it easy to implement an instance of 'BufferedIO'
91 -- for an object that supports 'RawIO'.
92
93 readBuf :: RawIO dev => dev -> Buffer Word8 -> IO (Int, Buffer Word8)
94 readBuf dev bbuf = do
95   let bytes = bufferAvailable bbuf
96   res <- withBuffer bbuf $ \ptr ->
97              RawIO.read dev (ptr `plusPtr` bufR bbuf) bytes
98   return (res, bbuf{ bufR = bufR bbuf + res })
99          -- zero indicates end of file
100
101 readBufNonBlocking :: RawIO dev => dev -> Buffer Word8
102                      -> IO (Maybe Int,   -- Nothing ==> end of file
103                                          -- Just n  ==> n bytes were read (n>=0)
104                             Buffer Word8)
105 readBufNonBlocking dev bbuf = do
106   let bytes = bufferAvailable bbuf
107   res <- withBuffer bbuf $ \ptr ->
108            IODevice.readNonBlocking dev (ptr `plusPtr` bufR bbuf) bytes
109   case res of
110      Nothing -> return (Nothing, bbuf)
111      Just n  -> return (Just n, bbuf{ bufR = bufR bbuf + n })
112
113 writeBuf :: RawIO dev => dev -> Buffer Word8 -> IO (Buffer Word8)
114 writeBuf dev bbuf = do
115   let bytes = bufferElems bbuf
116   withBuffer bbuf $ \ptr ->
117       IODevice.write dev (ptr `plusPtr` bufL bbuf) bytes
118   return bbuf{ bufL=0, bufR=0 }
119
120 -- XXX ToDo
121 writeBufNonBlocking :: RawIO dev => dev -> Buffer Word8 -> IO (Int, Buffer Word8)
122 writeBufNonBlocking dev bbuf = do
123   let bytes = bufferElems bbuf
124   res <- withBuffer bbuf $ \ptr ->
125             IODevice.writeNonBlocking dev (ptr `plusPtr` bufL bbuf) bytes
126   return (res, bufferAdjustL res bbuf)