1 -----------------------------------------------------------------------------
3 -- Fast write-buffered Handles
5 -- (c) The University of Glasgow 2005-2006
7 -- This is a simple abstraction over Handles that offers very fast write
8 -- buffering, but without the thread safety that Handles provide. It's used
9 -- to save time in Pretty.printDoc.
11 -----------------------------------------------------------------------------
23 #include "HsVersions.h"
29 import Control.Monad ( when )
30 import Data.Char ( ord )
34 -- -----------------------------------------------------------------------------
36 data BufHandle = BufHandle {-#UNPACK#-}!(Ptr Word8)
37 {-#UNPACK#-}!FastMutInt
40 newBufHandle :: Handle -> IO BufHandle
42 ptr <- mallocBytes buf_size
45 return (BufHandle ptr r hdl)
50 #define STRICT2(f) f a b | a `seq` b `seq` False = undefined
51 #define STRICT3(f) f a b c | a `seq` b `seq` c `seq` False = undefined
53 bPutChar :: BufHandle -> Char -> IO ()
55 bPutChar b@(BufHandle buf r hdl) c = do
58 then do hPutBuf hdl buf buf_size
61 else do pokeElemOff buf i (fromIntegral (ord c) :: Word8)
62 writeFastMutInt r (i+1)
64 bPutStr :: BufHandle -> String -> IO ()
66 bPutStr (BufHandle buf r hdl) str = do
69 where loop _ i | i `seq` False = undefined
70 loop "" i = do writeFastMutInt r i; return ()
73 hPutBuf hdl buf buf_size
76 pokeElemOff buf i (fromIntegral (ord c))
79 bPutFS :: BufHandle -> FastString -> IO ()
80 bPutFS b@(BufHandle buf r hdl) fs@(FastString _ len _ fp _) =
81 withForeignPtr fp $ \ptr -> do
83 if (i + len) >= buf_size
84 then do hPutBuf hdl buf i
87 then hPutBuf hdl ptr len
90 copyBytes (buf `plusPtr` i) ptr len
91 writeFastMutInt r (i+len)
93 bPutLitString :: BufHandle -> LitString -> FastInt -> IO ()
94 bPutLitString b@(BufHandle buf r hdl) a len_ = a `seq` do
97 if (i+len) >= buf_size
98 then do hPutBuf hdl buf i
101 then hPutBuf hdl a len
102 else bPutLitString b a len_
104 copyBytes (buf `plusPtr` i) a len
105 writeFastMutInt r (i+len)
107 bFlush :: BufHandle -> IO ()
108 bFlush (BufHandle buf r hdl) = do
109 i <- readFastMutInt r
110 when (i > 0) $ hPutBuf hdl buf i
115 myPutBuf s hdl buf i =
116 modifyIOError (\e -> ioeSetErrorString e (ioeGetErrorString e ++ ':':s ++ " (" ++ show buf ++ "," ++ show i ++ ")")) $