2 % (c) The GRASP/AQUA Project, Glasgow University, 1997
4 \section{String buffers}
6 Buffers for scanning string input stored in external arrays.
9 #include "HsVersions.h"
16 hGetStringBuffer, -- :: FilePath -> IO StringBuffer
17 freeStringBuffer, -- :: StringBuffer -> IO ()
20 currentChar, -- :: StringBuffer -> Char
21 currentChar#, -- :: StringBuffer -> Char#
22 indexSBuffer, -- :: StringBuffer -> Int -> Char
23 indexSBuffer#, -- :: StringBuffer -> Int# -> Char#
24 -- relative lookup, i.e, currentChar = lookAhead 0
25 lookAhead, -- :: StringBuffer -> Int -> Char
26 lookAhead#, -- :: StringBuffer -> Int# -> Char#
28 -- moving the end point of the current lexeme.
29 setCurrentPos#, -- :: StringBuffer -> Int# -> StringBuffer
30 incLexeme, -- :: StringBuffer -> StringBuffer
31 decLexeme, -- :: StringBuffer -> StringBuffer
33 -- move the start and end lexeme pointer on by x units.
34 stepOn, -- :: StringBuffer -> StringBuffer
35 stepOnBy#, -- :: StringBuffer -> Int# -> StringBuffer
36 stepOnTo#, -- :: StringBuffer -> Int# -> StringBuffer
37 stepOnUntil, -- :: (Char -> Bool) -> StringBuffer -> StringBuffer
38 stepOverLexeme, -- :: StringBuffer -> StringBuffer
39 scanNumLit, -- :: Int -> StringBuffer -> (Int, StringBuffer)
40 expandWhile, -- :: (Char -> Bool) -> StringBuffer -> StringBuffer
41 expandUntilMatch, -- :: StrinBuffer -> String -> StringBuffer
42 -- at or beyond end of buffer?
43 bufferExhausted, -- :: StringBuffer -> Bool
44 emptyLexeme, -- :: StringBuffer -> Bool
47 prefixMatch, -- :: StringBuffer -> String -> Bool
48 untilEndOfString#, -- :: StringBuffer -> Int#
49 untilEndOfChar#, -- :: StringBuffer -> Int#
50 untilChar#, -- :: StringBuffer -> Char# -> Int#
53 lexemeToString, -- :: StringBuffer -> String
54 lexemeToByteArray, -- :: StringBuffer -> _ByteArray Int
55 lexemeToFastString, -- :: StringBuffer -> FastString
56 lexemeToBuffer, -- :: StringBuffer -> StringBuffer
62 #if __GLASGOW_HASKELL__ <= 200
75 # if __GLASGOW_HASKELL__ == 202
76 import PrelBase ( Char(..) )
78 # if __GLASGOW_HASKELL__ >= 206
91 -- ForeignObj# -- the data
98 instance Text StringBuffer where
99 showsPrec _ s = showString ""
103 hGetStringBuffer :: FilePath -> IO StringBuffer
104 hGetStringBuffer fname =
105 -- trace ("Renamer: opening " ++ fname) $
106 openFile fname ReadMode >>= \ hndl ->
107 hFileSize hndl >>= \ len@(J# _ _ d#) ->
108 let len_i = fromInteger len in
109 -- Allocate an array for system call to store its bytes into.
110 -- ToDo: make it robust
111 -- trace (show ((len_i::Int)+1)) $
112 (_casm_ `` %r=(char *)malloc(sizeof(char)*(int)%0); '' (len_i::Int)) `CCALL_THEN` \ arr@(A# a#) ->
113 if addr2Int# a# ==# 0# then
114 failWith MkIOError(hndl,UserError,("hGetStringBuffer: Could not allocate "++show len_i ++ " bytes"))
117 -- _casm_ `` %r=NULL; '' `thenPrimIO` \ free_p ->
118 -- makeForeignObj arr free_p `thenPrimIO` \ fo@(_ForeignObj fo#) ->
119 _readHandle hndl >>= \ hndl_ ->
120 _writeHandle hndl hndl_ >>
121 let ptr = _filePtr hndl_ in
122 _ccall_ fread arr (1::Int) len_i ptr `CCALL_THEN` \ (I# read#) ->
123 -- trace ("DEBUG: opened " ++ fname ++ show (I# read#)) $
125 if read# ==# 0# then -- EOF or other error
126 failWith MkIOError(hndl,UserError,"hGetStringBuffer: EOF reached or some other error")
128 -- Add a sentinel NUL
129 _casm_ `` ((char *)%0)[(int)%1]=(char)0; '' arr (I# (read# -# 1#)) `CCALL_THEN` \ () ->
130 return (StringBuffer a# read# 0# 0#)
132 freeStringBuffer :: StringBuffer -> IO ()
133 freeStringBuffer (StringBuffer a# _ _ _) =
134 _casm_ `` free((char *)%0); '' (A# a#) `CCALL_THEN` \ () ->
137 unsafeWriteBuffer :: StringBuffer -> Int# -> Char# -> StringBuffer
138 unsafeWriteBuffer s@(StringBuffer a _ _ _) i# ch# =
139 unsafePerformPrimIO (
140 _casm_ `` ((char *)%0)[(int)%1]=(char)%2; '' (A# a) (I# i#) (C# ch#) `thenPrimIO` \ () ->
148 currentChar# :: StringBuffer -> Char#
149 currentChar# (StringBuffer fo# _ _ current#) = indexCharOffAddr# fo# current#
151 currentChar :: StringBuffer -> Char
152 currentChar sb = case currentChar# sb of c -> C# c
154 indexSBuffer# :: StringBuffer -> Int# -> Char#
155 indexSBuffer# (StringBuffer fo# _ _ _) i# = indexCharOffAddr# fo# i#
157 indexSBuffer :: StringBuffer -> Int -> Char
158 indexSBuffer sb (I# i#) = case indexSBuffer# sb i# of c -> C# c
160 -- relative lookup, i.e, currentChar = lookAhead 0
161 lookAhead# :: StringBuffer -> Int# -> Char#
162 lookAhead# (StringBuffer fo# _ _ c#) i# = indexCharOffAddr# fo# (c# +# i#)
164 lookAhead :: StringBuffer -> Int -> Char
165 lookAhead sb (I# i#) = case lookAhead# sb i# of c -> C# c
169 moving the start point of the current lexeme.
172 -- moving the end point of the current lexeme.
173 setCurrentPos# :: StringBuffer -> Int# -> StringBuffer
174 setCurrentPos# (StringBuffer fo l# s# c#) i# =
175 StringBuffer fo l# s# (c# +# i#)
177 -- augmenting the current lexeme by one.
178 incLexeme :: StringBuffer -> StringBuffer
179 incLexeme (StringBuffer fo l# s# c#) = StringBuffer fo l# s# (c# +# 1#)
181 decLexeme :: StringBuffer -> StringBuffer
182 decLexeme (StringBuffer fo l# s# c#) = StringBuffer fo l# s# (c# -# 1#)
186 -- move the start and end point of the buffer on by
190 stepOn :: StringBuffer -> StringBuffer
191 stepOn (StringBuffer fo l# s# c#) = StringBuffer fo l# (s# +# 1#) (s# +# 1#) -- assume they're the same.
193 stepOnBy# :: StringBuffer -> Int# -> StringBuffer
194 stepOnBy# (StringBuffer fo# l# s# c#) i# =
196 new_s# -> StringBuffer fo# l# new_s# new_s#
199 stepOnTo# :: StringBuffer -> Int# -> StringBuffer
200 stepOnTo# (StringBuffer fo l _ _) s# = StringBuffer fo l s# s#
202 stepOnUntil :: (Char -> Bool) -> StringBuffer -> StringBuffer
203 stepOnUntil pred (StringBuffer fo l# s# c#) =
207 case indexCharOffAddr# fo c# of
208 ch# | pred (C# ch#) -> StringBuffer fo l# c# c#
209 | ch# `eqChar#` '\NUL'# && c# >=# l# -> StringBuffer fo l# l# l# -- EOB, return immediately.
210 | otherwise -> loop (c# +# 1#)
212 stepOverLexeme :: StringBuffer -> StringBuffer
213 stepOverLexeme (StringBuffer fo l s# c#) = StringBuffer fo l c# c#
215 expandWhile :: (Char -> Bool) -> StringBuffer -> StringBuffer
216 expandWhile pred (StringBuffer fo l# s# c#) =
220 case indexCharOffAddr# fo c# of
221 ch# | pred (C# ch#) -> loop (c# +# 1#)
222 | ch# `eqChar#` '\NUL'# && c# >=# l# -> StringBuffer fo l# l# l# -- EOB, return immediately.
223 | otherwise -> StringBuffer fo l# s# c#
226 scanNumLit :: Int -> StringBuffer -> (Int,StringBuffer)
227 scanNumLit (I# acc#) (StringBuffer fo l# s# c#) =
231 case indexCharOffAddr# fo c# of
232 ch# | isDigit (C# ch#) -> loop (acc# *# 10# +# (ord# ch# -# ord# '0'#)) (c# +# 1#)
233 | ch# `eqChar#` '\NUL'# && c# >=# l# -> (I# acc#, StringBuffer fo l# l# l#) -- EOB, return immediately.
234 | otherwise -> (I# acc#,StringBuffer fo l# s# c#)
237 expandUntilMatch :: StringBuffer -> String -> StringBuffer
238 expandUntilMatch (StringBuffer fo l# s# c#) str =
241 loop c# [] = StringBuffer fo l# s# c#
242 loop c# ((C# x#):xs) =
243 if indexCharOffAddr# fo c# `eqChar#` x# then
250 -- at or beyond end of buffer?
251 bufferExhausted :: StringBuffer -> Bool
252 bufferExhausted (StringBuffer fo l# _ c#) = c# >=# l#
254 emptyLexeme :: StringBuffer -> Bool
255 emptyLexeme (StringBuffer fo l# s# c#) = s# ==# c#
258 prefixMatch :: StringBuffer -> String -> Maybe StringBuffer
259 prefixMatch (StringBuffer fo l# s# c#) str =
262 loop c# [] = Just (StringBuffer fo l# s# c#)
263 loop c# ((C# x#):xs) =
264 if indexCharOffAddr# fo c# `eqChar#` x# then
269 untilEndOfString# :: StringBuffer -> StringBuffer
270 untilEndOfString# (StringBuffer fo l# s# c#) =
274 case indexCharOffAddr# fo c# of
276 case indexCharOffAddr# fo (c# -# 1#) of
278 -- looks like an escaped something or other to me,
279 -- better count the number of "\\"s that are immediately
280 -- preceeding to decide if the " is escaped.
283 case indexCharOffAddr# fo i# of
284 '\\'# -> odd_slashes (not flg) (i# -# 1#)
287 if odd_slashes True (c# -# 2#) then
288 -- odd number, " is ecaped.
290 else -- a real end of string delimiter after all.
291 StringBuffer fo l# s# c#
292 _ -> StringBuffer fo l# s# c#
294 if c# >=# l# then -- hit sentinel, this doesn't look too good..
295 StringBuffer fo l# l# l#
301 untilEndOfChar# :: StringBuffer -> StringBuffer
302 untilEndOfChar# (StringBuffer fo l# s# c#) =
306 case indexCharOffAddr# fo c# of
308 case indexCharOffAddr# fo (c# -# 1#) of
310 case indexCharOffAddr# fo (c# -# 2#) of
311 '\\'# -> -- end of char
312 StringBuffer fo l# s# c#
313 _ -> loop (c# +# 1#) -- false alarm
314 _ -> StringBuffer fo l# s# c#
316 if c# >=# l# then -- hit sentinel, this doesn't look too good..
317 StringBuffer fo l# l# l#
322 untilChar# :: StringBuffer -> Char# -> StringBuffer
323 untilChar# (StringBuffer fo l# s# c#) x# =
327 if indexCharOffAddr# fo c# `eqChar#` x# then
328 StringBuffer fo l# s# c#
333 lexemeToString :: StringBuffer -> String
334 lexemeToString (StringBuffer fo _ start_pos# current#) =
335 if start_pos# ==# current# then
338 #if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ <= 205
339 byteArrayToString (copySubStr (A# fo) (I# start_pos#) (I# (current# -# start_pos#)))
341 unpackCStringBA (copySubStr (A# fo) (I# start_pos#) (I# (current# -# start_pos#)))
344 lexemeToByteArray :: StringBuffer -> _ByteArray Int
345 lexemeToByteArray (StringBuffer fo _ start_pos# current#) =
346 if start_pos# ==# current# then
347 error "lexemeToByteArray"
349 copySubStr (A# fo) (I# start_pos#) (I# (current# -# start_pos#))
351 lexemeToFastString :: StringBuffer -> FastString
352 lexemeToFastString (StringBuffer fo l# start_pos# current#) =
353 if start_pos# ==# current# then
354 mkFastCharString2 (A# fo) (I# 0#)
356 mkFastSubString (A# fo) (I# start_pos#) (I# (current# -# start_pos#))
359 Create a StringBuffer from the current lexeme, and add a sentinel
360 at the end. Know What You're Doing before taking this function
363 lexemeToBuffer :: StringBuffer -> StringBuffer
364 lexemeToBuffer (StringBuffer fo l# start_pos# current#) =
365 if start_pos# ==# current# then
366 StringBuffer fo 0# start_pos# current# -- an error, really.
368 unsafeWriteBuffer (StringBuffer fo (current# -# start_pos#) start_pos# start_pos#)