@@ -0,0 +1,118 @@
1+-----------------------------------------------------------------------------
2+-- |
3+-- Module : System.IO.UTF8
4+-- Copyright : (c) Eric Mertens 2007
5+-- License : BSD3-style (see LICENSE)
6+--
7+-- Maintainer: emertens@galois.com
8+-- Stability : experimental
9+-- Portability : portable
10+--
11+-- String IO preserving UTF8 encoding.
12+--
13+
14+module System.IO.UTF8 (
15+ print
16+ , putStr
17+ , putStrLn
18+ , getLine
19+ , readLn
20+ , readFile
21+ , writeFile
22+ , appendFile
23+ , getContents
24+ , hGetLine
25+ , hGetContents
26+ , hPutStr
27+ , hPutStrLn
28+ ) where
29+
30+import Control.Monad (liftM)
31+import Data.Char (ord, chr)
32+import Data.Word (Word8)
33+import Prelude (String, ($), (=<<), (>>=), (.), map, toEnum, fromEnum, Read,
34+ Show(..))
35+import System.IO (Handle, IO, FilePath)
36+import qualified System.IO as IO
37+
38+import Codec.Binary.UTF8.String (encode, decode)
39+
40+
41+-- | Encode a string in UTF8 form.
42+encodeString :: String -> String
43+encodeString xs = bytesToString (encode xs)
44+
45+-- | Decode a string from UTF8
46+decodeString :: String -> String
47+decodeString xs = decode (stringToBytes xs)
48+
49+-- | Convert a list of bytes to a String
50+bytesToString :: [Word8] -> String
51+bytesToString xs = map (chr . fromEnum) xs
52+
53+-- | String to list of bytes.
54+stringToBytes :: String -> [Word8]
55+stringToBytes xs = map (toEnum . ord) xs
56+
57+-- | The 'print' function outputs a value of any printable type to the
58+-- standard output device. This function differs from the
59+-- System.IO.print in that it preserves any UTF8 encoding of the shown value.
60+--
61+print :: Show a => a -> IO ()
62+print x = putStrLn (show x)
63+
64+-- | Write a UTF8 string to the standard output device
65+putStr :: String -> IO ()
66+putStr x = IO.putStr (encodeString x)
67+
68+-- | The same as 'putStr', but adds a newline character.
69+putStrLn :: String -> IO ()
70+putStrLn x = IO.putStrLn (encodeString x)
71+
72+-- | Read a UTF8 line from the standard input device
73+getLine :: IO String
74+getLine = liftM decodeString IO.getLine
75+
76+-- | The 'readLn' function combines 'getLine' and 'readIO', preserving UTF8
77+readLn :: Read a => IO a
78+readLn = IO.readIO =<< getLine
79+
80+-- | The 'readFile' function reads a file and
81+-- returns the contents of the file as a UTF8 string.
82+-- The file is read lazily, on demand, as with 'getContents'.
83+readFile :: FilePath -> IO String
84+readFile n = liftM decodeString (IO.openBinaryFile n IO.ReadMode >>=
85+ IO.hGetContents)
86+
87+-- | The computation 'writeFile' @file str@ function writes the UTF8 string @str@,
88+-- to the file @file@.
89+writeFile :: FilePath -> String -> IO ()
90+writeFile n c = IO.withBinaryFile n IO.WriteMode $ \ h ->
91+ IO.hPutStr h $ encodeString c
92+
93+-- | The computation 'appendFile' @file str@ function appends the UTF8 string @str@,
94+-- to the file @file@.
95+appendFile :: FilePath -> String -> IO ()
96+appendFile n c = IO.withBinaryFile n IO.AppendMode $ \h ->
97+ IO.hPutStr h $ encodeString c
98+
99+-- | Read a UTF8 line from a Handle
100+hGetLine :: Handle -> IO String
101+hGetLine h = liftM decodeString $ IO.hGetLine h
102+
103+-- | Lazily read a UTF8 string from a Handle
104+hGetContents :: Handle -> IO String
105+hGetContents h = liftM decodeString (IO.hGetContents h)
106+
107+-- | Write a UTF8 string to a Handle.
108+hPutStr :: Handle -> String -> IO ()
109+hPutStr h s = IO.hPutStr h (encodeString s)
110+
111+-- | Write a UTF8 string to a Handle, appending a newline.
112+hPutStrLn :: Handle -> String -> IO ()
113+hPutStrLn h s = IO.hPutStrLn h (encodeString s)
114+
115+-- | Lazily read stdin as a UTF8 string.
116+getContents :: IO String
117+getContents = liftM decodeString IO.getContents
118+