dataenc 0.12 → 0.12.1.0
raw patch · 17 files changed
+1106/−353 lines, 17 filesdep ~arraydep ~basedep ~containers
Dependency ranges changed: array, base, containers
Files
- DataencQC.hs +180/−0
- DataencUT.hs +306/−0
- GNUmakefile +32/−0
- QC.hs +0/−114
- Test.hs +19/−0
- UT.hs +0/−186
- dataenc.cabal +15/−15
- src/Codec/Binary/Base85.hs +10/−10
- src/Codec/Binary/DataEncoding.hs +75/−5
- src/Codec/Binary/Hexadecimal.hs +56/−0
- src/Codec/Binary/PythonString.hs +86/−0
- src/Codec/Binary/QuotedPrintable.hs +79/−0
- src/Codec/Binary/Url.hs +76/−0
- src/Codec/Binary/Util.hs +41/−0
- src/Codec/Binary/Uu.hs +8/−20
- src/Codec/Binary/Xx.hs +119/−0
- src/Codec/Binary/Yenc.hs +4/−3
+ DataencQC.hs view
@@ -0,0 +1,180 @@+{-+ - Copyright : (c) 2007 Magnus Therning+ - License : BSD3+ -}++module DataencQC+ where++import Data.Maybe+import Data.Word+import Test.QuickCheck+import Test.Framework.Providers.QuickCheck2++import qualified Codec.Binary.Uu as Uu+import qualified Codec.Binary.Uu as Xx+import qualified Codec.Binary.Base85 as Base85+import qualified Codec.Binary.Base64 as Base64+import qualified Codec.Binary.Base64Url as Base64Url+import qualified Codec.Binary.Base32 as Base32+import qualified Codec.Binary.Base32Hex as Base32Hex+import qualified Codec.Binary.Base16 as Base16+import qualified Codec.Binary.Yenc as Yenc+import qualified Codec.Binary.Hexadecimal as Hex+import qualified Codec.Binary.QuotedPrintable as QP+import qualified Codec.Binary.PythonString as Py+import qualified Codec.Binary.Url as Url++-- {{{1 Arbitrary instances+instance Arbitrary Word8 where+ arbitrary = do+ n <- choose ((fromIntegral (minBound::Word8))::Int,+ (fromIntegral (maxBound::Word8))::Int)+ return $ fromIntegral n++-- {{{1 uuencode properties+prop_uuEncode ws = ws == (fromJust . Uu.decode . Uu.encode) ws+ where types = ws::[Word8]++prop_uuChop n ws = s == (Uu.unchop . Uu.chop n) s+ where+ types = (n :: Int, ws::[Word8])+ s = Uu.encode ws++prop_uuCombined n ws = ws == (fromJust $ Uu.decode $ Uu.unchop $ Uu.chop n $ Uu.encode ws)+ where types = (n::Int, ws::[Word8])++-- {{{1 xxencode properties+prop_xxEncode ws = ws == (fromJust . Xx.decode . Xx.encode) ws+ where types = ws::[Word8]++prop_xxChop n ws = s == (Xx.unchop . Xx.chop n) s+ where+ types = (n:: Int, ws::[Word8])+ s = Xx.encode ws++prop_xxCombined n ws = ws == (fromJust $ Xx.decode $ Xx.unchop $ Xx.chop n $ Xx.encode ws)+ where types = (n::Int, ws::[Word8])++-- {{{1 base85 properties+prop_base85Encode ws = ws == (fromJust $ Base85.decode $ Base85.encode ws)+ where types = ws::[Word8]++prop_base85Chop n s = s == (Base85.unchop $ Base85.chop n s)+ where types = (n::Int, s::String)++-- {{{1 base64 properties+prop_base64Encode ws = ws == (fromJust $ Base64.decode $ Base64.encode ws)+ where types = ws::[Word8]++prop_base64Chop n s = s == (Base64.unchop $ Base64.chop n s)+ where types = (n::Int, s::String)++-- {{{1 base64url properties+prop_base64UrlEncode ws = ws == (fromJust $ Base64Url.decode $ Base64Url.encode ws)+ where types = ws::[Word8]++prop_base64UrlChop n s = s == (Base64Url.unchop $ Base64Url.chop n s)+ where types = (n::Int, s::String)++-- {{{1 base32+prop_base32Encode ws = ws == (fromJust $ Base32.decode $ Base32.encode ws)+ where types = ws::[Word8]++prop_base32Chop n s = s == (Base32.unchop $ Base32.chop n s)+ where types = (n::Int, s::String)++-- {{{1 base32hex+prop_base32HexEncode ws = ws == (fromJust $ Base32Hex.decode $ Base32Hex.encode ws)+ where types = ws::[Word8]++prop_base32HexChop n s = s == (Base32Hex.unchop $ Base32Hex.chop n s)+ where types = (n::Int, s::String)++-- {{{1 base16+prop_base16Encode ws = ws == (fromJust $ Base16.decode $ Base16.encode ws)+ where types = ws::[Word8]++prop_base16Chop n s = s == (Base16.unchop $ Base16.chop n s)+ where types = (n::Int, s::String)++-- {{{1 yEncoding+prop_yencEncode ws = ws == (fromJust $ Yenc.decode $ Yenc.encode ws)+ where types = ws ::[Word8]++prop_yencChop n ws = ws == (Yenc.unchop $ Yenc.chop n ws)+ where types = (n::Int, ws :: [Word8])++-- {{{1 hexadecimal+prop_hexEncode ws = ws == (fromJust $ Hex.decode $ Hex.encode ws)+ where types = ws :: [Word8]++prop_hexChop n s = s == (Hex.unchop $ Hex.chop n s)+ where types = (n :: Int, s :: String)++-- {{{1 qp+prop_qpEncode ws = ws == (fromJust $ QP.decode $ QP.encode ws)+ where types = ws :: [Word8]++prop_qpChop n ws = s == (QP.unchop . QP.chop n) s+ where+ types = (n::Int, ws::[Word8])+ s = QP.encode ws++prop_qpCombined n ws = ws == (fromJust $ QP.decode $ QP.unchop $ QP.chop n $ QP.encode ws)+ where types = (n::Int, ws::[Word8])++-- {{{1 py+prop_pyEncode ws = ws == (fromJust $ Py.decode $ Py.encode ws)+ where types = ws :: [Word8]++prop_pyChop n s = s == (Py.unchop $ Py.chop n s)+ where types = (n :: Int, s :: String)++prop_pyCombined n ws = ws == (fromJust $ runAll ws)+ where runAll = Py.decode . Py.unchop . Py.chop n . Py.encode++-- {{{1 url+prop_urlEncode ws = ws == (fromJust $ Url.decode $ Url.encode ws)+ where types = ws :: [Word8]++prop_urlChop n s = s == (Url.unchop $ Url.chop n s)+ where types = (n :: Int, s :: String)++prop_urlCombined n ws = ws == (fromJust $ runAll ws)+ where runAll = Url.decode . Url.unchop . Url.chop n . Url.encode++-- {{{1 all the tests+allTests =+ [ testProperty "uuEncode" prop_uuEncode+ , testProperty "uuChop" prop_uuChop+ , testProperty "uuCombined" prop_uuCombined+ , testProperty "xxEncode" prop_xxEncode+ , testProperty "xxChop" prop_xxChop+ , testProperty "xxCombined" prop_xxCombined+ , testProperty "base85Encode" prop_base85Encode+ , testProperty "base85Chop" prop_base85Chop+ , testProperty "base64Encode" prop_base64Encode+ , testProperty "base64Chop" prop_base64Chop+ , testProperty "base64UrlEncode" prop_base64UrlEncode+ , testProperty "base64UrlChop" prop_base64UrlChop+ , testProperty "base32Encode" prop_base32Encode+ , testProperty "base32Chop" prop_base32Chop+ , testProperty "base32HexEncode" prop_base32HexEncode+ , testProperty "base32HexChop" prop_base32HexChop+ , testProperty "base16Encode" prop_base16Encode+ , testProperty "base16Chop" prop_base16Chop+ , testProperty "yencEncode" prop_yencEncode+ , testProperty "yencChop" prop_yencChop+ , testProperty "hexEncode" prop_hexEncode+ , testProperty "hexChop" prop_hexChop+ , testProperty "qpEncode" prop_qpEncode+ , testProperty "qpChop" prop_qpChop+ , testProperty "qpCombined" prop_qpCombined+ , testProperty "pyEncode" prop_pyEncode+ , testProperty "pyChop" prop_pyChop+ , testProperty "pyCombined" prop_pyCombined+ , testProperty "urlEncode" prop_urlEncode+ , testProperty "urlChop" prop_urlChop+ , testProperty "urlCombined" prop_urlCombined+ ]
+ DataencUT.hs view
@@ -0,0 +1,306 @@+{-+ - Copyright : (c) 2007 Magnus Therning+ - License : BSD3+ -}++module DataencUT+ where++import Test.HUnit+import Control.Monad+import System.Exit+import Data.Maybe+import qualified Test.Framework.Providers.API as TFAPI+import Test.Framework.Providers.HUnit++import Codec.Binary.DataEncoding+import qualified Codec.Binary.Yenc as Yenc++-- {{{1 buildTestList+-- builds a list of successful tests based on a tuple (suite, description,+-- encoded data, decoded data, codec)+buildTestList td = TestList $ concat [+ [ TestLabel (suite ++ " encode " ++ desc) (enc ~=? (encode codec dec))+ , TestLabel (suite ++ " decode " ++ desc) (dec ~=? (fromJust $ decode codec $ enc))+ ] | (suite, desc, enc, dec, codec) <- td ]++-- {{{1 unitTest2TFTest+unitTest2TFTest :: Test -> [TFAPI.Test]+unitTest2TFTest t = let+ unitTest2TFTest' desc (TestCase a) = [testCase desc a]+ unitTest2TFTest' desc (TestLabel s t) = unitTest2TFTest' (desc ++ ":" ++ s) t+ unitTest2TFTest' desc (TestList ts) = concat $ map (unitTest2TFTest' desc) ts+ in unitTest2TFTest' "" t+++-- {{{1 uuencode tests+uuTestData =+ [ ("uu", "empty", "", [], uu)+ , ("uu", "\\0", "``", [0], uu)+ , ("uu", "\\255", "_P", [255], uu)+ , ("uu", "AA", "04$", [65, 65], uu)+ , ("uu", "AAA", "04%!", [65, 65, 65], uu)+ , ("uu", "AAAA", "04%!00", [65, 65, 65, 65], uu)+ , ("uu", "Example", "17AA;7!L90", [69,120,97,109,112,108,101], uu)+ ]+uuTests = buildTestList uuTestData++uuTests2 = test+ [ "uu unchop.chop" ~: "EI2" ~=? (unchop uu $ chop uu 1 "EI2")+ , "uu unchop.chop" ~: "EI3-" ~=? (unchop uu $ chop uu 1 "EI3-")+ , "uu unchop.chop" ~: "EI3-EE" ~=? (unchop uu $ chop uu 1 "EI3-EE")+ , "uu full circle" ~: [0..255] ~=? fromJust (decode uu $ unchop uu $ chop uu 1 $ encode uu [0..255])+ , "uu full circle" ~: [0..255] ~=? fromJust (decode uu $ unchop uu $ chop uu 61 $ encode uu [0..255])+ , "uu full circle" ~: [0..255] ~=? fromJust (decode uu $ unchop uu $ chop uu 100 $ encode uu [0..255])+ ]++uuTestsFail = test+ [ "uu decode short" ~: Nothing ~=? decode uu "A"+ , "uu decode' short" ~: [Nothing] ~=? decode' uu "A"+ , "uu decode illegal" ~: Nothing ~=? decode uu "aa"+ , "uu decode' illegal" ~: [Nothing] ~=? decode' uu "aa"+ ]++-- {{{1 xxencode tests+xxTestData =+ [ ("xx", "empty", "", [], xx)+ , ("xx", "\\0", "++", [0], xx)+ , ("xx", "\\255", "zk", [255], xx)+ , ("xx", "AA", "EI2", [65, 65], xx)+ , ("xx", "AAA", "EI3-", [65, 65, 65], xx)+ , ("xx", "AAAA", "EI3-EE", [65, 65, 65, 65], xx)+ , ("xx", "Example", "FLVVPL-gNE", [69,120,97,109,112,108,101], xx)+ ]+xxTests = buildTestList xxTestData++xxTests2 = test+ [ "xx unchop.chop" ~: "EI2" ~=? (unchop xx $ chop xx 1 "EI2")+ , "xx unchop.chop" ~: "EI3-" ~=? (unchop xx $ chop xx 1 "EI3-")+ , "xx unchop.chop" ~: "EI3-EE" ~=? (unchop xx $ chop xx 1 "EI3-EE")+ , "xx full circle" ~: [0..255] ~=? fromJust (decode xx $ unchop xx $ chop xx 1 $ encode xx [0..255])+ , "xx full circle" ~: [0..255] ~=? fromJust (decode xx $ unchop xx $ chop xx 61 $ encode xx [0..255])+ , "xx full circle" ~: [0..255] ~=? fromJust (decode xx $ unchop xx $ chop xx 100 $ encode xx [0..255])+ ]++xxTestsFail = test+ [ "xx decode short" ~: Nothing ~=? decode xx "A"+ , "xx decode' short" ~: [Nothing] ~=? decode' xx "A"+ , "xx decode illegal" ~: Nothing ~=? decode xx "''"+ , "xx decode' illegal" ~: [Nothing] ~=? decode' xx "''"+ ]++-- {{{1 base85 tests+base85TestData =+ [ ("base85", "empty", "", [], base85)+ , ("base85", "f", "Ac", [102], base85)+ , ("base85", "fo", "Ao@", [102,111], base85)+ , ("base85", "foo", "AoDS", [102,111,111], base85)+ , ("base85", "foob", "AoDTs", [102,111,111,98], base85)+ , ("base85", "fooba", "AoDTs@/", [102,111,111,98,97], base85)+ , ("base85", "foobar", "AoDTs@<)", [102,111,111,98,97,114], base85)+ , ("base85", "\0", "!!", [0], base85)+ , ("base85", "foob\0\0\0\0ar", "AoDTszEW", [102,111,111,98,0,0,0,0,114], base85)+ , ("base85", "Example", "7<i6XE,9(", [69,120,97,109,112,108,101], base85)+ ]+base85Tests = buildTestList base85TestData++base85TestsFail = test+ [ "base85 decode short" ~: Nothing ~=? decode base85 "A"+ , "base85 decode' short" ~: [Nothing] ~=? decode' base85 "A"+ , "base85 decode illegal" ~: Nothing ~=? decode base85 "!z"+ , "base85 decode' illegal" ~: [Nothing] ~=? decode' base85 "!z"+ ]++-- {{{1 base64 tests+base64TestData =+ [ ("base64", "empty", "", [], base64)+ , ("base64", "f", "Zg==", [102], base64)+ , ("base64", "fo", "Zm8=", [102,111], base64)+ , ("base64", "foo", "Zm9v", [102,111,111], base64)+ , ("base64", "foob", "Zm9vYg==", [102,111,111,98], base64)+ , ("base64", "fooba", "Zm9vYmE=", [102,111,111,98,97], base64)+ , ("base64", "foobar", "Zm9vYmFy", [102,111,111,98,97,114], base64)+ , ("base64", "\0", "AA==", [0], base64)+ , ("base64", "\255", "/w==", [255], base64)+ , ("base64", "Example", "RXhhbXBsZQ==", [69,120,97,109,112,108,101], base64)+ ]+base64Tests = buildTestList base64TestData++base64TestsFail = test+ [ "base64 decode short" ~: Nothing ~=? decode base64 "A"+ , "base64 decode' short" ~: [Nothing] ~=? decode' base64 "A"+ , "base64 decode illegal" ~: Nothing ~=? decode base64 "!!"+ , "base64 decode' illegal" ~: [Nothing] ~=? decode' base64 "!!"+ ]++-- {{{1 base64url tests+base64UrlTestData =+ [ ("base64url", "empty", "", [], base64Url)+ , ("base64url", "\0", "AA==", [0], base64Url)+ , ("base64url", "\255", "_w==", [255], base64Url)+ , ("base64url", "Example", "RXhhbXBsZQ==", [69,120,97,109,112,108,101], base64Url)+ ]+base64UrlTests = buildTestList base64UrlTestData++-- {{{1 base32 tests+base32TestData =+ [ ("base32", "empty", "", [], base32)+ , ("base32", "f", "MY======", [102], base32)+ , ("base32", "fo", "MZXQ====", [102,111], base32)+ , ("base32", "foo", "MZXW6===", [102,111,111], base32)+ , ("base32", "foob", "MZXW6YQ=", [102,111,111,98], base32)+ , ("base32", "fooba", "MZXW6YTB", [102,111,111,98,97], base32)+ , ("base32", "foobar", "MZXW6YTBOI======", [102,111,111,98,97,114], base32)+ ]+base32Tests = buildTestList base32TestData++base32TestsFail = test+ [ "base32 decode short" ~: Nothing ~=? decode base32 "A"+ , "base32 decode' short" ~: [Nothing] ~=? decode' base32 "A"+ , "base32 decode illegal" ~: Nothing ~=? decode base32 "gh"+ , "base32 decode' illegal" ~: [Nothing] ~=? decode' base32 "gh"+ ]++-- {{{1 base32hex tests+base32HexTestData =+ [ ("base32hex", "empty", "", [], base32Hex)+ , ("base32hex", "f", "CO======", [102], base32Hex)+ , ("base32hex", "fo", "CPNG====", [102,111], base32Hex)+ , ("base32hex", "foo", "CPNMU===", [102,111,111], base32Hex)+ , ("base32hex", "foob", "CPNMUOG=", [102,111,111,98], base32Hex)+ , ("base32hex", "fooba", "CPNMUOJ1", [102,111,111,98,97], base32Hex)+ , ("base32hex", "foobar", "CPNMUOJ1E8======", [102,111,111,98,97,114], base32Hex)+ ]+base32HexTests = buildTestList base32HexTestData++base32HexTestsFail = test+ [ "base32hex decode short" ~: Nothing ~=? decode base32Hex "A"+ , "base32hex decode' short" ~: [Nothing] ~=? decode' base32Hex "A"+ , "base32hex decode illegal" ~: Nothing ~=? decode base32Hex "gh"+ , "base32hex decode' illegal" ~: [Nothing] ~=? decode' base32Hex "gh"+ ]++-- {{{1 base16 (hex)+base16TestData =+ [ ("base16", "empty", "", [], base16)+ , ("base16", "f", "66", [102], base16)+ , ("base16", "fo", "666F", [102,111], base16)+ , ("base16", "foo", "666F6F", [102,111,111], base16)+ , ("base16", "foob", "666F6F62", [102,111,111,98], base16)+ , ("base16", "fooba", "666F6F6261", [102,111,111,98,97], base16)+ , ("base16", "foobar", "666F6F626172", [102,111,111,98,97,114], base16)+ ]+base16Tests = buildTestList base16TestData++base16TestsFail = test+ [ "base16 decode short" ~: Nothing ~=? decode base16 "A"+ , "base16 decode' short" ~: [Nothing] ~=? decode' base16 "A"+ , "base16 decode illegal" ~: Nothing ~=? decode base16 "GH"+ , "base16 decode' illegal" ~: [Nothing] ~=? decode' base16 "GH"+ ]++-- {{{1 yEncoding+yencTests = test+ [ "yEnc encode empty" ~: [] ~=? Yenc.encode []+ , "yEnc decode empty" ~: Just [] ~=? Yenc.decode []+ , "yEnc encode 'f'" ~: [0x90] ~=? Yenc.encode [0x66]+ , "yEnc decode enc('f')" ~: Just [0x66] ~=? Yenc.decode [0x90]+ , "yEnc encode 'foobar'" ~: [0x90, 0x99, 0x99, 0x8c, 0x8b, 0x9c] ~=? Yenc.encode [0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72]+ , "yEnc decode enc('foobar')" ~: Just [0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72] ~=? Yenc.decode [0x90, 0x99, 0x99, 0x8c, 0x8b, 0x9c]+ , "yEnc encode [0xd6, 0xd7]" ~: [0x3d, 0x40, 0x01] ~=? Yenc.encode [0xd6, 0xd7]+ , "yEnc decode enc([0xd6, 0xd7])" ~: Just [0xd6, 0xd7] ~=? Yenc.decode [0x3d, 0x40, 0x01]+ , "yEnc encode criticals" ~: [0x3d, 0x40, 0x3d, 0x4a, 0x3d, 0x4d, 0x3d, 0x7d] ~=? Yenc.encode [0xd6, 0xe0, 0xe3, 0x13]+ , "yEnc decode criticals" ~: Just [0xd6, 0xe0, 0xe3, 0x13] ~=? Yenc.decode [0x3d, 0x40, 0x3d, 0x4a, 0x3d, 0x4d, 0x3d, 0x7d]+ , "yEnc chop" ~: [[0x3d, 0x40], [0x01, 0x3d, 0x4a]] ~=? Yenc.chop 2 [0x3d, 0x40, 0x01, 0x3d, 0x4a]+ ]++-- {{{1 hexadecimal+hexTestData =+ [ ("hex", "empty", "", [], hex)+ , ("hex", "foobar", "666F6F626172", [102,111,111,98,97,114], hex)+ ]+hexTests = buildTestList hexTestData++hexTestsFail = test+ [ "hex decode short" ~: Nothing ~=? decode hex "0"+ , "hex decode' short" ~: [Nothing] ~=? decode' hex "0"+ , "hex decode illegal" ~: Nothing ~=? decode hex "H"+ , "hex decode' illegal" ~: [Nothing] ~=? decode' hex "H"+ ]++-- {{{1 quoted-printable+qpTestData =+ [ ("qp", "empty", "", [], qp)+ , ("qp", "foo=bar", "foo=3Dbar", [102,111,111,61,98,97,114], qp)+ ]+qpTests = buildTestList qpTestData++qpTestsSucc = test+ [ "qp chop one" ~: ["foo=","=3D=","bar"] ~=? chop qp 4 "foo=3Dbar"+ ]++qpTestsFail = test+ [ "qp decode short" ~: Nothing ~=? decode qp "=4"+ , "qp decode' short" ~: [Nothing] ~=? decode' qp "=4"+ , "qp decode non-hex" ~: Nothing ~=? decode qp "=G"+ , "qp decode' non-hex" ~: [Nothing] ~=? decode' qp "=G"+ ]++-- {{{1 python string+pyTestData =+ [ ("py", "empty", "", [], py)+ , ("py", "<0x00><0x1f><0x20><0x7e><0x7f><0xff>", "\\x00\\x1F ~\\x7F\\xFF", [0x00, 0x1f, 0x20, 0x7e, 0x7f, 0xff], py)+ , ("py", "\"\'\\", "\\\"\\'\\\\", [34, 39, 92], py)+ ]+pyTests = buildTestList pyTestData++pyTestsFail = test+ [ "py decode bad char after \\" ~: Nothing ~=? decode py "\\z"+ , "py decode' bad char after \\" ~: [Nothing] ~=? decode' py "\\z"+ ]++-- {{{1 url encoding+urlTestData =+ [ ("url", "empty", "", [], url)+ , ("url", "aA", "aA", [97, 65], url)+ , ("url", "~ ", "~%20", [126, 0x20], url)+ ]+urlTests = buildTestList urlTestData++urlTestsFail = test+ [ "url decode bad char after %" ~: Nothing ~=? decode url "%ga"+ , "url decode' bad char after %" ~: [Nothing] ~=? decode' url "%ga"+ , "url decode bad char after %" ~: Nothing ~=? decode url "%%"+ , "url decode' bad char after %" ~: [Nothing] ~=? decode' url "%%"+ ]++-- {{{1 all the tests+allTests = concat+ [ unitTest2TFTest uuTests+ , unitTest2TFTest uuTests2+ , unitTest2TFTest uuTestsFail+ , unitTest2TFTest xxTests+ , unitTest2TFTest xxTests2+ , unitTest2TFTest xxTestsFail+ , unitTest2TFTest base85Tests+ , unitTest2TFTest base85TestsFail+ , unitTest2TFTest base64Tests+ , unitTest2TFTest base64TestsFail+ , unitTest2TFTest base64UrlTests+ , unitTest2TFTest base32Tests+ , unitTest2TFTest base32TestsFail+ , unitTest2TFTest base32HexTests+ , unitTest2TFTest base32HexTestsFail+ , unitTest2TFTest base16Tests+ , unitTest2TFTest base16TestsFail+ , unitTest2TFTest yencTests+ , unitTest2TFTest hexTests+ , unitTest2TFTest hexTestsFail+ , unitTest2TFTest qpTests+ , unitTest2TFTest qpTestsSucc+ , unitTest2TFTest qpTestsFail+ , unitTest2TFTest pyTests+ , unitTest2TFTest pyTestsFail+ , unitTest2TFTest urlTests+ , unitTest2TFTest urlTestsFail+ ]
+ GNUmakefile view
@@ -0,0 +1,32 @@+.PHONY: all clean markup report test++TESTS = Test+ifeq (,$(shell ghc-pkg list dataenc | grep dataenc))+GHCOPTS = -fhpc -isrc+else+GHCOPTS = -fhpc -hide-package dataenc -isrc+endif+HPC_SUM_OPTS = --exclude=Main --exclude=DataencUT --exclude=DataencQC++% : %.hs+ ghc --make $(GHCOPTS) $<++all: $(TESTS)++test: $(TESTS)+ ./Test++report : test+ hpc6 sum $(HPC_SUM_OPTS) --output test.tix Test.tix+ hpc6 report test.tix++markup : test+ hpc6 sum $(HPC_SUM_OPTS) --output test.tix Test.tix+ hpc6 markup test.tix++clean:+ rm -f *~ Test *.tix *.html *.o *.hi+ rm -rf .hpc+ rm -f src/Codec/Binary/*.o+ rm -f src/Codec/Binary/*.hi+ rm -f src/Codec/Binary/*~
− QC.hs
@@ -1,114 +0,0 @@-{-- - Copyright : (c) 2007 Magnus Therning- - License : BSD3- -}--module Main- where--import Data.Maybe-import Data.Word-import Test.QuickCheck--import qualified Codec.Binary.Uu as Uu-import qualified Codec.Binary.Base85 as Base85-import qualified Codec.Binary.Base64 as Base64-import qualified Codec.Binary.Base64Url as Base64Url-import qualified Codec.Binary.Base32 as Base32-import qualified Codec.Binary.Base32Hex as Base32Hex-import qualified Codec.Binary.Base16 as Base16-import qualified Codec.Binary.Yenc as Yenc---- {{{1 Arbitrary instances-instance Arbitrary Char where- arbitrary = do- n <- choose ((fromEnum (minBound::Char))::Int,- (fromEnum (maxBound::Char))::Int)- return $ toEnum n--instance Arbitrary Word8 where- arbitrary = do- n <- choose ((fromIntegral (minBound::Word8))::Int,- (fromIntegral (maxBound::Word8))::Int)- return $ fromIntegral n---- {{{1 uuencode properties-prop_uuEncode ws = ws == (fromJust . Uu.decode . Uu.encode) ws- where types = ws::[Word8]--prop_uuChop s = properLength s ==> s == (Uu.unchop . Uu.chop 45) s- where- types = s::String- properLength s = length s `mod` 4 /= 1 -- property of uuencode guarantees this--prop_uuCombined ws = ws == (fromJust $ Uu.decode $ Uu.unchop $ Uu.chop 45 $ Uu.encode ws)- where types = ws::[Word8]---- {{{1 base85 properties-prop_base85Encode ws = ws == (fromJust $ Base85.decode $ Base85.encode ws)- where types = ws::[Word8]--prop_base85Chop s = s == (Base85.unchop $ Base85.chop 20 s)- where types = s::String---- {{{1 base64 properties-prop_base64Encode ws = ws == (fromJust $ Base64.decode $ Base64.encode ws)- where types = ws::[Word8]--prop_base64Chop s = s == (Base64.unchop $ Base64.chop 4 s)- where types = s::String---- {{{1 base64url properties-prop_base64UrlEncode ws = ws == (fromJust $ Base64Url.decode $ Base64Url.encode ws)- where types = ws::[Word8]--prop_base64UrlChop s = s == (Base64Url.unchop $ Base64Url.chop 64 s)- where types = s::String---- {{{1 base32-prop_base32Encode ws = ws == (fromJust $ Base32.decode $ Base32.encode ws)- where types = ws::[Word8]--prop_base32Chop s = s == (Base32.unchop $ Base32.chop 8 s)- where types = s::String---- {{{1 base32hex-prop_base32HexEncode ws = ws == (fromJust $ Base32Hex.decode $ Base32Hex.encode ws)- where types = ws::[Word8]--prop_base32HexChop s = s == (Base32Hex.unchop $ Base32Hex.chop 64 s)- where types = s::String---- {{{1 base16-prop_base16Encode ws = ws == (fromJust $ Base16.decode $ Base16.encode ws)- where types = ws::[Word8]--prop_base16Chop s = s == (Base16.unchop $ Base16.chop 6 s)- where types = s::String---- {{{1 yEncoding-prop_yencEncode ws = ws == (fromJust $ Yenc.decode $ Yenc.encode ws)- where types = ws ::[Word8]--prop_yencChop ws = ws == (Yenc.unchop $ Yenc.chop 6 ws)- where types = ws :: [Word8]---- {{{1 main-main = do- quickCheck prop_uuEncode- quickCheck prop_uuChop- quickCheck prop_uuCombined- quickCheck prop_base85Encode- quickCheck prop_base85Chop- quickCheck prop_base64Encode- quickCheck prop_base64Chop- quickCheck prop_base64UrlEncode- quickCheck prop_base64UrlChop- quickCheck prop_base32Encode- quickCheck prop_base32Chop- quickCheck prop_base32HexEncode- quickCheck prop_base32HexChop- quickCheck prop_base16Encode- quickCheck prop_base16Chop- quickCheck prop_yencEncode- quickCheck prop_yencChop
+ Test.hs view
@@ -0,0 +1,19 @@+{-+ - Copyright : (c) 2009 Magnus Therning+ - License : BSD3+ -}++module Main+ where++import Test.Framework++import qualified DataencQC as DQC+import qualified DataencUT as DUT++tests =+ [ testGroup "quickcheck" DQC.allTests+ , testGroup "unit test" DUT.allTests+ ]++main = defaultMain tests
− UT.hs
@@ -1,186 +0,0 @@-{-- - Copyright : (c) 2007 Magnus Therning- - License : BSD3- -}--module Main- where--import Test.HUnit-import Control.Monad-import System.Exit-import Data.Maybe--import Codec.Binary.DataEncoding-import qualified Codec.Binary.Yenc as Yenc---- {{{1 buildTestList--- builds a list of successful tests based on a tuple (suite, description,--- encoded data, decoded data, codec)-buildTestList td = TestList $ concat- [[ TestLabel (suite ++ " encode " ++ desc) (enc ~=? (encode codec dec))- , TestLabel (suite ++ " decode " ++ desc) (dec ~=? (fromJust $ decode codec $ enc))] - | (suite, desc, enc, dec, codec) <- td ]---- {{{1 uuencode tests-uuTestData =- [ ("uu", "empty", "", [], uu)- , ("uu", "\0", "``", [0], uu)- , ("uu", "\255", "_P", [255], uu)- , ("uu", "Example", "17AA;7!L90", [69,120,97,109,112,108,101], uu)- ]-uuTests = buildTestList uuTestData--uuTests2 = test- [ "chop . encode Example" ~: ["'17AA;7!L90"] ~=? (chop uu 61 . encode uu) [69,120,97,109,112,108,101]- , "decode . unchop Example" ~: [69,120,97,109,112,108,101] ~=? fromJust ((decode uu . unchop uu) ["'17AA;7!L90"])- ]--uuTestsFail = test- [ "uu decode short" ~: Nothing ~=? decode uu "A"- , "uu decode' short" ~: [Nothing] ~=? decode' uu "A"- , "uu decode illegal" ~: Nothing ~=? decode uu "aa"- , "uu decode' illegal" ~: [Nothing] ~=? decode' uu "aa"- ]---- {{{1 base85 tests-base85TestData =- [ ("base85", "empty", "", [], base85)- , ("base85", "f", "Ac", [102], base85)- , ("base85", "fo", "Ao@", [102,111], base85)- , ("base85", "foo", "AoDS", [102,111,111], base85)- , ("base85", "foob", "AoDTs", [102,111,111,98], base85)- , ("base85", "fooba", "AoDTs@/", [102,111,111,98,97], base85)- , ("base85", "foobar", "AoDTs@<)", [102,111,111,98,97,114], base85)- , ("base85", "\0", "!!", [0], base85)- , ("base85", "foob\0\0\0\0ar", "AoDTszEW", [102,111,111,98,0,0,0,0,114], base85)- , ("base85", "Example", "7<i6XE,9(", [69,120,97,109,112,108,101], base85)- ]-base85Tests = buildTestList base85TestData--base85TestsFail = test- [ "base85 decode short" ~: Nothing ~=? decode base85 "A"- , "base85 decode' short" ~: [Nothing] ~=? decode' base85 "A"- , "base85 decode illegal" ~: Nothing ~=? decode base85 "!z"- , "base85 decode' illegal" ~: [Nothing] ~=? decode' base85 "!z"- ]---- {{{1 base64 tests-base64TestData =- [ ("base64", "empty", "", [], base64)- , ("base64", "f", "Zg==", [102], base64)- , ("base64", "fo", "Zm8=", [102,111], base64)- , ("base64", "foo", "Zm9v", [102,111,111], base64)- , ("base64", "foob", "Zm9vYg==", [102,111,111,98], base64)- , ("base64", "fooba", "Zm9vYmE=", [102,111,111,98,97], base64)- , ("base64", "foobar", "Zm9vYmFy", [102,111,111,98,97,114], base64)- , ("base64", "\0", "AA==", [0], base64)- , ("base64", "\255", "/w==", [255], base64)- , ("base64", "Example", "RXhhbXBsZQ==", [69,120,97,109,112,108,101], base64)- ]-base64Tests = buildTestList base64TestData--base64TestsFail = test- [ "base64 decode short" ~: Nothing ~=? decode base64 "A"- , "base64 decode' short" ~: [Nothing] ~=? decode' base64 "A"- , "base64 decode illegal" ~: Nothing ~=? decode base64 "!!"- , "base64 decode' illegal" ~: [Nothing] ~=? decode' base64 "!!"- ]---- {{{1 base64url tests-base64UrlTestData =- [ ("base64url", "empty", "", [], base64Url)- , ("base64url", "\0", "AA==", [0], base64Url)- , ("base64url", "\255", "_w==", [255], base64Url)- , ("base64url", "Example", "RXhhbXBsZQ==", [69,120,97,109,112,108,101], base64Url)- ]-base64UrlTests = buildTestList base64UrlTestData---- {{{1 base32 tests-base32TestData =- [ ("base32", "empty", "", [], base32)- , ("base32", "f", "MY======", [102], base32)- , ("base32", "fo", "MZXQ====", [102,111], base32)- , ("base32", "foo", "MZXW6===", [102,111,111], base32)- , ("base32", "foob", "MZXW6YQ=", [102,111,111,98], base32)- , ("base32", "fooba", "MZXW6YTB", [102,111,111,98,97], base32)- , ("base32", "foobar", "MZXW6YTBOI======", [102,111,111,98,97,114], base32)- ]-base32Tests = buildTestList base32TestData--base32TestsFail = test- [ "base32 decode short" ~: Nothing ~=? decode base32 "A"- , "base32 decode' short" ~: [Nothing] ~=? decode' base32 "A"- , "base32 decode illegal" ~: Nothing ~=? decode base32 "gh"- , "base32 decode' illegal" ~: [Nothing] ~=? decode' base32 "gh"- ]---- {{{1 base32hex tests-base32HexTestData =- [ ("base32hex", "empty", "", [], base32Hex)- , ("base32hex", "f", "CO======", [102], base32Hex)- , ("base32hex", "fo", "CPNG====", [102,111], base32Hex)- , ("base32hex", "foo", "CPNMU===", [102,111,111], base32Hex)- , ("base32hex", "foob", "CPNMUOG=", [102,111,111,98], base32Hex)- , ("base32hex", "fooba", "CPNMUOJ1", [102,111,111,98,97], base32Hex)- , ("base32hex", "foobar", "CPNMUOJ1E8======", [102,111,111,98,97,114], base32Hex)- ]-base32HexTests = buildTestList base32HexTestData--base32HexTestsFail = test- [ "base32hex decode short" ~: Nothing ~=? decode base32Hex "A"- , "base32hex decode' short" ~: [Nothing] ~=? decode' base32Hex "A"- , "base32hex decode illegal" ~: Nothing ~=? decode base32Hex "gh"- , "base32hex decode' illegal" ~: [Nothing] ~=? decode' base32Hex "gh"- ]---- {{{1 base16 (hex)-base16TestData =- [ ("base16", "empty", "", [], base16)- , ("base16", "f", "66", [102], base16)- , ("base16", "fo", "666F", [102,111], base16)- , ("base16", "foo", "666F6F", [102,111,111], base16)- , ("base16", "foob", "666F6F62", [102,111,111,98], base16)- , ("base16", "fooba", "666F6F6261", [102,111,111,98,97], base16)- , ("base16", "foobar", "666F6F626172", [102,111,111,98,97,114], base16)- ]-base16Tests = buildTestList base16TestData--base16TestsFail = test- [ "base16 decode short" ~: Nothing ~=? decode base16 "A"- , "base16 decode' short" ~: [Nothing] ~=? decode' base16 "A"- , "base16 decode illegal" ~: Nothing ~=? decode base16 "GH"- , "base16 decode' illegal" ~: [Nothing] ~=? decode' base16 "GH"- ]---- {{{1 yEncoding-yencTests = test- [ "yEnc encode empty" ~: [] ~=? Yenc.encode []- , "yEnc decode empty" ~: Just [] ~=? Yenc.decode []- , "yEnc encode 'f'" ~: [0x90] ~=? Yenc.encode [0x66]- , "yEnc decode enc('f')" ~: Just [0x66] ~=? Yenc.decode [0x90]- , "yEnc encode 'foobar'" ~: [0x90, 0x99, 0x99, 0x8c, 0x8b, 0x9c] ~=? Yenc.encode [0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72]- , "yEnc decode enc('foobar')" ~: Just [0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72] ~=? Yenc.decode [0x90, 0x99, 0x99, 0x8c, 0x8b, 0x9c]- , "yEnc encode [0xd6, 0xd7]" ~: [0x3d, 0x40, 0x01] ~=? Yenc.encode [0xd6, 0xd7]- , "yEnc decode enc([0xd6, 0xd7])" ~: Just [0xd6, 0xd7] ~=? Yenc.decode [0x3d, 0x40, 0x01]- , "yEnc encode criticals" ~: [0x3d, 0x40, 0x3d, 0x4a, 0x3d, 0x4d, 0x3d, 0x7d] ~=? Yenc.encode [0xd6, 0xe0, 0xe3, 0x13]- , "yEnc decode criticals" ~: Just [0xd6, 0xe0, 0xe3, 0x13] ~=? Yenc.decode [0x3d, 0x40, 0x3d, 0x4a, 0x3d, 0x4d, 0x3d, 0x7d]- , "yEnc chop" ~: [[0x3d, 0x40], [0x01, 0x3d, 0x4a]] ~=? Yenc.chop 2 [0x3d, 0x40, 0x01, 0x3d, 0x4a]- ]---- {{{1 test list and main-testList = TestList- [ uuTests, uuTests2, uuTestsFail- , base85Tests, base85TestsFail- , base64Tests, base64TestsFail- , base64UrlTests- , base32Tests, base32TestsFail- , base32HexTests, base32HexTestsFail- , base16Tests, base16TestsFail- , yencTests- ]--main :: IO ()-main = do- counts <- runTestTT testList- when ((errors counts, failures counts) /= (0, 0)) $ exitWith (ExitFailure 1)
dataenc.cabal view
@@ -1,5 +1,5 @@ name: dataenc-version: 0.12+version: 0.12.1.0 license: BSD3 license-file: LICENSE cabal-version: >= 1.2@@ -7,30 +7,30 @@ author: Magnus Therning maintainer: magnus@therning.org homepage: http://www.haskell.org/haskellwiki/Library/Data_encoding-copyright: Magnus Therning, 2007+copyright: Magnus Therning, 2007-2009 category: Codec synopsis: Data encoding library description: Data encoding library currently providing Uuencode, Base64, Base64Url, Base32, Base32Hex, Base16, Base85, and yEncoding.-extra-source-files: UT.hs QC.hs--flag large_base- description: Choose the old larger, monolithic base package.- default: False+extra-source-files: DataencUT.hs DataencQC.hs Test.hs GNUmakefile library hs-source-dirs: src- if flag(large_base)- build-depends: base- else- build-depends: array, base, containers+ build-depends: array >= 0.2.0 && < 0.3, base >= 4.0.0 && < 4.1, containers >= 0.2.0 && < 0.3 exposed-modules:- Codec.Binary.DataEncoding Codec.Binary.Base16- Codec.Binary.Base32Hex Codec.Binary.Base32- Codec.Binary.Uu- Codec.Binary.Base64Url+ Codec.Binary.Base32Hex Codec.Binary.Base64+ Codec.Binary.Base64Url Codec.Binary.Base85+ Codec.Binary.DataEncoding+ Codec.Binary.Hexadecimal+ Codec.Binary.PythonString+ Codec.Binary.QuotedPrintable+ Codec.Binary.Url+ Codec.Binary.Uu+ Codec.Binary.Xx Codec.Binary.Yenc+ other-modules:+ Codec.Binary.Util
src/Codec/Binary/Base85.hs view
@@ -47,12 +47,12 @@ encode (0:0:0:0:bs) = "z" ++ encode bs encode (b1:b2:b3:b4:bs) = (foldr (\ i s -> (encodeArray ! i) : s) "" group) ++ (encode bs) where- group2Int :: Int- group2Int = foldl (\ a b -> a `shiftL` 8 + (fromIntegral b)) 0 [b1, b2, b3, b4]- encodeInt2Ints :: Int -> [Word8]- encodeInt2Ints = map fromIntegral . map (`mod` 85) . take 5 . iterate (`div` 85)+ group2Word32 :: Word32+ group2Word32 = foldl (\ a b -> a `shiftL` 8 + (fromIntegral b)) 0 [b1, b2, b3, b4]+ encodeWord32ToWord8s :: Word32 -> [Word8]+ encodeWord32ToWord8s = map fromIntegral . map (`mod` 85) . take 5 . iterate (`div` 85) adjustNReverse = reverse . map (+ 33)- group = (adjustNReverse .encodeInt2Ints) group2Int+ group = (adjustNReverse .encodeWord32ToWord8s) group2Word32 -- {{{1 decode -- | Decode data (lazy).@@ -70,11 +70,11 @@ dec l@[Just c1, Just c2, Just c3, Just c4] = take 3 . dec $ l ++ pad 1 dec l@[Just c1, Just c2, Just c3, Just c4, Just c5] = let adjRev = map (flip (-) 33) [c5, c4, c3, c2, c1]- group2Int :: [Word8] -> Int- group2Int = foldl1 (+) . map (uncurry (*)) . zip (map (85 ^) [0..4]) . map fromIntegral- int2Group :: Int -> [Maybe Word8]- int2Group = map Just . map fromIntegral . reverse . take 4 . iterate (`div` 256)- in (int2Group . group2Int) adjRev+ group2Word32 :: [Word8] -> Word32+ group2Word32 = foldl1 (+) . map (uncurry (*)) . zip (map (85 ^) [0..4]) . map fromIntegral+ word32ToGroup :: Word32 -> [Maybe Word8]+ word32ToGroup = map Just . map fromIntegral . reverse . take 4 . iterate (`div` 256)+ in (word32ToGroup . group2Word32) adjRev dec _ = [Nothing] in (dec . map (flip M.lookup decodeMap) $ take 5 cs) ++ decode' (drop 5 cs)
src/Codec/Binary/DataEncoding.hs view
@@ -11,18 +11,23 @@ -- <http://www.haskell.org/haskellwiki/Library/Data_encoding>. module Codec.Binary.DataEncoding ( DataCodec- , encode- , decode- , decode'- , chop- , unchop , base16 , base32 , base32Hex , base64 , base64Url , base85+ , chop+ , decode+ , decode'+ , encode+ , hex+ , py+ , qp+ , unchop+ , url , uu+ , xx ) where @@ -34,7 +39,12 @@ import qualified Codec.Binary.Base64 as Base64 import qualified Codec.Binary.Base64Url as Base64Url import qualified Codec.Binary.Base85 as Base85+import qualified Codec.Binary.Url as Url import qualified Codec.Binary.Uu as Uu+import qualified Codec.Binary.Xx as Xx+import qualified Codec.Binary.Hexadecimal as Hex+import qualified Codec.Binary.QuotedPrintable as QP+import qualified Codec.Binary.PythonString as Py -- {{{1 DataCodec -- | Used to group a specific data encoding's functions.@@ -129,3 +139,63 @@ chop=Uu.chop, unchop=Uu.unchop }++-- {{{1 xx+-- | Xxencoding, see "Codec.Binary.Xx" for more details on the+-- individual functions.+xx :: DataCodec+xx = DataCodec {+ encode=Xx.encode,+ decode=Xx.decode,+ decode'=Xx.decode',+ chop=Xx.chop,+ unchop=Xx.unchop+}++-- {{{1 hexadecimal+-- | Hexadecimal, see "Codec.Binary.Hexadecimal" for more details on the+-- individual functions.+hex :: DataCodec+hex = DataCodec+ { encode = Hex.encode+ , decode = Hex.decode+ , decode' = Hex.decode'+ , chop = Hex.chop+ , unchop = Hex.unchop+ }++-- {{{1 quoted-printable+-- | Quoted-printable, see "Codec.Binary.QuotedPrintable" for more details on+-- the individual functions.+qp :: DataCodec+qp = DataCodec+ { encode = QP.encode+ , decode = QP.decode+ , decode' = QP.decode'+ , chop = QP.chop+ , unchop = QP.unchop+ }++-- {{{1 python string+-- | Quoted-printable, see "Codec.Binary.PythonString" for more details on+-- the individual functions.+py :: DataCodec+py = DataCodec+ { encode = Py.encode+ , decode = Py.decode+ , decode' = Py.decode'+ , chop = Py.chop+ , unchop = Py.unchop+ }++-- {{{1 url encoding+-- | URL encoding, see "Codec.Binary.Url" for more details on the individual+-- functions.+url :: DataCodec+url = DataCodec+ { encode = Url.encode+ , decode = Url.decode+ , decode' = Url.decode'+ , chop = Url.chop+ , unchop = Url.unchop+ }
+ src/Codec/Binary/Hexadecimal.hs view
@@ -0,0 +1,56 @@+-- |+-- Module : Codec.Binary.Hexadecimal+-- Copyright : (c) 2009 Magnus Therning+-- License : BSD3+--+-- Simple hexadecimal encoding.+--+-- Further documentation and information can be found at+-- <http://www.haskell.org/haskellwiki/Library/Data_encoding>.+module Codec.Binary.Hexadecimal+ ( encode+ , decode+ , decode'+ , chop+ , unchop+ ) where++import Data.Word++import Codec.Binary.Util++-- {{{1 encode+-- | Encode data. Each nibble of the byte is converted into one character in+-- [0-9A-F].+encode :: [Word8]+ -> String+encode [] = ""+encode (o:os) = toHex o ++ encode os++-- {{{1 decode+-- | Decode data (lazy).+decode' :: String+ -> [Maybe Word8]+decode' "" = []+decode' (hn:ln:cs) = fromHex [hn, ln] : decode' cs+decode' _ = [Nothing]++-- | Decode data (strict).+decode :: String -> Maybe [Word8]+decode = sequence . decode'++-- {{{1 chop+-- | Chop up a string in parts.+chop :: Int -- ^ length of individual lines+ -> String+ -> [String]+chop n "" = []+chop n s = let+ enc_len | n < 2 = 2+ | otherwise = n `div` 2 * 2+ in (take enc_len s) : chop n (drop enc_len s)++-- {{{1 unchop+-- | Concatenate the list of strings into one long string.+unchop :: [String] -> String+unchop = foldr (++) ""
+ src/Codec/Binary/PythonString.hs view
@@ -0,0 +1,86 @@+-- |+-- Module : Codec.Binary.PythonString+-- Copyright : (c) 2009 Magnus Therning+-- License : BSD3+--+-- Implementation of python escaping.+--+-- This implementation encodes non-printable characters (0x00-0x1f, 0x7f-0xff)+-- to hex-value characters ('\xhh') while leaving printable characters as such:+--+-- @+-- \> encode [0, 10, 13, 110]+-- \"\\\\x00\\\\x0A\\\\x0Dn\"+-- \> putStrLn $ encode [0, 10, 13, 110]+-- \\x00\\x0A\\x0Dn+-- @+--+-- It also properly handles escaping of a few characters that require it:+--+-- @+-- \> encode [34, 39, 92]+-- \"\\\\\\\"\\\\\'\\\\\\\\\"+-- putStrLn $ encode [34, 39, 92]+-- \\\"\\'\\\\+-- @+--+-- Further documentation and information can be found at+-- <http://www.haskell.org/haskellwiki/Library/Data_encoding>.+module Codec.Binary.PythonString+ ( encode+ , decode+ , decode'+ , chop+ , unchop+ ) where++import Data.Char+import Data.Word++import Codec.Binary.Util++-- {{{1 encode+-- | Encode data.+encode :: [Word8]+ -> String+encode [] = ""+encode (o:os)+ | o < 0x20 || o > 0x7e = ('\\' : 'x' : toHex o) ++ encode os+ | o == 34 = "\\\"" ++ encode os+ | o == 39 = "\\'" ++ encode os+ | o == 92 = "\\\\" ++ encode os+ | otherwise = chr (fromIntegral o) : encode os++-- {{{1 decode+-- -- | Decode data (lazy).+decode' :: String+ -> [Maybe Word8]+decode' [] = []+decode' ('\\':'x':c0:c1:cs) = fromHex [c0, c1] : decode' cs+decode' ('\\':'\\':cs) = (Just $ fromIntegral $ ord '\\') : decode' cs+decode' ('\\':'\'':cs) = (Just $ fromIntegral $ ord '\'') : decode' cs+decode' ('\\':'\"':cs) = (Just $ fromIntegral $ ord '\"') : decode' cs+decode' (c:cs)+ | c /= '\\' = (Just $ fromIntegral $ ord c) : decode' cs+ | otherwise = [Nothing]++-- | Decode data (strict).+decode :: String -> Maybe [Word8]+decode = sequence . decode'++-- {{{1 chop+-- | Chop up a string in parts.+chop :: Int -- ^ length of individual lines (values @\< 1@ are ignored)+ -> String+ -> [String]+chop n = let+ _n = max 1 n+ _chop [] = []+ _chop cs = take _n cs : (_chop $ drop _n cs)+ in _chop++-- {{{1 unchop+-- | Concatenate the list of strings into one long string.+unchop :: [String]+ -> String+unchop = foldr (++) ""
+ src/Codec/Binary/QuotedPrintable.hs view
@@ -0,0 +1,79 @@+-- |+-- Module : Codec.Binary.QuotedPrintable+-- Copyright : (c) 2009 Magnus Therning+-- License : BSD3+--+-- Implementation of Quoted-Printable based on RFC 2045+-- (<http://tools.ietf.org/html/rfc2045>).+--+-- This encoding encodes _everything_ that is passed in, it will not try to+-- guess the native line ending for your architecture. In other words, if you+-- are using this to encode text you need to split it into separate lines+-- before encoding and chopping it up.+--+-- Further documentation and information can be found at+-- <http://www.haskell.org/haskellwiki/Library/Data_encoding>.+module Codec.Binary.QuotedPrintable+ ( encode+ , decode+ , decode'+ , chop+ , unchop+ ) where++import Data.Char+import Data.Word++import Codec.Binary.Util++-- {{{1 encode+-- | Encode data.+encode :: [Word8]+ -> String+encode [] = ""+encode (o:os)+ | o < 33 || o == 61 || o > 126 = ('=' : toHex o) ++ encode os+ | otherwise = chr (fromIntegral o) : encode os+++-- {{{1 decode+-- -- | Decode data (lazy).+decode' :: String+ -> [Maybe Word8]+decode' [] = []+decode' ('=':c0:c1:cs) = fromHex [c0, c1] : decode' cs+decode' (c:cs)+ | c /= '=' = (Just $ fromIntegral $ ord c) : decode' cs+ | otherwise = [Nothing]++-- | Decode data (strict).+decode :: String -> Maybe [Word8]+decode = sequence . decode'++-- {{{1 chop+-- | Chop up a string in parts.+chop :: Int -- ^ length of individual lines (values @\< 4@ are ignored)+ -> String+ -> [String]+chop n "" = []+chop n s = let+ n' = max 3 $ n - 1+ _c i ts "" acc = ts : acc+ _c i ts tss@('=':tss') acc+ | i + 2 < n' = _c (i + 1) ('=' : ts) tss' acc+ | otherwise = _c 0 "" tss (('=' : ts) : acc)+ _c i ts tss@(c:tss') acc+ | i < n' = _c (i + 1) (c : ts) tss' acc+ | otherwise = _c 0 "" tss (('=' : ts) : acc)+ in map reverse . reverse $ _c 0 "" s []++-- {{{1 unchop+-- | Concatenate the list of strings into one long string.+unchop :: [String] -> String+unchop [] = ""+unchop (s:ss) = let+ dropLast = last s == '='+ len = length s+ in if dropLast+ then (take (len - 1) s) ++ (unchop ss)+ else s ++ (unchop ss)
+ src/Codec/Binary/Url.hs view
@@ -0,0 +1,76 @@+-- |+-- Module : Codec.Binary.Url+-- Copyright : (c) 2009 Magnus Therning+-- License : BSD3+--+-- URL encoding, sometimes referred to as URI encoding or percent encoding.+-- Implemented based on RFC 3986 (<http://tools.ietf.org/html/rfc3986>).+--+-- Further documentation and information can be found at+-- <http://www.haskell.org/haskellwiki/Library/Data_encoding>.++module Codec.Binary.Url+ ( encode+ , decode+ , decode'+ , chop+ , unchop+ ) where++import qualified Data.Map as M+import Data.Char(ord)+import Data.Word(Word8)++import Codec.Binary.Util(toHex,fromHex)++_unreservedChars = (zip [65..90] "ABCDEFGHIJKLMNOPQRSTUVWXYZ")+ ++ (zip [97..122] "abcdefghijklmnopqrstuvwxyz")+ ++ (zip [48..57] "0123456789")+ ++ [(45, '-'), (95, '_'), (46, '.'), (126, '~')]++encodeMap :: M.Map Word8 Char+encodeMap = M.fromList _unreservedChars++decodeMap :: M.Map Char Word8+decodeMap = M.fromList [(b, a) | (a, b) <- _unreservedChars]++-- {{{1 encode+-- | Encode data.+encode :: [Word8]+ -> String+encode [] = ""+encode (o:os) = case (M.lookup o encodeMap) of+ Just c -> c : encode os+ Nothing -> ('%' : toHex o) ++ encode os++-- {{{1 decode+-- | Decode data (lazy).+decode' :: String+ -> [Maybe Word8]+decode' [] = []+decode' ('%':c0:c1:cs) = fromHex [c0, c1] : decode' cs+decode' (c:cs)+ | c /= '%' = (Just $ fromIntegral $ ord c) : decode' cs+ | otherwise = [Nothing]++-- | Decode data (strict).+decode :: String+ -> Maybe [Word8]+decode = sequence . decode'++-- {{{1 chop+-- | Chop up a string in parts.+chop :: Int -- ^ length of individual lines+ -> String+ -> [String]+chop n = let+ _n = max 1 n+ _chop [] = []+ _chop cs = take _n cs : (_chop $ drop _n cs)+ in _chop++-- {{{1 unchop+-- | Concatenate the strings into one long string+unchop :: [String]+ -> String+unchop = foldr (++) ""
+ src/Codec/Binary/Util.hs view
@@ -0,0 +1,41 @@+-- |+-- Module : Codec.Binary.Util+-- Copyright : (c) 2009 Magnus Therning+-- License : BSD3+--+-- Utility functions used in the other module.+module Codec.Binary.Util+ ( toHex+ , fromHex+ ) where++import Data.Array+import Data.Bits+import Data.Char+import Data.Word+import qualified Data.Map as M++-- {{{1 hex enc/dec assoc list and maps+hexEncMap = zip [0..] "0123456789ABCDEF"++hexEncodeArray :: Array Word8 Char+hexEncodeArray = array (0, 16) hexEncMap++hexDecodeMap :: M.Map Char Word8+hexDecodeMap = M.fromList [(b, a) | (a, b) <- hexEncMap]++-- {{{1 toHex+toHex :: Word8 -> String+toHex o = let+ hn = o `shiftR` 4+ ln = o .&. 0xf+ in [hexEncodeArray ! hn, hexEncodeArray ! ln]++-- {{{1 fromHex+fromHex :: String -> Maybe Word8+fromHex = let+ dec [Just hn, Just ln] = let+ o = hn `shiftL` 4 .|. ln+ in Just o+ dec _ = Nothing+ in dec . map ((flip M.lookup hexDecodeMap) . toUpper)
src/Codec/Binary/Uu.hs view
@@ -25,20 +25,7 @@ import qualified Data.Map as M -- {{{1 enc/dec map-_encMap =- [ (0, '`'), (1, '!'), (2, '"'), (3, '#'), (4, '$')- , (5, '%'), (6, '&'), (7, '\''), (8, '('), (9, ')')- , (10, '*'), (11, '+'), (12, ','), (13, '-'), (14, '.')- , (15, '/'), (16, '0'), (17, '1'), (18, '2'), (19, '3')- , (20, '4'), (21, '5'), (22, '6'), (23, '7'), (24, '8')- , (25, '9'), (26, ':'), (27, ';'), (28, '<'), (29, '=')- , (30, '>'), (31, '?'), (32, '@'), (33, 'A'), (34, 'B')- , (35, 'C'), (36, 'D'), (37, 'E'), (38, 'F'), (39, 'G')- , (40, 'H'), (41, 'I'), (42, 'J'), (43, 'K'), (44, 'L')- , (45, 'M'), (46, 'N'), (47, 'O'), (48, 'P'), (49, 'Q')- , (50, 'R'), (51, 'S'), (52, 'T'), (53, 'U') ,(54, 'V')- , (55, 'W'), (56, 'X'), (57, 'Y'), (58, 'Z'), (59, '[')- , (60, '\\'), (61, ']'), (62, '^'), (63, '_') ]+_encMap = zip [0..] "`!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" -- {{{1 encodeArray encodeArray :: Array Word8 Char@@ -94,18 +81,19 @@ -- -- /Notes:/ ----- * The length of the strings in the result will be @(n -1) `div` 4 * 4@.--- The @-1@ comes from the need to prepend the length. Keeping it to a--- multiple of 4 means that strings returned from 'encode' can be chopped--- without requiring any changes.+-- * The length of the strings in the result will be @(n -1) `div` 4 * 4 ++-- 1@. The @-1@ comes from the need to prepend the length (which explains+-- the final @+1@). Keeping it to a multiple of 4 means that strings+-- returned from 'encode' can be chopped without requiring any changes. -- -- * The length of lines in GNU's sharutils is 61.-chop :: Int -- ^ length (@1 < n <= 65@, not checked)+chop :: Int -- ^ length (value should be in the range @[5..85]@) -> String -> [String] chop n "" = [] chop n s = let- enc_len | n < 5 = 4+ enc_len | n < 5 = 4+ | n >= 85 = 84 | otherwise = (n - 1) `div` 4 * 4 enc_line = take enc_len s act_len = fromIntegral $ case (length enc_line `divMod` 4) of
+ src/Codec/Binary/Xx.hs view
@@ -0,0 +1,119 @@+-- |+-- Module : Codec.Binary.Xx+-- Copyright : (c) 2007 Magnus Therning+-- License : BSD3+--+-- Xxencoding is obsolete but still included for completeness. Further+-- information on the encoding can be found at+-- <http://en.wikipedia.org/wiki/Xxencode>. It should be noted that this+-- implementation performs no padding, due to the splitting up between encoding+-- and chopping.+--+-- Further documentation and information can be found at+-- <http://www.haskell.org/haskellwiki/Library/Data_encoding>.+module Codec.Binary.Xx+ ( encode+ , decode+ , decode'+ , chop+ , unchop+ ) where++import Control.Monad+import Data.Array+import Data.Bits+import Data.Maybe+import Data.Word+import qualified Data.Map as M++-- {{{1 enc/dec map+_encMap = zip [0..] "+-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"++-- {{{1 encodeArray+encodeArray :: Array Word8 Char+encodeArray = array (0, 64) _encMap++-- {{{1 decodeMap+decodeMap :: M.Map Char Word8+decodeMap = M.fromList [(snd i, fst i) | i <- _encMap]++-- {{{1 encode+-- | Encode data.+encode :: [Word8]+ -> String+encode = let+ pad n = take n $ repeat 0+ enc [] = ""+ enc l@[o] = take 2 . enc $ l ++ pad 2+ enc l@[o1, o2] = take 3 . enc $ l ++ pad 1+ enc (o1:o2:o3:os) = let+ i1 = o1 `shiftR` 2+ i2 = (o1 `shiftL` 4 .|. o2 `shiftR` 4) .&. 0x3f+ i3 = (o2 `shiftL` 2 .|. o3 `shiftR` 6) .&. 0x3f+ i4 = o3 .&. 0x3f+ in (foldr (\ i s -> (encodeArray ! i) : s) "" [i1, i2, i3, i4]) ++ enc os+ in enc++-- {{{1 decode+-- | Decode data (lazy).+decode' :: String+ -> [Maybe Word8]+decode' = let+ pad n = take n . repeat $ Just 0+ dec [] = []+ dec l@[Just eo1, Just eo2] = take 1 . dec $ l ++ pad 2+ dec l@[Just eo1, Just eo2, Just eo3] = take 2 . dec $ l ++ pad 1+ dec (Just eo1:Just eo2:Just eo3:Just eo4:eos) = let+ o1 = eo1 `shiftL` 2 .|. eo2 `shiftR` 4+ o2 = eo2 `shiftL` 4 .|. eo3 `shiftR` 2+ o3 = eo3 `shiftL` 6 .|. eo4+ in Just o1:Just o2:Just o3:(dec eos)+ dec _ = [Nothing]+ in+ dec . map (flip M.lookup decodeMap)++-- | Decode data (strict).+decode :: String+ -> Maybe [Word8]+decode = sequence . decode'++-- {{{1 chop+-- | Chop up a string in parts. Each string in the resulting list is prepended+-- with the length according to the xxencode \"specificiation\".+--+-- /Notes:/+--+-- * The length of the strings in the result will be @(n -1) `div` 4 * 4 ++-- 1@. The @-1@ comes from the need to prepend the length (which explains+-- the final @+1@). Keeping it to a multiple of 4 means that strings+-- returned from 'encode' can be chopped without requiring any changes.+chop :: Int -- ^ length (value should be in the range @[5..85]@)+ -> String+ -> [String]+chop n "" = []+chop n s = let+ enc_len | n < 5 = 4+ | n >= 85 = 84+ | otherwise = min 64 $ (n - 1) `div` 4 * 4+ enc_line = take enc_len s+ act_len = fromIntegral $ case (length enc_line `divMod` 4) of+ (l, 0) -> l * 3+ (l, 2) -> l * 3 + 1+ (l, 3) -> l * 3 + 2+ len = (encodeArray ! act_len)+ in (len : enc_line) : chop n (drop enc_len s)++-- {{{1 unchop+-- | Concatenate the strings into one long string. Each string is assumed to+-- be prepended with the length according to the xxencode specification.+unchop :: [String]+ -> String+unchop ss = let+ singleUnchop (l:cs) = let+ act_len = fromIntegral $ decodeMap M.! l+ enc_len = case (act_len `divMod` 3) of+ (n, 0) -> n * 4+ (n, 1) -> n * 4 + 2+ (n, 2) -> n * 4 + 3+ in take enc_len cs+ in foldr (\ s res -> (singleUnchop s) ++ res) "" ss
src/Codec/Binary/Yenc.hs view
@@ -50,11 +50,12 @@ -> [[Word8]] chop _ [] = [] chop n ws = let- (p1, p2) = splitAt n ws+ _n = max n 1+ (p1, p2) = splitAt _n ws in if (last p1 == _equal)- then (p1 ++ (take 1 p2)) : chop n (drop 1 p2)- else p1 : chop n p2+ then (p1 ++ (take 1 p2)) : chop _n (drop 1 p2)+ else p1 : chop _n p2 -- {{{1 unchop -- | Concatenate the strings into one long string.