6d00e46634f85149768ec6292fa659d315b35558
[ghc-hetmet.git] / ghc / compiler / utils / BufWrite.hs
1 -----------------------------------------------------------------------------
2 --
3 -- Fast write-buffered Handles
4 --
5 -- (c) The University of Glasgow 2005
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 import Panic            ( panic )
28
29 import Monad            ( when )
30 import Char             ( ord )
31 import Foreign
32 import IO
33
34 #if __GLASGOW_HASKELL__ < 503
35 import PrelIOBase       ( IO(..) )
36 import IOExts           ( hPutBufFull )
37 #else
38 import GHC.IOBase       ( IO(..) )
39 import System.IO        ( hPutBuf )
40 #endif
41
42 import GLAEXTS          ( touch#, byteArrayContents#, Int(..), Int#, Addr# )
43
44 import PrimPacked       ( Ptr(..) )
45
46 -- -----------------------------------------------------------------------------
47
48 data BufHandle = BufHandle {-#UNPACK#-}!(Ptr Word8)
49                            {-#UNPACK#-}!FastMutInt
50                            Handle
51
52 newBufHandle :: Handle -> IO BufHandle
53 newBufHandle hdl = do
54   ptr <- mallocBytes buf_size
55   r <- newFastMutInt
56   writeFastMutInt r 0
57   return (BufHandle ptr r hdl)
58
59 buf_size = 8192 :: Int
60
61 #define STRICT2(f) f a b | a `seq` b `seq` False = undefined
62 #define STRICT3(f) f a b c | a `seq` b `seq` c `seq` False = undefined
63
64 bPutChar :: BufHandle -> Char -> IO ()
65 STRICT2(bPutChar)
66 bPutChar b@(BufHandle buf r hdl) c = do
67   i <- readFastMutInt r
68   if (i >= buf_size)
69         then do hPutBuf hdl buf buf_size
70                 writeFastMutInt r 0
71                 bPutChar b c
72         else do pokeElemOff buf i (fromIntegral (ord c) :: Word8)
73                 writeFastMutInt r (i+1)
74
75 bPutStr :: BufHandle -> String -> IO ()
76 STRICT2(bPutStr)
77 bPutStr b@(BufHandle buf r hdl) str = do
78   i <- readFastMutInt r
79   loop str i
80   where loop _ i | i `seq` False = undefined
81         loop "" i = do writeFastMutInt r i; return ()
82         loop (c:cs) i
83            | i >= buf_size = do
84                 hPutBuf hdl buf buf_size
85                 loop (c:cs) 0
86            | otherwise = do
87                 pokeElemOff buf i (fromIntegral (ord c))
88                 loop cs (i+1)
89   
90 bPutFS :: BufHandle -> FastString -> IO ()
91 bPutFS b@(BufHandle buf r hdl) fs@(FastString _ len# arr#) = do
92   let len = I# len#
93   i <- readFastMutInt r
94   if (i + len) >= buf_size
95         then do hPutBuf hdl buf i
96                 writeFastMutInt r 0
97                 if (len >= buf_size) 
98                     then do
99                          let a# = byteArrayContents# arr#
100                          hPutBuf hdl (Ptr a#) len
101                          touch fs
102                     else bPutFS b fs
103         else do
104                 let a# = byteArrayContents# arr#
105                 copyBytes (buf `plusPtr` i) (Ptr a#) len
106                 touch fs
107                 writeFastMutInt r (i+len)
108 bPutFS _ _ = panic "bPutFS"
109
110 bPutLitString :: BufHandle -> Addr# -> Int# -> IO ()
111 bPutLitString b@(BufHandle buf r hdl) a# len# = do
112   let len = I# len#
113   i <- readFastMutInt r
114   if (i+len) >= buf_size
115         then do hPutBuf hdl buf i
116                 writeFastMutInt r 0
117                 if (len >= buf_size) 
118                     then hPutBuf hdl (Ptr a#) len
119                     else bPutLitString b a# len#
120         else do
121                 copyBytes (buf `plusPtr` i) (Ptr a#) len
122                 writeFastMutInt r (i+len)
123
124 bFlush :: BufHandle -> IO ()
125 bFlush b@(BufHandle buf r hdl) = do
126   i <- readFastMutInt r
127   when (i > 0) $ hPutBuf hdl buf i
128   free buf
129   return ()
130
131 touch r = IO $ \s -> case touch# r s of s -> (# s, () #)
132
133 #if 0
134 myPutBuf s hdl buf i = 
135   modifyIOError (\e -> ioeSetErrorString e (ioeGetErrorString e ++ ':':s ++ " (" ++ show buf ++ "," ++ show i ++ ")")) $
136
137   hPutBuf hdl buf i
138 #endif