On Mon, 04 Apr 2005 13:17:51 +0900 (JST), Daisuke IKEGAMI  
<ikegami / madscientist.jp> wrote:
>> * Haskell - zlib interface
> zlib は gzip format によるデータ圧縮/伸長ライブラリです。
>
> Macromedia Flash は gzipped されたファイルをサポートしています。
> そこで zlib が必要になりました。greencard と ghc 6.4 の Cabal を
> 使って、zlib の wrapper を作ろうと思っています。
> greencard も Cabal もどちらも使うのはとても簡単でした。
>
> zlib 自身は C 言語で書かれたライブラリなのですが、
> zlib の設計は無限長 stream も許すようになっていて、
> Haskell の state monad と相性がよさそうです。
> そこで、しばらく Flash は中座して zlib の interface を
> 眺めたりしています。
>
> これらはすでに誰かが作っていてもおかしくないので、
> もしも御存じでしたら教えてください。あと、協力/コメントは歓迎です。

QForeign や HDirect など他の FFI プリプロセッサには、Zlib サンプルが
ありますが、QForeign はメンテナンスが止まってますし、HDirect は実は
まだまだきちんと開発が進められています (GHC 6.2 対応版が去年でました
し、最近も CVS に commit が行われているようです) が IDL を使うので
あまりよくないかも。

もっとも QForeign の場合、QForeign に依存する部分だけを書き直すという
手もありますが。


Read/Write の interface ぐらいなら、darcs に使われているものやログの
どこにあったか忘れましたが本家の Mailing-list の方で以前紹介されてい
た以下のようなものがあるんですが。


\begin{code}
module Zlib ( gzOpenFile, gzWriteFile, gzReadFile ) where

import IO
import System.IO ( hGetBuf, hPutBuf )
import Control.Concurrent ( forkIO )
import Monad ( when )
import Foreign.C.String ( CString, withCString )
import Foreign.Marshal.Array ( mallocArray, withArray, peekArray )
import Foreign.Marshal.Alloc ( free )
import Foreign.Ptr ( Ptr )
import Data.Word
import GHC.Handle ( openFd )

fdToReadHandle fd fn = openFd fd Nothing fn ReadMode False False
fdToWriteHandle fd fn = openFd fd Nothing fn WriteMode False False

gzOpenFile :: FilePath -> IOMode -> IO Handle
gzWriteFile :: FilePath -> String -> IO ()

gzOpenFile f ReadMode =
     withCString f $ \fstr -> withCString "rb" $ \rb-> do
     gzf <- c_gzopen fstr rb
     withArray [0,0] $ \fds -> do
       err <- c_pipe fds
       when (err /= 0) $ error "Pipe problem!"
       [infd,outfd] <- peekArray 2 fds
       writeH <- fdToWriteHandle (fromIntegral outfd) f
       buf <- mallocArray 1024
       forkIO $ gzreader gzf writeH buf
       fdToReadHandle (fromIntegral infd) f
           where gzreader gzf h buf =
                     do done <- hIsClosed h
                        if done
                           then do c_gzclose gzf
                                   free buf
                                   hClose h
                           else do l <- c_gzread gzf buf 1024
                                   hPutBuf h buf l
                                   if l < 1024
                                      then do free buf
                                              c_gzclose gzf
                                              hClose h
                                      else gzreader gzf h buf
gzOpenFile f WriteMode =
     withCString f $ \fstr -> withCString "wb" $ \wb-> do
     gzf <- c_gzopen fstr wb
     withArray [0,0] $ \fds -> do
       err <- c_pipe fds
       when (err /= 0) $ error "Pipe problem!"
       [infd,outfd] <- peekArray 2 fds
       readH <- fdToReadHandle (fromIntegral infd) f
       buf <- mallocArray 1024
       forkIO $ gzwriter gzf readH buf
       fdToWriteHandle (fromIntegral outfd) f
           where gzwriter gzf h buf =
                     do done <- hIsEOF h
                        if done
                           then do c_gzclose gzf
                                   free buf
                                   hClose h
                           else do l <- hGetBuf h buf 1024
                                   c_gzwrite gzf buf l
                                   gzwriter gzf h buf

gzWriteFile f s = do h <- gzOpenFile f WriteMode
                      hPutStr h s
                      hClose h

gzReadFile f s = do h <- gzOpenFile f WriteMode
                     hGetContents h

foreign import ccall unsafe "static unistd.h pipe" c_pipe
     :: Ptr Int -> IO Int
foreign import ccall unsafe "static unistd.h read" c_read
     :: Ptr Word8 -> Int -> IO Int

foreign import ccall unsafe "static zlib.h gzopen" c_gzopen
     :: CString -> CString -> IO (Ptr ())
foreign import ccall unsafe "static zlib.h gzclose" c_gzclose
     :: Ptr () -> IO ()
foreign import ccall unsafe "static zlib.h gzread" c_gzread
     :: Ptr () -> Ptr Word8 -> Int -> IO Int
foreign import ccall unsafe "static zlib.h gzwrite" c_gzwrite
     :: Ptr () -> Ptr Word8 -> Int -> IO ()
\end{code}



-- 
shelarcy <shelarcy capella.freemail.ne.jp>
http://page.freett.com/shelarcy/