packages feed

hurdle-0.4.0: src/Hurdle/Ar/Parser.hs

{-# OPTIONS -Wall #-}

--------------------------------------------------------------------------------
-- |
-- Module      :  Hurdle.Ar.Parser
-- Copyright   :  (c) Stephen Tetley 2009, 2010
-- License     :  BSD3
--
-- Maintainer  :  Stephen Tetley <stephen.tetley@gmail.com>
-- Stability   :  highly unstable
-- Portability :  to be determined.
--
-- Read \".a\" archive...
--
--------------------------------------------------------------------------------

module Hurdle.Ar.Parser where

import Hurdle.Ar.Datatypes
import Hurdle.Base.Utils

import Control.Monad
import Data.Char

readAr :: FilePath -> IO ArArchive
readAr filename = do
    (ans,w) <- runKangaroo arArchive filename
    case ans of 
      Left err -> (putStrLn $ toList w) >> error err
      Right a -> return a




--------------------------------------------------------------------------------
-- 
    
    
arArchive :: Parser ArArchive
arArchive = do
    magic    <- arMagicString
    objects  <- runOn archiveObject
    return $ ArArchive 
                { ar_magic        = magic
                , ar_objects      = objects
                }


arMagicString :: Parser String
arMagicString = text 8 


archiveObject :: Parser ArchiveObject
archiveObject = do 
    liftIOAction $ putStrLn "ao"
    header  <- arHeader
    let sz  = arh_size header
    liftIOAction $ putStrLn ("size " ++ show sz)
    pos     <- position
    body    <- count sz word8
    end_pos <- position
    when (end_pos `mod` 2 /= 0) (anyChar >> return ())   -- should be a newline 
    return $ ArchiveObject 
                { ar_header         = header
                , ar_body           = (pos,sz)
                }

paddedNumber :: (Read a, Integral a) => Int -> Parser a
paddedNumber i = liftM fn $ count i anyChar
  where
    fn = read . takeWhile isDigit


arHeader :: Parser ArHeader
arHeader = do 
    name    <- text 16
    date    <- text 12
    uid     <- paddedNumber 6
    gid     <- paddedNumber 6
    mode    <- text 8
    size    <- paddedNumber 10
    trailer <- text 2
    return $ ArHeader 
                { arh_name            = name
                , arh_date            = date
                , arh_user_id         = uid
                , arh_group_id        = gid
                , arh_mode            = mode
                , arh_size            = size
                , arh_trailer         = trailer
                }