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
27 lexemeToString, -- :: StringBuffer -> Int -> String
28 lexemeToFastString, -- :: StringBuffer -> Int -> FastString
31 #include "HsVersions.h"
40 #if __GLASGOW_HASKELL__ < 503
45 import GHC.IO ( slurpFile )
48 import IO ( openFile, hFileSize, IOMode(ReadMode) )
49 #if __GLASGOW_HASKELL__ >= 601
50 import System.IO ( openBinaryFile )
52 import IOExts ( openFileEx, IOModeEx(..) )
55 #if __GLASGOW_HASKELL__ < 503
56 import IArray ( listArray )
57 import ArrayBase ( UArray(..) )
59 import IOExts ( hGetBufBA )
61 import Data.Array.IArray ( listArray )
62 import Data.Array.MArray ( unsafeFreeze, newArray_ )
63 import Data.Array.Base ( UArray(..) )
64 import Data.Array.IO ( IOArray, hGetArray )
69 #if __GLASGOW_HASKELL__ < 601
70 openBinaryFile fp mode = openFileEx fp (BinaryMode mode)
72 -- -----------------------------------------------------------------------------
73 -- The StringBuffer type
75 -- A StringBuffer is a ByteArray# with a pointer into it. We also cache
76 -- the length of the ByteArray# for speed.
84 instance Show StringBuffer where
85 showsPrec _ s = showString "<stringbuffer>"
87 -- -----------------------------------------------------------------------------
88 -- Creation / Destruction
90 hGetStringBuffer :: FilePath -> IO StringBuffer
91 hGetStringBuffer fname = do
92 h <- openBinaryFile fname ReadMode
94 let size_i@(I# sz#) = fromIntegral size
95 #if __GLASGOW_HASKELL__ < 503
96 arr <- stToIO (newCharArray (0,size_i-1))
97 r <- hGetBufBA h arr size_i
99 arr <- newArray_ (0,size_i-1)
100 r <- hGetArray h arr size_i
103 then ioError (userError "short read of file")
105 #if __GLASGOW_HASKELL__ < 503
106 frozen <- stToIO (unsafeFreezeByteArray arr)
108 ByteArray _ _ bytearr# -> return (StringBuffer bytearr# sz# 0#)
110 frozen <- unsafeFreeze arr
112 UArray _ _ bytearr# -> return (StringBuffer bytearr# sz# 0#)
115 #if __GLASGOW_HASKELL__ >= 502
116 stringToStringBuffer str = do
117 let size@(I# sz#) = length str
118 arr = listArray (0,size-1) (map (fromIntegral.ord) str)
121 UArray _ _ bytearr# -> return (StringBuffer bytearr# sz# 0#)
123 stringToStringBuffer = panic "stringToStringBuffer: not implemented"
126 -- -----------------------------------------------------------------------------
129 currentChar :: StringBuffer -> Char
130 currentChar (StringBuffer arr# l# current#) =
131 ASSERT(current# <# l#)
132 C# (indexCharArray# arr# current#)
134 prevChar :: StringBuffer -> Char -> Char
135 prevChar (StringBuffer _ _ 0#) deflt = deflt
136 prevChar s deflt = lookAhead s (-1)
138 lookAhead :: StringBuffer -> Int -> Char
139 lookAhead (StringBuffer arr# l# c#) (I# i#) =
140 ASSERT(off <# l# && off >=# 0#)
141 C# (indexCharArray# arr# off)
145 -- -----------------------------------------------------------------------------
148 stepOn :: StringBuffer -> StringBuffer
149 stepOn s = stepOnBy 1 s
151 stepOnBy :: Int -> StringBuffer -> StringBuffer
152 stepOnBy (I# i#) (StringBuffer fo# l# c#) = StringBuffer fo# l# (c# +# i#)
154 atEnd :: StringBuffer -> Bool
155 atEnd (StringBuffer _ l# c#) = l# ==# c#
157 -- -----------------------------------------------------------------------------
160 lexemeToString :: StringBuffer -> Int -> String
161 lexemeToString _ 0 = ""
162 lexemeToString (StringBuffer arr# _ current#) (I# len#) = unpack current#
164 end = current# +# len#
168 | otherwise = C# ch : unpack (nh +# 1#)
170 ch = indexCharArray# arr# nh
172 lexemeToFastString :: StringBuffer -> Int -> FastString
173 lexemeToFastString _ 0 = mkFastString ""
174 lexemeToFastString (StringBuffer fo _ current#) (I# len) =
175 mkFastSubStringBA# fo current# len