2 % (c) The University of Glasgow, 1997-2003
4 \section{String buffers}
6 Buffers for scanning string input stored in external arrays.
13 -- * Creation/destruction
14 hGetStringBuffer, -- :: FilePath -> IO StringBuffer
15 stringToStringBuffer, -- :: String -> IO StringBuffer
18 currentChar, -- :: StringBuffer -> Char
19 prevChar, -- :: StringBuffer -> Char -> Char
20 lookAhead, -- :: StringBuffer -> Int -> Char
21 atEnd, -- :: StringBuffer -> Bool
22 difference, -- :: StringBuffer -> StringBuffer -> Int
28 lexemeToString, -- :: StringBuffer -> Int -> String
29 lexemeToFastString, -- :: StringBuffer -> Int -> FastString
32 #include "HsVersions.h"
41 #if __GLASGOW_HASKELL__ < 503
46 import GHC.IO ( slurpFile )
49 import IO ( openFile, hFileSize, IOMode(ReadMode) )
51 #if __GLASGOW_HASKELL__ < 503
52 import IArray ( listArray )
53 import ArrayBase ( UArray(..) )
55 import IOExts ( hGetBufBA )
57 import Data.Array.IArray ( listArray )
58 import Data.Array.MArray ( unsafeFreeze, newArray_ )
59 import Data.Array.Base ( UArray(..) )
60 import Data.Array.IO ( IOArray, hGetArray )
65 -- -----------------------------------------------------------------------------
66 -- The StringBuffer type
68 -- A StringBuffer is a ByteArray# with a pointer into it. We also cache
69 -- the length of the ByteArray# for speed.
77 instance Show StringBuffer where
78 showsPrec _ s = showString "<stringbuffer>"
80 -- -----------------------------------------------------------------------------
81 -- Creation / Destruction
83 hGetStringBuffer :: FilePath -> IO StringBuffer
84 hGetStringBuffer fname = do
85 h <- openFile fname ReadMode
87 let size_i@(I# sz#) = fromIntegral size
88 #if __GLASGOW_HASKELL__ < 503
89 arr <- stToIO (newCharArray (0,size_i-1))
90 r <- hGetBufBA h arr size_i
92 arr <- newArray_ (0,size_i-1)
93 r <- hGetArray h arr size_i
96 then ioError (userError "short read of file")
98 #if __GLASGOW_HASKELL__ < 503
99 frozen <- stToIO (unsafeFreezeByteArray arr)
101 ByteArray _ _ bytearr# -> return (StringBuffer bytearr# sz# 0#)
103 frozen <- unsafeFreeze arr
105 UArray _ _ bytearr# -> return (StringBuffer bytearr# sz# 0#)
108 #if __GLASGOW_HASKELL__ >= 502
109 stringToStringBuffer str = do
110 let size@(I# sz#) = length str
111 arr = listArray (0,size-1) (map (fromIntegral.ord) str)
114 UArray _ _ bytearr# -> return (StringBuffer bytearr# sz# 0#)
116 stringToStringBuffer = panic "stringToStringBuffer: not implemented"
119 -- -----------------------------------------------------------------------------
122 currentChar :: StringBuffer -> Char
123 currentChar (StringBuffer arr# l# current#) =
124 ASSERT(current# <# l#)
125 C# (indexCharArray# arr# current#)
127 prevChar :: StringBuffer -> Char -> Char
128 prevChar (StringBuffer _ _ 0#) deflt = deflt
129 prevChar s deflt = lookAhead s (-1)
131 lookAhead :: StringBuffer -> Int -> Char
132 lookAhead (StringBuffer arr# l# c#) (I# i#) =
133 ASSERT(off <# l# && off >=# 0#)
134 C# (indexCharArray# arr# off)
138 difference :: StringBuffer -> StringBuffer -> Int
139 difference (StringBuffer _ _ c1#) (StringBuffer _ _ c2#) = I# (c2# -# c1#)
141 -- -----------------------------------------------------------------------------
144 stepOn :: StringBuffer -> StringBuffer
145 stepOn s = stepOnBy 1 s
147 stepOnBy :: Int -> StringBuffer -> StringBuffer
148 stepOnBy (I# i#) (StringBuffer fo# l# c#) = StringBuffer fo# l# (c# +# i#)
150 atEnd :: StringBuffer -> Bool
151 atEnd (StringBuffer _ l# c#) = l# ==# c#
153 -- -----------------------------------------------------------------------------
156 lexemeToString :: StringBuffer -> Int -> String
157 lexemeToString _ 0 = ""
158 lexemeToString (StringBuffer arr# _ current#) (I# len#) = unpack current#
160 end = current# +# len#
164 | otherwise = C# ch : unpack (nh +# 1#)
166 ch = indexCharArray# arr# nh
168 lexemeToFastString :: StringBuffer -> Int -> FastString
169 lexemeToFastString _ 0 = mkFastString ""
170 lexemeToFastString (StringBuffer fo _ current#) (I# len) =
171 mkFastSubStringBA# fo current# len