module Data.UniversalBinary (parseUniversalBinary, Object(..)) where
import Data.Binary
import Data.Binary.Get
import Control.Monad
import qualified Data.ByteString as B
import qualified Data.ByteString.Lazy as L
data Object = Object
{ cputype :: Int
, cpusubtype :: Int
, align :: Int
, object :: B.ByteString
} deriving (Eq, Show)
getFatArch = do
cputype <- liftM fromIntegral getWord32be
cpusubtype <- liftM fromIntegral getWord32be
offset <- liftM fromIntegral getWord32be
size <- liftM fromIntegral getWord32be
align <- liftM fromIntegral getWord32be
return (cputype, cpusubtype, offset, size, align)
getFatHeader = do
magic <- liftM fromIntegral getWord32be
if magic /= 0xcafebabe then
fail $ "Invalid magic number " ++ show magic
else do
num <- liftM fromIntegral getWord32be
archs <- sequence $ replicate num getFatArch
return archs
processArch bs (cputype, cpusubtype, offset, size, align) = Object
{ cputype = cputype
, cpusubtype = cpusubtype
, align = align
, object = B.take size $ B.drop offset bs
}
parseUniversalBinary :: B.ByteString -> [Object]
parseUniversalBinary bs =
let archs = runGet getFatHeader (L.fromChunks [bs])
in map (processArch bs) archs