-
-
Save nonowarn/262978 to your computer and use it in GitHub Desktop.
StringIO but in Haskell (on GHC-6.12)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
= | |
GHC 6.12 の Unicode I/O | |
Yusaku Hashimoto | |
<[email protected]> | |
- | |
自己紹介 | |
- | |
京都の組み込み系専門学生の | |
皮をかぶった Haskeller | |
- | |
ふだんは | |
nwn とか nonowarn とか | |
- | |
本題 | |
- | |
Unicode I/O | |
- | |
Char は Unicode をカバー | |
- | |
だけど ascii の範囲を超える文字を | |
入出力しようとすると化けてた (<= 6.10.*) | |
- | |
6.12 から Unicode を | |
ちゃんと扱えるようになる | |
= | |
do | |
fh <- openFile | |
"a_file.txt" WriteMode | |
hPutStrLn fh "〄" | |
hClose fh | |
= | |
-- いやこれでもいいけど | |
writeFile "a_file.txt" "〄" | |
- | |
デフォルトは | |
Locale の Encoding を使う | |
= | |
$ LANG=C ghci | |
= | |
それぞれの Handle が | |
エンコーダ/デコーダを | |
持つようになった | |
= | |
例題: | |
Shift-JIS で読んで | |
EUC-JP で出力 | |
= | |
import System.IO | |
main = do | |
sjis <- mkTextEncoding "SHIFT-JIS" | |
euc <- mkTextEncoding "EUC-JP" | |
hSetEncoding stdin sjis | |
hSetEncoding stdout euc | |
interact id | |
- | |
TextEncoding は | |
Encoder と Decoder のペア | |
= | |
mkTextEncoding | |
:: String -> IO TextEncoding | |
hSetEncoding | |
:: Handle -> Encoding -> IO () | |
- | |
Handle を使って入力/出力すると | |
デコーダ/エンコーダが動く | |
= | |
注意: | |
mkTextEncoding の実装は iconv | |
= | |
自前で書くのもあり | |
ghc -e | |
':i GHC.IO.Encoding.TextEncoding' | |
- | |
もう一個重要な変更点 | |
(Unicode からは離れるが) | |
- | |
Handle が FD 以外の | |
デバイスを持てるようになった | |
- | |
Handle | |
- | |
Handle of FD | |
= | |
Handle <=> Char | |
FD <=> バイト列 | |
- | |
<= 6.10 | |
= | |
Handle <=> Char | |
~~~~~~~~~~~~~~ | |
FD <=> バイト列 | |
- | |
>= 6.12 | |
= | |
Handle <=> Char | |
[TextEncoding] | |
FD <=> バイト列 | |
= | |
Handle <=> Char | |
[TextEncoding] | |
*Any* <=> バイト列 | |
- | |
ファイル以外の物を | |
Handle を通して扱える | |
- | |
3 Steps | |
= | |
data MyIO = ... | |
instance BufferedIO MyIO | |
instance IODevice MyIO | |
mkMyIO :: IO Handle | |
mkMyIO = mkFileHandle | |
(MyIO ...) ... | |
= | |
例: | |
StringIO | |
- | |
まとめ | |
- | |
Handle おもしろいよー | |
- | |
Simon Marlow さんありがとう | |
- | |
以上 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module StringIO where | |
import Prelude hiding (read) | |
import Foreign | |
import Foreign.ForeignPtr | |
import Foreign.C.Types | |
import GHC.IO.Handle | |
import GHC.IO.Buffer | |
import GHC.IO.BufferedIO | |
import GHC.IO.Device | |
import Control.Applicative | |
import Data.Typeable | |
import Data.Word | |
import Data.IORef | |
import System.IO | |
data StringIOBuffer = StringIOBuffer (IORef [Word8]) | |
deriving (Typeable) | |
instance RawIO StringIOBuffer where | |
read (StringIOBuffer ref) ptr len = do | |
(w,rest) <- fmap (splitAt len) $ readIORef ref | |
pokeArray ptr w | |
writeIORef ref rest | |
return $ length w | |
readNonBlocking buf ptr len = -- TODO | |
fmap Just $ read buf ptr len | |
write (StringIOBuffer ref) ptr len = do | |
r <- peekArray len ptr | |
modifyIORef ref (++r) | |
writeNonBlocking buf ptr len = | |
write buf ptr len >> return len -- TODO | |
instance BufferedIO StringIOBuffer where | |
newBuffer (StringIOBuffer ref) state = do | |
let buf_len = 1024 | |
buf_ptr <- mallocForeignPtrBytes buf_len | |
return (emptyBuffer buf_ptr buf_len state) | |
fillReadBuffer = readBuf | |
fillReadBuffer0 = readBufNonBlocking | |
flushWriteBuffer = writeBuf | |
flushWriteBuffer0 = writeBufNonBlocking | |
instance IODevice StringIOBuffer where | |
ready _ _ _ = return True | |
close _ = return () | |
devType _ = return RawDevice | |
makeStringIO :: IO Handle | |
makeStringIO = do | |
buffer <- StringIOBuffer <$> newIORef [] | |
mkFileHandle buffer "string io" ReadWriteMode (Just localeEncoding) nativeNewlineMode |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment