packages feed

base91 (empty) → 0.1.0

raw patch · 9 files changed

+390/−0 lines, 9 filesdep +QuickCheckdep +basedep +base91setup-changed

Dependencies added: QuickCheck, base, base91, bytestring, text

Files

+ Codec/Binary/Base91.hs view
@@ -0,0 +1,35 @@+-- 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++import Data.Word (Word8)++encoding :: [Char]+encoding = [+  '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',+  'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',+  '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '!', '#', '$',+  '%', '&', '(', ')', '*', '+', ',', '.', '/', ':', ';', '<', '=',+  '>', '?', '@', '[', ']', '^', '_', '`', '{', '|', '}', '~', '"']++decoding :: [Word8]+decoding = [+  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,+  52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 74, 75, 76, 77, 78, 79,+  80,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,+  15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 81, 91, 82, 83, 84,+  85, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,+  41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 86, 87, 88, 89, 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,+  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, 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, 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]
+ Codec/Binary/Base91/ByteString.hs view
@@ -0,0 +1,58 @@+-- 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 qualified Data.ByteString as BS++-- | 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               = []++-- | 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))
+ Codec/Binary/Base91/Efficient.hs view
@@ -0,0 +1,59 @@+-- 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 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               = []++-- | 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))
+ Codec/Binary/Base91/String.hs view
@@ -0,0 +1,56 @@+-- 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)++-- | 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               = []++-- | 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)]
+ Codec/Binary/Base91/Text.hs view
@@ -0,0 +1,58 @@+-- 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 qualified Data.Text as T++-- | 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               = []++-- | 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)]
+ LICENSE.md view
@@ -0,0 +1,20 @@+The MIT License (MIT)++Copyright (c) 2015 Alvaro J. Genial++Permission is hereby granted, free of charge, to any person obtaining a copy of+this software and associated documentation files (the "Software"), to deal in+the Software without restriction, including without limitation the rights to+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of+the Software, and to permit persons to whom the Software is furnished to do so,+subject to the following conditions:++The above copyright notice and this permission notice shall be included in all+copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ Setup.hs view
@@ -0,0 +1,4 @@+-- Copyright 2015 Alvaro J. Genial (http://alva.ro) -- see LICENSE.md for more.++import Distribution.Simple+main = defaultMain
+ Test.hs view
@@ -0,0 +1,54 @@+-- Copyright 2015 Alvaro J. Genial (http://alva.ro) -- see LICENSE.md for more.++import Codec.Binary.Base91.ByteString as A (decode, encode)+import Codec.Binary.Base91.Efficient  as B (decode, encode)+import Codec.Binary.Base91.String     as C (decode, encode)+import Codec.Binary.Base91.Text       as D (decode, encode)+import qualified Data.ByteString as BS+import qualified Data.Text as T+import Test.QuickCheck++main :: IO ()+main = do+    testByteString+    testEfficient+    testString+    testText where++  -- Note that the reverse identities, e.g. encode (decode cs) == cs, aren't true because not every+  -- arbitrary character sequence is valid Base91, even if each character is constrained to the+  -- Base91 alphabet.++  testByteString = do+      quickCheck $ prop_identity+      quickCheck $ example ([], [])+      quickCheck $ example helloWorld+    where+      prop_identity ws = A.decode (A.encode bs) == bs           where bs = BS.pack ws+      example (ws, cs) = A.encode bs == cs && A.decode cs == bs where bs = BS.pack ws++  testEfficient = do+      quickCheck $ prop_identity+      quickCheck $ example ([], [])+      quickCheck $ example helloWorld+    where+      prop_identity ws = B.decode (B.encode bs) == bs          where bs = BS.pack ws+      example (ws, cs) = B.encode bs == t && B.decode t  == bs where (bs, t) = (BS.pack ws, T.pack cs)++  testString = do+      quickCheck $ prop_identity+      quickCheck $ example ([], [])+      quickCheck $ example helloWorld+    where+      prop_identity ws = C.decode (C.encode ws) == ws+      example (ws, cs) = C.encode ws == cs && C.decode cs == ws++  testText = do+      quickCheck $ prop_identity+      quickCheck $ example ([], [])+      quickCheck $ example helloWorld+    where+      prop_identity ws = D.decode (D.encode ws) == ws+      example (ws, cs) = D.encode ws == t && D.decode t == ws where t = T.pack cs++  helloWorld = ([72,101,108,108,111,44,32,119,111,114,108,100,33], ">OwJh>}A\"=r@@Y?F") -- Hello, World!
+ base91.cabal view
@@ -0,0 +1,46 @@+Name:                  base91+Version:               0.1.0+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.+License:               MIT+License-File:          LICENSE.md+Category:              Codec+Build-Type:            Simple+Cabal-Version:         >= 1.8++Flag ByteString+  Description:         Enable Data.ByteString support.+  Default:             True++Flag Text+  Description:         Enable Data.Text support.+  Default:             True++Library+  Build-Depends:       base >= 4 && < 5+  Exposed-Modules:     Codec.Binary.Base91.String+  Other-Modules:       Codec.Binary.Base91++  if flag(ByteString)+    Build-Depends:     bytestring+    Exposed-Modules:   Codec.Binary.Base91.ByteString++  if flag(Text)+    Build-Depends:     text+    Exposed-Modules:   Codec.Binary.Base91.Text++  if flag(ByteString) && flag(Text)+    Exposed-Modules:   Codec.Binary.Base91.Efficient++Test-Suite tests+  Hs-Source-Dirs:      .+  Main-Is:             Test.hs+  Type:                exitcode-stdio-1.0+  Build-Depends:       base, base91, bytestring, text, QuickCheck++Source-Repository head+  type:                git+  location:            https://github.com/ajg/base91/tree/master