d625a6e6c3de5b39b3e29d61471240828bed28df
[ghc-hetmet.git] / compiler / utils / BufWrite.hs
1 -----------------------------------------------------------------------------
2 --
3 -- Fast write-buffered Handles
4 --
5 -- (c) The University of Glasgow 2005-2006
6 --
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.
10 --
11 -----------------------------------------------------------------------------
12
13 module BufWrite (
14         BufHandle(..),
15         newBufHandle,
16         bPutChar,
17         bPutStr,
18         bPutFS,
19         bPutLitString,
20         bFlush,
21   ) where
22
23 #include "HsVersions.h"
24
25 import FastString
26 import FastMutInt
27
28 import Control.Monad    ( when )
29 import Data.Char        ( ord )
30 import Foreign
31 import System.IO
32
33 import GHC.IOBase       ( IO(..) )
34 import GHC.Ptr          ( Ptr(..) )
35
36 import GHC.Exts         ( Int(..), Int#, Addr# )
37
38 -- -----------------------------------------------------------------------------
39
40 data BufHandle = BufHandle {-#UNPACK#-}!(Ptr Word8)
41                            {-#UNPACK#-}!FastMutInt
42                            Handle
43
44 newBufHandle :: Handle -> IO BufHandle
45 newBufHandle hdl = do
46   ptr <- mallocBytes buf_size
47   r <- newFastMutInt
48   writeFastMutInt r 0
49   return (BufHandle ptr r hdl)
50
51 buf_size :: Int
52 buf_size = 8192
53
54 #define STRICT2(f) f a b | a `seq` b `seq` False = undefined
55 #define STRICT3(f) f a b c | a `seq` b `seq` c `seq` False = undefined
56
57 bPutChar :: BufHandle -> Char -> IO ()
58 STRICT2(bPutChar)
59 bPutChar b@(BufHandle buf r hdl) c = do
60   i <- readFastMutInt r
61   if (i >= buf_size)
62         then do hPutBuf hdl buf buf_size
63                 writeFastMutInt r 0
64                 bPutChar b c
65         else do pokeElemOff buf i (fromIntegral (ord c) :: Word8)
66                 writeFastMutInt r (i+1)
67
68 bPutStr :: BufHandle -> String -> IO ()
69 STRICT2(bPutStr)
70 bPutStr (BufHandle buf r hdl) str = do
71   i <- readFastMutInt r
72   loop str i
73   where loop _ i | i `seq` False = undefined
74         loop "" i = do writeFastMutInt r i; return ()
75         loop (c:cs) i
76            | i >= buf_size = do
77                 hPutBuf hdl buf buf_size
78                 loop (c:cs) 0
79            | otherwise = do
80                 pokeElemOff buf i (fromIntegral (ord c))
81                 loop cs (i+1)
82   
83 bPutFS :: BufHandle -> FastString -> IO ()
84 bPutFS b@(BufHandle buf r hdl) fs@(FastString _ len _ fp _) =
85  withForeignPtr fp $ \ptr -> do
86   i <- readFastMutInt r
87   if (i + len) >= buf_size
88         then do hPutBuf hdl buf i
89                 writeFastMutInt r 0
90                 if (len >= buf_size) 
91                     then hPutBuf hdl ptr len
92                     else bPutFS b fs
93         else do
94                 copyBytes (buf `plusPtr` i) ptr len
95                 writeFastMutInt r (i+len)
96
97 bPutLitString :: BufHandle -> Addr# -> Int# -> IO ()
98 bPutLitString b@(BufHandle buf r hdl) a# len# = do
99   let len = I# len#
100   i <- readFastMutInt r
101   if (i+len) >= buf_size
102         then do hPutBuf hdl buf i
103                 writeFastMutInt r 0
104                 if (len >= buf_size) 
105                     then hPutBuf hdl (Ptr a#) len
106                     else bPutLitString b a# len#
107         else do
108                 copyBytes (buf `plusPtr` i) (Ptr a#) len
109                 writeFastMutInt r (i+len)
110
111 bFlush :: BufHandle -> IO ()
112 bFlush (BufHandle buf r hdl) = do
113   i <- readFastMutInt r
114   when (i > 0) $ hPutBuf hdl buf i
115   free buf
116   return ()
117
118 #if 0
119 myPutBuf s hdl buf i = 
120   modifyIOError (\e -> ioeSetErrorString e (ioeGetErrorString e ++ ':':s ++ " (" ++ show buf ++ "," ++ show i ++ ")")) $
121
122   hPutBuf hdl buf i
123 #endif