-----------------------------------------------------------------------------
-- |
-- Module : System.UTF8IO
-- Copyright : (c) Péter Diviánszky 2008
-- License : BSD3-style (see LICENSE)
--
-- Maintainer: divip@aszt.inf.elte.hu
-- Stability : alpha
-- Portability : portable
--
-- "System.UTF8IO" defines the same entities as "System.IO" but with UTF8 text I/O operations.
--
-- "System.UTF8IO" re-exports "System.IO.UTF8" (utf8-string package) and "System.IO" but hides the duplicate definitions (in favor of "System.IO.UTF8").
module System.UTF8IO
( module System.IO
, module System.IO.UTF8
-- * Functions not defined in "System.IO.UTF8"
, putChar
, getChar
, hPutChar
, hGetChar
, hLookAhead
, hPrint
) where
import Codec.Binary.UTF8.String (decodeString)
import Data.Bits ((.&.))
import System.IO.UTF8
import System.IO hiding
( print
, putStr
, putStrLn
, getLine
, readLn
, readFile
, writeFile
, appendFile
, getContents
, putChar
, getChar
, hGetLine
, hGetContents
, hPutStr
, hPutStrLn
, hPutChar
, hGetChar
, hLookAhead
, hPrint
, openBinaryFile
, withBinaryFile
)
import qualified System.IO
import Prelude hiding
( print
, putStr
, putStrLn
, getLine
, readLn
, readFile
, writeFile
, appendFile
, getContents
, putChar
, getChar
)
-- | Computation 'hPutChar' @hdl ch@ writes the character @ch@ to the file or channel managed by @hdl@.
-- Characters may be buffered if buffering is enabled for @hdl@.
--
-- Note: The implementation of 'hPutChar' is not as efficient as it could be.
hPutChar :: Handle -> Char -> IO ()
hPutChar h c = hPutStr h [c]
-- | Computation 'hGetChar' @hdl@ reads a character from the file or channel
-- managed by 'hdl', blocking until a character is available.
--
-- Note: The implementation of 'hGetChar' is not as efficient as it could be.
hGetChar :: Handle -> IO Char
hGetChar h = do
c <- System.IO.hGetChar h
s <- getBytes [c] (estimated_size c)
return $ head $ decodeString $ reverse s -- may have faster implementation
where
estimated_size c
| c < toEnum 0xc0 = 0
| c < toEnum 0xe0 = 1
| c < toEnum 0xf0 = 2
| c < toEnum 0xf8 = 3
| c < toEnum 0xfc = 4
| c < toEnum 0xfe = 5
| otherwise = 0
getBytes :: String -> Int -> IO String
getBytes acc 0 = return acc
getBytes acc n = do
eof <- hIsEOF h
if eof
then return acc
else do
c <- System.IO.hLookAhead h
if fromEnum c .&. 0xc0 == 0x80
then do
System.IO.hGetChar h
getBytes (c: acc) (n-1)
else return acc
-- | Computation 'hLookAhead' @hdl@ returns the next character from the handle
-- without removing it from the input buffer, blocking until a character is available.
--
-- Note: 'hLookAhead' is not implemented; it halts with a run-time error.
hLookAhead :: Handle -> IO Char
hLookAhead = error "System.UTF8IO.hLookAhead: Not implemented"
-- | Write a character to the standard output device
-- (same as 'hPutChar' 'stdout').
--
-- Note: The implementation of 'putChar' is not as efficient as it could be.
putChar :: Char -> IO ()
putChar c = hPutChar stdout c
-- | Read a character from the standard input device
-- (same as 'hGetChar' 'stdin').
--
-- Note: The implementation of 'getChar' is not as efficient as it could be.
getChar :: IO Char
getChar = hGetChar stdin
-- | Computation 'hPrint' @hdl t@ writes the UTF8 string representation of @t@
-- to the file or channel managed by @hdl@ and appends a newline
-- (same as 'hPutStrLn' @hdl .@ 'show' @t@).
--
-- Note: 'hPrint' has the same behaviour as @System.IO.hPrint@ because 'show' always produces an ASCII string.
hPrint :: Show a => Handle -> a -> IO ()
hPrint hdl = hPutStrLn hdl . show