language-c-0.4.2: src/Language/C/Data/InputStream.hs
{-# LANGUAGE CPP, BangPatterns #-}
{-# OPTIONS -Wall #-}
-----------------------------------------------------------------------------
-- |
-- Module : Language.C.Data.InputStream
-- Copyright : (c) 2008,2011 Benedikt Huber
-- License : BSD-style
-- Maintainer : benedikt.huber@gmail.com
-- Stability : experimental
-- Portability : ghc
--
-- Compile time input abstraction for the parser, relying on ByteString.
-- The String interface only supports Latin-1 since alex-3, as alex now requires
-- byte based access to the input stream.
-------------------------------------------------------------------------------
module Language.C.Data.InputStream (
InputStream, readInputStream,inputStreamToString,inputStreamFromString,
takeByte, takeChar, inputStreamEmpty, takeChars,
countLines,
)
where
import Data.Word
#ifndef NO_BYTESTRING
import Data.ByteString (ByteString)
import qualified Data.ByteString as BSW
import qualified Data.ByteString.Char8 as BSC
#else
import qualified Data.Char as Char
#endif
-- Generic InputStream stuff
-- | read a file into an 'InputStream'
readInputStream :: FilePath -> IO InputStream
-- | convert 'InputStream' to 'String'
inputStreamToString :: InputStream -> String
{-# INLINE inputStreamToString #-}
-- | convert a 'String' to an 'InputStream'
inputStreamFromString :: String -> InputStream
-- | @(b,is') = takeByte is@ reads and removes
-- the first byte @b@ from the 'InputStream' @is@
takeByte :: InputStream -> (Word8, InputStream)
{-# INLINE takeByte #-}
-- | @(c,is') = takeChar is@ reads and removes
-- the first character @c@ from the 'InputStream' @is@
takeChar :: InputStream -> (Char, InputStream)
{-# INLINE takeChar #-}
-- | return @True@ if the given input stream is empty
inputStreamEmpty :: InputStream -> Bool
{-# INLINE inputStreamEmpty #-}
-- | @str = takeChars n is@ returns the first @n@ characters
-- of the given input stream, without removing them
takeChars :: Int -> InputStream -> [Char]
{-# INLINE takeChars #-}
-- | @countLines@ returns the number of text lines in the
-- given 'InputStream'
countLines :: InputStream -> Int
#ifndef NO_BYTESTRING
type InputStream = ByteString
takeByte bs = BSW.head bs `seq` (BSW.head bs, BSW.tail bs)
takeChar bs = BSC.head bs `seq` (BSC.head bs, BSC.tail bs)
inputStreamEmpty = BSW.null
#ifndef __HADDOCK__
takeChars !n bstr = BSC.unpack $ BSC.take n bstr --leaks
#endif
readInputStream = BSW.readFile
inputStreamToString = BSC.unpack
inputStreamFromString = BSC.pack
countLines = length . BSC.lines
#else
type InputStream = String
takeByte bs
| Char.isLatin1 c = let b = fromIntegral (Char.ord c) in b `seq` (b, tail bs)
| otherwise = error "takeByte: not a latin-1 character"
where c = head bs
takeChar bs = (head bs, tail bs)
inputStreamEmpty = null
takeChars n str = take n str
readInputStream = readFile
inputStreamToString = id
inputStreamFromString = id
countLines = length . lines
#endif