Monday, March 15, 2010

[radxivfc] fread of an int in haskell

Here is the C++ code

#include <cstdio> int main(void){ for(;;){ int x; int code=fread(&x,sizeof(x),1,stdin); if(code!=1)break; printf("%08x\n",x); } }

and here is the Haskell code

module Main where{ import Data.Binary.Get; import qualified Data.ByteString.Lazy as B; import Data.Word; import Text.Printf; import Data.Int; takes :: Int64 -> B.ByteString -> [B.ByteString]; takes n s = let { (x,y) = B.splitAt n s; {- The implementation of splitAt suggests that it is better to call splitAt than take and drop separately -} } in if (B.length x == n) then (x : (takes n y)) else []; {- ignore if less than four bytes left over -} readWord :: B.ByteString -> Word32; readWord = runGet getWord32host; main::IO(); main = B.getContents >>= mapM_ (printf "%08x\n") . map readWord . takes 4; }

It took a while to achieve this. I wanted lazy IO (do not read the entire input into memory), ignore leftover bytes at the end, and works OK when run interactively.

Update: a better version

module Main where{ import Data.Binary.Get; import qualified Data.ByteString.Lazy as B; import Data.Word; import Text.Printf; import System.IO; readWord :: B.ByteString -> Word32; readWord = runGet getWord32host; main::IO(); main = catch (sequence_ $ repeat $ do { x <- B.hGet stdin 4; if (B.length x/=4) then (fail "done") else printf "%08x\n" (readWord x);} ) (const $ return ()); }

No comments :