+{-# OPTIONS -#include "HsBase.h" #-}
-----------------------------------------------------------------------------
---
+-- |
-- Module : Data.Array.IO
-- Copyright : (c) The University of Glasgow 2001
--- License : BSD-style (see the file libraries/core/LICENSE)
+-- License : BSD-style (see the file libraries/base/LICENSE)
--
-- Maintainer : libraries@haskell.org
-- Stability : experimental
-- Portability : non-portable
--
--- $Id: IO.hs,v 1.2 2001/09/14 11:25:23 simonmar Exp $
---
--- Mutable boxed/unboxed arrays in the IO monad.
+-- Mutable boxed and unboxed arrays in the IO monad.
--
-----------------------------------------------------------------------------
module Data.Array.IO (
- module Data.Array.MArray,
+ -- * @IO@ arrays with boxed elements
IOArray, -- instance of: Eq, Typeable
+
+ -- * @IO@ arrays with unboxed elements
IOUArray, -- instance of: Eq, Typeable
castIOUArray, -- :: IOUArray i a -> IO (IOUArray i b)
+
+ -- * Overloaded mutable array interface
+ module Data.Array.MArray,
+
+ -- * Doing I\/O with @IOUArray@s
hGetArray, -- :: Handle -> IOUArray Int Word8 -> Int -> IO Int
hPutArray, -- :: Handle -> IOUArray Int Word8 -> Int -> IO ()
) where
import GHC.Base
-----------------------------------------------------------------------------
--- Polymorphic non-strict mutable arrays (IO monad)
-
+-- | Mutable, boxed, non-strict arrays in the 'IO' monad. The type
+-- arguments are as follows:
+--
+-- * @i@: the index type of the array (should be an instance of @Ix@)
+--
+-- * @e@: the element type of the array.
+--
newtype IOArray i e = IOArray (STArray RealWorld i e) deriving Eq
iOArrayTc :: TyCon
-----------------------------------------------------------------------------
-- Flat unboxed mutable arrays (IO monad)
+-- | Mutable, unboxed, strict arrays in the 'IO' monad. The type
+-- arguments are as follows:
+--
+-- * @i@: the index type of the array (should be an instance of @Ix@)
+--
+-- * @e@: the element type of the array. Only certain element types
+-- are supported: see 'MArray' for a list of instances.
+--
newtype IOUArray i e = IOUArray (STUArray RealWorld i e) deriving Eq
iOUArrayTc :: TyCon
castSTUArray :: STUArray s ix a -> ST s (STUArray s ix b)
castSTUArray (STUArray l u marr#) = return (STUArray l u marr#)
+-- | Casts an 'IOUArray' with one element type into one with a
+-- different element type. All the elements of the resulting array
+-- are undefined (unless you know what you\'re doing...).
castIOUArray :: IOUArray ix a -> IO (IOUArray ix b)
castIOUArray (IOUArray marr) = stToIO $ do
marr' <- castSTUArray marr
-- ---------------------------------------------------------------------------
-- hGetArray
-hGetArray :: Handle -> IOUArray Int Word8 -> Int -> IO Int
+-- | Reads a number of 'Word8's from the specified 'Handle' directly
+-- into an array.
+hGetArray
+ :: Handle -- ^ Handle to read from
+ -> IOUArray Int Word8 -- ^ Array in which to place the values
+ -> Int -- ^ Number of 'Word8's to read
+ -> IO Int
+ -- ^ Returns: the number of 'Word8's actually
+ -- read, which might be smaller than the number requested
+ -- if the end of file was reached.
+
hGetArray handle (IOUArray (STUArray l u ptr)) count
| count <= 0 || count > rangeSize (l,u)
= illegalBufferSize handle "hGetArray" count
| otherwise = do
wantReadableHandle "hGetArray" handle $
- \ handle_@Handle__{ haFD=fd, haBuffer=ref } -> do
+ \ handle_@Handle__{ haFD=fd, haBuffer=ref, haIsStream=is_stream } -> do
buf@Buffer{ bufBuf=raw, bufWPtr=w, bufRPtr=r } <- readIORef ref
if bufferEmpty buf
- then readChunkBA fd ptr 0 count
+ then readChunk fd is_stream ptr 0 count
else do
let avail = w - r
copied <- if (count >= avail)
let remaining = count - copied
if remaining > 0
- then do rest <- readChunkBA fd ptr copied remaining
+ then do rest <- readChunk fd is_stream ptr copied remaining
return (rest + count)
else return count
-
-readChunkBA :: FD -> RawBuffer -> Int -> Int -> IO Int
-readChunkBA fd ptr init_off bytes = loop init_off bytes
+
+readChunk :: FD -> Bool -> RawBuffer -> Int -> Int -> IO Int
+readChunk fd is_stream ptr init_off bytes = loop init_off bytes
where
loop :: Int -> Int -> IO Int
loop off bytes | bytes <= 0 = return (off - init_off)
loop off bytes = do
r' <- throwErrnoIfMinus1RetryMayBlock "readChunk"
- (readBA (fromIntegral fd) ptr
+ (read_off_ba (fromIntegral fd) is_stream ptr
(fromIntegral off) (fromIntegral bytes))
(threadWaitRead fd)
let r = fromIntegral r'
then return (off - init_off)
else loop (off + r) (bytes - r)
-foreign import "read_ba_wrap" unsafe
- readBA :: FD -> RawBuffer -> Int -> CInt -> IO CInt
-
- -----------------------------------------------------------------------------
+-- ---------------------------------------------------------------------------
-- hPutArray
+-- | Writes an array of 'Word8' to the specified 'Handle'.
hPutArray
- :: Handle -- handle to write to
- -> IOUArray Int Word8 -- buffer
- -> Int -- number of bytes of data to write
+ :: Handle -- ^ Handle to write to
+ -> IOUArray Int Word8 -- ^ Array to write from
+ -> Int -- ^ Number of 'Word8's to write
-> IO ()
hPutArray handle (IOUArray (STUArray l u raw)) count
= illegalBufferSize handle "hPutArray" count
| otherwise
= do wantWritableHandle "hPutArray" handle $
- \ handle_@Handle__{ haFD=fd, haBuffer=ref } -> do
+ \ handle_@Handle__{ haFD=fd, haBuffer=ref, haIsStream=stream } -> do
old_buf@Buffer{ bufBuf=old_raw, bufRPtr=r, bufWPtr=w, bufSize=size }
<- readIORef ref
return ()
-- else, we have to flush
- else do flushed_buf <- flushWriteBuffer fd old_buf
+ else do flushed_buf <- flushWriteBuffer fd stream old_buf
writeIORef ref flushed_buf
let this_buf =
Buffer{ bufBuf=raw, bufState=WriteBuffer,
bufRPtr=0, bufWPtr=count, bufSize=count }
- flushWriteBuffer fd this_buf
+ flushWriteBuffer fd stream this_buf
return ()
------------------------------------------------------------------------------
+-- ---------------------------------------------------------------------------
-- Internal Utils
-foreign import "memcpy_wrap_dst_off" unsafe
+foreign import ccall unsafe "__hscore_memcpy_dst_off"
memcpy_baoff_ba :: RawBuffer -> Int -> RawBuffer -> CSize -> IO (Ptr ())
-foreign import "memcpy_wrap_src_off" unsafe
+foreign import ccall unsafe "__hscore_memcpy_src_off"
memcpy_ba_baoff :: RawBuffer -> RawBuffer -> Int -> CSize -> IO (Ptr ())
illegalBufferSize :: Handle -> String -> Int -> IO a
-illegalBufferSize handle fn (sz :: Int) =
+illegalBufferSize handle fn sz =
ioException (IOError (Just handle)
InvalidArgument fn
- ("illegal buffer size " ++ showsPrec 9 sz [])
+ ("illegal buffer size " ++ showsPrec 9 (sz::Int) [])
Nothing)
#endif /* __GLASGOW_HASKELL__ */