packages feed

binary-file 0.13.2 → 0.14.1

raw patch · 14 files changed

+548/−600 lines, 14 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- File.Binary: concatBinary :: Binary a => [a] -> a
- File.Binary: emptyBinary :: Binary a => a -> Bool
- File.Binary: fii :: Binary a => Int -> Int -> a
- File.Binary: tii :: Binary a => Int -> a -> (Int, a)
- File.Binary.Data.BigEndian: instance Field Int
- File.Binary.Data.BigEndian: lintToBin :: Int -> Integer -> String
- File.Binary.Data.LittleEndian: instance Field Int
+ File.Binary.Instances: instance Binary ByteString
+ File.Binary.Instances: instance Binary String
+ File.Binary.Instances: instance Field ByteString
+ File.Binary.Instances: instance Field Char
+ File.Binary.Instances: instance Field r => Field [r]
+ File.Binary.Instances.BigEndian: instance Field Int
+ File.Binary.Instances.BigEndian: instance Field Integer
+ File.Binary.Instances.BigEndian: intToWords :: Integral i => Int -> i -> [Word8]
+ File.Binary.Instances.LittleEndian: instance Field Int
+ File.Binary.Instances.LittleEndian: instance Field Integer
+ File.Binary.Instances.LittleEndian: intToWords :: Integral i => Int -> i -> [Word8]
+ File.Binary.Instances.LittleEndian: wordsToInt :: Integral i => [Word8] -> i
- File.Binary: class Binary a
+ File.Binary: class (Eq b, Monoid b) => Binary b
- File.Binary: getBytes :: Binary a => Int -> a -> (ByteString, a)
+ File.Binary: getBytes :: Binary b => Int -> b -> (ByteString, b)
- File.Binary: makeBinary :: Binary a => ByteString -> a
+ File.Binary: makeBinary :: Binary b => ByteString -> b

Files

binary-file.cabal view
@@ -2,7 +2,7 @@ cabal-version:	>= 1.8  name:		binary-file-version:	0.13.2+version:	0.14.1 stability:	experimental author:		Yoshikuni Jujo <PAF01143@nifty.ne.jp> maintainer:	Yoshikuni Jujo <PAF01143@nifty.ne.jp>@@ -21,7 +21,8 @@     exam.hs:     .     > import File.Binary-    > import File.Binary.Data.LittleEndian+    > import File.Binary.Instances+    > import File.Binary.Instances.LittleEndian     > import System.Environment     > import Data.ByteString.Lazy as BSL     >@@ -63,8 +64,8 @@     > 4: resolutionV     > 4: color_num     > 4: important_color_num-    > ((), Just color_num)<[(Int, Int, Int)]>: colors-    > ((), image_size)<String>: image+    > ((), Just color_num)[OPENBRACKET](Int, Int, Int)[CLOSEBRACKET]: colors+    > ((), image_size)[OPENBRACKET]String[CLOSEBRACKET]: image     >     > |]     .@@ -78,14 +79,19 @@ source-repository	this     type:	git     location:	git://github.com/YoshikuniJujo/binary-file.git-    tag:	0.13.2+    tag:	0.14.1  library     hs-source-dirs:	src-    exposed-modules:	File.Binary,-        File.Binary.Data.LittleEndian,-        File.Binary.Data.BigEndian-    other-modules:	QuoteBinaryStructure, ParseBinaryStructure, Classes+    exposed-modules:+        File.Binary,+        File.Binary.Instances+        File.Binary.Instances.LittleEndian,+        File.Binary.Instances.BigEndian+    other-modules:+        File.Binary.Classes,+        File.Binary.Parse,+        File.Binary.Quote     build-depends:	base > 3 && < 5, template-haskell, peggy, bytestring,         monads-tf     ghc-options:	-Wall
examples/readPNG.hs view
@@ -1,66 +1,31 @@ {-# LANGUAGE QuasiQuotes, TypeFamilies, FlexibleInstances #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}  import File.Binary-import File.Binary.Data.BigEndian+import File.Binary.Instances()+import File.Binary.Instances.BigEndian import System.Environment import Data.Word import qualified Data.ByteString as BS import qualified Data.ByteString.Char8 as BSC import qualified Data.ByteString.Lazy as BSL-import qualified Data.ByteString.Lazy.Char8 as BSLC import Codec.Compression.Zlib import CRC (crc) import Control.Applicative+import Data.Monoid +main :: IO () main = do 	[fin, fout] <- getArgs---	cnt <- readBinaryFile fin 	cnt <- BS.readFile fin-	let (png, rest) = fromBinary () cnt+	let (png, _) = fromBinary () cnt  	putStrLn $ take 1000 (show png) ++ "..." ---	writeBinaryFile fout $ toBinary () png---	BS.writeFile fout $ writePNG () png--	let	ChankIDAT idt = chankData $ chanks png !! 6-		dat = idat idt-{- ----		dec = decompress dat-		recomp = compressWith defaultCompressParams {-			compressLevel = bestCompression,---			compressLevel = bestSpeed,-			compressWindowBits = WindowBits 15-		 } dec-{--	print $ length dat-	print $ length recomp--}--	let	chank6 = chanks png !! 6-		newDat = chank6 {-			chankSize = fromIntegral $ BSL.length recomp,-			chankData = ChankIDAT $ IDAT recomp,-			chankCRC = crc $ "IDAT" ++ BSL.unpack recomp-		 }-		new = png {-			chanks = take 6 (chanks png) ++ [newDat] ++-				drop 7 (chanks png)-		 }-{--	print new--}--	print $ dat == recomp---- -}----	BS.writeFile fout $ toBinary () new- 	let	dat = makeData png 		decomp = decompress dat 		recomp = compressWith defaultCompressParams { 			compressLevel = bestCompression,---			compressLevel = bestSpeed, 			compressWindowBits = WindowBits 10 		 } decomp 		newData = makeDataChank recomp@@ -68,12 +33,6 @@ 			chanks = headerChanks png ++ newData ++ 				footerChanks png 		 }-{--		newnew = png {-			chanks = head (chanks png) : newData ++-				[last $ chanks png]-		 }--} 	BS.writeFile fout $ toBinary () newnew 	print $ dat == recomp @@ -112,7 +71,7 @@ 2: "\r\n" 1: "\SUB" 1: "\n"-((), Nothing)<[Chank]>: chanks+((), Nothing){[Chank]}: chanks  |] @@ -121,15 +80,15 @@ Chank  4: chankSize-((), Just 4)<String>: chankName-(chankSize, chankName)<ChankBody>: chankData-4<Word32>:chankCRC+((), Just 4){String}: chankName+(chankSize, chankName){ChankBody}: chankData+4{Word32}:chankCRC  |]  instance Field Word32 where 	type FieldArgument Word32 = Int-	toBinary n = makeBinary . BSLC.pack . reverse . lintToBin n . fromIntegral+	toBinary n = makeBinary . BSL.pack . intToWords n 	fromBinary n s = (fromIntegral $ toIntgr $ BSL.reverse t, d) 		where 		(t, d) = getBytes n s@@ -146,7 +105,7 @@  mkNum :: [Integer] -> Integer mkNum [] = 0-mkNum (x : xs) = x + 2 ^ 8 * mkNum xs+mkNum (x : xs) = x + 2 ^ (8 :: Integer) * mkNum xs  data ChankBody 	= ChankIHDR IHDR@@ -163,32 +122,32 @@  instance Field ChankBody where 	type FieldArgument ChankBody = (Int, String)-	toBinary _ (ChankIHDR ihdr) = toBinary () ihdr-	toBinary _ (ChankGAMA gama) = toBinary () gama-	toBinary _ (ChankSRGB srgb) = toBinary () srgb+	toBinary _ (ChankIHDR c) = toBinary () c+	toBinary _ (ChankGAMA c) = toBinary () c+	toBinary _ (ChankSRGB c) = toBinary () c 	toBinary (n, _) (ChankCHRM chrm) = toBinary n chrm 	toBinary (n, _) (ChankPLTE plte) = toBinary n plte-	toBinary _ (ChankBKGD bkgd) = toBinary () bkgd-	toBinary (n, _) (ChankIDAT idat) = toBinary n idat-	toBinary (n, _) (ChankTEXT text) = toBinary n text-	toBinary _ (ChankIEND iend) = toBinary () iend+	toBinary _ (ChankBKGD c) = toBinary () c+	toBinary (n, _) (ChankIDAT c) = toBinary n c+	toBinary (n, _) (ChankTEXT c) = toBinary n c+	toBinary _ (ChankIEND c) = toBinary () c 	toBinary (n, _) (Others str) = toBinary ((), Just n) str 	fromBinary (_, "IHDR") str = let (ihdr, rest) = fromBinary () str in 		(ChankIHDR ihdr, rest) 	fromBinary (_, "gAMA") str = let (gama, rest) = fromBinary () str in 		(ChankGAMA gama, rest)-	fromBinary (_, "sRGB") str = let (srgb, rest) = fromBinary () str in-		(ChankSRGB srgb, rest)+	fromBinary (_, "sRGB") str = let (c, rest) = fromBinary () str in+		(ChankSRGB c, rest) 	fromBinary (n, "cHRM") str = let (chrm, rest) = fromBinary n str in 		(ChankCHRM chrm, rest) 	fromBinary (n, "PLTE") str = let (plte, rest) = fromBinary n str in 		(ChankPLTE plte, rest)-	fromBinary (_, "bKGD") str = let (bkgd, rest) = fromBinary () str in-		(ChankBKGD bkgd, rest)-	fromBinary (n, "IDAT") str = let (idat, rest) = fromBinary n str in-		(ChankIDAT idat, rest)-	fromBinary (n, "tEXt") str = let (text, rest) = fromBinary n str in-		(ChankTEXT text, rest)+	fromBinary (_, "bKGD") str = let (c, rest) = fromBinary () str in+		(ChankBKGD c, rest)+	fromBinary (n, "IDAT") str = let (c, rest) = fromBinary n str in+		(ChankIDAT c, rest)+	fromBinary (n, "tEXt") str = let (c, rest) = fromBinary n str in+		(ChankTEXT c, rest) 	fromBinary (_, "IEND") str = let (iend, rest) = fromBinary () str in 		(ChankIEND iend, rest) 	fromBinary (n, _) str = let (others, rest) = fromBinary ((), Just n) str in@@ -230,7 +189,7 @@  arg :: Int -(4, Just (arg `div` 4))<[Int]>: chrms+(4, Just (arg `div` 4)){[Int]}: chrms  |] @@ -240,13 +199,14 @@  arg :: Int -((), Just (arg `div` 3))<[(Int, Int, Int)]>: colors+((), Just (arg `div` 3)){[(Int, Int, Int)]}: colors  |]  instance Field (Int, Int, Int) where 	type FieldArgument (Int, Int, Int) = ()-	toBinary _ (b, g, r) = concatBinary [toBinary 1 b, toBinary 1 g, toBinary 1 r]+	toBinary _ (b, g, r) =+		mconcat [toBinary 1 b, toBinary 1 g, toBinary 1 r] 	fromBinary _ s = let 		(b, rest) = fromBinary 1 s 		(g, rest') = fromBinary 1 rest@@ -267,18 +227,21 @@  arg :: Int -arg<BSL.ByteString>: idat---((), Just arg)<String>: idat+arg{BSL.ByteString}: idat+--((), Just arg){String}: idat  |]  [binary|  TEXT+{-+test {- hoge -}+-}  arg :: Int -((), Just arg)<String>: text+((), Just arg){String}: text  |] 
− src/Classes.hs
@@ -1,124 +0,0 @@-{-# LANGUAGE-	TypeSynonymInstances,-	FlexibleInstances,-	TypeFamilies,-	OverloadedStrings #-}--module Classes (-	Field(..),-	Binary(..),-	fii, tii,-	readInt,-	dp, fs, ti, cc,-	lintToBin-) where--import qualified Data.ByteString as BS-import qualified Data.ByteString.Lazy as BSL-import qualified Data.ByteString.Lazy.Char8 as BSLC-import Data.Char-import Control.Arrow--data Endian = BigEndian | LittleEndian deriving Show--readInt :: Endian -> String -> Integer-readInt LittleEndian "" = 0-readInt LittleEndian (c : cs) = fromIntegral (ord c) + 2 ^ (8 :: Integer) * readInt LittleEndian cs-readInt BigEndian str = readInt LittleEndian $ reverse str--class Field r where-	type FieldArgument r-	fromBinary :: Binary s => FieldArgument r -> s -> (r, s)-	toBinary :: Binary s => FieldArgument r -> r -> s--instance Field r => Field [r] where-	type FieldArgument [r] = (FieldArgument r, Maybe Int)-	fromBinary (a, Just b) s = (b `times` fromBinary a) s-	fromBinary (a, Nothing) s = whole (fromBinary a) s-	toBinary (a, _) rs = cc $ map (toBinary a) rs--instance Field Char where-	type FieldArgument Char = ()-	fromBinary _ str = (head $ BSLC.unpack t, d)-		where-		(t, d) = getBytes 1 str-	toBinary _ = fs . (: [])--instance Field BS.ByteString where-	type FieldArgument BS.ByteString = Int-	fromBinary n str =-		first (BS.concat . BSL.toChunks) $ getBytes n str-	toBinary _ = makeBinary . BSL.fromChunks . (: [])--class Binary a where-	getBytes :: Int -> a -> (BSL.ByteString, a)-	makeBinary :: BSL.ByteString -> a-	concatBinary :: [a] -> a-	emptyBinary :: a -> Bool--empty :: Binary a => a -> Bool-empty = emptyBinary--cc :: Binary a => [a] -> a-cc = concatBinary--ti :: Binary a => a -> Integer-ti = readInt LittleEndian . BSLC.unpack . fst . getBytes 100--fs :: Binary a => String -> a-fs = makeBinary . BSLC.pack--dp :: Binary a => Int -> a -> a-dp n = snd . getBytes n--instance Binary String where-	getBytes n = BSLC.pack . take n &&& drop n-	makeBinary = BSLC.unpack--	concatBinary = concat-	emptyBinary = null--fii :: Binary a => Int -> Int -> a-fii n = makeBinary . BSLC.pack . intToBin LittleEndian n . fromIntegral-tii :: Binary a => Int -> a -> (Int, a)-tii _ str = let-	(t, d) = getBytes 4 str in-	(fromIntegral $ ti t, d)--instance Binary BSL.ByteString where-	getBytes n = BSL.take (fromIntegral n) &&& BSL.drop (fromIntegral n)-	makeBinary = id--	concatBinary = BSL.concat-	emptyBinary = (== 0) . BSL.length--instance Binary BS.ByteString where-	getBytes n = BSL.fromChunks . (: []) . BS.take n &&& BS.drop n-	makeBinary = BS.concat . BSL.toChunks--	concatBinary = BS.concat-	emptyBinary = (== 0) . BS.length--lintToBin :: Int -> Integer -> String-lintToBin = intToBin LittleEndian--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 :: Binary 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
@@ -4,12 +4,12 @@ 	binary, 	Field(..), 	Binary(..),-	tii, -- tiiBE,-	fii, -- fiiBE+--	tii, -- tiiBE,+--	fii, -- fiiBE --	times  ) where -import QuoteBinaryStructure+import File.Binary.Quote import System.IO  readBinaryFile :: FilePath -> IO String
+ src/File/Binary/Classes.hs view
@@ -0,0 +1,15 @@+{-# LANGUAGE TypeFamilies #-}++module File.Binary.Classes (Field(..), Binary(..)) where++import Data.Monoid (Monoid)+import Data.ByteString.Lazy (ByteString)++class Field r where+	type FieldArgument r+	fromBinary :: Binary s => FieldArgument r -> s -> (r, s)+	toBinary :: Binary s => FieldArgument r -> r -> s++class (Eq b, Monoid b) => Binary b where+	getBytes :: Int -> b -> (ByteString, b)+	makeBinary :: ByteString -> b
− src/File/Binary/Data/BigEndian.hs
@@ -1,15 +0,0 @@-{-# LANGUAGE TypeFamilies #-}--module File.Binary.Data.BigEndian (-	lintToBin-) where--import Classes-import qualified Data.ByteString.Lazy.Char8 as BSLC---- retTypeInt BigEndian--instance Field Int where-	type FieldArgument Int = Int-	fromBinary n s = (fromIntegral $ ti $ BSLC.reverse $ fst $ getBytes n s, dp n s)-	toBinary n = makeBinary . BSLC.pack . reverse . lintToBin n . fromIntegral
− src/File/Binary/Data/LittleEndian.hs
@@ -1,15 +0,0 @@-{-# LANGUAGE TypeFamilies #-}--module File.Binary.Data.LittleEndian where--import Classes-import qualified Data.ByteString.Lazy.Char8 as BSLC---- retTypeInt LittleEndian--instance Field Int where-	type FieldArgument Int = Int-	fromBinary n s = (fromIntegral $ ti t, d)-		where-		(t, d) = getBytes n s-	toBinary n = makeBinary . BSLC.pack . reverse . lintToBin n . fromIntegral
+ src/File/Binary/Instances.hs view
@@ -0,0 +1,81 @@+{-# LANGUAGE+	TypeFamilies,+	TypeSynonymInstances,+	FlexibleInstances #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}++module File.Binary.Instances () where++import File.Binary.Classes (Field(..), Binary(..))+import qualified Data.ByteString as BS+	(ByteString, take, drop, concat)+import qualified Data.ByteString.Lazy as BSL+	(ByteString, take, drop, toChunks, fromChunks)+import qualified Data.ByteString.Lazy.Char8 as BSLC (pack, unpack)+import Control.Arrow (first, (&&&))+import Data.Monoid++instance Field BS.ByteString where+	type FieldArgument BS.ByteString = Int+	fromBinary n str =+		first (BS.concat . BSL.toChunks) $ getBytes n str+	toBinary _ = makeBinary . BSL.fromChunks . (: [])++instance Field Char where+	type FieldArgument Char = ()+	fromBinary _ str = (head $ BSLC.unpack t, d)+		where+		(t, d) = getBytes 1 str+	toBinary _ = makeBinary . BSLC.pack . (: [])++instance Field r => Field [r] where+	type FieldArgument [r] = (FieldArgument r, Maybe Int)+	fromBinary (a, Just b) s = (b `times` fromBinary a) s+	fromBinary (a, Nothing) s = whole (fromBinary a) s+	toBinary (a, _) rs = mconcat $ map (toBinary a) rs++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 :: Binary s => (s -> (ret, s)) -> s -> ([ret], s)+whole f s+	| s == mempty = ([], s)+	| otherwise = let+		(ret, rest) = f s+		(rets, rest') = whole f rest in+		(ret : rets, rest')++--------------------------------------------------------------------------------++instance Binary String where+	getBytes n = BSLC.pack . take n &&& drop n+	makeBinary = BSLC.unpack++{-+	appendBinary = (++)+	emptyBinary = null+-}++instance Binary BSL.ByteString where+	getBytes n = BSL.take (fromIntegral n) &&& BSL.drop (fromIntegral n)+	makeBinary = id++{-+	appendBinary = BSL.append+	concatBinary = BSL.concat+	emptyBinary = (== 0) . BSL.length+-}++instance Binary BS.ByteString where+	getBytes n = BSL.fromChunks . (: []) . BS.take n &&& BS.drop n+	makeBinary = BS.concat . BSL.toChunks++{-+	appendBinary = BS.append+	concatBinary = BS.concat+	emptyBinary = (== 0) . BS.length+-}
+ src/File/Binary/Instances/BigEndian.hs view
@@ -0,0 +1,38 @@+{-# LANGUAGE TypeFamilies #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}++module File.Binary.Instances.BigEndian (+	intToWords+) where++import File.Binary.Classes+import qualified Data.ByteString.Lazy as BSL+import Data.Word++instance Field Int where+	type FieldArgument Int = Int+	fromBinary n s = (+		wordsToInt $ BSL.unpack $ fst $ getBytes n s,+		snd $ getBytes n s+	 )+--	toBinary n = makeBinary . BSLC.pack . reverse . lintToBin n . fromIntegral+	toBinary n = makeBinary . BSL.pack . intToWords n++wordsToInt :: Integral i => [Word8] -> i+wordsToInt = foldl (\i w -> i * 256 + fromIntegral w) 0++intToWords :: Integral i => Int -> i -> [Word8]+intToWords = itw []+	where+	itw result 0 _ = result+	itw result n i =+		itw (fromIntegral (i `mod` 256) : result) (n - 1) (i `div` 256)++instance Field Integer where+	type FieldArgument Integer = Int+	fromBinary n s = (+		wordsToInt $ BSL.unpack $ fst $ getBytes n s,+		snd $ getBytes n s+	 )+--	toBinary n = makeBinary . BSLC.pack . reverse . lintToBin n . fromIntegral+	toBinary n = makeBinary . BSL.pack . intToWords n
+ src/File/Binary/Instances/LittleEndian.hs view
@@ -0,0 +1,26 @@+{-# LANGUAGE TypeFamilies #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}++module File.Binary.Instances.LittleEndian where++import File.Binary.Classes+import qualified Data.ByteString.Lazy as BSL+import Data.Word+import Control.Arrow++instance Field Int where+	type FieldArgument Int = Int+	fromBinary n = first (wordsToInt . BSL.unpack) . getBytes n+	toBinary n = makeBinary . BSL.pack . intToWords n++instance Field Integer where+	type FieldArgument Integer = Int+	fromBinary n = first (wordsToInt . BSL.unpack) . getBytes n+	toBinary n = makeBinary . BSL.pack . intToWords n++wordsToInt :: Integral i => [Word8] -> i+wordsToInt = foldr (\w i -> fromIntegral w + 256 * i) 0++intToWords :: Integral i => Int -> i -> [Word8]+intToWords 0 _ = []+intToWords n i = fromIntegral (i `mod` 256) : intToWords (n - 1) (i `div` 256)
+ src/File/Binary/Parse.hs view
@@ -0,0 +1,143 @@+{-# LANGUAGE TemplateHaskell, QuasiQuotes, FlexibleContexts, PackageImports #-}++{-# OPTIONS_GHC+	-fno-warn-name-shadowing+	-fno-warn-unused-binds+	-fno-warn-unused-matches+	-fno-warn-unused-do-bind #-}++module File.Binary.Parse (+	parse,+	BinaryStructure, bsName, bsArgName, bsArgType, bsBody,+	BinaryStructureItem, bytesOf, typeOf, valueOf,+	Value(..), variables,+	Expression, expression,+) where++import Prelude hiding (exp)+import Control.Applicative ((<$>), (<*>))+import "monads-tf" Control.Monad.Reader (Reader, runReader, ask)+import Numeric (readHex)++import Text.Peggy (peggy, parseString, space, defaultDelimiter)+import Language.Haskell.TH (+	ExpQ, litE, varE, conE, appE, tupE, integerL, uInfixE, parensE,+	TypeQ, appT, conT, listT, tupleT, Name, mkName)++--------------------------------------------------------------------------------++parse :: String -> BinaryStructure+parse = either (error . show) id . parseString top ""++data BinaryStructure = BinaryStructure {+	bsName :: Name,+	bsArgName :: Name,+	bsArgType :: TypeQ,+	bsBody :: [BinaryStructureItem]+ }++data BinaryStructureItem = BinaryStructureItem {+	bytesOf :: Expression,+	typeOf :: TypeQ,+	valueOf :: Value+ }++type Expression	= Reader (ExpQ, ExpQ, Name) ExpQ++expression :: ExpQ -> ExpQ -> Name -> Expression -> ExpQ+expression ret arg argn e = runReader e (ret, arg, argn)++data Value+	= Constant { constant :: Either Integer String }+	| Variable { variable :: Name }++variables :: [Value] -> [Name]+variables =+	map variable . filter (\v -> case v of Variable _ -> True; _ -> False)++[peggy|++top :: BinaryStructure+	= emp lname arg dat*		{ BinaryStructure $2 (fst $3) (snd $3) $4 }++arg :: (Name, TypeQ)+	= emp var sp '::' sp typ	{ ($2, $5) }+	/ ''				{ (mkName "_", conT $ mkName "()") }++dat :: BinaryStructureItem+	= emp exp sp typS sp ':' sp val	{ BinaryStructureItem $2 $4 $7 }++typS :: TypeQ+	= '{' typ '}'			{ $1 }+	/ ''				{ conT $ mkName "Int" }++val :: Value+	= var				{ Variable $1 }+	/ num				{ Constant $ Left $1 }+	/ string			{ Constant $ Right $1 }++exp :: Expression+	= exp sp op sp expOp1		{ uInfixE <$> $1 <*> $3 <*> $5 }+	/ expOp1++expOp1 :: Expression+	= expOp1 sp exp1		{ appE <$> $1 <*> $3 }+	/ exp1++exp1 :: Expression+	= '(' tupExp ')'+	/ '(' exp ')'			{ parensE <$> $1 }+	/ '()'				{ return $ conE $ mkName "()" }+	/ num				{ return $ litE $ integerL $1 }+	/ lname				{ return $ conE $1 }+	/ var				{ flip fmap ask $ \(ret, arg, argn) ->+						if $1 == argn+							then arg+							else appE (varE $1) ret }+op :: Expression+	= [!\\#$%&*+./<=>?@^|~-:]+	{ return $ varE $ mkName $1 }+	/ '`' var '`'			{ return $ varE $1 }+tupExp :: Expression = exp (sp ',' sp exp)++	{ (.) tupE . (:) <$> $1 <*> mapM (\(_, _, e) -> e) $2 }++typ :: TypeQ+	= typ typ1			{ appT $1 $2 }+	/ typ1++typ1 :: TypeQ+	= '(' tupType ')'		{ foldl appT (tupleT $ length $1) $1 }+	/ '(' typ ')'+	/ '()'				{ conT $ mkName "()" }+	/ '[' typ ']'			{ appT listT $1 }+	/ lname				{ conT $1 }+tupType :: [TypeQ]+	= typ sp (',' sp typ)+	{ $1 : map snd $3 }++lname :: Name+	= (ln '.')* ln			{ mkName $ concatMap (++ ".") $1 ++ $2 }++var :: Name+	= (ln '.')* sn			{ mkName $ concatMap (++ ".") $1 ++ $2 }++num :: Integer+	= '0x' [0-9a-fA-F]+		{ fst $ head $ readHex $1 }+	/ [1-9][0-9]*			{ read $ $1 : $2 }+	/ '0'				{ 0 }++string :: String = '\"' char* '\"'+char :: Char = [^\\\"] / '\\' esc+esc :: Char+	= 'n'						{ '\n' }+	/ 'r'						{ '\r' }+	/ '\\'						{ '\\' }+	/ 'SUB'						{ '\SUB' }++ln :: String = [A-Z][_a-zA-Z0-9]*			{ $1 : $2 }+sn :: String = [a-z][_a-zA-Z0-9]*			{ $1 : $2 }++sp :: () = (comm / [ \t])*				{ () }+emp :: () = (comm / lcomm / [ \n])*			{ () }+lcomm :: Char = '--' [^\n]* [\n]			{ ' ' }+comm :: Char = '{-' (!'{-' !'-}' . / comm)* '-}'	{ ' ' }++|]
+ src/File/Binary/Quote.hs view
@@ -0,0 +1,190 @@+{-# LANGUAGE+	TemplateHaskell,+	TupleSections,+	PatternGuards,+	TypeSynonymInstances,+	FlexibleInstances #-}++module File.Binary.Quote (+	binary,+	Field(..),+	Binary(..),+--	fii, -- fiiBE,+--	tii, -- tiiBE,+	times+) where++import Prelude hiding (sequence)++import Language.Haskell.TH hiding (Type)+import Language.Haskell.TH.Quote+import Data.Traversable hiding (mapM)+import Data.Maybe+import qualified Data.ByteString.Lazy.Char8 as BSLC++import File.Binary.Parse+import File.Binary.Classes++import Data.Monoid++binary :: QuasiQuoter+binary = QuasiQuoter {+	quoteExp = undefined,+	quotePat = undefined,+	quoteType = undefined,+	quoteDec = mkHaskellTree . parse+ }++mkHaskellTree :: BinaryStructure -> DecsQ+mkHaskellTree bs = do+		d <- mkData bsn body+		i <- mkInst bsn argn typ body+		return $ d ++ [i]+	where+	bsn = bsName bs+	argn = bsArgName bs+	typ = bsArgType bs+	body = bsBody bs++mkInst :: Name -> Name -> TypeQ -> [BinaryStructureItem] -> DecQ+mkInst bsn argn typ body =+	instanceD (cxt []) (appT (conT ''Field) (conT bsn)) [+		tySynInstD ''FieldArgument [conT bsn] typ,+		reading "fromBinary" bsn argn body,+		writing "toBinary" argn body+	 ]++writing :: String -> Name -> [BinaryStructureItem] -> DecQ+writing name argn body = do+	arg <- newName "_arg"+	bs <- newName "_bs"+	let run = appE (varE 'mconcat) $ listE $ map+		(\bsi -> writeField bs arg argn (bytesOf bsi) (valueOf bsi)) body+	funD (mkName name)+		[clause [varP arg, varP bs] (normalB run) []]++writeField :: Name -> Name -> Name -> Expression -> Value -> ExpQ+writeField bs arg argn size (Constant (Left n)) =+	appsE [fiend', expression (varE bs) (varE arg) argn size,+		sigE (litE $ integerL $ fromIntegral n)+		(conT ''Int)]+	where+	fiend' = varE 'toBinary+writeField _ _ _ _ (Constant (Right s)) =+	appsE [varE 'fs, litE $ stringL s]+writeField bs arg argn bytes (Variable v) =+	fieldValueToStr bs arg argn bytes False $ getField bs v++fs :: Binary a => String -> a+fs = makeBinary . BSLC.pack++fieldValueToStr :: Name -> Name -> Name -> Expression -> Bool -> ExpQ -> ExpQ+fieldValueToStr bs arg argn size False =+	appE $ appE (varE 'toBinary) (expression (varE bs) (varE arg) argn size)+fieldValueToStr bs arg argn size True = \val ->+	appE (varE 'mconcat) $ appsE [+		varE 'map, appE (varE 'toBinary) (expression (varE bs) (varE arg) argn size), val]++reading :: String -> Name -> Name -> [BinaryStructureItem] -> DecQ+reading name bsn argn body = do+	arg <- newName "_arg"+	cs <- newName "cs1"+	ret <- newName "ret"+	funD (mkName name) [clause [varP arg, varP cs]+		(normalB $ mkLetRec ret $ mkBody bsn arg argn body cs) []]++mkLetRec :: Name -> (Name -> ExpQ) -> ExpQ+mkLetRec n f = do+	rest <- newName "rest"+	letE [valD (tupP [varP n, varP rest]) (normalB $ f n) []] $+		tupE [varE n, varE rest]++mkBody :: Name -> Name -> Name -> [BinaryStructureItem] -> Name -> Name -> ExpQ+mkBody bsn arg argn body cs ret = do+	namePairs <- for names $ \n -> return . (n ,) =<< newName "tmp"+	(defs, rest) <- gather cs body $ mkDef namePairs+	letE (map return defs) $ tupE+		[recConE bsn (map toPair2 namePairs), varE rest]+	where+	names = variables $ map valueOf body+	toPair2 (n, nn) = return (n, VarE nn)+	mkDef :: [(Name, Name)] -> BinaryStructureItem -> Name -> Q ([Dec], Name)+	mkDef np item cs'+	    | Constant (Left val) <- valueOf item = do+		cs'' <- newName "cs"+		let	t = dropE' n $ varE cs'+			p = val `equal` appE (varE 'fst)+				(appE (appE (varE 'fromBinary) arg') $+					takeE' n $ varE cs')+			e = [e| error "bad value" |]+		d <- valD (varP cs'') (normalB $ condE p t e) []+		return ([d], cs'')+	    | Constant (Right val) <- valueOf item = do+		cs'' <- newName "cs"+		let t = dropE' n $ varE cs'+		let p = val `equal'` takeE' n (varE cs')+		let e = [e| error "bad value" |]+		d <- valD (varP cs'') (normalB $ condE p t e) []+		return ([d], cs'')+	    | Variable var <- valueOf item = do+		cs'' <- newName "cs"+		def <- valD (tupP [varP $ fromJust $ lookup var np, varP cs''])+			(normalB $ appE (appE (varE 'fromBinary) arg') $ varE cs') []+		return ([def], cs'')+	    | otherwise = error "bad"+	    where+	    n = expression (varE ret) (varE arg) argn $ bytesOf item+	    arg' = expression (varE ret) (varE arg) argn $ bytesOf item++getField :: Name -> Name -> ExpQ+getField bs v = appE (varE v) (varE bs)++equal :: Integer -> ExpQ -> ExpQ+equal x y = infixE (Just $ sigE (litE $ integerL x) (conT ''Integer))+	(varE '(==)) (Just y)++equal' :: String -> ExpQ -> ExpQ+equal' x y = infixE (Just $ litE $ stringL x) (varE '(==)) (Just y)++takeE' :: ExpQ -> ExpQ -> ExpQ+takeE' n xs = -- appE (varE 'ts) $ appsE [varE 'tk, n, xs]+	appE (varE 'BSLC.unpack) $ appE (varE 'fst) $ appsE [varE 'getBytes, n, xs]++dropE' :: ExpQ -> ExpQ -> ExpQ+dropE' n xs = appsE [varE 'dp, n, xs]++dp :: Binary a => Int -> a -> a+dp n = snd . getBytes n++gather :: Monad m => s -> [a] -> (a -> s -> m ([b], s)) -> m ([b], s)+gather s [] _ = return ([], s)+gather s (x : xs) f = do+	(ys, s') <- f x s+	(zs, s'') <- gather s' xs f+	return (ys ++ zs, s'')++mkData :: Name -> [BinaryStructureItem] -> DecsQ+mkData bsn body = do+	d <- dataD (cxt []) name [] [con] [''Show]+	return [d]+	where+	name = bsn+	con = recC bsn vsts++	vsts = flip map (filter isRight body) $ \item ->+		varStrictType (variable $ valueOf item) $+			strictType notStrict $ mkType False $ typeOf item+	isRight item+		| Variable _ <- valueOf item = True+		| otherwise = False++mkType :: Bool -> TypeQ -> TypeQ+mkType True t = appT listT $ mkType False t+mkType False typ = typ++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')
− src/ParseBinaryStructure.hs
@@ -1,166 +0,0 @@-{-# LANGUAGE-	TemplateHaskell,-	QuasiQuotes,-	FlexibleContexts,-	FlexibleInstances,-	PackageImports #-}--{-# OPTIONS_GHC-	-fno-warn-unused-do-bind-	-fno-warn-unused-matches-	-fno-warn-name-shadowing-	-fno-warn-orphans #-}--module ParseBinaryStructure (-	parseBinaryStructure,--	BinaryStructure,-	binaryStructureName,-	binaryStructureArgName,-	binaryStructureArgType,-	binaryStructureBody,--	BinaryStructureItem,-	bytesOf,-	typeOf,-	valueOf,--	Expression,-	expression,-	Binary(..),-	Field(..),-	fii, tii,-	dp, fs, cc-) where--import Text.Peggy-import Language.Haskell.TH-import Numeric--import Classes--import "monads-tf" Control.Monad.Reader-import Control.Applicative--parseBinaryStructure :: String -> BinaryStructure-parseBinaryStructure src = case parseString top "<code>" src of-	Right bs -> bs-	Left ps -> error $ show ps--data BinaryStructure = BinaryStructure {-	binaryStructureName :: String,-	binaryStructureArgName :: String,-	binaryStructureArgType :: TypeQ,-	binaryStructureBody :: [BinaryStructureItem]- }--data BinaryStructureItem = BinaryStructureItem {-	bytesOf :: Expression,-	typeOf :: TypeQ,-	valueOf :: Either (Either Int String) String- }--type Expression	= Reader (Name, Name, String) ExpQ--expression :: Name -> Name -> String -> Expression -> ExpQ-expression ret arg argn e = runReader e (ret, arg, argn)--applyOp :: Name -> Expression -> Expression -> Expression-applyOp op re1 re2 = flip infixApp (varE op) <$> re1 <*> re2--[peggy|--top :: BinaryStructure-	= emptyLines name emptyLines argType dat*-				{ BinaryStructure $2 (fst $4) (snd $4) $5 }--argType :: (String, TypeQ)-	= spaces var spaces '::' spaces typeGen [\n]+-				{ ($2, $5) }-	/ ""			{ ("_", conT $ mkName "()") }--emptyLines :: ()-	= "--" [^\n]* [\n]	{ () }-	/ [ \n]*		{ () }--spaces :: ()-	= [ ]*			{ () }---name :: String-	= [A-Z][a-zA-Z0-9]*	{ $1 : $2 }--dat :: BinaryStructureItem-	= expr typ size? ':' spaces val emptyLines-				{ BinaryStructureItem $1 $2 $5 }--typ :: TypeQ-	= [<] typeGen [>]	{ $2 }-	/ ""			{ conT $ mkName "Int" }--typeGen :: TypeQ-	= [(] tupleGen_ [)]	{ foldl appT (tupleT $ length $2) $2 }-	/ [\[] typeGen [\]]	{ appT listT $ $2 }-	/ [A-Z][.a-zA-Z0-9]*	{ 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] }--expr :: Expression-	= expr spaces '*' spaces expr		{ applyOp (mkName "*") $1 $4 }-	/ expr spaces '`div`' spaces expr	{ applyOp (mkName "div") $1 $4 }-	/ expr spaces '+' spaces expr		{ applyOp (mkName "+") $1 $4 }-	/ num			{ return $ litE $ integerL $ fromIntegral $1 }-	/ var			{ ask >>= \(ret, arg, argn) -> return $-					if $1 == argn-						then varE arg-						else appE (varE $ mkName $1) $-							varE ret }-	/ [(] tupleExpr [)]	{ $2 }-	/ 'Just' spaces expr	{ appE (conE $ mkName "Just") <$> $2 }-	/ 'Nothing'		{ return $ conE $ mkName "Nothing" }--tupleExpr :: Expression-	= expr ', ' expr	{ (\e1 e2 -> tupE [e1, e2]) <$> $1 <*> $2 }-	/ expr-	/ ""			{ return $ conE $ mkName "()" }--size :: Expression-	= '[' expr ']'--val :: Either (Either Int String) String-	= num			{ Left $ Left $1 }-	/ var			{ Right $ $1 }-	/ stringLit		{ Left $ Right $1 }--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 }--num :: Int-	= '0x' [0-9a-fA-F]+	{ fst $ head $ readHex $1 }-	/ [1-9][0-9]*		{ read $ $1 : $2 }-	/ '0'			{ 0 }--|]
− src/QuoteBinaryStructure.hs
@@ -1,194 +0,0 @@-{-# LANGUAGE-	TemplateHaskell,-	TupleSections,-	PatternGuards,-	TypeSynonymInstances,-	FlexibleInstances #-}--module QuoteBinaryStructure (-	binary,-	Field(..),-	Binary(..),-	fii, -- fiiBE,-	tii, -- tiiBE,-	times-) where--import Prelude hiding (sequence)--import Language.Haskell.TH hiding (Type)-import Language.Haskell.TH.Quote-import Data.Traversable hiding (mapM)-import Data.Either-import Data.Maybe-import qualified Data.ByteString.Lazy.Char8 as BSLC--import ParseBinaryStructure--binary :: QuasiQuoter-binary = QuasiQuoter {-	quoteExp = undefined,-	quotePat = undefined,-	quoteType = undefined,-	quoteDec = mkHaskellTree . parseBinaryStructure- }--mkHaskellTree :: BinaryStructure -> DecsQ-mkHaskellTree bs = do-		d <- mkData bsn body-		i <- mkInst bsn argn typ body-		return $ d ++ [i]-	where-	bsn = binaryStructureName bs-	argn = binaryStructureArgName bs-	typ = binaryStructureArgType bs-	body = binaryStructureBody bs--mkInst :: String -> String -> TypeQ -> [BinaryStructureItem] -> DecQ-mkInst bsn argn typ body =-	instanceD (cxt []) (appT (conT ''Field) (conT $ mkName bsn)) [-		tySynInstD ''FieldArgument [conT $ mkName bsn] typ,-		reading "fromBinary" bsn argn body,-		writing "toBinary" argn body-	 ]--writing :: String -> String -> [BinaryStructureItem] -> DecQ-writing name argn body = do-	arg <- newName "arg"-	bs <- newName "bs"-	let run = appE (varE 'cc) $ listE $ map-		(\bsi -> writeField bs arg argn (bytesOf bsi) (valueOf bsi)) body-	funD (mkName name)-		[clause [varP arg, varP bs] (normalB run) []]--writeField :: Name -> Name -> String -> Expression -> Either (Either Int String) String -> ExpQ-writeField bs arg argn size (Left (Left n)) =-	appsE [fiend', expression bs arg argn size, sigE (litE $ integerL $ fromIntegral n)-		(conT ''Int)]-	where-	fiend' = varE 'toBinary-writeField _ _ _ _ (Left (Right s)) =-	appsE [varE 'fs, litE $ stringL s]-writeField bs arg argn bytes (Right v) =-	fieldValueToStr bs arg argn bytes False $ getField bs v--fieldValueToStr :: Name -> Name -> String -> Expression -> Bool -> ExpQ -> ExpQ-fieldValueToStr bs arg argn size False =-	appE $ appE (varE 'toBinary) (expression bs arg argn size)-fieldValueToStr bs arg argn size True = \val ->-	appE (varE 'cc) $ appsE [-		varE 'map, appE (varE 'toBinary) (expression bs arg argn size), val]--reading :: String -> String -> String -> [BinaryStructureItem] -> DecQ-reading name bsn argn body = do-	arg <- newName "arg"-	cs <- newName "cs"-	ret <- newName "ret"-	funD (mkName name) [clause [varP arg, varP cs]-		(normalB $ mkLetRec ret $ mkBody bsn arg argn body cs) []]--mkLetRec :: Name -> (Name -> ExpQ) -> ExpQ-mkLetRec n f = do-	rest <- newName "rest"-	letE [valD (tupP [varP n, varP rest]) (normalB $ f n) []] $-		tupE [varE n, varE rest]--mkBody :: String -> Name -> String -> [BinaryStructureItem] -> Name -> Name -> ExpQ-mkBody bsn arg argn body cs ret = do-	namePairs <- for names $ \n -> return . (n ,) =<< newName "tmp"-	(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-	toPair2 (n, nn) = return (mkName n, VarE nn)-	mkDef :: [(String, Name)] -> BinaryStructureItem -> Name -> Q ([Dec], Name)-	mkDef np item cs'-	    | Left (Left val) <- valueOf item = do-		cs'' <- newName "cs"-		let	t = dropE' n $ varE cs'-			p = val `equal` appE (varE 'fst)-				(appE (appE (varE 'fromBinary) arg') $-					takeE' n $ varE cs')-			e = [e| error "bad value" |]-		d <- valD (varP cs'') (normalB $ condE p t e) []-		return ([d], cs'')-	    | Left (Right val) <- valueOf item = do-		cs'' <- newName "cs"-		let t = dropE' n $ varE cs'-		let p = val `equal'` 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 = do-		cs'' <- newName "cs"-		def <- valD (tupP [varP $ fromJust $ lookup var np, varP cs''])-			(normalB $ appE (appE (varE 'fromBinary) arg') $ varE cs') []-		return ([def], cs'')-	    | otherwise = error "bad"-	    where-	    n = expression ret arg argn $ bytesOf item-	    arg' = expression ret arg argn $ bytesOf item--getField :: Name -> String -> ExpQ-getField bs v = appE (varE $ mkName v) (varE bs)--equal :: Int -> ExpQ -> ExpQ-equal x y = infixE (Just $ sigE (litE $ integerL $ fromIntegral x) (conT ''Int))-	(varE '(==)) (Just y)--equal' :: String -> ExpQ -> ExpQ-equal' x y = infixE (Just $ litE $ stringL x) (varE '(==)) (Just y)--takeE' :: ExpQ -> ExpQ -> ExpQ-takeE' n xs = -- appE (varE 'ts) $ appsE [varE 'tk, n, xs]-	appE (varE 'BSLC.unpack) $ appE (varE 'fst) $ appsE [varE 'getBytes, 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], s)-gather s [] _ = return ([], s)-gather s (x : xs) f = do-	(ys, s') <- f x s-	(zs, s'') <- gather s' xs f-	return (ys ++ zs, s'')--mkInstance :: String -> DecQ-mkInstance name =-	instanceD (cxt []) (appT (conT ''Field) (conT $ mkName name)) [-		valD (varP $ 'toBinary)-			(normalB $ varE $ mkName $ "write" ++ name) [],-		valD (varP $ 'fromBinary)-			(normalB $ varE $ mkName $ "read" ++ name) []-	 ]--mkData :: String -> [BinaryStructureItem] -> DecsQ-mkData bsn body = do-	d <- dataD (cxt []) name [] [con] [''Show]-	_ <- mkInstance bsn-	return [d]-	where-	name = mkName bsn-	con = recC (mkName bsn) vsts--	vsts = flip map (filter isRight body) $ \item ->-		varStrictType (mkName $ fromRight $ valueOf item) $-			strictType notStrict $ mkType False $ typeOf item-	isRight item-		| Right _ <- valueOf item = True-		| otherwise = False--mkType :: Bool -> TypeQ -> TypeQ-mkType True t = appT listT $ mkType False t-mkType False typ = typ--fromRight :: Either a b -> b-fromRight = either (error "not Right") id--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')