2 % (c) The GRASP/AQUA Project, Glasgow University, 1997
4 \section{String buffers}
6 Buffers for scanning string input stored in external arrays.
14 hGetStringBuffer, -- :: FilePath -> IO StringBuffer
15 freeStringBuffer, -- :: StringBuffer -> IO ()
18 currentChar, -- :: StringBuffer -> Char
19 currentChar#, -- :: StringBuffer -> Char#
20 indexSBuffer, -- :: StringBuffer -> Int -> Char
21 indexSBuffer#, -- :: StringBuffer -> Int# -> Char#
22 -- relative lookup, i.e, currentChar = lookAhead 0
23 lookAhead, -- :: StringBuffer -> Int -> Char
24 lookAhead#, -- :: StringBuffer -> Int# -> Char#
26 -- moving the end point of the current lexeme.
27 setCurrentPos#, -- :: StringBuffer -> Int# -> StringBuffer
28 incLexeme, -- :: StringBuffer -> StringBuffer
29 decLexeme, -- :: StringBuffer -> StringBuffer
31 -- move the start and end lexeme pointer on by x units.
32 stepOn, -- :: StringBuffer -> StringBuffer
33 stepOnBy#, -- :: StringBuffer -> Int# -> StringBuffer
34 stepOnTo#, -- :: StringBuffer -> Int# -> StringBuffer
35 stepOnUntil, -- :: (Char -> Bool) -> StringBuffer -> StringBuffer
36 stepOverLexeme, -- :: StringBuffer -> StringBuffer
37 scanNumLit, -- :: Int -> StringBuffer -> (Int, StringBuffer)
38 expandWhile, -- :: (Char -> Bool) -> StringBuffer -> StringBuffer
39 expandUntilMatch, -- :: StrinBuffer -> String -> StringBuffer
40 -- at or beyond end of buffer?
41 bufferExhausted, -- :: StringBuffer -> Bool
42 emptyLexeme, -- :: StringBuffer -> Bool
45 prefixMatch, -- :: StringBuffer -> String -> Bool
46 untilEndOfString#, -- :: StringBuffer -> Int#
47 untilEndOfChar#, -- :: StringBuffer -> Int#
48 untilChar#, -- :: StringBuffer -> Char# -> Int#
51 lexemeToString, -- :: StringBuffer -> String
52 lexemeToByteArray, -- :: StringBuffer -> _ByteArray Int
53 lexemeToFastString, -- :: StringBuffer -> FastString
54 lexemeToBuffer, -- :: StringBuffer -> StringBuffer
73 -- ForeignObj# -- the data
81 hGetStringBuffer :: FilePath -> IO StringBuffer
82 hGetStringBuffer fname =
83 -- _trace ("Renamer: opening " ++ fname)
84 openFile fname ReadMode >>= \ hndl ->
85 hFileSize hndl >>= \ len@(J# _ _ d#) ->
86 let len_i = fromInteger len in
87 -- Allocate an array for system call to store its bytes into.
88 -- ToDo: make it robust
89 -- _trace (show (len_i::Int)+1)
90 (_casm_ `` %r=(char *)malloc(sizeof(char)*(int)%0); '' (len_i::Int)) `thenPrimIO` \ arr@(A# a#) ->
91 if addr2Int# a# ==# 0# then
92 failWith (UserError ("hGetStringBuffer: Could not allocate "++show len_i ++ " bytes"))
95 -- _casm_ `` %r=NULL; '' `thenPrimIO` \ free_p ->
96 -- makeForeignObj arr free_p `thenPrimIO` \ fo@(_ForeignObj fo#) ->
97 _readHandle hndl >>= \ _hndl ->
98 _writeHandle hndl _hndl >>
99 let ptr = _filePtr _hndl in
100 _ccall_ fread arr (1::Int) len_i ptr `thenPrimIO` \ (I# read#) ->
101 -- _trace ("DEBUG: opened " ++ fname ++ show (I# read#)) $
103 if read# ==# 0# then -- EOF or other error
104 failWith (UserError "hGetStringBuffer: EOF reached or some other error")
106 -- Add a sentinel NUL
107 _casm_ `` ((char *)%0)[(int)%1]=(char)0; '' arr (I# (read# -# 1#)) `thenPrimIO` \ () ->
108 return (StringBuffer a# read# 0# 0#)
110 freeStringBuffer :: StringBuffer -> IO ()
111 freeStringBuffer (StringBuffer a# _ _ _) =
112 _casm_ `` free((char *)%0); '' (A# a#) `thenPrimIO` \ () ->
115 unsafeWriteBuffer :: StringBuffer -> Int# -> Char# -> StringBuffer
116 unsafeWriteBuffer s@(StringBuffer a _ _ _) i# ch# =
117 unsafePerformPrimIO (
118 _casm_ `` ((char *)%0)[(int)%1]=(char)%2; '' (A# a) (I# i#) (C# ch#) `thenPrimIO` \ () ->
126 currentChar# :: StringBuffer -> Char#
127 currentChar# (StringBuffer fo# _ _ current#) = indexCharOffAddr# fo# current#
129 currentChar :: StringBuffer -> Char
130 currentChar sb = case currentChar# sb of c -> C# c
132 indexSBuffer# :: StringBuffer -> Int# -> Char#
133 indexSBuffer# (StringBuffer fo# _ _ _) i# = indexCharOffAddr# fo# i#
135 indexSBuffer :: StringBuffer -> Int -> Char
136 indexSBuffer sb (I# i#) = case indexSBuffer# sb i# of c -> C# c
138 -- relative lookup, i.e, currentChar = lookAhead 0
139 lookAhead# :: StringBuffer -> Int# -> Char#
140 lookAhead# (StringBuffer fo# _ _ c#) i# = indexCharOffAddr# fo# (c# +# i#)
142 lookAhead :: StringBuffer -> Int -> Char
143 lookAhead sb (I# i#) = case lookAhead# sb i# of c -> C# c
147 moving the start point of the current lexeme.
150 -- moving the end point of the current lexeme.
151 setCurrentPos# :: StringBuffer -> Int# -> StringBuffer
152 setCurrentPos# (StringBuffer fo l# s# c#) i# =
153 StringBuffer fo l# s# (c# +# i#)
155 -- augmenting the current lexeme by one.
156 incLexeme :: StringBuffer -> StringBuffer
157 incLexeme (StringBuffer fo l# s# c#) = StringBuffer fo l# s# (c# +# 1#)
159 decLexeme :: StringBuffer -> StringBuffer
160 decLexeme (StringBuffer fo l# s# c#) = StringBuffer fo l# s# (c# -# 1#)
164 -- move the start and end point of the buffer on by
168 stepOn :: StringBuffer -> StringBuffer
169 stepOn (StringBuffer fo l# s# c#) = StringBuffer fo l# (s# +# 1#) (s# +# 1#) -- assume they're the same.
171 stepOnBy# :: StringBuffer -> Int# -> StringBuffer
172 stepOnBy# (StringBuffer fo# l# s# c#) i# =
174 new_s# -> StringBuffer fo# l# new_s# new_s#
177 stepOnTo# :: StringBuffer -> Int# -> StringBuffer
178 stepOnTo# (StringBuffer fo l _ _) s# = StringBuffer fo l s# s#
180 stepOnUntil :: (Char -> Bool) -> StringBuffer -> StringBuffer
181 stepOnUntil pred (StringBuffer fo l# s# c#) =
185 case indexCharOffAddr# fo c# of
186 ch# | pred (C# ch#) -> StringBuffer fo l# c# c#
187 | otherwise -> loop (c# +# 1#)
189 stepOverLexeme :: StringBuffer -> StringBuffer
190 stepOverLexeme (StringBuffer fo l s# c#) = StringBuffer fo l c# c#
192 expandWhile :: (Char -> Bool) -> StringBuffer -> StringBuffer
193 expandWhile pred (StringBuffer fo l# s# c#) =
197 case indexCharOffAddr# fo c# of
198 ch# | pred (C# ch#) -> loop (c# +# 1#)
199 | otherwise -> StringBuffer fo l# s# c#
202 scanNumLit :: Int -> StringBuffer -> (Int,StringBuffer)
203 scanNumLit (I# acc#) (StringBuffer fo l# s# c#) =
207 case indexCharOffAddr# fo c# of
208 ch# | isDigit (C# ch#) -> loop (acc# *# 10# +# (ord# ch# -# ord# '0'#)) (c# +# 1#)
209 | otherwise -> (I# acc#,StringBuffer fo l# s# c#)
212 expandUntilMatch :: StringBuffer -> String -> StringBuffer
213 expandUntilMatch (StringBuffer fo l# s# c#) str =
216 loop c# [] = StringBuffer fo l# s# c#
217 loop c# ((C# x#):xs) =
218 if indexCharOffAddr# fo c# `eqChar#` x# then
225 -- at or beyond end of buffer?
226 bufferExhausted :: StringBuffer -> Bool
227 bufferExhausted (StringBuffer fo l# _ c#) = c# >=# l#
229 emptyLexeme :: StringBuffer -> Bool
230 emptyLexeme (StringBuffer fo l# s# c#) = s# ==# c#
233 prefixMatch :: StringBuffer -> String -> Maybe StringBuffer
234 prefixMatch (StringBuffer fo l# s# c#) str =
237 loop c# [] = Just (StringBuffer fo l# s# c#)
238 loop c# ((C# x#):xs) =
239 if indexCharOffAddr# fo c# `eqChar#` x# then
244 untilEndOfString# :: StringBuffer -> StringBuffer
245 untilEndOfString# (StringBuffer fo l# s# c#) =
249 case indexCharOffAddr# fo c# of
251 case indexCharOffAddr# fo (c# -# 1#) of
252 '\\'# -> --escaped, false alarm.
254 _ -> StringBuffer fo l# s# c#
258 untilEndOfChar# :: StringBuffer -> StringBuffer
259 untilEndOfChar# (StringBuffer fo l# s# c#) =
263 case indexCharOffAddr# fo c# of
265 case indexCharOffAddr# fo (c# -# 1#) of
266 '\\'# -> --escaped, false alarm.
268 _ -> StringBuffer fo l# s# c#
271 untilChar# :: StringBuffer -> Char# -> StringBuffer
272 untilChar# (StringBuffer fo l# s# c#) x# =
276 if indexCharOffAddr# fo c# `eqChar#` x# then
277 StringBuffer fo l# s# c#
282 lexemeToString :: StringBuffer -> String
283 lexemeToString (StringBuffer fo _ start_pos# current#) =
284 if start_pos# ==# current# then
287 byteArrayToString (copySubStr (A# fo) (I# start_pos#) (I# (current# -# start_pos#)))
290 lexemeToByteArray :: StringBuffer -> _ByteArray Int
291 lexemeToByteArray (StringBuffer fo _ start_pos# current#) =
292 if start_pos# ==# current# then
293 error "lexemeToByteArray"
295 copySubStr (A# fo) (I# start_pos#) (I# (current# -# start_pos#))
297 lexemeToFastString :: StringBuffer -> FastString
298 lexemeToFastString (StringBuffer fo l# start_pos# current#) =
299 if start_pos# ==# current# then
300 mkFastCharString2 (A# fo) (I# 0#)
302 mkFastSubString (A# fo) (I# start_pos#) (I# (current# -# start_pos#))
305 Create a StringBuffer from the current lexeme, and add a sentinel
306 at the end. Know What You're Doing before taking this function
309 lexemeToBuffer :: StringBuffer -> StringBuffer
310 lexemeToBuffer (StringBuffer fo l# start_pos# current#) =
311 if start_pos# ==# current# then
312 StringBuffer fo 0# start_pos# current# -- an error, really.
314 unsafeWriteBuffer (StringBuffer fo (current# -# start_pos#) start_pos# start_pos#)