Rewrite of the IO library, including Unicode support
[packages/base.git] / GHC / IO / BufferedIO.hs
1 {-# OPTIONS_GHC -fno-implicit-prelude -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