1 -----------------------------------------------------------------------------
3 -- Module : Data.Array.IO
4 -- Copyright : (c) The University of Glasgow 2001
5 -- License : BSD-style (see the file libraries/core/LICENSE)
7 -- Maintainer : libraries@haskell.org
8 -- Stability : experimental
9 -- Portability : non-portable
11 -- $Id: IO.hs,v 1.2 2001/09/14 11:25:23 simonmar Exp $
13 -- Mutable boxed/unboxed arrays in the IO monad.
15 -----------------------------------------------------------------------------
17 module Data.Array.IO (
18 module Data.Array.MArray,
19 IOArray, -- instance of: Eq, Typeable
20 IOUArray, -- instance of: Eq, Typeable
21 castIOUArray, -- :: IOUArray i a -> IO (IOUArray i b)
22 hGetArray, -- :: Handle -> IOUArray Int Word8 -> Int -> IO Int
23 hPutArray, -- :: Handle -> IOUArray Int Word8 -> Int -> IO ()
28 import Data.Array ( Array )
29 import Data.Array.MArray
35 import Foreign.Ptr ( Ptr, FunPtr )
36 import Foreign.StablePtr ( StablePtr )
38 #ifdef __GLASGOW_HASKELL__
39 -- GHC only to the end of file
41 import Data.Array.Base
42 import GHC.Arr ( STArray, freezeSTArray, unsafeFreezeSTArray,
43 thawSTArray, unsafeThawSTArray )
45 import GHC.ST ( ST(..) )
53 -----------------------------------------------------------------------------
54 -- Polymorphic non-strict mutable arrays (IO monad)
56 newtype IOArray i e = IOArray (STArray RealWorld i e) deriving Eq
59 iOArrayTc = mkTyCon "IOArray"
61 instance (Typeable a, Typeable b) => Typeable (IOArray a b) where
62 typeOf a = mkAppTy iOArrayTc [typeOf ((undefined :: IOArray a b -> a) a),
63 typeOf ((undefined :: IOArray a b -> b) a)]
65 instance HasBounds IOArray where
67 bounds (IOArray marr) = bounds marr
69 instance MArray IOArray e IO where
70 {-# INLINE newArray #-}
71 newArray lu init = stToIO $ do
72 marr <- newArray lu init; return (IOArray marr)
73 {-# INLINE newArray_ #-}
74 newArray_ lu = stToIO $ do
75 marr <- newArray_ lu; return (IOArray marr)
76 {-# INLINE unsafeRead #-}
77 unsafeRead (IOArray marr) i = stToIO (unsafeRead marr i)
78 {-# INLINE unsafeWrite #-}
79 unsafeWrite (IOArray marr) i e = stToIO (unsafeWrite marr i e)
81 -----------------------------------------------------------------------------
82 -- Flat unboxed mutable arrays (IO monad)
84 newtype IOUArray i e = IOUArray (STUArray RealWorld i e) deriving Eq
87 iOUArrayTc = mkTyCon "IOUArray"
89 instance (Typeable a, Typeable b) => Typeable (IOUArray a b) where
90 typeOf a = mkAppTy iOUArrayTc [typeOf ((undefined :: IOUArray a b -> a) a),
91 typeOf ((undefined :: IOUArray a b -> b) a)]
93 instance HasBounds IOUArray where
95 bounds (IOUArray marr) = bounds marr
97 instance MArray IOUArray Bool IO where
98 {-# INLINE newArray #-}
99 newArray lu init = stToIO $ do
100 marr <- newArray lu init; return (IOUArray marr)
101 {-# INLINE newArray_ #-}
102 newArray_ lu = stToIO $ do
103 marr <- newArray_ lu; return (IOUArray marr)
104 {-# INLINE unsafeRead #-}
105 unsafeRead (IOUArray marr) i = stToIO (unsafeRead marr i)
106 {-# INLINE unsafeWrite #-}
107 unsafeWrite (IOUArray marr) i e = stToIO (unsafeWrite marr i e)
109 instance MArray IOUArray Char IO where
110 {-# INLINE newArray #-}
111 newArray lu init = stToIO $ do
112 marr <- newArray lu init; return (IOUArray marr)
113 {-# INLINE newArray_ #-}
114 newArray_ lu = stToIO $ do
115 marr <- newArray_ lu; return (IOUArray marr)
116 {-# INLINE unsafeRead #-}
117 unsafeRead (IOUArray marr) i = stToIO (unsafeRead marr i)
118 {-# INLINE unsafeWrite #-}
119 unsafeWrite (IOUArray marr) i e = stToIO (unsafeWrite marr i e)
121 instance MArray IOUArray Int IO where
122 {-# INLINE newArray #-}
123 newArray lu init = stToIO $ do
124 marr <- newArray lu init; return (IOUArray marr)
125 {-# INLINE newArray_ #-}
126 newArray_ lu = stToIO $ do
127 marr <- newArray_ lu; return (IOUArray marr)
128 {-# INLINE unsafeRead #-}
129 unsafeRead (IOUArray marr) i = stToIO (unsafeRead marr i)
130 {-# INLINE unsafeWrite #-}
131 unsafeWrite (IOUArray marr) i e = stToIO (unsafeWrite marr i e)
133 instance MArray IOUArray Word IO where
134 {-# INLINE newArray #-}
135 newArray lu init = stToIO $ do
136 marr <- newArray lu init; return (IOUArray marr)
137 {-# INLINE newArray_ #-}
138 newArray_ lu = stToIO $ do
139 marr <- newArray_ lu; return (IOUArray marr)
140 {-# INLINE unsafeRead #-}
141 unsafeRead (IOUArray marr) i = stToIO (unsafeRead marr i)
142 {-# INLINE unsafeWrite #-}
143 unsafeWrite (IOUArray marr) i e = stToIO (unsafeWrite marr i e)
145 instance MArray IOUArray (Ptr a) IO where
146 {-# INLINE newArray #-}
147 newArray lu init = stToIO $ do
148 marr <- newArray lu init; return (IOUArray marr)
149 {-# INLINE newArray_ #-}
150 newArray_ lu = stToIO $ do
151 marr <- newArray_ lu; return (IOUArray marr)
152 {-# INLINE unsafeRead #-}
153 unsafeRead (IOUArray marr) i = stToIO (unsafeRead marr i)
154 {-# INLINE unsafeWrite #-}
155 unsafeWrite (IOUArray marr) i e = stToIO (unsafeWrite marr i e)
157 instance MArray IOUArray (FunPtr a) IO where
158 {-# INLINE newArray #-}
159 newArray lu init = stToIO $ do
160 marr <- newArray lu init; return (IOUArray marr)
161 {-# INLINE newArray_ #-}
162 newArray_ lu = stToIO $ do
163 marr <- newArray_ lu; return (IOUArray marr)
164 {-# INLINE unsafeRead #-}
165 unsafeRead (IOUArray marr) i = stToIO (unsafeRead marr i)
166 {-# INLINE unsafeWrite #-}
167 unsafeWrite (IOUArray marr) i e = stToIO (unsafeWrite marr i e)
169 instance MArray IOUArray Float IO where
170 {-# INLINE newArray #-}
171 newArray lu init = stToIO $ do
172 marr <- newArray lu init; return (IOUArray marr)
173 {-# INLINE newArray_ #-}
174 newArray_ lu = stToIO $ do
175 marr <- newArray_ lu; return (IOUArray marr)
176 {-# INLINE unsafeRead #-}
177 unsafeRead (IOUArray marr) i = stToIO (unsafeRead marr i)
178 {-# INLINE unsafeWrite #-}
179 unsafeWrite (IOUArray marr) i e = stToIO (unsafeWrite marr i e)
181 instance MArray IOUArray Double IO where
182 {-# INLINE newArray #-}
183 newArray lu init = stToIO $ do
184 marr <- newArray lu init; return (IOUArray marr)
185 {-# INLINE newArray_ #-}
186 newArray_ lu = stToIO $ do
187 marr <- newArray_ lu; return (IOUArray marr)
188 {-# INLINE unsafeRead #-}
189 unsafeRead (IOUArray marr) i = stToIO (unsafeRead marr i)
190 {-# INLINE unsafeWrite #-}
191 unsafeWrite (IOUArray marr) i e = stToIO (unsafeWrite marr i e)
193 instance MArray IOUArray (StablePtr a) IO where
194 {-# INLINE newArray #-}
195 newArray lu init = stToIO $ do
196 marr <- newArray lu init; return (IOUArray marr)
197 {-# INLINE newArray_ #-}
198 newArray_ lu = stToIO $ do
199 marr <- newArray_ lu; return (IOUArray marr)
200 {-# INLINE unsafeRead #-}
201 unsafeRead (IOUArray marr) i = stToIO (unsafeRead marr i)
202 {-# INLINE unsafeWrite #-}
203 unsafeWrite (IOUArray marr) i e = stToIO (unsafeWrite marr i e)
205 instance MArray IOUArray Int8 IO where
206 {-# INLINE newArray #-}
207 newArray lu init = stToIO $ do
208 marr <- newArray lu init; return (IOUArray marr)
209 {-# INLINE newArray_ #-}
210 newArray_ lu = stToIO $ do
211 marr <- newArray_ lu; return (IOUArray marr)
212 {-# INLINE unsafeRead #-}
213 unsafeRead (IOUArray marr) i = stToIO (unsafeRead marr i)
214 {-# INLINE unsafeWrite #-}
215 unsafeWrite (IOUArray marr) i e = stToIO (unsafeWrite marr i e)
217 instance MArray IOUArray Int16 IO where
218 {-# INLINE newArray #-}
219 newArray lu init = stToIO $ do
220 marr <- newArray lu init; return (IOUArray marr)
221 {-# INLINE newArray_ #-}
222 newArray_ lu = stToIO $ do
223 marr <- newArray_ lu; return (IOUArray marr)
224 {-# INLINE unsafeRead #-}
225 unsafeRead (IOUArray marr) i = stToIO (unsafeRead marr i)
226 {-# INLINE unsafeWrite #-}
227 unsafeWrite (IOUArray marr) i e = stToIO (unsafeWrite marr i e)
229 instance MArray IOUArray Int32 IO where
230 {-# INLINE newArray #-}
231 newArray lu init = stToIO $ do
232 marr <- newArray lu init; return (IOUArray marr)
233 {-# INLINE newArray_ #-}
234 newArray_ lu = stToIO $ do
235 marr <- newArray_ lu; return (IOUArray marr)
236 {-# INLINE unsafeRead #-}
237 unsafeRead (IOUArray marr) i = stToIO (unsafeRead marr i)
238 {-# INLINE unsafeWrite #-}
239 unsafeWrite (IOUArray marr) i e = stToIO (unsafeWrite marr i e)
241 instance MArray IOUArray Int64 IO where
242 {-# INLINE newArray #-}
243 newArray lu init = stToIO $ do
244 marr <- newArray lu init; return (IOUArray marr)
245 {-# INLINE newArray_ #-}
246 newArray_ lu = stToIO $ do
247 marr <- newArray_ lu; return (IOUArray marr)
248 {-# INLINE unsafeRead #-}
249 unsafeRead (IOUArray marr) i = stToIO (unsafeRead marr i)
250 {-# INLINE unsafeWrite #-}
251 unsafeWrite (IOUArray marr) i e = stToIO (unsafeWrite marr i e)
253 instance MArray IOUArray Word8 IO where
254 {-# INLINE newArray #-}
255 newArray lu init = stToIO $ do
256 marr <- newArray lu init; return (IOUArray marr)
257 {-# INLINE newArray_ #-}
258 newArray_ lu = stToIO $ do
259 marr <- newArray_ lu; return (IOUArray marr)
260 {-# INLINE unsafeRead #-}
261 unsafeRead (IOUArray marr) i = stToIO (unsafeRead marr i)
262 {-# INLINE unsafeWrite #-}
263 unsafeWrite (IOUArray marr) i e = stToIO (unsafeWrite marr i e)
265 instance MArray IOUArray Word16 IO where
266 {-# INLINE newArray #-}
267 newArray lu init = stToIO $ do
268 marr <- newArray lu init; return (IOUArray marr)
269 {-# INLINE newArray_ #-}
270 newArray_ lu = stToIO $ do
271 marr <- newArray_ lu; return (IOUArray marr)
272 {-# INLINE unsafeRead #-}
273 unsafeRead (IOUArray marr) i = stToIO (unsafeRead marr i)
274 {-# INLINE unsafeWrite #-}
275 unsafeWrite (IOUArray marr) i e = stToIO (unsafeWrite marr i e)
277 instance MArray IOUArray Word32 IO where
278 {-# INLINE newArray #-}
279 newArray lu init = stToIO $ do
280 marr <- newArray lu init; return (IOUArray marr)
281 {-# INLINE newArray_ #-}
282 newArray_ lu = stToIO $ do
283 marr <- newArray_ lu; return (IOUArray marr)
284 {-# INLINE unsafeRead #-}
285 unsafeRead (IOUArray marr) i = stToIO (unsafeRead marr i)
286 {-# INLINE unsafeWrite #-}
287 unsafeWrite (IOUArray marr) i e = stToIO (unsafeWrite marr i e)
289 instance MArray IOUArray Word64 IO where
290 {-# INLINE newArray #-}
291 newArray lu init = stToIO $ do
292 marr <- newArray lu init; return (IOUArray marr)
293 {-# INLINE newArray_ #-}
294 newArray_ lu = stToIO $ do
295 marr <- newArray_ lu; return (IOUArray marr)
296 {-# INLINE unsafeRead #-}
297 unsafeRead (IOUArray marr) i = stToIO (unsafeRead marr i)
298 {-# INLINE unsafeWrite #-}
299 unsafeWrite (IOUArray marr) i e = stToIO (unsafeWrite marr i e)
301 -----------------------------------------------------------------------------
304 freezeIOArray :: Ix ix => IOArray ix e -> IO (Array ix e)
305 freezeIOArray (IOArray marr) = stToIO (freezeSTArray marr)
307 freezeIOUArray :: Ix ix => IOUArray ix e -> IO (UArray ix e)
308 freezeIOUArray (IOUArray marr) = stToIO (freezeSTUArray marr)
311 "freeze/IOArray" freeze = freezeIOArray
312 "freeze/IOUArray" freeze = freezeIOUArray
315 {-# INLINE unsafeFreezeIOArray #-}
316 unsafeFreezeIOArray :: Ix ix => IOArray ix e -> IO (Array ix e)
317 unsafeFreezeIOArray (IOArray marr) = stToIO (unsafeFreezeSTArray marr)
319 {-# INLINE unsafeFreezeIOUArray #-}
320 unsafeFreezeIOUArray :: Ix ix => IOUArray ix e -> IO (UArray ix e)
321 unsafeFreezeIOUArray (IOUArray marr) = stToIO (unsafeFreezeSTUArray marr)
324 "unsafeFreeze/IOArray" unsafeFreeze = unsafeFreezeIOArray
325 "unsafeFreeze/IOUArray" unsafeFreeze = unsafeFreezeIOUArray
328 -----------------------------------------------------------------------------
331 thawIOArray :: Ix ix => Array ix e -> IO (IOArray ix e)
332 thawIOArray arr = stToIO $ do
333 marr <- thawSTArray arr
334 return (IOArray marr)
336 thawIOUArray :: Ix ix => UArray ix e -> IO (IOUArray ix e)
337 thawIOUArray arr = stToIO $ do
338 marr <- thawSTUArray arr
339 return (IOUArray marr)
342 "thaw/IOArray" thaw = thawIOArray
343 "thaw/IOUArray" thaw = thawIOUArray
346 {-# INLINE unsafeThawIOArray #-}
347 unsafeThawIOArray :: Ix ix => Array ix e -> IO (IOArray ix e)
348 unsafeThawIOArray arr = stToIO $ do
349 marr <- unsafeThawSTArray arr
350 return (IOArray marr)
352 {-# INLINE unsafeThawIOUArray #-}
353 unsafeThawIOUArray :: Ix ix => UArray ix e -> IO (IOUArray ix e)
354 unsafeThawIOUArray arr = stToIO $ do
355 marr <- unsafeThawSTUArray arr
356 return (IOUArray marr)
359 "unsafeThaw/IOArray" unsafeThaw = unsafeThawIOArray
360 "unsafeThaw/IOUArray" unsafeThaw = unsafeThawIOUArray
363 castSTUArray :: STUArray s ix a -> ST s (STUArray s ix b)
364 castSTUArray (STUArray l u marr#) = return (STUArray l u marr#)
366 castIOUArray :: IOUArray ix a -> IO (IOUArray ix b)
367 castIOUArray (IOUArray marr) = stToIO $ do
368 marr' <- castSTUArray marr
369 return (IOUArray marr')
371 -- ---------------------------------------------------------------------------
374 hGetArray :: Handle -> IOUArray Int Word8 -> Int -> IO Int
375 hGetArray handle (IOUArray (STUArray l u ptr)) count
376 | count <= 0 || count > rangeSize (l,u)
377 = illegalBufferSize handle "hGetArray" count
379 wantReadableHandle "hGetArray" handle $
380 \ handle_@Handle__{ haFD=fd, haBuffer=ref } -> do
381 buf@Buffer{ bufBuf=raw, bufWPtr=w, bufRPtr=r } <- readIORef ref
383 then readChunkBA fd ptr 0 count
386 copied <- if (count >= avail)
388 memcpy_ba_baoff ptr raw r (fromIntegral avail)
389 writeIORef ref buf{ bufWPtr=0, bufRPtr=0 }
392 memcpy_ba_baoff ptr raw r (fromIntegral count)
393 writeIORef ref buf{ bufRPtr = r + count }
396 let remaining = count - copied
398 then do rest <- readChunkBA fd ptr copied remaining
399 return (rest + count)
402 readChunkBA :: FD -> RawBuffer -> Int -> Int -> IO Int
403 readChunkBA fd ptr init_off bytes = loop init_off bytes
405 loop :: Int -> Int -> IO Int
406 loop off bytes | bytes <= 0 = return (off - init_off)
408 r' <- throwErrnoIfMinus1RetryMayBlock "readChunk"
409 (readBA (fromIntegral fd) ptr
410 (fromIntegral off) (fromIntegral bytes))
412 let r = fromIntegral r'
414 then return (off - init_off)
415 else loop (off + r) (bytes - r)
417 foreign import "read_ba_wrap" unsafe
418 readBA :: FD -> RawBuffer -> Int -> CInt -> IO CInt
420 -----------------------------------------------------------------------------
424 :: Handle -- handle to write to
425 -> IOUArray Int Word8 -- buffer
426 -> Int -- number of bytes of data to write
429 hPutArray handle (IOUArray (STUArray l u raw)) count
430 | count <= 0 || count > rangeSize (l,u)
431 = illegalBufferSize handle "hPutArray" count
433 = do wantWritableHandle "hPutArray" handle $
434 \ handle_@Handle__{ haFD=fd, haBuffer=ref } -> do
436 old_buf@Buffer{ bufBuf=old_raw, bufRPtr=r, bufWPtr=w, bufSize=size }
439 -- enough room in handle buffer?
440 if (size - w > count)
441 -- There's enough room in the buffer:
442 -- just copy the data in and update bufWPtr.
443 then do memcpy_baoff_ba old_raw w raw (fromIntegral count)
444 writeIORef ref old_buf{ bufWPtr = w + count }
447 -- else, we have to flush
448 else do flushed_buf <- flushWriteBuffer fd old_buf
449 writeIORef ref flushed_buf
451 Buffer{ bufBuf=raw, bufState=WriteBuffer,
452 bufRPtr=0, bufWPtr=count, bufSize=count }
453 flushWriteBuffer fd this_buf
456 -----------------------------------------------------------------------------
459 foreign import "memcpy_wrap_dst_off" unsafe
460 memcpy_baoff_ba :: RawBuffer -> Int -> RawBuffer -> CSize -> IO (Ptr ())
461 foreign import "memcpy_wrap_src_off" unsafe
462 memcpy_ba_baoff :: RawBuffer -> RawBuffer -> Int -> CSize -> IO (Ptr ())
464 illegalBufferSize :: Handle -> String -> Int -> IO a
465 illegalBufferSize handle fn (sz :: Int) =
466 ioException (IOError (Just handle)
468 ("illegal buffer size " ++ showsPrec 9 sz [])
471 #endif /* __GLASGOW_HASKELL__ */