\begin{code}
module StringBuffer
(
- StringBuffer,
+ StringBuffer(..),
+ -- non-abstract for vs/HaskellService
-- * Creation/destruction
hGetStringBuffer, -- :: FilePath -> IO StringBuffer
prevChar, -- :: StringBuffer -> Char -> Char
lookAhead, -- :: StringBuffer -> Int -> Char
atEnd, -- :: StringBuffer -> Bool
- difference, -- :: StringBuffer -> StringBuffer -> Int
-- * Moving
stepOn, stepOnBy,
-- * Conversion
lexemeToString, -- :: StringBuffer -> Int -> String
lexemeToFastString, -- :: StringBuffer -> Int -> FastString
+
+ -- * Parsing integers
+ parseInteger,
) where
#include "HsVersions.h"
#endif
import IO ( openFile, hFileSize, IOMode(ReadMode) )
+#if __GLASGOW_HASKELL__ >= 601
+import System.IO ( openBinaryFile )
+#else
+import IOExts ( openFileEx, IOModeEx(..) )
+#endif
#if __GLASGOW_HASKELL__ < 503
import IArray ( listArray )
import Char ( ord )
+#if __GLASGOW_HASKELL__ < 601
+openBinaryFile fp mode = openFileEx fp (BinaryMode mode)
+#endif
-- -----------------------------------------------------------------------------
-- The StringBuffer type
hGetStringBuffer :: FilePath -> IO StringBuffer
hGetStringBuffer fname = do
- h <- openFile fname ReadMode
+ h <- openBinaryFile fname ReadMode
size <- hFileSize h
let size_i@(I# sz#) = fromIntegral size
#if __GLASGOW_HASKELL__ < 503
r <- hGetBufBA h arr size_i
#else
arr <- newArray_ (0,size_i-1)
- r <- hGetArray h arr size_i
+ r <- if size_i == 0 then return 0 else hGetArray h arr size_i
#endif
if (r /= size_i)
then ioError (userError "short read of file")
where
off = c# +# i#
-difference :: StringBuffer -> StringBuffer -> Int
-difference (StringBuffer _ _ c1#) (StringBuffer _ _ c2#) = I# (c2# -# c1#)
-
-- -----------------------------------------------------------------------------
-- Moving
lexemeToFastString _ 0 = mkFastString ""
lexemeToFastString (StringBuffer fo _ current#) (I# len) =
mkFastSubStringBA# fo current# len
+
+-- -----------------------------------------------------------------------------
+-- Parsing integer strings in various bases
+
+parseInteger :: StringBuffer -> Int -> Integer -> (Char->Int) -> Integer
+parseInteger buf len radix to_int
+ = go 0 0
+ where go i x | i == len = x
+ | otherwise = go (i+1) (x * radix + toInteger (to_int (lookAhead buf i)))
\end{code}