binary-file 0.6 → 0.12.6
raw patch · 7 files changed
+454/−221 lines, 7 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ File.Binary: cc :: Str a => [a] -> a
+ File.Binary: class RetType r where type family Argument r
+ File.Binary: class Str a
+ File.Binary: dp :: Str a => Int -> a -> a
+ File.Binary: empty :: Str a => a -> Bool
+ File.Binary: fbs :: Str a => ByteString -> a
+ File.Binary: fi :: Str a => Int -> Integer -> a
+ File.Binary: fiBE :: Str a => Int -> Integer -> a
+ File.Binary: fii :: Str a => Int -> Int -> a
+ File.Binary: fiiBE :: Str a => Int -> Int -> a
+ File.Binary: fromType :: (RetType r, Str s) => Argument r -> r -> s
+ File.Binary: fs :: Str a => String -> a
+ File.Binary: len :: Str a => a -> Int
+ File.Binary: rev :: Str a => a -> a
+ File.Binary: tbs :: Str a => a -> ByteString
+ File.Binary: ti :: Str a => a -> Integer
+ File.Binary: tiBE :: Str a => a -> Integer
+ File.Binary: tii :: Str a => Int -> a -> (Int, a)
+ File.Binary: tiiBE :: Str a => Int -> a -> (Int, a)
+ File.Binary: tk :: Str a => Int -> a -> a
+ File.Binary: toType :: (RetType r, Str s) => Argument r -> s -> (r, s)
+ File.Binary: ts :: Str a => a -> String
+ File.Binary: zero :: Str a => a
+ File.Binary.Data.BigEndian: instance RetType Int
+ File.Binary.Data.LittleEndian: instance RetType Int
Files
- binary-file.cabal +26/−10
- src/Classes.hs +147/−0
- src/File/Binary.hs +6/−1
- src/File/Binary/Data/BigEndian.hs +12/−0
- src/File/Binary/Data/LittleEndian.hs +12/−0
- src/ParseBinaryStructure.hs +135/−45
- src/QuoteBinaryStructure.hs +116/−165
binary-file.cabal view
@@ -2,7 +2,7 @@ cabal-version: >= 1.8 name: binary-file-version: 0.6+version: 0.12.6 stability: experimental author: Yoshikuni Jujo <PAF01143@nifty.ne.jp> maintainer: Yoshikuni Jujo <PAF01143@nifty.ne.jp>@@ -19,24 +19,33 @@ exam.hs: . > import File.Binary+ > import File.Binary.Data.LittleEndian > import System.Environment > import Data.ByteString as BS > > main = do > [inf, outf] <- getArgs >- > -- cnt <- readBinaryFile inf > cnt <- BS.readFile inf- > let bmp = readBitmap cnt- > print $ readBitmap cnt+ > let bmp = readBitmap $ cnt `BS.append` replicate 20 ' '+ > print bmp > > let out = writeBitmap bmp { > authorFirst = "Yoshikuni ", > authorSecond = "Jujo " > }- > -- writeBinaryFile outf out > BS.writeFile outf out >+ > instance RetType (Int, Int, Int) where+ > type Argument (Int, Int, Int) = ()+ > fromType _ (b, g, r) = cc $ [+ > fromType 1 b, fromType 1 g, fromType 1 r, zero]+ > toType _ str = let+ > (b, rest) = toType 1 str+ > (g, rest') = toType 1 rest+ > (r, rest'') = toType 1 rest' in+ > ((b, g, r), dp 1 rest'')+ > > [binary| > > Bitmap@@ -46,6 +55,7 @@ > 2: 0 > 2: 0 > 4: offset+ > > 4: 40 > 4: bitmapWidth > 4: bitmapHeight@@ -57,18 +67,24 @@ > 4: verticalResolution > 4: numberOfColors > 4: importantColors- > 4<(Int, Int, Int)>[numberOfColors]: colors- > -- bitsPerPixel/8[imageSize*8/bitsPerPixel]: image- > imageSize<ByteString>: image+ > ((), Just numberOfColors)<[(Int, Int, Int)]>: colors+ > imageSize<BS.ByteString>: image+ > > 10<String>: authorFirst > 10<String>: authorSecond > > |] . +source-repository head+ type: git+ location: git://github.com/YoshikuniJujo/binary-file.git+ library hs-source-dirs: src- exposed-modules: File.Binary- other-modules: QuoteBinaryStructure, ParseBinaryStructure, Here+ exposed-modules: File.Binary,+ File.Binary.Data.LittleEndian,+ File.Binary.Data.BigEndian+ other-modules: QuoteBinaryStructure, ParseBinaryStructure, Here, Classes build-depends: base > 3 && < 5, template-haskell, peggy, bytestring ghc-options: -Wall
+ src/Classes.hs view
@@ -0,0 +1,147 @@+{-# LANGUAGE+ TemplateHaskell,+ TypeSynonymInstances,+ FlexibleInstances,+ TypeFamilies,+ OverloadedStrings #-}++module Classes (+ RetType(..),+ Str(..),+ retTypeInt,+ fii, fiiBE,+ tii, tiiBE,+ Endian(..)+) where++import qualified Data.ByteString as BS+import ParseBinaryStructure+import Data.Char+import Language.Haskell.TH++class RetType r where+ type Argument r+ fromType :: Str s => Argument r -> r -> s+ toType :: Str s => Argument r -> s -> (r, s)++instance RetType r => RetType [r] where+ type Argument [r] = (Argument r, Maybe Int)+ fromType (a, _) rs = cc $ map (fromType a) rs+ toType (a, Just b) s = (b `times` toType a) s+ toType (a, Nothing) s = whole (toType a) s++retTypeInt :: Endian -> DecsQ+retTypeInt endian = fmap (:[]) $+ instanceD (cxt []) (appT (conT ''RetType) (conT ''Int)) [argt, dfii, dtii]+ where+ argt = tySynInstD ''Argument [conT ''Int] $ conT ''Int+ dfii = valD (varP 'fromType) (normalB $ fiiend) []+ dtii = valD (varP 'toType) (normalB $ tiiend) []+ sffx = case endian of+ LittleEndian -> ""+ BigEndian -> "BE"+ fiiend = varE $ mkName $ "fii" ++ sffx+ tiiend = varE $ mkName $ "tii" ++ sffx++{-+instance RetType Int where+ fromType = fii+ toType = tii+-}++{-+instance RetType String where+ type Argument String = Int+ fromType _ = fs+ toType _ str = (ts str, undefined)+-}++instance RetType Char where+ type Argument Char = ()+ fromType _ = fs . (: [])+ toType _ str = (head $ ts str, dp 1 str)++instance RetType BS.ByteString where+ type Argument BS.ByteString = Int+ fromType _ = fbs+ toType n str = (tbs $ tk n str, dp n str)+-- toType n str = (tbs $ tk n str, fs $ show (len str) ++ show n ++ "hoge hoge hage hage ") -- dp n str)++class Str a where+ tk :: Int -> a -> a+ dp :: Int -> a -> a+ ts :: a -> String+ fs :: String -> a+ fbs :: BS.ByteString -> a+ tbs :: a -> BS.ByteString+ ti :: a -> Integer+ fi :: Int -> Integer -> a+ tiBE :: a -> Integer+ fiBE :: Int -> Integer -> a+ cc :: [a] -> a+ zero :: a+ len :: a -> Int+ empty :: a -> Bool+ rev :: a -> a++instance Str String where+ tk = take+ dp = drop+ ts = id+ fs = id+ fbs = ts+ tbs = fs+ ti = readInt LittleEndian+ fi = intToBin LittleEndian+ tiBE = readInt BigEndian+ fiBE = intToBin BigEndian+ cc = concat+ zero = "\0"+ len = length+ empty = null+ rev = reverse++fii, fiiBE :: Str a => Int -> Int -> a+fii n = fi n . fromIntegral+fiiBE n = fiBE n . fromIntegral+tii, tiiBE :: Str a => Int -> a -> (Int, a)+tii _ str = (fromIntegral $ ti $ tk 4 str, dp 4 str)+tiiBE _ str = (fromIntegral $ tiBE $ tk 4 str, dp 4 str)++instance Str BS.ByteString where+ tk = BS.take+ dp = BS.drop+ ts = map (chr . fromIntegral) . BS.unpack+ fs = BS.pack . map (fromIntegral . ord)+ fbs = id+ tbs = id+ ti = readInt LittleEndian . map (chr . fromIntegral) . BS.unpack+ fi n = BS.pack . map (fromIntegral . ord) . intToBin LittleEndian n+ tiBE = readInt BigEndian . map (chr . fromIntegral) . BS.unpack+ fiBE n = BS.pack . map (fromIntegral . ord) . intToBin BigEndian n+ cc = BS.concat+ zero = BS.singleton 0+ len = BS.length+ empty = (== 0) . BS.length+ rev = BS.reverse++intToBin :: Endian -> Int -> Integer -> String+intToBin LittleEndian 0 _ = ""+intToBin LittleEndian n x = chr (fromIntegral $ x `mod` 256) :+ intToBin LittleEndian (fromIntegral n - 1) (x `div` 256)+intToBin BigEndian n x = reverse $ intToBin LittleEndian n x++times :: Int -> (s -> (ret, s)) -> s -> ([ret], s)+times 0 _ s = ([], s)+times n f s = let+ (ret, rest) = f s+ (rets, rest') = times (n - 1) f rest in+ (ret : rets, rest')++whole :: Str s => (s -> (ret, s)) -> s -> ([ret], s)+whole f s+ | empty s = ([], s)+ | otherwise = let+ (ret, rest) = f s+ (rets, rest') = whole f rest in+ (ret : rets, rest')
src/File/Binary.hs view
@@ -1,7 +1,12 @@ module File.Binary ( readBinaryFile, writeBinaryFile,- binary+ binary,+ RetType(..),+ Str(..),+ tii, tiiBE,+ fii, fiiBE+-- times ) where import QuoteBinaryStructure
+ src/File/Binary/Data/BigEndian.hs view
@@ -0,0 +1,12 @@+{-# LANGUAGE TemplateHaskell, TypeFamilies #-}++module File.Binary.Data.BigEndian where++import Classes++-- retTypeInt BigEndian++instance RetType Int where+ type Argument Int = Int+ fromType n = rev . fi n . fromIntegral+ toType n s = (fromIntegral $ ti $ rev $ tk n s, dp n s)
+ src/File/Binary/Data/LittleEndian.hs view
@@ -0,0 +1,12 @@+{-# LANGUAGE TemplateHaskell, TypeFamilies #-}++module File.Binary.Data.LittleEndian where++import Classes++-- retTypeInt LittleEndian++instance RetType Int where+ type Argument Int = Int+ fromType n = fi n . fromIntegral+ toType n s = (fromIntegral $ ti $ tk n s, dp n s)
src/ParseBinaryStructure.hs view
@@ -1,6 +1,7 @@ {-# LANGUAGE TemplateHaskell, QuasiQuotes, FlexibleContexts #-} module ParseBinaryStructure (+ Endian(..), BinaryStructure(..), BinaryStructureItem, Expression(..),@@ -10,13 +11,17 @@ sizeOf, valueOf, parseBinaryStructure,- readInt+ readInt,+ isRepeat,+ getRepeat ) where import Text.Peggy import Here import Control.Arrow import Data.Char+import Language.Haskell.TH hiding (Type)+import Numeric hiding (readInt) main :: IO () main = do@@ -25,6 +30,8 @@ BitmapFileHeader +set big_endian+ 2: 19778 4: fileSize 2: 0@@ -43,73 +50,105 @@ 4: colorIndexNumber 4: neededIndexNumber +(4, colorIndexNumber)<[Int]>: colors 4<(Int,Int,Int)>[colorIndexNumber]: colors -- 1[3]: image imageSize<ByteString>: image 10<String>: author 10<ByteString>: hoge+10<Some>: some+10: "abc\n\r\SUB"+10: 0x89 +repeat {++Chank++4: chankSize+4<String>: chankData+chankSize<String>: chankData+4<Word32>:chankCRC++}+ |] data Expression = Multiple Expression Expression | Division Expression Expression+ | Addition Expression Expression | Variable String | Number Int- deriving Show+ | ExpressionQ {expressionQ :: Name -> ExpQ} +instance Show Expression where+ show _ = "Expression"++sumExp :: [Expression] -> Expression+sumExp [] = Number 0+sumExp (e1 : e2) = Addition e1 $ sumExp e2+ data ConstantValue = ConstantInt Int | ConstantString String deriving Show -constantInt (ConstantInt v) = v-constantInt (ConstantString v) = readInt v+constantInt endian (ConstantInt v) = v+constantInt endian (ConstantString v) = fromIntegral $ readInt endian v -data Type = String | Int | ByteString | Tuple [Type] deriving (Show, Eq)+data Type+-- = Tuple [Type]+ = Type { typeQ :: TypeQ } -- String +instance Show Type where+ show _ = "Type"+ data VariableValue = VariableValue { variableValue :: String } deriving Show -data BinaryStructureItem = BinaryStructureItem {- binaryStructureItemBytes :: Expression,- binaryStructureItemType :: Type,- binaryStructureItemListSize :: Maybe Expression, -- (Either Int String),- binaryStructureItemValue :: Either ConstantValue VariableValue -- Int String- } deriving Show+data BinaryStructureItem+ = BinaryStructureItem {+ binaryStructureItemBytes :: Expression,+ binaryStructureItemType :: Type,+ binaryStructureItemListSize :: Maybe Expression, -- (Either Int String),+ binaryStructureItemValue :: Either ConstantValue VariableValue -- Int String+ }+ | Repeat { getRepeat :: BinaryStructure }+ deriving Show +isRepeat (Repeat _) = True+isRepeat _ = False+ bytesOf :: BinaryStructureItem -> Expression-bytesOf = binaryStructureItemBytes+bytesOf (Repeat BinaryStructure{binaryStructureBody = body}) =+ sumExp $ map bytesOf body+bytesOf BinaryStructureItem { binaryStructureItemBytes = b } = b typeOf :: BinaryStructureItem -> Type-typeOf = binaryStructureItemType+typeOf (Repeat BinaryStructure{binaryStructureName = name}) =+ Type $ appT listT $ conT $ mkName name+typeOf BinaryStructureItem{binaryStructureItemType = t} = t sizeOf :: BinaryStructureItem -> Maybe Expression-sizeOf = binaryStructureItemListSize+sizeOf (Repeat BinaryStructure{}) = Nothing+sizeOf BinaryStructureItem{binaryStructureItemListSize = s} = s -valueOf :: BinaryStructureItem -> Either Int String-valueOf = (constantInt +++ variableValue) . binaryStructureItemValue+valueOf :: Endian -> BinaryStructureItem -> Either Int String+valueOf endian BinaryStructureItem { binaryStructureItemValue = v } =+ (constantInt endian +++ variableValue) v+valueOf endian (Repeat BinaryStructure{binaryStructureName = name}) =+ Right $ "repeat" ++ name binaryStructureItem :: Expression -> Type -> Maybe Expression -> Either ConstantValue VariableValue -> BinaryStructureItem binaryStructureItem = BinaryStructureItem -{--type BinaryStructureItem = (Int, Either Int String)--bytesOf :: (Int, Either Int String) -> Int-bytesOf = fst--valueOf :: (Int, Either Int String) -> Either Int String-valueOf = snd--binaryStructureItem :: Int -> Either Int String -> BinaryStructureItem-binaryStructureItem = (,)--}+data Endian = BigEndian | LittleEndian deriving Show data BinaryStructure = BinaryStructure { binaryStructureName :: String,+ binaryStructureEndian :: Endian, binaryStructureBody :: [BinaryStructureItem] } deriving Show @@ -118,16 +157,26 @@ Right bs -> bs Left ps -> error $ show ps -readInt :: String -> Int-readInt "" = 0-readInt (c : cs) = ord c + 2 ^ 8 * readInt cs+readInt :: Endian -> String -> Integer+readInt LittleEndian "" = 0+readInt LittleEndian (c : cs) = fromIntegral (ord c) + 2 ^ 8 * readInt LittleEndian cs+readInt BigEndian str = readInt LittleEndian $ reverse str +tupT :: [TypeQ] -> TypeQ+tupT ts = foldl appT (tupleT $ length ts) ts+ [peggy| top :: BinaryStructure- = emptyLines name emptyLines dat*- { BinaryStructure $2 $4 }+ = emptyLines name emptyLines endian emptyLines dat*+ { BinaryStructure $2 $4 $6 }+ / emptyLines name emptyLines dat*+ { BinaryStructure $2 LittleEndian $4 } +endian :: Endian+ = "set" spaces "big_endian"+ { BigEndian }+ emptyLines :: () = "--" [^\n]* [\n] { () } / [ \n]* { () }@@ -142,43 +191,84 @@ dat :: BinaryStructureItem = expr typ size? ':' spaces val emptyLines { binaryStructureItem $1 $2 $3 $5 }+ / "repeat" spaces "{" top "}"+ { Repeat $2 } typ :: Type = [<] typeGen [>] { $2 }- / "" { Int }+ / "" { Type $ conT $ mkName "Int" } typeGen :: Type- = [(] tupleGen [)] { Tuple $2 }- / "String" { String }- / "ByteString" { ByteString }- / "Int" { Int }+ = [(] tupleGen_ [)] { Type $ tupT $2 }+ / [\[] typeGen [\]] { Type $ appT listT $ typeQ $2 }+-- = [(] tupleGen [)] { Tuple $2 }+ / [A-Z][.a-zA-Z0-9]* { Type $ conT $ mkName $ $1 : $2 } +typeGen_ :: TypeQ+ = [A-Z][.a-zA-Z0-9]* { conT $ mkName $ $1 : $2 }++tupleGen_ :: [TypeQ]+ = typeGen_ spaces "," spaces tupleGen_+ { $1 : $4 }+ / typeGen_ spaces "," spaces typeGen_+ { [$1, $4] }+ tupleGen :: [Type] = typeGen spaces "," spaces tupleGen { $1 : $4 } / typeGen spaces "," spaces typeGen { [$1, $4] } +-- = [\(] [\)] { ExpressionQ $ const $ conE $ mkName "()" } expr :: Expression = expr '*' expr { Multiple $1 $2 } / expr '/' expr { Division $1 $2 }- / num { Number $1 }- / var { Variable $1 }+ / expr '+' expr { Addition $1 $2 }+ / num { ExpressionQ $ const $ litE $ integerL $ fromIntegral $1 }+ / var { ExpressionQ $ appE (varE $ mkName $1) . varE }+ / [(] tupleExpr [)] { ExpressionQ $2 }+ / 'Just' spaces expr { ExpressionQ $ \ret -> appE (conE $ mkName "Just") $+ expressionQ $2 ret }+ / 'Nothing' { ExpressionQ $ const $ conE $ mkName "Nothing" } +-- / [(] expr ', ' expr [)]+-- { ExpressionQ $ \ret -> tupE+-- [expressionQ $2 ret, expressionQ $3 ret] }++tupleExpr :: Name -> ExpQ+ = expr ', ' expr { \ret -> tupE+ [expressionQ $1 ret, expressionQ $2 ret] }+ / "" { const $ conE $ mkName "()" }+ size :: Expression = '[' expr ']' val :: Either ConstantValue VariableValue = num { Left $ ConstantInt $1 } / var { Right $ VariableValue $1 }- / stringL { Left $ ConstantString $1 }+ / stringLit { Left $ ConstantString $1 } -stringL :: String- = '\"' [^\"]* '\"'+stringLit :: String+ = '\"' strL '\"' +strL :: String+ = charLit*++charLit :: Char+ = [^\\\"]+ / "\\" escLit++escLit :: Char+ = "n" { '\n' }+ / "r" { '\r' }+ / "\\" { '\\' }+ / "SUB" { '\SUB' }+ var :: String- = [a-z][a-zA-Z0-9]* { $1 : $2 }+ = [a-z][_a-zA-Z0-9]* { $1 : $2 } num :: Int- = [0-9]+ { read $1 }+ = '0x' [0-9a-fA-F]+ { fst $ head $ readHex $1 }+ / [1-9][0-9]* { read $ $1 : $2 }+ / '0' { 0 } |]
src/QuoteBinaryStructure.hs view
@@ -6,7 +6,12 @@ FlexibleInstances #-} module QuoteBinaryStructure (- binary+ binary,+ RetType(..),+ Str(..),+ fii, fiiBE,+ tii, tiiBE,+ times ) where import Prelude hiding (sequence)@@ -22,6 +27,7 @@ import Data.Bits import ParseBinaryStructure+import Classes import qualified Data.ByteString as BS @@ -39,64 +45,52 @@ mkHaskellTree :: BinaryStructure -> DecsQ mkHaskellTree BinaryStructure{ binaryStructureName = bsn,+ binaryStructureEndian = endian, binaryStructureBody = body } = do- d <- mkData bsn body--- dbg <- debugReadType- r <- mkReader bsn body- w <- mkWriter bsn body- return [d, r, w]+ d <- mkData endian bsn body+ r <- mkReader endian bsn body+ w <- mkWriter endian bsn body+ i <- retTypeInt endian+ return $ d ++ [r, w] -mkWriter :: String -> [BinaryStructureItem] -> DecQ-mkWriter bsn body = do+mkWriter :: Endian -> String -> [BinaryStructureItem] -> DecQ+mkWriter endian bsn body = do bs <- newName "bs" let run = appE (varE 'cc) $ listE $ map- (\bsi -> writeField bs (bytesOf bsi) (typeOf bsi) (sizeOf bsi) (valueOf bsi))+ (\bsi -> writeField endian bs (bytesOf bsi) (typeOf bsi) (sizeOf bsi)+ (valueOf endian bsi)) body funD (mkName $ "write" ++ bsn) [clause [varP bs] (normalB run) []] -writeField :: Name -> Expression -> Type -> Maybe Expression ->+writeField :: Endian -> Name -> Expression -> Type -> Maybe Expression -> Either Int String -> ExpQ-writeField bs size Int Nothing (Left n) =- appsE [varE 'fi, expression bs size, litE $ integerL $ fromIntegral n]-writeField bs bytes typ size (Right v) =- fieldValueToStr bs bytes (isJust size) typ $ getField bs v+writeField endian bs size (Type _) Nothing (Left n) =+ appsE [fiend, expression bs size, litE $ integerL $ fromIntegral n]+ where+ fiend = case endian of+ LittleEndian -> varE 'fii+ BigEndian -> varE 'fiiBE+writeField endian bs bytes typ size (Right v) =+ fieldValueToStr endian bs bytes (isJust size) typ $ getField bs v -fieldValueToStr :: Name -> Expression -> Bool -> Type -> ExpQ -> ExpQ-fieldValueToStr bs size False Int = appE $ appE (varE 'fi) (expression bs size)-fieldValueToStr bs size True Int = appE (varE 'cc) . appE (appsE [varE 'map,- appE (varE 'fi) (expression bs size)])-fieldValueToStr bs size False String = appE $ varE 'fs-fieldValueToStr bs size False ByteString = appE $ varE 'fbs-fieldValueToStr bs size False (Tuple ts) = \val -> do- nl <- newNameList $ length ts- let def = valD (tupP $ map varP nl) (normalB val) []- bdy = zipWith (fieldValueToStr bs (Number 1) False) ts $ map varE nl- in letE [def] $ appE (varE 'cc) $ listE bdy-fieldValueToStr bs size True (Tuple ts) = \val -> do+fiend :: Endian -> ExpQ+fiend endian = case endian of+ LittleEndian -> varE 'fii+ BigEndian -> varE 'fiiBE++fieldValueToStr :: Endian -> Name -> Expression -> Bool -> Type -> ExpQ -> ExpQ+fieldValueToStr endian bs size False (Type typ) =+ appE $ appE (varE 'fromType) (expression bs size)+fieldValueToStr endian bs size True typ = \val -> do runIO $ do- putStrLn "here"- print ts- nl <- newNameList $ length ts- let ps = tupP $ map varP nl- bdy = zipWith (fieldValueToStr bs (Number 1) False) ts $ map varE nl- in appE (varE 'cc) $ appsE [- varE 'map,- lamE [ps] $ appE (varE 'cc) $ addZero $ listE bdy,- val]+ putStrLn "there"+ appE (varE 'cc) $ appsE [+ varE 'map, appE (varE 'fromType) (expression bs size), val] where- addZero = -- appE $ addZeros 1- appE $ correctSize' $ expression bs size-{-- let ps = tupP $ map varP nl- bdy = zipWith (fieldValueToStr bs (Number 1) False) ts $ map varE nl- in appE (varE 'cc) $ appE (correctSize' $ expression bs size) $ appsE [- varE 'map, lamE [ps] $ appE (varE 'cc) $ listE bdy, val]--}-{-- in appE (varE 'cc) $ correctSize (expression bs size) $ appsE [- varE 'map, lamE [ps] $ appE (varE 'cc) $ listE bdy, val]--}+ addZero = appE $ correctSize' $ expression bs size+ +fieldValueToStr endian bs size bool typ = error $ show (endian, bs, size, bool, typ) addZeros :: Int -> ExpQ addZeros ln = do@@ -107,7 +101,6 @@ correctSize' :: ExpQ -> ExpQ correctSize' size = do--- let size = litE $ IntegerL 100 lst <- newName "lst" let bdy = infixApp (varE lst) (varE '(++)) $ appsE [varE 'replicate,@@ -128,90 +121,62 @@ mapTuple :: (Type -> ExpQ) -> [Type] -> ExpQ mapTuple f ts = varE 'show -intToBin :: Int -> Int -> String-intToBin n x = intToBinGen (fromIntegral n) (fromIntegral x)--intToBinGen :: Integer -> Integer -> String-intToBinGen 0 _ = ""-intToBinGen n x = chr (fromIntegral $ x `mod` 256) :- intToBinGen (n - 1) (x `div` 256)---- readerType :: String -> DecQ--- readerType = sigD (mkName $ "read" ++ bsn) [t| Str a => a ->---- debugReadType :: DecQ = [d| readBitmap :: Str a => a -> Bitmap |]--mkReader :: String -> [BinaryStructureItem] -> DecQ-mkReader bsn body = do+mkReader :: Endian -> String -> [BinaryStructureItem] -> DecQ+mkReader endian bsn body = do cs <- newName "cs" ret <- newName "ret" funD (mkName $ "read" ++ bsn)- [clause [varP cs] (normalB $ mkLetRec ret $ mkBody bsn body cs) []]+ [clause [varP cs] (normalB $ mkLetRec ret $+ mkBody endian bsn body cs) []] mkLetRec :: Name -> (Name -> ExpQ) -> ExpQ-mkLetRec n f = letE [valD (varP n) (normalB $ f n) []] $ varE n+mkLetRec n f = do+ rest <- newName "rest"+ letE [valD (tupP [varP n, varP rest]) (normalB $ f n) []] $+ tupE [varE n, varE rest] -mkBody :: String -> [BinaryStructureItem] -> Name -> Name -> ExpQ-mkBody bsn body cs ret = do+mkBody :: Endian -> String -> [BinaryStructureItem] -> Name -> Name -> ExpQ+mkBody endian bsn body cs ret = do namePairs <- for names $ \n -> return . (n ,) =<< newName "tmp"- defs <- gather cs body $ mkDef namePairs- letE (map return defs) $ recConE (mkName bsn) (map toPair2 namePairs)+ (defs, rest) <- gather cs body $ mkDef namePairs+ letE (map return defs) $ tupE+ [recConE (mkName bsn) (map toPair2 namePairs), varE rest] where- names = rights $ map valueOf body+ names = rights $ map (valueOf endian) body toPair2 (n, nn) = return $ (mkName n, VarE nn) mkValD v = valD (varP v) (normalB $ litE $ integerL 45) [] mkDef :: [(String, Name)] -> BinaryStructureItem -> Name -> Q ([Dec], Name) mkDef np item cs'- | Left val <- valueOf item = do+ | Left val <- valueOf endian item = do cs'' <- newName "cs" let t = dropE' n $ varE cs'- let p = val `equal` appE (varE 'ti) (takeE' n $ varE cs')+ let p = val `equal` appE (varE 'fst)+ (appE tiend $ takeE' n $ varE cs') let e = [e| error "bad value" |] d <- valD (varP cs'') (normalB $ condE p t e) [] return ([d], cs'')- | Right var <- valueOf item, Nothing <- sizeOf item, Int <- typeOf item = do- cs'' <- newName "cs"- def <- valD (varP $ fromJust $ lookup var np)- (normalB $ appE (varE 'ti) $ takeE' n $ varE cs') []- next <- valD (varP cs'') (normalB $ dropE' n $ varE cs') []- return ([def, next], cs'')- | Right var <- valueOf item, Nothing <- sizeOf item, ByteString <- typeOf item = do- cs'' <- newName "cs"- def <- valD (varP $ fromJust $ lookup var np)- (normalB $ takeE'' n $ varE cs') []- next <- valD (varP cs'') (normalB $ dropE' n $ varE cs') []- return ([def, next], cs'')- | Right var <- valueOf item, Nothing <- sizeOf item = do+ | Right var <- valueOf endian item, Just expr <- sizeOf item = do cs'' <- newName "cs"- def <- valD (varP $ fromJust $ lookup var np)- (normalB $ takeE' n $ varE cs') []- next <- valD (varP cs'') (normalB $ dropE' n $ varE cs') []- return ([def, next], cs'')- | Right var <- valueOf item, Just expr <- sizeOf item, Tuple ts <- typeOf item =- if all (== Int) ts then do- cs'' <- newName "cs"- def <- valD (varP $ fromJust $ lookup var np)- (normalB $- appsE [varE 'map, strToTupple $ length ts,- appsE [varE 'devideN, n,- takeE' (multiE' n $ expression ret expr) $ varE cs']]) []- next <- valD (varP cs'') (normalB $- dropE' (multiE' n $ expression ret expr) $ varE cs') []- return ([def, next], cs'')- else error "hogeru"- | Right var <- valueOf item, Just expr <- sizeOf item = do+ def <- valD (tupP [varP $ fromJust $ lookup var np, varP cs''])+ (normalB (appsE+ [(varE 'times), expression ret expr,+ appE (varE 'toType) arg, varE cs']))+ []+ return ([def], cs'')+ | Right var <- valueOf endian item, Nothing <- sizeOf item,+ Type typ <- typeOf item = do cs'' <- newName "cs"- def <- valD (varP $ fromJust $ lookup var np)- (normalB $- appsE [varE 'map, varE 'ti,- appsE [varE 'devideN, n,- takeE' (multiE' n $ expression ret expr) $ varE cs']]) []- next <- valD (varP cs'') (normalB $- dropE' (multiE' n $ expression ret expr) $ varE cs') []- return ([def, next], cs'')+ def <- valD (tupP [varP $ fromJust $ lookup var np, varP cs''])+ (normalB $ appE (appE (varE 'toType) arg) $ varE cs') []+ return ([def], cs'') | otherwise = error $ show $ typeOf item where n = expression ret $ bytesOf item+ tiend' = varE 'toType+ tiend = case endian of+ LittleEndian -> appE (varE 'tii) (litE $ integerL 4)+ BigEndian -> appE (varE 'tiiBE) (litE $ integerL 4)+ arg = expression ret $ bytesOf item strToTupple :: Int -> ExpQ strToTupple n = (toTupple n) `dot` appE (varE 'map) (varE 'ord) `dot`@@ -230,6 +195,8 @@ expression _ (Number n) = litE $ integerL $ fromIntegral n expression ret (Division x y) = divE (expression ret x) (expression ret y) expression ret (Multiple x y) = multiE' (expression ret x) (expression ret y)+expression ret (Addition x y) = addE' (expression ret x) (expression ret y)+expression ret (ExpressionQ e) = e ret getField :: Name -> String -> ExpQ getField bs v = appE (varE $ mkName v) (varE bs)@@ -240,37 +207,52 @@ multiE' :: ExpQ -> ExpQ -> ExpQ multiE' x y = infixE (Just x) (varE '(*)) (Just y) +addE' :: ExpQ -> ExpQ -> ExpQ+addE' x y = infixE (Just x) (varE '(+)) (Just y)+ divE :: ExpQ -> ExpQ -> ExpQ divE x y = infixE (Just x) (varE 'div) (Just y) equal :: Int -> ExpQ -> ExpQ equal x y = infixE (Just $ litE $ integerL $ fromIntegral x) (varE '(==)) (Just y) --- takeE :: Int -> ExpQ -> ExpQ--- takeE n xs = appsE [varE 'tk, litE $ integerL $ fromIntegral n, xs]- takeE' :: ExpQ -> ExpQ -> ExpQ takeE' n xs = appE (varE 'ts) $ appsE [varE 'tk, n, xs] takeE'' :: ExpQ -> ExpQ -> ExpQ takeE'' n xs = appE (varE 'tbs) $ appsE [varE 'tk, n, xs] --- dropE :: Int -> ExpQ -> ExpQ--- dropE n xs = appsE [varE 'dp, litE $ integerL $ fromIntegral n, xs]- dropE' :: ExpQ -> ExpQ -> ExpQ dropE' n xs = appsE [varE 'dp, n, xs] -gather :: Monad m => s -> [a] -> (a -> s -> m ([b], s)) -> m [b]-gather s [] f = return []+gather :: Monad m => s -> [a] -> (a -> s -> m ([b], s)) -> m ([b], s)+gather s [] f = return ([], s) gather s (x : xs) f = do (ys, s') <- f x s- zs <- gather s' xs f- return $ ys ++ zs+ (zs, s'') <- gather s' xs f+ return $ (ys ++ zs, s'') -mkData :: String -> [BinaryStructureItem] -> DecQ-mkData bsn body =- dataD (cxt []) name [] [con] [''Show]+makeData :: BinaryStructure -> DecsQ+makeData BinaryStructure{+ binaryStructureName = bsn,+ binaryStructureEndian = endian,+ binaryStructureBody = body } = mkData endian bsn body++mkInstance :: String -> DecQ+mkInstance name =+ instanceD (cxt []) (appT (conT ''RetType) (conT $ mkName name)) [+ valD (varP $ 'fromType)+ (normalB $ varE $ mkName $ "write" ++ name) [],+ valD (varP $ 'toType)+ (normalB $ varE $ mkName $ "read" ++ name) []+ ]++mkData :: Endian -> String -> [BinaryStructureItem] -> DecsQ+mkData endian bsn body = do+ d <- dataD (cxt []) name [] [con] [''Show]+ mkInstance bsn+ ds <- mapM makeData $ map getRepeat $ filter isRepeat body+ return $ [d] ++ concat ds where name = mkName bsn con = recC (mkName bsn) vsts@@ -278,18 +260,16 @@ vsts = flip map (filter isRight body) $ \item -> case (sizeOf item, typeOf item) of (sz, tp) -> varStrictType- (mkName $ fromRight $ valueOf item) $- strictType notStrict $ mkType (isJust sz) tp -- conT ''Int+ (mkName $ fromRight $ valueOf endian item) $+ strictType notStrict $+ mkType (isJust sz) tp isRight item- | Right _ <- valueOf item = True+ | Right _ <- valueOf endian item = True | otherwise = False mkType :: Bool -> Type -> TypeQ mkType True t = appT listT $ mkType False t-mkType False Int = conT ''Int-mkType False String = conT ''String-mkType False ByteString = conT ''BS.ByteString-mkType False (Tuple ts) = appsT $ tupleT (length ts) : map (mkType False) ts+mkType False (Type typ) = typ appsT :: [TypeQ] -> TypeQ appsT [t] = t@@ -304,38 +284,9 @@ devideN _ [] = [] devideN n xs = take n xs : devideN n (drop n xs) -class Str a where- tk :: Int -> a -> a- dp :: Int -> a -> a- ts :: a -> String- fs :: String -> a- fbs :: BS.ByteString -> a- tbs :: a -> BS.ByteString- ti :: a -> Int- fi :: Int -> Int -> a- cc :: [a] -> a- zero :: a--instance Str String where- tk = take- dp = drop- ts = id- fs = id- fbs = ts- tbs = fs- ti = readInt- fi = intToBin- cc = concat- zero = "\0"--instance Str BS.ByteString where- tk = BS.take- dp = BS.drop- ts = map (chr . fromIntegral) . BS.unpack- fs = BS.pack . map (fromIntegral . ord)- fbs = id- tbs = id- ti = readInt . map (chr . fromIntegral) . BS.unpack- fi n = BS.pack . map (fromIntegral . ord) . intToBin n- cc = BS.concat- zero = BS.singleton 0+times :: Int -> (s -> (ret, s)) -> s -> ([ret], s)+times 0 _ s = ([], s)+times n f s = let+ (ret, rest) = f s+ (rets, rest') = times (n - 1) f rest in+ (ret : rets, rest')