Supongamos que necesito analizar un archivo binario, que comienza con tres números mágicos de 4 bytes. Dos de ellos son cadenas fijas. El otro, sin embargo, es la longitud del archivo.E/S Iteratee: necesita saber el tamaño del archivo de antemano
{-# LANGUAGE OverloadedStrings #-}
module Main where
import Data.Attoparsec
import Data.Attoparsec.Enumerator
import Data.Enumerator hiding (foldl, foldl', map, head)
import Data.Enumerator.Binary hiding (map)
import qualified Data.ByteString as S
import System
main = do
f:_ <- getArgs
eitherStat <- run (enumFile f $$ iterMagics)
case eitherStat of
Left _err -> putStrLn $ "Not a beam file: " ++ f
Right _ -> return()
iterMagics :: Monad m => Iteratee S.ByteString m()
iterMagics = iterParser parseMagics
parseMagics :: Parser()
parseMagics = do
_ <- string "FOR1"
len <- big_endians 4 -- need to compare with actual file length
_ <- string "BEAM"
return()
big_endians :: Int -> Parser Int
big_endians n = do
ws <- count n anyWord8
return $ foldl1 (\a b -> a * 256 + b) $ map fromIntegral ws
Si la longitud indicada no coincide con la longitud real, idealmente iterMagics
debe devolver un error. ¿Pero cómo? ¿Es la única manera de pasar la longitud real como argumento? ¿Es esta la forma iterativa de hacerlo? No muy incremental para mí :)
¿Cuál es el programa que pasa la longitud real del archivo como argumento al generar inicialmente un iterador? Tal vez cambie su función 'iterMagics' para tomar la longitud del archivo como argumento. Si programa de manera inteligente, su código necesita pasar la longitud solo una vez. – fuz