2 % (c) The GRASP/AQUA Project, Glasgow University, 1997
4 \section{String buffers}
6 Buffers for scanning string input stored in external arrays.
10 {-# OPTIONS -fno-prune-tydecls #-}
11 -- Don't really understand this!
12 -- ERROR: Can't see the data constructor(s) for _ccall_/_casm_ argument;
13 -- type: ForeignObj(try compiling with -fno-prune-tydecls ..)
21 hGetStringBuffer, -- :: FilePath -> IO StringBuffer
22 freeStringBuffer, -- :: StringBuffer -> IO ()
25 currentChar, -- :: StringBuffer -> Char
26 currentChar#, -- :: StringBuffer -> Char#
27 indexSBuffer, -- :: StringBuffer -> Int -> Char
28 indexSBuffer#, -- :: StringBuffer -> Int# -> Char#
29 -- relative lookup, i.e, currentChar = lookAhead 0
30 lookAhead, -- :: StringBuffer -> Int -> Char
31 lookAhead#, -- :: StringBuffer -> Int# -> Char#
33 -- moving the end point of the current lexeme.
34 setCurrentPos#, -- :: StringBuffer -> Int# -> StringBuffer
35 incLexeme, -- :: StringBuffer -> StringBuffer
36 decLexeme, -- :: StringBuffer -> StringBuffer
38 -- move the start and end lexeme pointer on by x units.
39 stepOn, -- :: StringBuffer -> StringBuffer
40 stepOnBy#, -- :: StringBuffer -> Int# -> StringBuffer
41 stepOnTo#, -- :: StringBuffer -> Int# -> StringBuffer
42 stepOnUntil, -- :: (Char -> Bool) -> StringBuffer -> StringBuffer
43 stepOverLexeme, -- :: StringBuffer -> StringBuffer
44 scanNumLit, -- :: Int -> StringBuffer -> (Int, StringBuffer)
45 expandWhile, -- :: (Char -> Bool) -> StringBuffer -> StringBuffer
46 expandUntilMatch, -- :: StrinBuffer -> String -> StringBuffer
47 -- at or beyond end of buffer?
48 bufferExhausted, -- :: StringBuffer -> Bool
49 emptyLexeme, -- :: StringBuffer -> Bool
52 prefixMatch, -- :: StringBuffer -> String -> Bool
53 untilEndOfString#, -- :: StringBuffer -> Int#
54 untilEndOfChar#, -- :: StringBuffer -> Int#
55 untilChar#, -- :: StringBuffer -> Char# -> Int#
58 lexemeToString, -- :: StringBuffer -> String
59 lexemeToByteArray, -- :: StringBuffer -> _ByteArray Int
60 lexemeToFastString, -- :: StringBuffer -> FastString
61 lexemeToBuffer, -- :: StringBuffer -> StringBuffer
67 #include "HsVersions.h"
70 import Addr ( Addr(..) )
87 -- ForeignObj# -- the data
94 instance Text StringBuffer where
95 showsPrec _ s = showString ""
99 hGetStringBuffer :: FilePath -> IO StringBuffer
100 hGetStringBuffer fname =
101 -- trace ("Renamer: opening " ++ fname) $
102 openFile fname ReadMode >>= \ hndl ->
103 hFileSize hndl >>= \ len@(J# _ _ d#) ->
104 let len_i = fromInteger len in
105 -- Allocate an array for system call to store its bytes into.
106 -- ToDo: make it robust
107 -- trace (show ((len_i::Int)+1)) $
108 _casm_ `` %r=(char *)malloc(sizeof(char)*(int)%0); '' (len_i::Int) >>= \ arr@(A# a#) ->
109 if addr2Int# a# ==# 0# then
110 failWith MkIOError(hndl,UserError,("hGetStringBuffer: Could not allocate "++show len_i ++ " bytes"))
113 -- _casm_ `` %r=NULL; '' >>= \ free_p ->
114 -- makeForeignObj arr free_p >>= \ fo@(_ForeignObj fo#) ->
115 readHandle hndl >>= \ hndl_ ->
116 writeHandle hndl hndl_ >>
117 let ptr = _filePtr hndl_ in
118 _ccall_ fread arr (1::Int) len_i ptr >>= \ (I# read#) ->
119 -- trace ("DEBUG: opened " ++ fname ++ show (I# read#)) $
121 if read# ==# 0# then -- EOF or other error
122 failWith MkIOError(hndl,UserError,"hGetStringBuffer: EOF reached or some other error")
124 -- Add a sentinel NUL
125 _casm_ `` ((char *)%0)[(int)%1]=(char)0; '' arr (I# (read# -# 1#)) >>= \ () ->
126 return (StringBuffer a# read# 0# 0#)
128 freeStringBuffer :: StringBuffer -> IO ()
129 freeStringBuffer (StringBuffer a# _ _ _) =
130 _casm_ `` free((char *)%0); '' (A# a#)
132 unsafeWriteBuffer :: StringBuffer -> Int# -> Char# -> StringBuffer
133 unsafeWriteBuffer s@(StringBuffer a _ _ _) i# ch# =
135 _casm_ `` ((char *)%0)[(int)%1]=(char)%2; '' (A# a) (I# i#) (C# ch#) >>= \ () ->
144 currentChar# :: StringBuffer -> Char#
145 currentChar# (StringBuffer fo# _ _ current#) = indexCharOffAddr# fo# current#
147 currentChar :: StringBuffer -> Char
148 currentChar sb = case currentChar# sb of c -> C# c
150 indexSBuffer# :: StringBuffer -> Int# -> Char#
151 indexSBuffer# (StringBuffer fo# _ _ _) i# = indexCharOffAddr# fo# i#
153 indexSBuffer :: StringBuffer -> Int -> Char
154 indexSBuffer sb (I# i#) = case indexSBuffer# sb i# of c -> C# c
156 -- relative lookup, i.e, currentChar = lookAhead 0
157 lookAhead# :: StringBuffer -> Int# -> Char#
158 lookAhead# (StringBuffer fo# _ _ c#) i# = indexCharOffAddr# fo# (c# +# i#)
160 lookAhead :: StringBuffer -> Int -> Char
161 lookAhead sb (I# i#) = case lookAhead# sb i# of c -> C# c
165 moving the start point of the current lexeme.
168 -- moving the end point of the current lexeme.
169 setCurrentPos# :: StringBuffer -> Int# -> StringBuffer
170 setCurrentPos# (StringBuffer fo l# s# c#) i# =
171 StringBuffer fo l# s# (c# +# i#)
173 -- augmenting the current lexeme by one.
174 incLexeme :: StringBuffer -> StringBuffer
175 incLexeme (StringBuffer fo l# s# c#) = StringBuffer fo l# s# (c# +# 1#)
177 decLexeme :: StringBuffer -> StringBuffer
178 decLexeme (StringBuffer fo l# s# c#) = StringBuffer fo l# s# (c# -# 1#)
182 -- move the start and end point of the buffer on by
186 stepOn :: StringBuffer -> StringBuffer
187 stepOn (StringBuffer fo l# s# c#) = StringBuffer fo l# (s# +# 1#) (s# +# 1#) -- assume they're the same.
189 stepOnBy# :: StringBuffer -> Int# -> StringBuffer
190 stepOnBy# (StringBuffer fo# l# s# c#) i# =
192 new_s# -> StringBuffer fo# l# new_s# new_s#
195 stepOnTo# :: StringBuffer -> Int# -> StringBuffer
196 stepOnTo# (StringBuffer fo l _ _) s# = StringBuffer fo l s# s#
198 stepOnUntil :: (Char -> Bool) -> StringBuffer -> StringBuffer
199 stepOnUntil pred (StringBuffer fo l# s# c#) =
203 case indexCharOffAddr# fo c# of
204 ch# | pred (C# ch#) -> StringBuffer fo l# c# c#
205 | ch# `eqChar#` '\NUL'# && c# >=# l# -> StringBuffer fo l# l# l# -- EOB, return immediately.
206 | otherwise -> loop (c# +# 1#)
208 stepOverLexeme :: StringBuffer -> StringBuffer
209 stepOverLexeme (StringBuffer fo l s# c#) = StringBuffer fo l c# c#
211 expandWhile :: (Char -> Bool) -> StringBuffer -> StringBuffer
212 expandWhile pred (StringBuffer fo l# s# c#) =
216 case indexCharOffAddr# fo c# of
217 ch# | pred (C# ch#) -> loop (c# +# 1#)
218 | ch# `eqChar#` '\NUL'# && c# >=# l# -> StringBuffer fo l# l# l# -- EOB, return immediately.
219 | otherwise -> StringBuffer fo l# s# c#
222 scanNumLit :: Int -> StringBuffer -> (Int,StringBuffer)
223 scanNumLit (I# acc#) (StringBuffer fo l# s# c#) =
227 case indexCharOffAddr# fo c# of
228 ch# | isDigit (C# ch#) -> loop (acc# *# 10# +# (ord# ch# -# ord# '0'#)) (c# +# 1#)
229 | ch# `eqChar#` '\NUL'# && c# >=# l# -> (I# acc#, StringBuffer fo l# l# l#) -- EOB, return immediately.
230 | otherwise -> (I# acc#,StringBuffer fo l# s# c#)
233 expandUntilMatch :: StringBuffer -> String -> StringBuffer
234 expandUntilMatch (StringBuffer fo l# s# c#) str =
237 loop c# [] = StringBuffer fo l# s# c#
238 loop c# ((C# x#):xs) =
239 if indexCharOffAddr# fo c# `eqChar#` x# then
246 -- at or beyond end of buffer?
247 bufferExhausted :: StringBuffer -> Bool
248 bufferExhausted (StringBuffer fo l# _ c#) = c# >=# l#
250 emptyLexeme :: StringBuffer -> Bool
251 emptyLexeme (StringBuffer fo l# s# c#) = s# ==# c#
254 prefixMatch :: StringBuffer -> String -> Maybe StringBuffer
255 prefixMatch (StringBuffer fo l# s# c#) str =
258 loop c# [] = Just (StringBuffer fo l# s# c#)
259 loop c# ((C# x#):xs) =
260 if indexCharOffAddr# fo c# `eqChar#` x# then
265 untilEndOfString# :: StringBuffer -> StringBuffer
266 untilEndOfString# (StringBuffer fo l# s# c#) =
270 case indexCharOffAddr# fo c# of
272 case indexCharOffAddr# fo (c# -# 1#) of
274 -- looks like an escaped something or other to me,
275 -- better count the number of "\\"s that are immediately
276 -- preceeding to decide if the " is escaped.
279 case indexCharOffAddr# fo i# of
280 '\\'# -> odd_slashes (not flg) (i# -# 1#)
283 if odd_slashes True (c# -# 2#) then
284 -- odd number, " is ecaped.
286 else -- a real end of string delimiter after all.
287 StringBuffer fo l# s# c#
288 _ -> StringBuffer fo l# s# c#
290 if c# >=# l# then -- hit sentinel, this doesn't look too good..
291 StringBuffer fo l# l# l#
297 untilEndOfChar# :: StringBuffer -> StringBuffer
298 untilEndOfChar# (StringBuffer fo l# s# c#) =
302 case indexCharOffAddr# fo c# of
304 case indexCharOffAddr# fo (c# -# 1#) of
306 case indexCharOffAddr# fo (c# -# 2#) of
307 '\\'# -> -- end of char
308 StringBuffer fo l# s# c#
309 _ -> loop (c# +# 1#) -- false alarm
310 _ -> StringBuffer fo l# s# c#
312 if c# >=# l# then -- hit sentinel, this doesn't look too good..
313 StringBuffer fo l# l# l#
318 untilChar# :: StringBuffer -> Char# -> StringBuffer
319 untilChar# (StringBuffer fo l# s# c#) x# =
323 if indexCharOffAddr# fo c# `eqChar#` x# then
324 StringBuffer fo l# s# c#
329 lexemeToString :: StringBuffer -> String
330 lexemeToString (StringBuffer fo _ start_pos# current#) =
331 if start_pos# ==# current# then
334 #if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ <= 205
335 byteArrayToString (copySubStr (A# fo) (I# start_pos#) (I# (current# -# start_pos#)))
337 unpackCStringBA (copySubStr (A# fo) (I# start_pos#) (I# (current# -# start_pos#)))
340 lexemeToByteArray :: StringBuffer -> _ByteArray Int
341 lexemeToByteArray (StringBuffer fo _ start_pos# current#) =
342 if start_pos# ==# current# then
343 error "lexemeToByteArray"
345 copySubStr (A# fo) (I# start_pos#) (I# (current# -# start_pos#))
347 lexemeToFastString :: StringBuffer -> FastString
348 lexemeToFastString (StringBuffer fo l# start_pos# current#) =
349 if start_pos# ==# current# then
350 mkFastCharString2 (A# fo) (I# 0#)
352 mkFastSubString (A# fo) (I# start_pos#) (I# (current# -# start_pos#))
355 Create a StringBuffer from the current lexeme, and add a sentinel
356 at the end. Know What You're Doing before taking this function
359 lexemeToBuffer :: StringBuffer -> StringBuffer
360 lexemeToBuffer (StringBuffer fo l# start_pos# current#) =
361 if start_pos# ==# current# then
362 StringBuffer fo 0# start_pos# current# -- an error, really.
364 unsafeWriteBuffer (StringBuffer fo (current# -# start_pos#) start_pos# start_pos#)