/hugs98-plus-Sep2006/fptools/hslibs/lang/IOExts.hs

# · Haskell · 197 lines · 125 code · 35 blank · 37 comment · 16 complexity · 51ef7661c62970c4b1efbbd27e0a311b MD5 · raw file

  1. module IOExts
  2. {-# DEPRECATED "This library will go away soon; see Data.Array.IO, Data.IORef, and System.IO" #-}
  3. (
  4. module System.IO.Unsafe,
  5. IOArray,
  6. newIOArray,
  7. boundsIOArray,
  8. readIOArray,
  9. writeIOArray,
  10. freezeIOArray,
  11. thawIOArray,
  12. unsafeFreezeIOArray,
  13. unsafeThawIOArray,
  14. module Data.IORef,
  15. System.IO.fixIO,
  16. IOModeEx(..),
  17. openFileEx,
  18. hSetBinaryMode
  19. , hGetBuf -- :: Handle -> Ptr a -> Int -> IO Int
  20. , hGetBufBA -- :: Handle -> MutableByteArray RealWorld a
  21. -- -> Int -> IO Int
  22. , hPutBuf -- :: Handle -> Ptr a -> Int -> IO ()
  23. , hPutBufBA -- :: Handle -> MutableByteArray RealWorld a
  24. -- -> Int -> IO ()
  25. , slurpFile
  26. , trace -- :: String -> a -> a
  27. , hIsTerminalDevice -- :: Handle -> IO Bool
  28. , hSetEcho -- :: Handle -> Bool -> IO ()
  29. , hGetEcho -- :: Handle -> IO Bool
  30. , performGC
  31. , hTell -- :: Handle -> IO Integer
  32. {- unsafePtrEq -- :: a -> a -> Bool
  33. freeHaskellFunctionPtr
  34. extended IOError predicates
  35. isHardwareFault -- :: IOError -> Bool
  36. isInappropriateType -- :: IOError -> Bool
  37. isInterrupted -- :: IOError -> Bool
  38. isInvalidArgument -- :: IOError -> Bool
  39. isOtherError -- :: IOError -> Bool
  40. isProtocolError -- :: IOError -> Bool
  41. isResourceVanished -- :: IOError -> Bool
  42. isSystemError -- :: IOError -> Bool
  43. isTimeExpired -- :: IOError -> Bool
  44. isUnsatisfiedConstraints -- :: IOError -> Bool
  45. isUnsupportedOperation -- :: IOError -> Bool
  46. #if defined(cygwin32_HOST_OS) || defined(mingw32_HOST_OS)
  47. isComError -- :: IOError -> Bool
  48. #endif
  49. -}
  50. ) where
  51. import GHC.IOBase
  52. import System.IO
  53. import System.IO.Unsafe
  54. import System.Mem ( performGC )
  55. import Data.Array.IO
  56. import Data.IORef
  57. import Debug.Trace ( trace )
  58. import Data.Array ( Array )
  59. import GHC.Base ( RealWorld )
  60. import GHC.IO ( slurpFile, memcpy_ba_baoff, memcpy_baoff_ba )
  61. import GHC.Handle
  62. import MutableArray
  63. import Control.Monad ( liftM )
  64. -- ---------------------------------------------------------------------------
  65. -- IOArray compat.
  66. unsafeThawIOArray :: Ix ix => Array ix elt -> IO (IOArray ix elt)
  67. unsafeThawIOArray = unsafeThaw
  68. unsafeFreezeIOArray :: Ix ix => IOArray ix elt -> IO (Array ix elt)
  69. unsafeFreezeIOArray = unsafeFreeze
  70. thawIOArray :: Ix ix => Array ix elt -> IO (IOArray ix elt)
  71. thawIOArray = thaw
  72. freezeIOArray :: Ix ix => IOArray ix elt -> IO (Array ix elt)
  73. freezeIOArray = freeze
  74. boundsIOArray :: Ix ix => IOArray ix elt -> (ix, ix)
  75. boundsIOArray = bounds
  76. -- ---------------------------------------------------------------------------
  77. -- hGetBufBA
  78. hGetBufBA :: Handle -> MutableByteArray RealWorld a -> Int -> IO Int
  79. hGetBufBA handle (MutableByteArray _ _ ptr) count
  80. | count <= 0 = illegalBufferSize handle "hGetBuf" count
  81. | otherwise =
  82. wantReadableHandle "hGetBuf" handle $
  83. \ handle_@Handle__{ haFD=fd, haBuffer=ref, haIsStream=isStream } -> do
  84. buf@Buffer{ bufBuf=raw, bufWPtr=w, bufRPtr=r } <- readIORef ref
  85. if bufferEmpty buf
  86. then readChunkBA fd isStream ptr 0 count
  87. else do
  88. let avail = w - r
  89. copied <- if (count >= avail)
  90. then do
  91. memcpy_ba_baoff ptr raw r (fromIntegral avail)
  92. writeIORef ref buf{ bufWPtr=0, bufRPtr=0 }
  93. return avail
  94. else do
  95. memcpy_ba_baoff ptr raw r (fromIntegral count)
  96. writeIORef ref buf{ bufRPtr = r + count }
  97. return count
  98. let remaining = count - copied
  99. if remaining > 0
  100. then do rest <- readChunkBA fd isStream ptr copied remaining
  101. return (rest + copied)
  102. else return count
  103. readChunkBA :: FD -> Bool -> RawBuffer -> Int -> Int -> IO Int
  104. readChunkBA fd is_stream ptr init_off bytes = loop init_off bytes
  105. where
  106. loop :: Int -> Int -> IO Int
  107. loop off bytes | bytes <= 0 = return (off - init_off)
  108. loop off bytes = do
  109. r <- fromIntegral `liftM`
  110. readRawBuffer "IOExts.readChunk" (fromIntegral fd) is_stream ptr
  111. (fromIntegral off) (fromIntegral bytes)
  112. if r == 0
  113. then return (off - init_off)
  114. else loop (off + r) (bytes - r)
  115. -- -----------------------------------------------------------------------------
  116. -- hPutBufBA
  117. hPutBufBA
  118. :: Handle -- handle to write to
  119. -> MutableByteArray RealWorld a -- buffer
  120. -> Int -- number of bytes of data in buffer
  121. -> IO ()
  122. hPutBufBA handle (MutableByteArray _ _ raw) count
  123. | count <= 0 = illegalBufferSize handle "hPutBufBA" count
  124. | otherwise = do
  125. wantWritableHandle "hPutBufBA" handle $
  126. \ handle_@Handle__{ haFD=fd, haBuffer=ref } -> do
  127. old_buf@Buffer{ bufBuf=old_raw, bufWPtr=w, bufSize=size }
  128. <- readIORef ref
  129. -- enough room in handle buffer?
  130. if (size - w > count)
  131. -- There's enough room in the buffer:
  132. -- just copy the data in and update bufWPtr.
  133. then do memcpy_baoff_ba old_raw w raw (fromIntegral count)
  134. writeIORef ref old_buf{ bufWPtr = w + count }
  135. return ()
  136. -- else, we have to flush
  137. else do flushed_buf <- flushWriteBuffer fd (haIsStream handle_) old_buf
  138. writeIORef ref flushed_buf
  139. let this_buf =
  140. Buffer{ bufBuf=raw, bufState=WriteBuffer,
  141. bufRPtr=0, bufWPtr=count, bufSize=count }
  142. flushWriteBuffer fd (haIsStream handle_) this_buf
  143. return ()
  144. -----------------------------------------------------------------------------
  145. -- Internal Utils
  146. illegalBufferSize :: Handle -> String -> Int -> IO a
  147. illegalBufferSize handle fn (sz :: Int) =
  148. ioException (IOError (Just handle)
  149. InvalidArgument fn
  150. ("illegal buffer size " ++ showsPrec 9 sz [])
  151. Nothing)
  152. -- -----------------------------------------------------------------------------
  153. -- openFileEx
  154. {-# DEPRECATED openFileEx, IOModeEx "use System.IO.openBinaryFile instead" #-}
  155. data IOModeEx
  156. = BinaryMode IOMode
  157. | TextMode IOMode
  158. deriving (Eq, Read, Show)
  159. openFileEx :: FilePath -> IOModeEx -> IO Handle
  160. openFileEx path (TextMode mode) = openFile path mode
  161. openFileEx path (BinaryMode mode) = openBinaryFile path mode