2 % (c) The University of Glasgow, 1997-2003
4 \section{String buffers}
6 Buffers for scanning string input stored in external arrays.
12 -- non-abstract for vs/HaskellService
14 -- * Creation/destruction
15 hGetStringBuffer, -- :: FilePath -> IO StringBuffer
16 stringToStringBuffer, -- :: String -> IO StringBuffer
19 currentChar, -- :: StringBuffer -> Char
20 prevChar, -- :: StringBuffer -> Char -> Char
21 lookAhead, -- :: StringBuffer -> Int -> Char
22 atEnd, -- :: StringBuffer -> Bool
28 lexemeToString, -- :: StringBuffer -> Int -> String
29 lexemeToFastString, -- :: StringBuffer -> Int -> FastString
35 #include "HsVersions.h"
44 #if __GLASGOW_HASKELL__ < 503
49 import GHC.IO ( slurpFile )
52 import IO ( openFile, hFileSize, IOMode(ReadMode) )
53 #if __GLASGOW_HASKELL__ >= 601
54 import System.IO ( openBinaryFile )
56 import IOExts ( openFileEx, IOModeEx(..) )
59 #if __GLASGOW_HASKELL__ < 503
60 import IArray ( listArray )
61 import ArrayBase ( UArray(..) )
63 import IOExts ( hGetBufBA )
65 import Data.Array.IArray ( listArray )
66 import Data.Array.MArray ( unsafeFreeze, newArray_ )
67 import Data.Array.Base ( UArray(..) )
68 import Data.Array.IO ( IOArray, hGetArray )
73 #if __GLASGOW_HASKELL__ < 601
74 openBinaryFile fp mode = openFileEx fp (BinaryMode mode)
76 -- -----------------------------------------------------------------------------
77 -- The StringBuffer type
79 -- A StringBuffer is a ByteArray# with a pointer into it. We also cache
80 -- the length of the ByteArray# for speed.
88 instance Show StringBuffer where
89 showsPrec _ s = showString "<stringbuffer>"
91 -- -----------------------------------------------------------------------------
92 -- Creation / Destruction
94 hGetStringBuffer :: FilePath -> IO StringBuffer
95 hGetStringBuffer fname = do
96 h <- openBinaryFile fname ReadMode
98 let size_i@(I# sz#) = fromIntegral size
99 #if __GLASGOW_HASKELL__ < 503
100 arr <- stToIO (newCharArray (0,size_i-1))
101 r <- hGetBufBA h arr size_i
103 arr <- newArray_ (0,size_i-1)
104 r <- if size_i == 0 then return 0 else hGetArray h arr size_i
107 then ioError (userError "short read of file")
109 #if __GLASGOW_HASKELL__ < 503
110 frozen <- stToIO (unsafeFreezeByteArray arr)
112 ByteArray _ _ bytearr# -> return (StringBuffer bytearr# sz# 0#)
114 frozen <- unsafeFreeze arr
116 UArray _ _ bytearr# -> return (StringBuffer bytearr# sz# 0#)
119 #if __GLASGOW_HASKELL__ >= 502
120 stringToStringBuffer str = do
121 let size@(I# sz#) = length str
122 arr = listArray (0,size-1) (map (fromIntegral.ord) str)
125 UArray _ _ bytearr# -> return (StringBuffer bytearr# sz# 0#)
127 stringToStringBuffer = panic "stringToStringBuffer: not implemented"
130 -- -----------------------------------------------------------------------------
133 currentChar :: StringBuffer -> Char
134 currentChar (StringBuffer arr# l# current#) =
135 ASSERT(current# <# l#)
136 C# (indexCharArray# arr# current#)
138 prevChar :: StringBuffer -> Char -> Char
139 prevChar (StringBuffer _ _ 0#) deflt = deflt
140 prevChar s deflt = lookAhead s (-1)
142 lookAhead :: StringBuffer -> Int -> Char
143 lookAhead (StringBuffer arr# l# c#) (I# i#) =
144 ASSERT(off <# l# && off >=# 0#)
145 C# (indexCharArray# arr# off)
149 -- -----------------------------------------------------------------------------
152 stepOn :: StringBuffer -> StringBuffer
153 stepOn s = stepOnBy 1 s
155 stepOnBy :: Int -> StringBuffer -> StringBuffer
156 stepOnBy (I# i#) (StringBuffer fo# l# c#) = StringBuffer fo# l# (c# +# i#)
158 atEnd :: StringBuffer -> Bool
159 atEnd (StringBuffer _ l# c#) = l# ==# c#
161 -- -----------------------------------------------------------------------------
164 lexemeToString :: StringBuffer -> Int -> String
165 lexemeToString _ 0 = ""
166 lexemeToString (StringBuffer arr# _ current#) (I# len#) = unpack current#
168 end = current# +# len#
172 | otherwise = C# ch : unpack (nh +# 1#)
174 ch = indexCharArray# arr# nh
176 lexemeToFastString :: StringBuffer -> Int -> FastString
177 lexemeToFastString _ 0 = mkFastString ""
178 lexemeToFastString (StringBuffer fo _ current#) (I# len) =
179 mkFastSubStringBA# fo current# len
181 -- -----------------------------------------------------------------------------
182 -- Parsing integer strings in various bases
184 parseInteger :: StringBuffer -> Int -> Integer -> (Char->Int) -> Integer
185 parseInteger buf len radix to_int
187 where go i x | i == len = x
188 | otherwise = go (i+1) (x * radix + toInteger (to_int (lookAhead buf i)))