@@ -45,24 +45,18 @@ module Data.Text.IO
45
45
import Data.Text (Text )
46
46
import Prelude hiding (appendFile , getContents , getLine , interact ,
47
47
putStr , putStrLn , readFile , writeFile )
48
- import System.IO (Handle , IOMode (.. ), hPutChar , openFile , stdin , stdout ,
48
+ import System.IO (Handle , IOMode (.. ), openFile , stdin , stdout ,
49
49
withFile )
50
50
import qualified Control.Exception as E
51
51
import Control.Monad (liftM2 , when )
52
- import Data.IORef (readIORef , writeIORef )
52
+ import Data.IORef (readIORef )
53
53
import qualified Data.Text as T
54
54
import Data.Text.Internal.Fusion (stream , streamLn )
55
- import Data.Text.Internal.Fusion.Types (Step (.. ), Stream (.. ))
56
- import Data.Text.Internal.IO (hGetLineWith , readChunk )
57
- import GHC.IO.Buffer (Buffer (.. ), BufferState (.. ), RawCharBuffer , CharBuffer ,
58
- emptyBuffer , isEmptyBuffer , newCharBuffer )
59
- import qualified GHC.IO.Buffer
55
+ import Data.Text.Internal.IO (hGetLineWith , readChunk , hPutStream )
56
+ import GHC.IO.Buffer (CharBuffer , isEmptyBuffer )
60
57
import GHC.IO.Exception (IOException (ioe_type ), IOErrorType (InappropriateType ))
61
- import GHC.IO.Handle.Internals (augmentIOError , hClose_help , wantReadableHandle ,
62
- wantWritableHandle )
63
- import GHC.IO.Handle.Text (commitBuffer' )
64
- import GHC.IO.Handle.Types (BufferList (.. ), BufferMode (.. ), Handle__ (.. ),
65
- HandleType (.. ), Newline (.. ))
58
+ import GHC.IO.Handle.Internals (augmentIOError , hClose_help , wantReadableHandle )
59
+ import GHC.IO.Handle.Types (BufferMode (.. ), Handle__ (.. ), HandleType (.. ))
66
60
import System.IO (hGetBuffering , hFileSize , hSetBuffering , hTell )
67
61
import System.IO.Error (isEOFError )
68
62
@@ -174,111 +168,11 @@ hGetLine = hGetLineWith T.concat
174
168
175
169
-- | Write a string to a handle.
176
170
hPutStr :: Handle -> Text -> IO ()
177
- hPutStr h = hPutStr' h . stream
178
-
179
- -- This function is lifted almost verbatim from GHC.IO.Handle.Text.
180
- hPutStr' :: Handle -> Stream Char -> IO ()
181
- hPutStr' h str = do
182
- (buffer_mode, nl) <-
183
- wantWritableHandle " hPutStr" h $ \ h_ -> do
184
- bmode <- getSpareBuffer h_
185
- return (bmode, haOutputNL h_)
186
- case buffer_mode of
187
- (NoBuffering , _) -> hPutChars h str
188
- (LineBuffering , buf) -> writeLines h nl buf str
189
- (BlockBuffering _, buf) -> writeBlocks (nl == CRLF ) h buf str
190
-
191
- hPutChars :: Handle -> Stream Char -> IO ()
192
- hPutChars h (Stream next0 s0 _len) = loop s0
193
- where
194
- loop ! s = case next0 s of
195
- Done -> return ()
196
- Skip s' -> loop s'
197
- Yield x s' -> hPutChar h x >> loop s'
198
-
199
- -- The following functions are largely lifted from GHC.IO.Handle.Text,
200
- -- but adapted to a coinductive stream of data instead of an inductive
201
- -- list.
202
- --
203
- -- We have several variations of more or less the same code for
204
- -- performance reasons. Splitting the original buffered write
205
- -- function into line- and block-oriented versions gave us a 2.1x
206
- -- performance improvement. Lifting out the raw/cooked newline
207
- -- handling gave a few more percent on top.
208
-
209
- writeLines :: Handle -> Newline -> CharBuffer -> Stream Char -> IO ()
210
- writeLines h nl buf0 (Stream next0 s0 _len) = outer s0 buf0
211
- where
212
- outer s1 Buffer {bufRaw= raw, bufSize= len} = inner s1 (0 :: Int )
213
- where
214
- inner ! s ! n =
215
- case next0 s of
216
- Done -> commit n False {- no flush-} True {- release-} >> return ()
217
- Skip s' -> inner s' n
218
- Yield x s'
219
- | n + 1 >= len -> commit n True {- needs flush-} False >>= outer s
220
- | x == ' \n ' -> do
221
- n' <- if nl == CRLF
222
- then do n1 <- writeCharBuf raw len n ' \r '
223
- writeCharBuf raw len n1 ' \n '
224
- else writeCharBuf raw len n x
225
- commit n' True {- needs flush-} False >>= outer s'
226
- | otherwise -> writeCharBuf raw len n x >>= inner s'
227
- commit = commitBuffer h raw len
228
-
229
- writeBlocks :: Bool -> Handle -> CharBuffer -> Stream Char -> IO ()
230
- writeBlocks isCRLF h buf0 (Stream next0 s0 _len) = outer s0 buf0
231
- where
232
- outer s1 Buffer {bufRaw= raw, bufSize= len} = inner s1 (0 :: Int )
233
- where
234
- inner ! s ! n =
235
- case next0 s of
236
- Done -> commit n False {- no flush-} True {- release-} >> return ()
237
- Skip s' -> inner s' n
238
- Yield x s'
239
- | isCRLF && x == ' \n ' && n + 1 < len -> do
240
- n1 <- writeCharBuf raw len n ' \r '
241
- writeCharBuf raw len n1 ' \n ' >>= inner s'
242
- | n < len -> writeCharBuf raw len n x >>= inner s'
243
- | otherwise -> commit n True {- needs flush-} False >>= outer s
244
- commit = commitBuffer h raw len
245
-
246
- -- | Only modifies the raw buffer and not the buffer attributes
247
- writeCharBuf :: RawCharBuffer -> Int -> Int -> Char -> IO Int
248
- writeCharBuf bufRaw bufSize n c = E. assert (n >= 0 && n < bufSize) $
249
- GHC.IO.Buffer. writeCharBuf bufRaw n c
250
-
251
- -- This function is completely lifted from GHC.IO.Handle.Text.
252
- getSpareBuffer :: Handle__ -> IO (BufferMode , CharBuffer )
253
- getSpareBuffer Handle__ {haCharBuffer= ref,
254
- haBuffers= spare_ref,
255
- haBufferMode= mode}
256
- = do
257
- case mode of
258
- NoBuffering -> return (mode, error " no buffer!" )
259
- _ -> do
260
- bufs <- readIORef spare_ref
261
- buf <- readIORef ref
262
- case bufs of
263
- BufferListCons b rest -> do
264
- writeIORef spare_ref rest
265
- return ( mode, emptyBuffer b (bufSize buf) WriteBuffer )
266
- BufferListNil -> do
267
- new_buf <- newCharBuffer (bufSize buf) WriteBuffer
268
- return (mode, new_buf)
269
-
270
-
271
- -- This function is modified from GHC.Internal.IO.Handle.Text.
272
- commitBuffer :: Handle -> RawCharBuffer -> Int -> Int -> Bool -> Bool
273
- -> IO CharBuffer
274
- commitBuffer hdl ! raw ! sz ! count flush release =
275
- wantWritableHandle " commitAndReleaseBuffer" hdl $
276
- commitBuffer' raw sz count flush release
277
- {-# INLINE commitBuffer #-}
171
+ hPutStr h = hPutStream h . stream
278
172
279
173
-- | Write a string to a handle, followed by a newline.
280
174
hPutStrLn :: Handle -> Text -> IO ()
281
- hPutStrLn h = hPutStr' h . streamLn
175
+ hPutStrLn h = hPutStream h . streamLn
282
176
283
177
-- | The 'interact' function takes a function of type @Text -> Text@
284
178
-- as its argument. The entire input from the standard input device is
0 commit comments