diff options
Diffstat (limited to 'src/Codec/Binary/Yenc.hs')
-rw-r--r-- | src/Codec/Binary/Yenc.hs | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/src/Codec/Binary/Yenc.hs b/src/Codec/Binary/Yenc.hs new file mode 100644 index 0000000..526d9fe --- /dev/null +++ b/src/Codec/Binary/Yenc.hs | |||
@@ -0,0 +1,83 @@ | |||
1 | -- | | ||
2 | -- Module : Codec.Binary.Yenc | ||
3 | -- Copyright : (c) 2007 Magnus Therning | ||
4 | -- License : BSD3 | ||
5 | -- | ||
6 | -- Implementation based on the specification found at | ||
7 | -- <http://yence.sourceforge.net/docs/protocol/version1_3_draft.html>. | ||
8 | -- | ||
9 | -- Further documentation and information can be found at | ||
10 | -- <http://www.haskell.org/haskellwiki/Library/Data_encoding>. | ||
11 | module Codec.Binary.Yenc | ||
12 | ( EncIncData(..) | ||
13 | , EncIncRes(..) | ||
14 | , encodeInc | ||
15 | , encode | ||
16 | , DecIncData(..) | ||
17 | , DecIncRes(..) | ||
18 | , decodeInc | ||
19 | , decode | ||
20 | , chop | ||
21 | , unchop | ||
22 | ) where | ||
23 | |||
24 | import Codec.Binary.Util | ||
25 | |||
26 | import Data.Word | ||
27 | |||
28 | _criticalsIn = [0xd6, 0xe0, 0xe3, 0x13] | ||
29 | _equal = 0x3d | ||
30 | |||
31 | -- {{{1 encode | ||
32 | -- | Incremental encoder function. | ||
33 | encodeInc :: EncIncData -> EncIncRes [Word8] | ||
34 | encodeInc e = eI e | ||
35 | where | ||
36 | enc [] = [] | ||
37 | enc (o:os) | ||
38 | | o `elem` _criticalsIn = _equal : o + 106 : enc os | ||
39 | | otherwise = o + 42 : enc os | ||
40 | |||
41 | eI EDone = EFinal [] | ||
42 | eI (EChunk bs) = EPart (enc bs) encodeInc | ||
43 | |||
44 | -- | Encode data. | ||
45 | encode :: [Word8] -> [Word8] | ||
46 | encode = encoder encodeInc | ||
47 | |||
48 | -- {{{1 decode | ||
49 | -- | Incremental decoder function. | ||
50 | decodeInc :: DecIncData [Word8] -> DecIncRes [Word8] | ||
51 | decodeInc d = dI [] d | ||
52 | where | ||
53 | dI [] DDone = DFinal [] [] | ||
54 | dI lo DDone = DFail [] lo | ||
55 | dI lo (DChunk s) = doDec [] (lo ++ s) | ||
56 | where | ||
57 | doDec acc (0x3d:d:ds) = doDec (acc ++ [d + 150]) ds | ||
58 | doDec acc (d:ds) = doDec (acc ++ [d + 214]) ds | ||
59 | doDec acc s' = DPart acc (dI s') | ||
60 | |||
61 | -- | Decode data. | ||
62 | decode :: [Word8] -> Maybe [Word8] | ||
63 | decode = decoder decodeInc | ||
64 | |||
65 | -- {{{1 chop | ||
66 | -- | Chop up a string in parts. | ||
67 | chop :: Int -- ^ length of individual lines | ||
68 | -> [Word8] | ||
69 | -> [[Word8]] | ||
70 | chop _ [] = [] | ||
71 | chop n ws = let | ||
72 | _n = max n 1 | ||
73 | (p1, p2) = splitAt _n ws | ||
74 | in | ||
75 | if last p1 == _equal | ||
76 | then (p1 ++ take 1 p2) : chop _n (drop 1 p2) | ||
77 | else p1 : chop _n p2 | ||
78 | |||
79 | -- {{{1 unchop | ||
80 | -- | Concatenate the strings into one long string. | ||
81 | unchop :: [[Word8]] | ||
82 | -> [Word8] | ||
83 | unchop = concat | ||