base91 0.1.0 → 0.1.1
raw patch · 6 files changed
+87/−204 lines, 6 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Codec.Binary.Base91: alphabet :: [Char]
+ Codec.Binary.Base91: decodeBy :: LeftFold (Int, Int, Int, o) Char s -> (o -> [Word8] -> o) -> o -> s -> o
+ Codec.Binary.Base91: encodeBy :: LeftFold (Int, Int, o) Word8 s -> (o -> [Char] -> o) -> o -> s -> o
Files
- Codec/Binary/Base91.hs +56/−5
- Codec/Binary/Base91/ByteString.hs +6/−49
- Codec/Binary/Base91/Efficient.hs +5/−49
- Codec/Binary/Base91/String.hs +7/−48
- Codec/Binary/Base91/Text.hs +7/−49
- base91.cabal +6/−4
Codec/Binary/Base91.hs view
@@ -1,12 +1,63 @@ -- Copyright 2015 Alvaro J. Genial (http://alva.ro) -- see LICENSE.md for more. -- Informed by Mario Rodriguez's C++ implementation. -module Codec.Binary.Base91 (decoding, encoding) where+module Codec.Binary.Base91 (alphabet, decodeBy, encodeBy) where +import Data.Bits ((.&.), (.|.), shiftL, shiftR)+import Data.Char (ord) import Data.Word (Word8) -encoding :: [Char]-encoding = [++type LeftFold a b c = (a -> b -> a) -> a -> c -> a+++encodeBy :: LeftFold (Int, Int, o) Word8 s -> (o -> [Char] -> o) -> o -> s -> o+encodeBy fold append empty source = g . fold f (0, 0, empty) $ source where++--f :: (Int, Int, o) -> Word8 -> (Int, Int, o)+ f (queue, nbits, output) w =+ let queue' = queue .|. (fromIntegral w `shiftL` nbits)+ nbits' = nbits + 8+ in if nbits' <= 13 then (queue', nbits', output) else+ let val = queue' .&. 8191+ val' = queue' .&. 16383+ (v, q, n) = if val > 88+ then (val, queue' `shiftR` 13, nbits' - 13)+ else (val', queue' `shiftR` 14, nbits' - 14)+ trail = [alphabet !! (v `mod` 91),+ alphabet !! (v `div` 91)]+ in (q, n, append output trail)++--g :: (Int, Int, o) -> o+ g (_, 0, output) = output+ g (queue, nbits, output) = append output (y:z)+ where y = alphabet !! (queue `mod` 91)+ z | nbits > 7 || queue > 90 = [alphabet !! (queue `div` 91)]+ | otherwise = []++decodeBy :: LeftFold (Int, Int, Int, o) Char s -> (o -> [Word8] -> o) -> o -> s -> o+decodeBy fold append empty source = g . fold f (0, 0, -1, empty) $ source where++--f :: (Int, Int, Int, o) -> Char -> (Int, Int, Int, o)+ f (queue, nbits, val, output) c =+ let d = fromIntegral $ octets !! ord c+ in if d == 91 then (queue, nbits, val, output) else+ if val == -1 then (queue, nbits, d, output) else+ let v = val + (d * 91)+ q = queue .|. (v `shiftL` nbits)+ n = nbits + (if (v .&. 8191) > 88 then 13 else 14)+ (queue', nbits', trail) = if n - 8 > 7+ then (q `shiftR` 16, n - 16, [q, q `shiftR` 8])+ else (q `shiftR` 8, n - 8, [q])+ in (queue', nbits', -1, append output $ map fromIntegral trail)++--g :: (Int, Int, Int, o) -> o+ g (_, _, -1, output) = output+ g (queue, nbits, val, output) = append output [fromIntegral $ queue .|. (val `shiftL` nbits)]++-- | The list of valid characters within a Base91-encoded string.+alphabet :: [Char]+alphabet = [ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',@@ -15,8 +66,8 @@ '%', '&', '(', ')', '*', '+', ',', '.', '/', ':', ';', '<', '=', '>', '?', '@', '[', ']', '^', '_', '`', '{', '|', '}', '~', '"'] -decoding :: [Word8]-decoding = [+octets :: [Word8]+octets = [ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 62, 90, 63, 64, 65, 66, 91, 67, 68, 69, 70, 71, 91, 72, 73,
Codec/Binary/Base91/ByteString.hs view
@@ -1,58 +1,15 @@ -- Copyright 2015 Alvaro J. Genial (http://alva.ro) -- see LICENSE.md for more.--- Informed by Mario Rodriguez's C++ implementation. module Codec.Binary.Base91.ByteString (decode, encode) where -import qualified Codec.Binary.Base91 as B91-import Data.Bits ((.&.), (.|.), shiftL, shiftR)-import Data.Char (ord)-import Data.List (foldl')-import Data.Word (Word8)-import Data.ByteString (ByteString)+import Codec.Binary.Base91 (decodeBy, encodeBy) import qualified Data.ByteString as BS+import qualified Data.List as L -- | Encodes octets ('ByteString') to a '[Char]' in Base91; the opposite of 'decode'.-encode :: ByteString -> [Char]-encode = g . BS.foldl' f (0, 0, []) where-- f :: (Int, Int, [Char]) -> Word8 -> (Int, Int, [Char])- f (queue, nbits, cs) w =- let queue' = queue .|. (fromIntegral w `shiftL` nbits)- nbits' = nbits + 8- in if nbits' <= 13 then (queue', nbits', cs) else- let val = queue' .&. 8191- val' = queue' .&. 16383- (v, q, n) = if val > 88- then (val, queue' `shiftR` 13, nbits' - 13)- else (val', queue' `shiftR` 14, nbits' - 14)- trail = [B91.encoding !! (v `mod` 91),- B91.encoding !! (v `div` 91)]- in (q, n, cs ++ trail)-- g :: (Int, Int, [Char]) -> [Char]- g (_, 0, cs) = cs- g (queue, nbits, cs) = cs ++ [y] ++ z- where y = B91.encoding !! (queue `mod` 91)- z | nbits > 7 || queue > 90 = [B91.encoding !! (queue `div` 91)]- | otherwise = []+encode :: BS.ByteString -> [Char]+encode = encodeBy BS.foldl' (++) [] -- | Decodes octets ('ByteString') from a '[Char]' in Base91; the opposite of 'encode'.-decode :: [Char] -> ByteString-decode = g . foldl' f (0, 0, -1, BS.empty) where-- f :: (Int, Int, Int, ByteString) -> Char -> (Int, Int, Int, ByteString)- f (queue, nbits, val, bs) c =- let d = fromIntegral $ B91.decoding !! ord c- in if d == 91 then (queue, nbits, val, bs) else- if val == -1 then (queue, nbits, d, bs) else- let v = val + (d * 91)- q = queue .|. (v `shiftL` nbits)- n = nbits + (if (v .&. 8191) > 88 then 13 else 14)- (queue', nbits', trail) = if n - 8 > 7- then (q `shiftR` 16, n - 16, [q, q `shiftR` 8])- else (q `shiftR` 8, n - 8, [q])- in (queue', nbits', -1, BS.append bs $ BS.pack (map fromIntegral trail))-- g :: (Int, Int, Int, ByteString) -> ByteString- g (_, _, -1, bs) = bs- g (queue, nbits, val, bs) = BS.snoc bs (fromIntegral $ queue .|. (val `shiftL` nbits))+decode :: [Char] -> BS.ByteString+decode = decodeBy L.foldl' (\bs -> BS.append bs . BS.pack) BS.empty
Codec/Binary/Base91/Efficient.hs view
@@ -1,59 +1,15 @@ -- Copyright 2015 Alvaro J. Genial (http://alva.ro) -- see LICENSE.md for more.--- Informed by Mario Rodriguez's C++ implementation. module Codec.Binary.Base91.Efficient (decode, encode) where -import qualified Codec.Binary.Base91 as B91-import Data.Bits ((.&.), (.|.), shiftL, shiftR)-import Data.Char (ord)-import Data.Word (Word8)-import Data.ByteString (ByteString)+import Codec.Binary.Base91 (decodeBy, encodeBy) import qualified Data.ByteString as BS-import Data.Text (Text) import qualified Data.Text as T -- | Encodes octets ('ByteString') to 'Text' in Base91; the opposite of 'decode'.-encode :: ByteString -> Text-encode = g . BS.foldl' f (0, 0, T.empty) where-- f :: (Int, Int, Text) -> Word8 -> (Int, Int, Text)- f (queue, nbits, t) w =- let queue' = queue .|. (fromIntegral w `shiftL` nbits)- nbits' = nbits + 8- in if nbits' <= 13 then (queue', nbits', t) else- let val = queue' .&. 8191- val' = queue' .&. 16383- (v, q, n) = if val > 88- then (val, queue' `shiftR` 13, nbits' - 13)- else (val', queue' `shiftR` 14, nbits' - 14)- trail = [B91.encoding !! (v `mod` 91),- B91.encoding !! (v `div` 91)]- in (q, n, T.append t (T.pack trail))-- g :: (Int, Int, Text) -> Text- g (_, 0, t) = t- g (queue, nbits, t) = T.append t (T.pack $ [y] ++ z)- where y = B91.encoding !! (queue `mod` 91)- z | nbits > 7 || queue > 90 = [B91.encoding !! (queue `div` 91)]- | otherwise = []+encode :: BS.ByteString -> T.Text+encode = encodeBy BS.foldl' (\t -> T.append t . T.pack) T.empty -- | Decodes octets ('ByteString') from 'Text' in Base91; the opposite of 'encode'.-decode :: Text -> ByteString-decode = g . T.foldl' f (0, 0, -1, BS.empty) where-- f :: (Int, Int, Int, ByteString) -> Char -> (Int, Int, Int, ByteString)- f (queue, nbits, val, bs) c =- let d = fromIntegral $ B91.decoding !! ord c- in if d == 91 then (queue, nbits, val, bs) else- if val == -1 then (queue, nbits, d, bs) else- let v = val + (d * 91)- q = queue .|. (v `shiftL` nbits)- n = nbits + (if (v .&. 8191) > 88 then 13 else 14)- (queue', nbits', trail) = if n - 8 > 7- then (q `shiftR` 16, n - 16, [q, q `shiftR` 8])- else (q `shiftR` 8, n - 8, [q])- in (queue', nbits', -1, BS.append bs $ BS.pack (map fromIntegral trail))-- g :: (Int, Int, Int, ByteString) -> ByteString- g (_, _, -1, bs) = bs- g (queue, nbits, val, bs) = BS.snoc bs (fromIntegral $ queue .|. (val `shiftL` nbits))+decode :: T.Text -> BS.ByteString+decode = decodeBy T.foldl' (\bs -> BS.append bs . BS.pack) BS.empty
Codec/Binary/Base91/String.hs view
@@ -1,56 +1,15 @@ -- Copyright 2015 Alvaro J. Genial (http://alva.ro) -- see LICENSE.md for more.--- Informed by Mario Rodriguez's C++ implementation. module Codec.Binary.Base91.String (decode, encode) where -import qualified Codec.Binary.Base91 as B91-import Data.Bits ((.&.), (.|.), shiftL, shiftR)-import Data.Char (ord)-import Data.List (foldl')-import Data.Word (Word8)+import Codec.Binary.Base91 (decodeBy, encodeBy)+import qualified Data.List as L+import qualified Data.Word as W -- | Encodes octets ('[Word8]') to a 'String' in Base91; the opposite of 'decode'.-encode :: [Word8] -> String-encode = g . foldl' f (0, 0, []) where-- f :: (Int, Int, [Char]) -> Word8 -> (Int, Int, [Char])- f (queue, nbits, cs) w =- let queue' = queue .|. (fromIntegral w `shiftL` nbits)- nbits' = nbits + 8- in if nbits' <= 13 then (queue', nbits', cs) else- let val = queue' .&. 8191- val' = queue' .&. 16383- (v, q, n) = if val > 88- then (val, queue' `shiftR` 13, nbits' - 13)- else (val', queue' `shiftR` 14, nbits' - 14)- trail = [B91.encoding !! (v `mod` 91),- B91.encoding !! (v `div` 91)]- in (q, n, cs ++ trail)-- g :: (Int, Int, [Char]) -> [Char]- g (_, 0, cs) = cs- g (queue, nbits, cs) = cs ++ [y] ++ z- where y = B91.encoding !! (queue `mod` 91)- z | nbits > 7 || queue > 90 = [B91.encoding !! (queue `div` 91)]- | otherwise = []+encode :: [W.Word8] -> String+encode = encodeBy L.foldl' (++) [] -- | Decodes octets ('[Word8]') from a 'String' in Base91; the opposite of 'encode'.-decode :: String -> [Word8]-decode = g . foldl' f (0, 0, -1, []) where-- f :: (Int, Int, Int, [Word8]) -> Char -> (Int, Int, Int, [Word8])- f (queue, nbits, val, ws) c =- let d = fromIntegral $ B91.decoding !! ord c- in if d == 91 then (queue, nbits, val, ws) else- if val == -1 then (queue, nbits, d, ws) else- let v = val + (d * 91)- q = queue .|. (v `shiftL` nbits)- n = nbits + (if (v .&. 8191) > 88 then 13 else 14)- (queue', nbits', trail) = if n - 8 > 7- then (q `shiftR` 16, n - 16, [q, q `shiftR` 8])- else (q `shiftR` 8, n - 8, [q])- in (queue', nbits', -1, ws ++ map fromIntegral trail)-- g :: (Int, Int, Int, [Word8]) -> [Word8]- g (_, _, -1, ws) = ws- g (queue, nbits, val, ws) = ws ++ [fromIntegral $ queue .|. (val `shiftL` nbits)]+decode :: String -> [W.Word8]+decode = decodeBy L.foldl' (++) []
Codec/Binary/Base91/Text.hs view
@@ -1,58 +1,16 @@ -- Copyright 2015 Alvaro J. Genial (http://alva.ro) -- see LICENSE.md for more.--- Informed by Mario Rodriguez's C++ implementation. module Codec.Binary.Base91.Text (decode, encode) where -import qualified Codec.Binary.Base91 as B91-import Data.Bits ((.&.), (.|.), shiftL, shiftR)-import Data.Char (ord)-import Data.List (foldl')-import Data.Word (Word8)-import Data.Text (Text)+import Codec.Binary.Base91 (decodeBy, encodeBy)+import qualified Data.List as L import qualified Data.Text as T+import qualified Data.Word as W -- | Encodes octets ('[Word8]') to 'Text' in Base91; the opposite of 'decode'.-encode :: [Word8] -> Text-encode = g . foldl' f (0, 0, T.empty) where-- f :: (Int, Int, Text) -> Word8 -> (Int, Int, Text)- f (queue, nbits, t) w =- let queue' = queue .|. (fromIntegral w `shiftL` nbits)- nbits' = nbits + 8- in if nbits' <= 13 then (queue', nbits', t) else- let val = queue' .&. 8191- val' = queue' .&. 16383- (v, q, n) = if val > 88- then (val, queue' `shiftR` 13, nbits' - 13)- else (val', queue' `shiftR` 14, nbits' - 14)- trail = [B91.encoding !! (v `mod` 91),- B91.encoding !! (v `div` 91)]- in (q, n, T.append t (T.pack trail))-- g :: (Int, Int, Text) -> Text- g (_, 0, t) = t- g (queue, nbits, t) = T.append t (T.pack $ [y] ++ z)- where y = B91.encoding !! (queue `mod` 91)- z | nbits > 7 || queue > 90 = [B91.encoding !! (queue `div` 91)]- | otherwise = []+encode :: [W.Word8] -> T.Text+encode = encodeBy L.foldl' (\t -> T.append t . T.pack) T.empty -- | Decodes octets ('[Word8]') from 'Text' in Base91; the opposite of 'encode'.-decode :: Text -> [Word8]-decode = g . T.foldl' f (0, 0, -1, []) where-- f :: (Int, Int, Int, [Word8]) -> Char -> (Int, Int, Int, [Word8])- f (queue, nbits, val, ws) c =- let d = fromIntegral $ B91.decoding !! ord c- in if d == 91 then (queue, nbits, val, ws) else- if val == -1 then (queue, nbits, d, ws) else- let v = val + (d * 91)- q = queue .|. (v `shiftL` nbits)- n = nbits + (if (v .&. 8191) > 88 then 13 else 14)- (queue', nbits', trail) = if n - 8 > 7- then (q `shiftR` 16, n - 16, [q, q `shiftR` 8])- else (q `shiftR` 8, n - 8, [q])- in (queue', nbits', -1, ws ++ map fromIntegral trail)-- g :: (Int, Int, Int, [Word8]) -> [Word8]- g (_, _, -1, ws) = ws- g (queue, nbits, val, ws) = ws ++ [fromIntegral $ queue .|. (val `shiftL` nbits)]+decode :: T.Text -> [W.Word8]+decode = decodeBy T.foldl' (++) []
base91.cabal view
@@ -1,10 +1,13 @@ Name: base91-Version: 0.1.0+Version: 0.1.1 Author: Alvaro J. Genial Maintainer: ajg Homepage: https://github.com/ajg/base91 Synopsis: A Base91 encoder & decoder-Description: An implementation of Base91 encoding & decoding of bytes to/from strings.+Description: An implementation of Base91 encoding & decoding of arbitrary bytes (octets)+ to/from characters (all in the ASCII printable range; it includes support for+ plain Strings, as well as optional support for ByteString and/or Text; see+ the Flags section for details. License: MIT License-File: LICENSE.md Category: Codec@@ -21,8 +24,7 @@ Library Build-Depends: base >= 4 && < 5- Exposed-Modules: Codec.Binary.Base91.String- Other-Modules: Codec.Binary.Base91+ Exposed-Modules: Codec.Binary.Base91, Codec.Binary.Base91.String if flag(ByteString) Build-Depends: bytestring