1 {-# OPTIONS -#include "HsBase.h" #-}
2 -----------------------------------------------------------------------------
4 -- Module : Data.Array.IO
5 -- Copyright : (c) The University of Glasgow 2001
6 -- License : BSD-style (see the file libraries/base/LICENSE)
8 -- Maintainer : libraries@haskell.org
9 -- Stability : experimental
10 -- Portability : non-portable
12 -- Mutable boxed and unboxed arrays in the IO monad.
14 -----------------------------------------------------------------------------
16 module Data.Array.IO (
17 -- * @IO@ arrays with boxed elements
18 IOArray, -- instance of: Eq, Typeable
20 -- * @IO@ arrays with unboxed elements
21 IOUArray, -- instance of: Eq, Typeable
22 #ifdef __GLASGOW_HASKELL__
23 castIOUArray, -- :: IOUArray i a -> IO (IOUArray i b)
26 -- * Overloaded mutable array interface
27 module Data.Array.MArray,
29 #ifdef __GLASGOW_HASKELL__
30 -- * Doing I\/O with @IOUArray@s
31 hGetArray, -- :: Handle -> IOUArray Int Word8 -> Int -> IO Int
32 hPutArray, -- :: Handle -> IOUArray Int Word8 -> Int -> IO ()
38 import Data.Array ( Array )
39 import Data.Array.MArray
46 import Data.Array.Storable
49 #ifdef __GLASGOW_HASKELL__
51 import Foreign.Ptr ( Ptr, FunPtr )
52 import Foreign.StablePtr ( StablePtr )
54 import Data.Array.Base
55 import GHC.Arr ( STArray, freezeSTArray, unsafeFreezeSTArray,
56 thawSTArray, unsafeThawSTArray )
58 import GHC.ST ( ST(..) )
65 #endif /* __GLASGOW_HASKELL__ */
68 instance HasBounds IOArray where
69 bounds = boundsIOArray
71 instance MArray IOArray e IO where
73 unsafeRead = unsafeReadIOArray
74 unsafeWrite = unsafeWriteIOArray
76 type IOUArray = StorableArray
80 iOArrayTc = mkTyCon "IOArray"
82 instance (Typeable a, Typeable b) => Typeable (IOArray a b) where
83 typeOf a = mkAppTy iOArrayTc [typeOf ((undefined :: IOArray a b -> a) a),
84 typeOf ((undefined :: IOArray a b -> b) a)]
86 #ifdef __GLASGOW_HASKELL__
87 -- GHC only to the end of file
89 -----------------------------------------------------------------------------
90 -- | Mutable, boxed, non-strict arrays in the 'IO' monad. The type
91 -- arguments are as follows:
93 -- * @i@: the index type of the array (should be an instance of @Ix@)
95 -- * @e@: the element type of the array.
97 newtype IOArray i e = IOArray (STArray RealWorld i e) deriving Eq
99 instance HasBounds IOArray where
100 {-# INLINE bounds #-}
101 bounds (IOArray marr) = bounds marr
103 instance MArray IOArray e IO where
104 {-# INLINE newArray #-}
105 newArray lu init = stToIO $ do
106 marr <- newArray lu init; return (IOArray marr)
107 {-# INLINE newArray_ #-}
108 newArray_ lu = stToIO $ do
109 marr <- newArray_ lu; return (IOArray marr)
110 {-# INLINE unsafeRead #-}
111 unsafeRead (IOArray marr) i = stToIO (unsafeRead marr i)
112 {-# INLINE unsafeWrite #-}
113 unsafeWrite (IOArray marr) i e = stToIO (unsafeWrite marr i e)
115 -----------------------------------------------------------------------------
116 -- Flat unboxed mutable arrays (IO monad)
118 -- | Mutable, unboxed, strict arrays in the 'IO' monad. The type
119 -- arguments are as follows:
121 -- * @i@: the index type of the array (should be an instance of @Ix@)
123 -- * @e@: the element type of the array. Only certain element types
124 -- are supported: see 'MArray' for a list of instances.
126 newtype IOUArray i e = IOUArray (STUArray RealWorld i e) deriving Eq
129 iOUArrayTc = mkTyCon "IOUArray"
131 instance (Typeable a, Typeable b) => Typeable (IOUArray a b) where
132 typeOf a = mkAppTy iOUArrayTc [typeOf ((undefined :: IOUArray a b -> a) a),
133 typeOf ((undefined :: IOUArray a b -> b) a)]
135 instance HasBounds IOUArray where
136 {-# INLINE bounds #-}
137 bounds (IOUArray marr) = bounds marr
139 instance MArray IOUArray Bool IO where
140 {-# INLINE newArray #-}
141 newArray lu init = stToIO $ do
142 marr <- newArray lu init; return (IOUArray marr)
143 {-# INLINE newArray_ #-}
144 newArray_ lu = stToIO $ do
145 marr <- newArray_ lu; return (IOUArray marr)
146 {-# INLINE unsafeRead #-}
147 unsafeRead (IOUArray marr) i = stToIO (unsafeRead marr i)
148 {-# INLINE unsafeWrite #-}
149 unsafeWrite (IOUArray marr) i e = stToIO (unsafeWrite marr i e)
151 instance MArray IOUArray Char IO where
152 {-# INLINE newArray #-}
153 newArray lu init = stToIO $ do
154 marr <- newArray lu init; return (IOUArray marr)
155 {-# INLINE newArray_ #-}
156 newArray_ lu = stToIO $ do
157 marr <- newArray_ lu; return (IOUArray marr)
158 {-# INLINE unsafeRead #-}
159 unsafeRead (IOUArray marr) i = stToIO (unsafeRead marr i)
160 {-# INLINE unsafeWrite #-}
161 unsafeWrite (IOUArray marr) i e = stToIO (unsafeWrite marr i e)
163 instance MArray IOUArray Int IO where
164 {-# INLINE newArray #-}
165 newArray lu init = stToIO $ do
166 marr <- newArray lu init; return (IOUArray marr)
167 {-# INLINE newArray_ #-}
168 newArray_ lu = stToIO $ do
169 marr <- newArray_ lu; return (IOUArray marr)
170 {-# INLINE unsafeRead #-}
171 unsafeRead (IOUArray marr) i = stToIO (unsafeRead marr i)
172 {-# INLINE unsafeWrite #-}
173 unsafeWrite (IOUArray marr) i e = stToIO (unsafeWrite marr i e)
175 instance MArray IOUArray Word IO where
176 {-# INLINE newArray #-}
177 newArray lu init = stToIO $ do
178 marr <- newArray lu init; return (IOUArray marr)
179 {-# INLINE newArray_ #-}
180 newArray_ lu = stToIO $ do
181 marr <- newArray_ lu; return (IOUArray marr)
182 {-# INLINE unsafeRead #-}
183 unsafeRead (IOUArray marr) i = stToIO (unsafeRead marr i)
184 {-# INLINE unsafeWrite #-}
185 unsafeWrite (IOUArray marr) i e = stToIO (unsafeWrite marr i e)
187 instance MArray IOUArray (Ptr a) IO where
188 {-# INLINE newArray #-}
189 newArray lu init = stToIO $ do
190 marr <- newArray lu init; return (IOUArray marr)
191 {-# INLINE newArray_ #-}
192 newArray_ lu = stToIO $ do
193 marr <- newArray_ lu; return (IOUArray marr)
194 {-# INLINE unsafeRead #-}
195 unsafeRead (IOUArray marr) i = stToIO (unsafeRead marr i)
196 {-# INLINE unsafeWrite #-}
197 unsafeWrite (IOUArray marr) i e = stToIO (unsafeWrite marr i e)
199 instance MArray IOUArray (FunPtr a) IO where
200 {-# INLINE newArray #-}
201 newArray lu init = stToIO $ do
202 marr <- newArray lu init; return (IOUArray marr)
203 {-# INLINE newArray_ #-}
204 newArray_ lu = stToIO $ do
205 marr <- newArray_ lu; return (IOUArray marr)
206 {-# INLINE unsafeRead #-}
207 unsafeRead (IOUArray marr) i = stToIO (unsafeRead marr i)
208 {-# INLINE unsafeWrite #-}
209 unsafeWrite (IOUArray marr) i e = stToIO (unsafeWrite marr i e)
211 instance MArray IOUArray Float IO where
212 {-# INLINE newArray #-}
213 newArray lu init = stToIO $ do
214 marr <- newArray lu init; return (IOUArray marr)
215 {-# INLINE newArray_ #-}
216 newArray_ lu = stToIO $ do
217 marr <- newArray_ lu; return (IOUArray marr)
218 {-# INLINE unsafeRead #-}
219 unsafeRead (IOUArray marr) i = stToIO (unsafeRead marr i)
220 {-# INLINE unsafeWrite #-}
221 unsafeWrite (IOUArray marr) i e = stToIO (unsafeWrite marr i e)
223 instance MArray IOUArray Double IO where
224 {-# INLINE newArray #-}
225 newArray lu init = stToIO $ do
226 marr <- newArray lu init; return (IOUArray marr)
227 {-# INLINE newArray_ #-}
228 newArray_ lu = stToIO $ do
229 marr <- newArray_ lu; return (IOUArray marr)
230 {-# INLINE unsafeRead #-}
231 unsafeRead (IOUArray marr) i = stToIO (unsafeRead marr i)
232 {-# INLINE unsafeWrite #-}
233 unsafeWrite (IOUArray marr) i e = stToIO (unsafeWrite marr i e)
235 instance MArray IOUArray (StablePtr a) IO where
236 {-# INLINE newArray #-}
237 newArray lu init = stToIO $ do
238 marr <- newArray lu init; return (IOUArray marr)
239 {-# INLINE newArray_ #-}
240 newArray_ lu = stToIO $ do
241 marr <- newArray_ lu; return (IOUArray marr)
242 {-# INLINE unsafeRead #-}
243 unsafeRead (IOUArray marr) i = stToIO (unsafeRead marr i)
244 {-# INLINE unsafeWrite #-}
245 unsafeWrite (IOUArray marr) i e = stToIO (unsafeWrite marr i e)
247 instance MArray IOUArray Int8 IO where
248 {-# INLINE newArray #-}
249 newArray lu init = stToIO $ do
250 marr <- newArray lu init; return (IOUArray marr)
251 {-# INLINE newArray_ #-}
252 newArray_ lu = stToIO $ do
253 marr <- newArray_ lu; return (IOUArray marr)
254 {-# INLINE unsafeRead #-}
255 unsafeRead (IOUArray marr) i = stToIO (unsafeRead marr i)
256 {-# INLINE unsafeWrite #-}
257 unsafeWrite (IOUArray marr) i e = stToIO (unsafeWrite marr i e)
259 instance MArray IOUArray Int16 IO where
260 {-# INLINE newArray #-}
261 newArray lu init = stToIO $ do
262 marr <- newArray lu init; return (IOUArray marr)
263 {-# INLINE newArray_ #-}
264 newArray_ lu = stToIO $ do
265 marr <- newArray_ lu; return (IOUArray marr)
266 {-# INLINE unsafeRead #-}
267 unsafeRead (IOUArray marr) i = stToIO (unsafeRead marr i)
268 {-# INLINE unsafeWrite #-}
269 unsafeWrite (IOUArray marr) i e = stToIO (unsafeWrite marr i e)
271 instance MArray IOUArray Int32 IO where
272 {-# INLINE newArray #-}
273 newArray lu init = stToIO $ do
274 marr <- newArray lu init; return (IOUArray marr)
275 {-# INLINE newArray_ #-}
276 newArray_ lu = stToIO $ do
277 marr <- newArray_ lu; return (IOUArray marr)
278 {-# INLINE unsafeRead #-}
279 unsafeRead (IOUArray marr) i = stToIO (unsafeRead marr i)
280 {-# INLINE unsafeWrite #-}
281 unsafeWrite (IOUArray marr) i e = stToIO (unsafeWrite marr i e)
283 instance MArray IOUArray Int64 IO where
284 {-# INLINE newArray #-}
285 newArray lu init = stToIO $ do
286 marr <- newArray lu init; return (IOUArray marr)
287 {-# INLINE newArray_ #-}
288 newArray_ lu = stToIO $ do
289 marr <- newArray_ lu; return (IOUArray marr)
290 {-# INLINE unsafeRead #-}
291 unsafeRead (IOUArray marr) i = stToIO (unsafeRead marr i)
292 {-# INLINE unsafeWrite #-}
293 unsafeWrite (IOUArray marr) i e = stToIO (unsafeWrite marr i e)
295 instance MArray IOUArray Word8 IO where
296 {-# INLINE newArray #-}
297 newArray lu init = stToIO $ do
298 marr <- newArray lu init; return (IOUArray marr)
299 {-# INLINE newArray_ #-}
300 newArray_ lu = stToIO $ do
301 marr <- newArray_ lu; return (IOUArray marr)
302 {-# INLINE unsafeRead #-}
303 unsafeRead (IOUArray marr) i = stToIO (unsafeRead marr i)
304 {-# INLINE unsafeWrite #-}
305 unsafeWrite (IOUArray marr) i e = stToIO (unsafeWrite marr i e)
307 instance MArray IOUArray Word16 IO where
308 {-# INLINE newArray #-}
309 newArray lu init = stToIO $ do
310 marr <- newArray lu init; return (IOUArray marr)
311 {-# INLINE newArray_ #-}
312 newArray_ lu = stToIO $ do
313 marr <- newArray_ lu; return (IOUArray marr)
314 {-# INLINE unsafeRead #-}
315 unsafeRead (IOUArray marr) i = stToIO (unsafeRead marr i)
316 {-# INLINE unsafeWrite #-}
317 unsafeWrite (IOUArray marr) i e = stToIO (unsafeWrite marr i e)
319 instance MArray IOUArray Word32 IO where
320 {-# INLINE newArray #-}
321 newArray lu init = stToIO $ do
322 marr <- newArray lu init; return (IOUArray marr)
323 {-# INLINE newArray_ #-}
324 newArray_ lu = stToIO $ do
325 marr <- newArray_ lu; return (IOUArray marr)
326 {-# INLINE unsafeRead #-}
327 unsafeRead (IOUArray marr) i = stToIO (unsafeRead marr i)
328 {-# INLINE unsafeWrite #-}
329 unsafeWrite (IOUArray marr) i e = stToIO (unsafeWrite marr i e)
331 instance MArray IOUArray Word64 IO where
332 {-# INLINE newArray #-}
333 newArray lu init = stToIO $ do
334 marr <- newArray lu init; return (IOUArray marr)
335 {-# INLINE newArray_ #-}
336 newArray_ lu = stToIO $ do
337 marr <- newArray_ lu; return (IOUArray marr)
338 {-# INLINE unsafeRead #-}
339 unsafeRead (IOUArray marr) i = stToIO (unsafeRead marr i)
340 {-# INLINE unsafeWrite #-}
341 unsafeWrite (IOUArray marr) i e = stToIO (unsafeWrite marr i e)
343 -----------------------------------------------------------------------------
346 freezeIOArray :: Ix ix => IOArray ix e -> IO (Array ix e)
347 freezeIOArray (IOArray marr) = stToIO (freezeSTArray marr)
349 freezeIOUArray :: Ix ix => IOUArray ix e -> IO (UArray ix e)
350 freezeIOUArray (IOUArray marr) = stToIO (freezeSTUArray marr)
353 "freeze/IOArray" freeze = freezeIOArray
354 "freeze/IOUArray" freeze = freezeIOUArray
357 {-# INLINE unsafeFreezeIOArray #-}
358 unsafeFreezeIOArray :: Ix ix => IOArray ix e -> IO (Array ix e)
359 unsafeFreezeIOArray (IOArray marr) = stToIO (unsafeFreezeSTArray marr)
361 {-# INLINE unsafeFreezeIOUArray #-}
362 unsafeFreezeIOUArray :: Ix ix => IOUArray ix e -> IO (UArray ix e)
363 unsafeFreezeIOUArray (IOUArray marr) = stToIO (unsafeFreezeSTUArray marr)
366 "unsafeFreeze/IOArray" unsafeFreeze = unsafeFreezeIOArray
367 "unsafeFreeze/IOUArray" unsafeFreeze = unsafeFreezeIOUArray
370 -----------------------------------------------------------------------------
373 thawIOArray :: Ix ix => Array ix e -> IO (IOArray ix e)
374 thawIOArray arr = stToIO $ do
375 marr <- thawSTArray arr
376 return (IOArray marr)
378 thawIOUArray :: Ix ix => UArray ix e -> IO (IOUArray ix e)
379 thawIOUArray arr = stToIO $ do
380 marr <- thawSTUArray arr
381 return (IOUArray marr)
384 "thaw/IOArray" thaw = thawIOArray
385 "thaw/IOUArray" thaw = thawIOUArray
388 {-# INLINE unsafeThawIOArray #-}
389 unsafeThawIOArray :: Ix ix => Array ix e -> IO (IOArray ix e)
390 unsafeThawIOArray arr = stToIO $ do
391 marr <- unsafeThawSTArray arr
392 return (IOArray marr)
394 {-# INLINE unsafeThawIOUArray #-}
395 unsafeThawIOUArray :: Ix ix => UArray ix e -> IO (IOUArray ix e)
396 unsafeThawIOUArray arr = stToIO $ do
397 marr <- unsafeThawSTUArray arr
398 return (IOUArray marr)
401 "unsafeThaw/IOArray" unsafeThaw = unsafeThawIOArray
402 "unsafeThaw/IOUArray" unsafeThaw = unsafeThawIOUArray
405 castSTUArray :: STUArray s ix a -> ST s (STUArray s ix b)
406 castSTUArray (STUArray l u marr#) = return (STUArray l u marr#)
408 -- | Casts an 'IOUArray' with one element type into one with a
409 -- different element type. All the elements of the resulting array
410 -- are undefined (unless you know what you\'re doing...).
411 castIOUArray :: IOUArray ix a -> IO (IOUArray ix b)
412 castIOUArray (IOUArray marr) = stToIO $ do
413 marr' <- castSTUArray marr
414 return (IOUArray marr')
416 -- ---------------------------------------------------------------------------
419 -- | Reads a number of 'Word8's from the specified 'Handle' directly
422 :: Handle -- ^ Handle to read from
423 -> IOUArray Int Word8 -- ^ Array in which to place the values
424 -> Int -- ^ Number of 'Word8's to read
426 -- ^ Returns: the number of 'Word8's actually
427 -- read, which might be smaller than the number requested
428 -- if the end of file was reached.
430 hGetArray handle (IOUArray (STUArray l u ptr)) count
431 | count <= 0 || count > rangeSize (l,u)
432 = illegalBufferSize handle "hGetArray" count
434 wantReadableHandle "hGetArray" handle $
435 \ handle_@Handle__{ haFD=fd, haBuffer=ref, haIsStream=is_stream } -> do
436 buf@Buffer{ bufBuf=raw, bufWPtr=w, bufRPtr=r } <- readIORef ref
438 then readChunk fd is_stream ptr 0 count
441 copied <- if (count >= avail)
443 memcpy_ba_baoff ptr raw r (fromIntegral avail)
444 writeIORef ref buf{ bufWPtr=0, bufRPtr=0 }
447 memcpy_ba_baoff ptr raw r (fromIntegral count)
448 writeIORef ref buf{ bufRPtr = r + count }
451 let remaining = count - copied
453 then do rest <- readChunk fd is_stream ptr copied remaining
454 return (rest + count)
457 readChunk :: FD -> Bool -> RawBuffer -> Int -> Int -> IO Int
458 readChunk fd is_stream ptr init_off bytes = loop init_off bytes
460 loop :: Int -> Int -> IO Int
461 loop off bytes | bytes <= 0 = return (off - init_off)
463 r' <- throwErrnoIfMinus1RetryMayBlock "readChunk"
464 (read_off_ba (fromIntegral fd) is_stream ptr
465 (fromIntegral off) (fromIntegral bytes))
467 let r = fromIntegral r'
469 then return (off - init_off)
470 else loop (off + r) (bytes - r)
472 -- ---------------------------------------------------------------------------
475 -- | Writes an array of 'Word8' to the specified 'Handle'.
477 :: Handle -- ^ Handle to write to
478 -> IOUArray Int Word8 -- ^ Array to write from
479 -> Int -- ^ Number of 'Word8's to write
482 hPutArray handle (IOUArray (STUArray l u raw)) count
483 | count <= 0 || count > rangeSize (l,u)
484 = illegalBufferSize handle "hPutArray" count
486 = do wantWritableHandle "hPutArray" handle $
487 \ handle_@Handle__{ haFD=fd, haBuffer=ref, haIsStream=stream } -> do
489 old_buf@Buffer{ bufBuf=old_raw, bufRPtr=r, bufWPtr=w, bufSize=size }
492 -- enough room in handle buffer?
493 if (size - w > count)
494 -- There's enough room in the buffer:
495 -- just copy the data in and update bufWPtr.
496 then do memcpy_baoff_ba old_raw w raw (fromIntegral count)
497 writeIORef ref old_buf{ bufWPtr = w + count }
500 -- else, we have to flush
501 else do flushed_buf <- flushWriteBuffer fd stream old_buf
502 writeIORef ref flushed_buf
504 Buffer{ bufBuf=raw, bufState=WriteBuffer,
505 bufRPtr=0, bufWPtr=count, bufSize=count }
506 flushWriteBuffer fd stream this_buf
509 -- ---------------------------------------------------------------------------
512 foreign import ccall unsafe "__hscore_memcpy_dst_off"
513 memcpy_baoff_ba :: RawBuffer -> Int -> RawBuffer -> CSize -> IO (Ptr ())
514 foreign import ccall unsafe "__hscore_memcpy_src_off"
515 memcpy_ba_baoff :: RawBuffer -> RawBuffer -> Int -> CSize -> IO (Ptr ())
517 illegalBufferSize :: Handle -> String -> Int -> IO a
518 illegalBufferSize handle fn sz =
519 ioException (IOError (Just handle)
521 ("illegal buffer size " ++ showsPrec 9 (sz::Int) [])
524 #endif /* __GLASGOW_HASKELL__ */