omnicodec 0.4.0 → 0.5
raw patch · 3 files changed
+206/−141 lines, 3 filesdep +cmdargsdep +mtldep −directorydep −filepathdep −haskell98dep ~basedep ~bytestringdep ~dataenc
Dependencies added: cmdargs, mtl
Dependencies removed: directory, filepath, haskell98
Dependency ranges changed: base, bytestring, dataenc
Files
- omnicodec.cabal +11/−13
- src/odec.hs +105/−66
- src/oenc.hs +90/−62
omnicodec.cabal view
@@ -1,26 +1,24 @@ name: omnicodec-version: 0.4.0+version: 0.5 license: GPL license-file: COPYING author: Magnus Therning maintainer: magnus@therning.org-copyright: Magnus Therning, 2007-2010+copyright: Magnus Therning, 2007-2011 synopsis: data encoding and decoding command line utilities description: Two simple command line tools built on dataenc. build-type: Simple category: Codec-cabal-version: >= 1.2+cabal-version: >= 1.6 executable odec- main-is: odec.hs- hs-source-dirs: src- build-depends: base >= 4.0.0 && < 4.3, dataenc >= 0.13, directory, filepath,- haskell98, bytestring- ghc-options: -Wall+ main-is: odec.hs+ hs-source-dirs: src+ build-depends: base ==4.2.*, cmdargs ==0.6.*, bytestring ==0.9.*,+ mtl ==1.1.*, dataenc ==0.14.*+ ghc-options: -Wall executable oenc- main-is: oenc.hs- hs-source-dirs: src- build-depends: base >= 4.0.0 && < 4.3, dataenc >= 0.13, directory, filepath,- haskell98, bytestring- ghc-options: -Wall+ main-is: oenc.hs+ hs-source-dirs: src+ ghc-options: -Wall
src/odec.hs view
@@ -1,3 +1,5 @@+{-# LANGUAGE DeriveDataTypeable #-}+ {- odec - command line utility for data decoding Copyright (C) 2008 Magnus Therning@@ -20,84 +22,121 @@ ( main ) where -import Codec.Binary.DataEncoding-import Data.Maybe-import Data.Version (showVersion)-import Data.Word-import System-import System.Console.GetOpt-import Control.Exception as CE-import System.Directory-import qualified Data.ByteString as BS- import Paths_omnicodec (version) +import Codec.Binary.Base64 as B64+import qualified Codec.Binary.Base64Url as B64U+import qualified Codec.Binary.Base32 as B32+import qualified Codec.Binary.Base32Hex as B32H+import qualified Codec.Binary.Base16 as B16+import qualified Codec.Binary.Base85 as B85+import qualified Codec.Binary.PythonString as PS+import qualified Codec.Binary.QuotedPrintable as QP+import qualified Codec.Binary.Url as Url+import qualified Codec.Binary.Uu as Uu+import qualified Codec.Binary.Xx as Xx+import Data.ByteString.Iteratee+import Data.ByteString.Iteratee.Internals++import qualified Data.ByteString as BS+import qualified Data.ByteString.Char8 as BSC+import System.Console.CmdArgs+import Data.Version(showVersion)+import System.IO+import Data.Maybe++-- {{{1 command line options ver :: String ver = "omnicode decode (odec) " ++ (showVersion version)- ++ "\nCopyright 2007-2010 Magnus Therning <magnus@therning.org>"---- {{{1 Options-data DecOptions = DecOptions {- optDecode :: [String] -> [Maybe Word8],- optRead :: IO String,- optWrite :: BS.ByteString -> IO (),- optFn :: Maybe String -- needed in case we need to clean up later on- }+ ++ "\nCopyright 2007-2011 Magnus Therning <magnus@therning.org>" -defaultOptions :: DecOptions-defaultOptions = DecOptions {- optDecode = decode' uu . unchop uu,- optRead = getContents,- optWrite = BS.putStr,- optFn = Nothing- }+data Codec = B64 | B64U | B32 | B32H | B16 | B85 | PS | QP | Url | Uu | Xx+ deriving(Show, Eq, Data, Typeable) --- {{{2 Command line-options :: [OptDescr (DecOptions -> IO DecOptions)]-options = [- Option "o" ["output"] (ReqArg setOptOutput "FILE") "output to file",- Option "c" ["codec"] (ReqArg setOptCodec "CODEC") "use codec (uu,xx,qp,py,b85,b64,b64u,b32,b32h,b16)",- Option "" ["version"] (NoArg optShowVersion) "",- Option "h" ["help"] (NoArg optShowHelp) ""+codecMap :: [(Codec, DecIncData String -> DecIncRes String)]+codecMap =+ [ (B64, B64.decodeInc)+ , (B64U, B64U.decodeInc)+ , (B32, B32.decodeInc)+ , (B32H, B32H.decodeInc)+ , (B16, B16.decodeInc)+ , (B85, B85.decodeInc)+ , (PS, PS.decodeInc)+ , (QP, QP.decodeInc)+ , (Url, Url.decodeInc)+ , (Uu, Uu.decodeInc)+ , (Xx, Xx.decodeInc) ] --- {{{2 Processing command line-setOptOutput :: FilePath -> DecOptions -> IO DecOptions-setOptOutput fn opts = return opts { optWrite = BS.writeFile fn, optFn = Just fn }--setOptCodec :: String -> DecOptions -> IO DecOptions-setOptCodec codec opts = case codec of- "uu" -> return opts { optDecode = decode' uu . unchop uu }- "xx" -> return opts { optDecode = decode' xx . unchop xx }- "qp" -> return opts { optDecode = decode' qp . unchop qp }- "py" -> return opts { optDecode = decode' py . unchop py }- "b85" -> return opts { optDecode = decode' base85 . unchop base85 }- "b64" -> return opts { optDecode = decode' base64 . unchop base64 }- "b64u" -> return opts { optDecode = decode' base64Url . unchop base64Url }- "b32" -> return opts { optDecode = decode' base32 . unchop base32 }- "b32h" -> return opts { optDecode = decode' base32Hex . unchop base32Hex }- "b16" -> return opts { optDecode = decode' base16 . unchop base16 }- _ -> error "Unknown encoding."--optShowVersion :: a -> IO DecOptions-optShowVersion _ = putStrLn ver >> exitWith ExitSuccess+data MyArgs = MyArgs { argInput :: Maybe FilePath, argOutput :: Maybe FilePath, argCodec :: Codec }+ deriving(Show, Data, Typeable) -optShowHelp :: DecOptions -> IO DecOptions-optShowHelp _ = putStrLn (usageInfo "Usage:" options) >> exitWith ExitSuccess+myArgs :: MyArgs+myArgs = MyArgs+ { argInput = Nothing &= name "i" &= name "in" &= explicit &= typFile &= help "read encoded data from file"+ , argOutput = Nothing &= name "o" &= name "out" &= explicit &= typFile &= help "write decoded data to file"+ , argCodec = B64 &= name "c" &= name "codec" &= explicit &= typ "CODEC" &= help "codec b64, b64u, b32, b32h, b16, b85, ps, qp, url, uu, xx (b64)"+ } &= summary ver &= details+ [ "Decoder tool for multiple encodings:"+ , " b64 - base64 (default)"+ , " b64u - base64url"+ , " b32 - base32"+ , " b32h - base32hex"+ , " b16 - base16"+ , " b85 - base85"+ , " ps - python string escaping"+ , " qp - quoted printable"+ , " url - url encoding"+ , " uu - uu encoding"+ , " xx - xx encoding"+ ] -processFileName :: [String] -> IO DecOptions-processFileName (fn:_) = return defaultOptions { optRead = readFile fn }-processFileName _ = return defaultOptions+-- {{{1 decode enumeratee+decEnumeratee :: Monad m => (DecIncData String -> DecIncRes String) -> Enumeratee m a+decEnumeratee decF iter = Iteratee $ step decF iter+ where+ step f i Eof = let+ d = f DDone+ in do+ case d of+ DFinal dbs _ -> do+ ir <- runIteratee i (Chunk $ BS.pack dbs)+ case ir of+ Done a _ -> return $ Done (Iteratee $ \ _ -> return $ Done a Eof) Eof+ NeedAnotherChunk i' -> do+ ir' <- runIteratee i' Eof+ case ir' of+ Done a _ -> return $ Done (Iteratee $ \ _ -> return $ Done a Eof) Eof+ NeedAnotherChunk _ -> error "decEnumeratee: inner iteratee diverges on Eof"+ DFail _ _ -> error "decEnumeratee: decoder failed on data"+ DPart _ _ -> error "decEnumeratee: decoder didn't terminate on DDone" --- {{{1 decode'-_decode :: DecOptions -> String -> IO BS.ByteString-_decode opts = return . BS.pack. map (fromMaybe (error "Illegal character")) . optDecode opts . lines+ step f i (Chunk bs) = let+ d = f (DChunk $ BSC.unpack bs)+ in do+ case d of+ DFinal dbs r -> do+ ir <- runIteratee i (Chunk $ BS.pack dbs)+ case ir of+ Done a _ -> return $ Done (Iteratee $ \ _ -> return $ Done a (Chunk $ BSC.pack r)) (Chunk $ BSC.pack r)+ NeedAnotherChunk i' -> do+ ir' <- runIteratee i' Eof+ case ir' of+ Done a _ -> return $ Done (Iteratee $ \ _ -> return $ Done a Eof) Eof+ NeedAnotherChunk _ -> error "decEnumeratee: inner iteratee diverges on Eof"+ DFail _ _ -> error "decEnumeratee: decoder failed on data"+ DPart dbs f' -> do+ ir <- runIteratee i (Chunk $ BS.pack dbs)+ case ir of+ Done a _ -> return $ Done (Iteratee $ \ _ -> return $ Done a (Chunk BS.empty)) (Chunk BS.empty)+ NeedAnotherChunk i' -> return $ NeedAnotherChunk $ Iteratee $ step f' i' -- {{{1 main main :: IO () main = do- args <- getArgs- let (actions, nonOpts, _) = getOpt RequireOrder options args- opts <- foldl (>>=) (processFileName nonOpts) actions- CE.catch (optRead opts >>= _decode opts >>= optWrite opts)- (\ (CE.SomeException e) -> maybe (return ()) removeFile (optFn opts) >> throwIO e)+ cmdArgs myArgs >>= \ a -> do+ hIn <- maybe (return stdin) (\ fn -> openFile fn ReadMode) (argInput a)+ hOut <- maybe (return stdout) (\ fn -> openFile fn WriteMode) (argOutput a)+ let dI = fromJust $ lookup (argCodec a) codecMap+ (enumHandle hIn $ decEnumeratee dI (sinkHandle hOut)) >>= run >>= run+ hClose hOut
src/oenc.hs view
@@ -1,3 +1,5 @@+{-# LANGUAGE DeriveDataTypeable #-}+ {- oenc - command line utility for data encoding Copyright (C) 2008 Magnus Therning@@ -16,80 +18,106 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. -} -module Main- where--import Codec.Binary.DataEncoding-import Data.Version (showVersion)-import Data.Word-import System-import System.Console.GetOpt-import qualified Data.ByteString as BS+module Main where import Paths_omnicodec (version) +import Codec.Binary.Base64 as B64+import qualified Codec.Binary.Base64Url as B64U+import qualified Codec.Binary.Base32 as B32+import qualified Codec.Binary.Base32Hex as B32H+import qualified Codec.Binary.Base16 as B16+import qualified Codec.Binary.Base85 as B85+import qualified Codec.Binary.PythonString as PS+import qualified Codec.Binary.QuotedPrintable as QP+import qualified Codec.Binary.Url as Url+import qualified Codec.Binary.Uu as Uu+import qualified Codec.Binary.Xx as Xx+import Data.ByteString.Iteratee+import Data.ByteString.Iteratee.Internals++import Data.Version(showVersion)+import System.Console.CmdArgs+import qualified Data.ByteString as BS+import qualified Data.ByteString.Char8 as BSC+import System.IO+import Data.Maybe++-- {{{1 command line options ver :: String ver = "omnicode encode (oenc) " ++ (showVersion version)- ++ "\nCopyright 2007-2010 Magnus Therning <magnus@therning.org>"---- {{{1 Options-data EncOptions = EncOptions {- optEncode :: [Word8] -> [String],- optRead :: IO BS.ByteString,- optWrite :: String -> IO ()- }+ ++ "\nCopyright 2007-2011 Magnus Therning <magnus@therning.org>" -defaultOptions :: EncOptions-defaultOptions = EncOptions {- optEncode = chop uu 61 . encode uu,- optRead = BS.getContents,- optWrite = putStr- }+data Codec = B64 | B64U | B32 | B32H | B16 | B85 | PS | QP | Url | Uu | Xx+ deriving(Show, Eq, Data, Typeable) -options :: [OptDescr (EncOptions -> IO EncOptions)]-options = [- Option "o" ["output"] (ReqArg setOptOutput "FILE") "output to file",- Option "c" ["codec"] (ReqArg setOptCodec "CODEC") "use codec (uu,xx,qp,py,b85,b64,b64u,b32,b32h,b16)",- Option "" ["version"] (NoArg optShowVersion) "",- Option "h" ["help"] (NoArg optShowHelp) ""+codecMap :: [(Codec, EncIncData -> EncIncRes String)]+codecMap =+ [ (B64, B64.encodeInc)+ , (B64U, B64U.encodeInc)+ , (B32, B32.encodeInc)+ , (B32H, B32H.encodeInc)+ , (B16, B16.encodeInc)+ , (B85, B85.encodeInc)+ , (PS, PS.encodeInc)+ , (QP, QP.encodeInc)+ , (Url, Url.encodeInc)+ , (Uu, Uu.encodeInc)+ , (Xx, Xx.encodeInc) ] --- {{{2 option actions-setOptCodec :: String -> EncOptions -> IO EncOptions-setOptCodec codec opts = case codec of- "uu" -> return opts { optEncode = chop uu 61 . encode uu }- "xx" -> return opts { optEncode = chop xx 61 . encode xx }- "qp" -> return opts { optEncode = chop qp 60 . encode qp }- "py" -> return opts { optEncode = chop py 60 . encode py }- "b85" -> return opts { optEncode = chop base85 60 . encode base85 }- "b64" -> return opts { optEncode = chop base64 60 . encode base64 }- "b64u" -> return opts { optEncode = chop base64Url 60 . encode base64Url }- "b32" -> return opts { optEncode = chop base32 60 . encode base32 }- "b32h" -> return opts { optEncode = chop base32Hex 60 . encode base32Hex }- "b16" -> return opts { optEncode = chop base16 60 . encode base16 }- _ -> error "Unknown encoding."--setOptOutput :: FilePath -> EncOptions -> IO EncOptions-setOptOutput fn opts = return opts { optWrite = writeFile fn }--optShowVersion :: EncOptions -> IO EncOptions-optShowVersion _ = putStrLn ver >> exitWith ExitSuccess--optShowHelp :: EncOptions -> IO EncOptions-optShowHelp _ = putStr (usageInfo "Usage:" options) >> exitWith ExitSuccess+data MyArgs = MyArgs { argInput :: Maybe FilePath, argOutput :: Maybe FilePath, argCodec :: Codec }+ deriving(Show, Data, Typeable) -processFileName :: [String] -> IO EncOptions-processFileName (fn:_) = return defaultOptions { optRead = BS.readFile fn }-processFileName _ = return defaultOptions+myArgs :: MyArgs+myArgs = MyArgs+ { argInput = Nothing &= name "i" &= name "in" &= explicit &= typFile &= help "read data from file"+ , argOutput = Nothing &= name "o" &= name "out" &= explicit &= typFile &= help "write encoded data to file"+ , argCodec = B64 &= name "c" &= name "codec" &= explicit &= typ "CODEC" &= help "codec b64, b64u, b32, b32h, b16, b85, ps, qp, url, uu, xx (b64)"+ } &= summary ver &= details+ [ "Encoder tool for multiple encodings:"+ , " b64 - base64 (default)"+ , " b64u - base64url"+ , " b32 - base32"+ , " b32h - base32hex"+ , " b16 - base16"+ , " b85 - base85"+ , " ps - python string escaping"+ , " qp - quoted printable"+ , " url - url encoding"+ , " uu - uu encoding"+ , " xx - xx encoding"+ ] --- {{{1 encode-_encode :: EncOptions -> BS.ByteString -> IO String-_encode opts = return . unlines . optEncode opts . BS.unpack+-- {{{1 encode enumeratee+encEnumeratee :: Monad m => (EncIncData -> EncIncRes String) -> Enumeratee m a+encEnumeratee encF iter = Iteratee $ step encF iter+ where+ step f i Eof = let+ EFinal ebs = f EDone+ in do+ ir <- runIteratee i (Chunk $ BSC.pack ebs)+ case ir of+ Done a _ -> return $ Done (Iteratee $ \ _ -> return $ Done a Eof) Eof+ NeedAnotherChunk i' -> do+ ir' <- runIteratee i' Eof+ case ir' of+ Done a _ -> return $ Done (Iteratee $ \ _ -> return $ Done a Eof) Eof+ NeedAnotherChunk _ -> error "encEnumeratee: inner iteratee diverges on Eof"+ step f i (Chunk bs) = let+ EPart ebs f' = f (EChunk $ BS.unpack bs)+ in do+ ir <- runIteratee i (Chunk $ BSC.pack ebs)+ case ir of+ Done a _ -> return $ Done (Iteratee $ \ _ -> return $ Done a (Chunk BS.empty)) (Chunk BS.empty)+ NeedAnotherChunk i' -> return $ NeedAnotherChunk $ Iteratee $ step f' i' -- {{{1 main main :: IO () main = do- args <- getArgs- let (actions, nonOpts, _) = getOpt RequireOrder options args- opts <- foldl (>>=) (processFileName nonOpts) actions- optRead opts >>= _encode opts >>= optWrite opts+ cmdArgs myArgs >>= \ a -> do+ hIn <- maybe (return stdin) (\ fn -> openFile fn ReadMode) (argInput a)+ hOut <- maybe (return stdout) (\ fn -> openFile fn WriteMode) (argOutput a)+ let eI = fromJust $ lookup (argCodec a) codecMap+ (enumHandle hIn $ encEnumeratee eI (sinkHandle hOut)) >>= run >>= run+ hClose hOut