remove empty dir
[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 import GHC.IOBase       ( IO(..) )
35 import System.IO        ( hPutBuf )
36 import GHC.Ptr          ( Ptr(..) )
37
38 import GLAEXTS          ( Int(..), Int#, Addr# )
39
40 -- -----------------------------------------------------------------------------
41
42 data BufHandle = BufHandle {-#UNPACK#-}!(Ptr Word8)
43                            {-#UNPACK#-}!FastMutInt
44                            Handle
45
46 newBufHandle :: Handle -> IO BufHandle
47 newBufHandle hdl = do
48   ptr <- mallocBytes buf_size
49   r <- newFastMutInt
50   writeFastMutInt r 0
51   return (BufHandle ptr r hdl)
52
53 buf_size = 8192 :: Int
54
55 #define STRICT2(f) f a b | a `seq` b `seq` False = undefined
56 #define STRICT3(f) f a b c | a `seq` b `seq` c `seq` False = undefined
57
58 bPutChar :: BufHandle -> Char -> IO ()
59 STRICT2(bPutChar)
60 bPutChar b@(BufHandle buf r hdl) c = do
61   i <- readFastMutInt r
62   if (i >= buf_size)
63         then do hPutBuf hdl buf buf_size
64                 writeFastMutInt r 0
65                 bPutChar b c
66         else do pokeElemOff buf i (fromIntegral (ord c) :: Word8)
67                 writeFastMutInt r (i+1)
68
69 bPutStr :: BufHandle -> String -> IO ()
70 STRICT2(bPutStr)
71 bPutStr b@(BufHandle buf r hdl) str = do
72   i <- readFastMutInt r
73   loop str i
74   where loop _ i | i `seq` False = undefined
75         loop "" i = do writeFastMutInt r i; return ()
76         loop (c:cs) i
77            | i >= buf_size = do
78                 hPutBuf hdl buf buf_size
79                 loop (c:cs) 0
80            | otherwise = do
81                 pokeElemOff buf i (fromIntegral (ord c))
82                 loop cs (i+1)
83   
84 bPutFS :: BufHandle -> FastString -> IO ()
85 bPutFS b@(BufHandle buf r hdl) fs@(FastString _ len _ fp _) =
86  withForeignPtr fp $ \ptr -> do
87   i <- readFastMutInt r
88   if (i + len) >= buf_size
89         then do hPutBuf hdl buf i
90                 writeFastMutInt r 0
91                 if (len >= buf_size) 
92                     then hPutBuf hdl ptr len
93                     else bPutFS b fs
94         else do
95                 copyBytes (buf `plusPtr` i) ptr len
96                 writeFastMutInt r (i+len)
97
98 bPutLitString :: BufHandle -> Addr# -> Int# -> IO ()
99 bPutLitString b@(BufHandle buf r hdl) a# len# = do
100   let len = I# len#
101   i <- readFastMutInt r
102   if (i+len) >= buf_size
103         then do hPutBuf hdl buf i
104                 writeFastMutInt r 0
105                 if (len >= buf_size) 
106                     then hPutBuf hdl (Ptr a#) len
107                     else bPutLitString b a# len#
108         else do
109                 copyBytes (buf `plusPtr` i) (Ptr a#) len
110                 writeFastMutInt r (i+len)
111
112 bFlush :: BufHandle -> IO ()
113 bFlush b@(BufHandle buf r hdl) = do
114   i <- readFastMutInt r
115   when (i > 0) $ hPutBuf hdl buf i
116   free buf
117   return ()
118
119 #if 0
120 myPutBuf s hdl buf i = 
121   modifyIOError (\e -> ioeSetErrorString e (ioeGetErrorString e ++ ':':s ++ " (" ++ show buf ++ "," ++ show i ++ ")")) $
122
123   hPutBuf hdl buf i
124 #endif