packages feed

base64-bytestring 0.1.0.3 → 0.1.1.0

raw patch · 5 files changed

+360/−211 lines, 5 filesdep +HUnitdep +QuickCheckdep +base64-bytestringdep ~basedep ~bytestringPVP ok

version bump matches the API change (PVP)

Dependencies added: HUnit, QuickCheck, base64-bytestring, containers, test-framework, test-framework-hunit, test-framework-quickcheck2

Dependency ranges changed: base, bytestring

API changes (from Hackage documentation)

+ Data.ByteString.Base64.URL: decode :: ByteString -> Either String ByteString
+ Data.ByteString.Base64.URL: decodeLenient :: ByteString -> ByteString
+ Data.ByteString.Base64.URL: encode :: ByteString -> ByteString
+ Data.ByteString.Base64.URL: joinWith :: ByteString -> Int -> ByteString -> ByteString

Files

Data/ByteString/Base64.hs view
@@ -19,226 +19,35 @@     , joinWith     ) where -import Data.Bits ((.|.), (.&.), shiftL, shiftR)+import Data.ByteString.Base64.Internal import qualified Data.ByteString as B-import Data.ByteString.Internal (ByteString(..), mallocByteString, memcpy,-                                 unsafeCreate)-import Data.Word (Word8, Word16, Word32)-import Foreign.ForeignPtr (ForeignPtr, withForeignPtr, castForeignPtr)-import Foreign.Ptr (Ptr, castPtr, minusPtr, plusPtr)-import Foreign.Storable (peek, peekElemOff, poke)-import System.IO.Unsafe (unsafePerformIO)--peek8 :: Ptr Word8 -> IO Word8-peek8 = peek--poke8 :: Ptr Word8 -> Word8 -> IO ()-poke8 = poke--peek8_32 :: Ptr Word8 -> IO Word32-peek8_32 = fmap fromIntegral . peek8+import Data.ByteString.Internal (ByteString(..))+import Data.Word (Word8)+import Foreign.ForeignPtr (ForeignPtr)  -- | Encode a string into base64 form.  The result will always be a -- multiple of 4 bytes in length. encode :: ByteString -> ByteString-encode (PS sfp soff slen)-    | slen > maxBound `div` 4 =-        error "Data.ByteString.Base64.encode: input too long"-    | otherwise = unsafePerformIO $ do-  let dlen = ((slen + 2) `div` 3) * 4-  dfp <- mallocByteString dlen-  withForeignPtr alfaFP $ \aptr ->-    withForeignPtr encodeTable $ \ep ->-      withForeignPtr sfp $ \sptr -> do-        let aidx n = peek8 (aptr `plusPtr` n)-            sEnd = sptr `plusPtr` (slen + soff)-            fill !dp !sp-              | sp `plusPtr` 2 >= sEnd = complete (castPtr dp) sp-              | otherwise = {-# SCC "encode/fill" #-} do-              i <- peek8_32 sp-              j <- peek8_32 (sp `plusPtr` 1)-              k <- peek8_32 (sp `plusPtr` 2)-              let w = (i `shiftL` 16) .|. (j `shiftL` 8) .|. k-                  enc = peekElemOff ep . fromIntegral-              poke dp =<< enc (w `shiftR` 12)-              poke (dp `plusPtr` 2) =<< enc (w .&. 0xfff)-              fill (dp `plusPtr` 4) (sp `plusPtr` 3)-            complete dp sp-                | sp == sEnd = return ()-                | otherwise  = {-# SCC "encode/complete" #-} do-              let peekSP n f = (f . fromIntegral) `fmap` peek8 (sp `plusPtr` n)-                  twoMore    = sp `plusPtr` 2 == sEnd-                  equals     = 0x3d :: Word8-                  {-# INLINE equals #-}-              a <- peekSP 0 ((`shiftR` 2) . (.&. 0xfc))-              b <- peekSP 0 ((`shiftL` 4) . (.&. 0x03))-              !b' <- if twoMore-                     then peekSP 1 ((.|. b) . (`shiftR` 4) . (.&. 0xf0))-                     else return b-              poke8 dp =<< aidx a-              poke8 (dp `plusPtr` 1) =<< aidx b'-              c <- if twoMore-                   then aidx =<< peekSP 1 ((`shiftL` 2) . (.&. 0x0f))-                   else return equals-              poke8 (dp `plusPtr` 2) c-              poke8 (dp `plusPtr` 3) equals-        withForeignPtr dfp $ \dptr ->-          fill (castPtr dptr) (sptr `plusPtr` soff)-  return $! PS dfp 0 dlen---- | Efficiently intersperse a terminator string into another at--- regular intervals, and terminate the input with it.------ Examples:------ > joinWith "|" 2 "----" = "--|--|"------ > joinWith "\r\n" 3 "foobarbaz" = "foo\r\nbar\r\nbaz\r\n"-joinWith :: ByteString  -- ^ String to intersperse and end with-         -> Int         -- ^ Interval at which to intersperse, in bytes-         -> ByteString  -- ^ String to transform-         -> ByteString-joinWith brk@(PS bfp boff blen) every bs@(PS sfp soff slen)-    | every <= 0 = error "invalid interval"-    | blen <= 0  = bs-    | B.null bs = brk-    | otherwise =-  unsafeCreate dlen $ \dptr ->-    withForeignPtr bfp $ \bptr -> do-      withForeignPtr sfp $ \sptr -> do-          let bp = bptr `plusPtr` boff-          let dEnd = dptr `plusPtr` dlen-              loop !dp !sp | dp >= dEnd = return ()-                           | otherwise = do-                let n = min every (dEnd `minusPtr` dp)-                memcpy dp sp (fromIntegral n)-                memcpy (dp `plusPtr` n) bp (fromIntegral blen)-                loop (dp `plusPtr` (n + blen)) (sp `plusPtr` every)-          loop dptr (sptr `plusPtr` soff)-  where dlen = slen + blen * numBreaks-        numBreaks = slen `div` every+encode = encodeWithAlphabet alphabet  -- | Decode a base64-encoded string.  This function strictly follows -- the specification in RFC 4648, -- <http://www.apps.ietf.org/rfc/rfc4648.html>. decode :: ByteString -> Either String ByteString-decode (PS sfp soff slen)-    | drem /= 0 = Left "invalid padding"-    | dlen <= 0 = Right B.empty-    | otherwise = unsafePerformIO $ do-  dfp <- mallocByteString dlen-  withForeignPtr decodeFP $ \decptr -> do-    let finish dbytes = return . Right $! if dbytes > 0-                                          then PS dfp 0 dbytes-                                          else B.empty-        bail = return . Left-    withForeignPtr sfp $ \sptr -> do-      let sEnd = sptr `plusPtr` (slen + soff)-          look p = do-            ix <- fromIntegral `fmap` peek8 p-            v <- peek8 (decptr `plusPtr` ix)-            return $! fromIntegral v :: IO Word32-          fill !dp !sp !n-            | sp >= sEnd = finish n-            | otherwise = {-# SCC "decode/fill" #-} do-            a <- look sp-            b <- look (sp `plusPtr` 1)-            c <- look (sp `plusPtr` 2)-            d <- look (sp `plusPtr` 3)-            let w = (a `shiftL` 18) .|. (b `shiftL` 12) .|.-                    (c `shiftL` 6) .|. d-            if a == done || b == done-              then bail $ "invalid padding near offset " ++-                   show (sp `minusPtr` sptr)-              else if a .|. b .|. c .|. d == x-              then bail $ "invalid base64 encoding near offset " ++-                   show (sp `minusPtr` sptr)-              else do-                poke8 dp $ fromIntegral (w `shiftR` 16)-                if c == done-                  then finish $ n + 1-                  else do-                    poke8 (dp `plusPtr` 1) $ fromIntegral (w `shiftR` 8)-                    if d == done-                      then finish $! n + 2-                      else do-                        poke8 (dp `plusPtr` 2) $ fromIntegral w-                        fill (dp `plusPtr` 3) (sp `plusPtr` 4) (n+3)-      withForeignPtr dfp $ \dptr ->-        fill dptr (sptr `plusPtr` soff) 0-  where (di,drem) = slen `divMod` 4-        dlen = di * 3--data D = D { dNext :: {-# UNPACK #-} !(Ptr Word8)-           , dValue :: {-# UNPACK #-} !Word32 }+decode = decodeWithTable decodeFP  -- | Decode a base64-encoded string.  This function is lenient in -- following the specification from RFC 4648, -- <http://www.apps.ietf.org/rfc/rfc4648.html>, and will not generate -- parse errors no matter how poor its input. decodeLenient :: ByteString -> ByteString-decodeLenient (PS sfp soff slen)-    | dlen <= 0 = B.empty-    | otherwise = unsafePerformIO $ do-  dfp <- mallocByteString dlen-  dbytes <- withForeignPtr decodeFP $ \decptr ->-    withForeignPtr sfp $ \sptr -> do-      let sEnd = sptr `plusPtr` (slen + soff)-          fill !dp !sp !n-            | sp >= sEnd = return n-            | otherwise = {-# SCC "decodeLenient/fill" #-} do-            let look skipPad = go-                  where-                    go p | p >= sEnd = return $! D (sEnd `plusPtr` (-1)) done-                         | otherwise =  {-# SCC "decodeLenient/look" #-} do-                      ix <- fromIntegral `fmap` peek8 p-                      v <- peek8 (decptr `plusPtr` ix)-                      if v == x || (v == done && skipPad)-                        then go (p `plusPtr` 1)-                        else return $! D (p `plusPtr` 1) (fromIntegral v)-            !a <- look True  sp-            !b <- look True  (dNext a)-            !c <- look False (dNext b)-            !d <- look False (dNext c)-            let w = (dValue a `shiftL` 18) .|. (dValue b `shiftL` 12) .|.-                    (dValue c `shiftL` 6) .|. dValue d-            if dValue a == done || dValue b == done-              then return n-              else do-                poke8 dp $ fromIntegral (w `shiftR` 16)-                if dValue c == done-                  then return $! n + 1-                  else do-                    poke8 (dp `plusPtr` 1) $ fromIntegral (w `shiftR` 8)-                    if dValue d == done-                      then return $! n + 2-                      else do-                        poke8 (dp `plusPtr` 2) $ fromIntegral w-                        fill (dp `plusPtr` 3) (dNext d) (n+3)-      withForeignPtr dfp $ \dptr ->-        fill dptr (sptr `plusPtr` soff) 0-  return $! if dbytes > 0-            then PS dfp 0 dbytes-            else B.empty-  where dlen = ((slen + 3) `div` 4) * 3+decodeLenient = decodeLenientWithTable decodeFP + alphabet :: ByteString-alfaFP :: ForeignPtr Word8-alphabet@(PS alfaFP _ _) = B.pack $ [65..90] ++ [97..122] ++ [48..57] ++ [43,47]+alphabet = B.pack $ [65..90] ++ [97..122] ++ [48..57] ++ [43,47] {-# NOINLINE alphabet #-} --- The encoding table is constructed such that the expansion of a 12bit block--- to a 16bit block can be done by a single Word16 copy from the correspoding--- table entry to the target address. The 16bit blocks are stored in big-endian--- order, as the indices into the table are built in big-endian order.-encodeTable :: ForeignPtr Word16-encodeTable = -    case table of PS fp _ _ -> castForeignPtr fp-  where-    ix    = fromIntegral . B.index alphabet-    table = B.pack $ concat $ [ [ix j, ix k] | j <- [0..63], k <- [0..63] ]-{-# NOINLINE encodeTable #-}- decodeFP :: ForeignPtr Word8 PS decodeFP _ _ = B.pack $ replicate 43 x ++ [62,x,x,x,63] ++ [52..61] ++ [x,x,   x,done,x,x,x] ++ [0..25] ++ [x,x,x,x,x,x] ++ [26..51] ++ replicate 133 x@@ -247,7 +56,3 @@ x :: Integral a => a x = 255 {-# INLINE x #-}--done :: Integral a => a-done = 99-{-# INLINE done #-}
+ Data/ByteString/Base64/Internal.hs view
@@ -0,0 +1,249 @@+{-# LANGUAGE BangPatterns #-}++-- |+-- Module      : Data.ByteString.Base64.Internal+-- Copyright   : (c) 2010 Bryan O'Sullivan+--+-- License     : BSD-style+-- Maintainer  : bos@serpentine.com+-- Stability   : experimental+-- Portability : GHC+--+-- Fast and efficient encoding and decoding of base64-encoded strings.++module Data.ByteString.Base64.Internal+    (+      encodeWithAlphabet+    , decodeWithTable+    , decodeLenientWithTable+    , joinWith+    , done+    , peek8, poke8, peek8_32+    ) where++import Data.Bits ((.|.), (.&.), shiftL, shiftR)+import qualified Data.ByteString as B+import Data.ByteString.Internal (ByteString(..), mallocByteString, memcpy,+                                 unsafeCreate)+import Data.Word (Word8, Word16, Word32)+import Foreign.ForeignPtr (ForeignPtr, withForeignPtr, castForeignPtr)+import Foreign.Ptr (Ptr, castPtr, minusPtr, plusPtr)+import Foreign.Storable (peek, peekElemOff, poke)+import System.IO.Unsafe (unsafePerformIO)++peek8 :: Ptr Word8 -> IO Word8+peek8 = peek++poke8 :: Ptr Word8 -> Word8 -> IO ()+poke8 = poke++peek8_32 :: Ptr Word8 -> IO Word32+peek8_32 = fmap fromIntegral . peek8++-- | Encode a string into base64 form.  The result will always be a+-- multiple of 4 bytes in length. This function takes the encoding+-- alphabet (for @base64@ or @base64url@) as the first paramert.+encodeWithAlphabet :: ByteString -> ByteString -> ByteString+encodeWithAlphabet alphabet@(PS alfaFP _ _) (PS sfp soff slen)+    | slen > maxBound `div` 4 =+        error "Data.ByteString.Base64.encode: input too long"+    | otherwise = unsafePerformIO $ do+  let dlen = ((slen + 2) `div` 3) * 4+  dfp <- mallocByteString dlen+  withForeignPtr alfaFP $ \aptr ->+    withForeignPtr encodeTable $ \ep ->+      withForeignPtr sfp $ \sptr -> do+        let aidx n = peek8 (aptr `plusPtr` n)+            sEnd = sptr `plusPtr` (slen + soff)+            fill !dp !sp+              | sp `plusPtr` 2 >= sEnd = complete (castPtr dp) sp+              | otherwise = {-# SCC "encode/fill" #-} do+              i <- peek8_32 sp+              j <- peek8_32 (sp `plusPtr` 1)+              k <- peek8_32 (sp `plusPtr` 2)+              let w = (i `shiftL` 16) .|. (j `shiftL` 8) .|. k+                  enc = peekElemOff ep . fromIntegral+              poke dp =<< enc (w `shiftR` 12)+              poke (dp `plusPtr` 2) =<< enc (w .&. 0xfff)+              fill (dp `plusPtr` 4) (sp `plusPtr` 3)+            complete dp sp+                | sp == sEnd = return ()+                | otherwise  = {-# SCC "encode/complete" #-} do+              let peekSP n f = (f . fromIntegral) `fmap` peek8 (sp `plusPtr` n)+                  twoMore    = sp `plusPtr` 2 == sEnd+                  equals     = 0x3d :: Word8+                  {-# INLINE equals #-}+              a <- peekSP 0 ((`shiftR` 2) . (.&. 0xfc))+              b <- peekSP 0 ((`shiftL` 4) . (.&. 0x03))+              !b' <- if twoMore+                     then peekSP 1 ((.|. b) . (`shiftR` 4) . (.&. 0xf0))+                     else return b+              poke8 dp =<< aidx a+              poke8 (dp `plusPtr` 1) =<< aidx b'+              c <- if twoMore+                   then aidx =<< peekSP 1 ((`shiftL` 2) . (.&. 0x0f))+                   else return equals+              poke8 (dp `plusPtr` 2) c+              poke8 (dp `plusPtr` 3) equals+        withForeignPtr dfp $ \dptr ->+          fill (castPtr dptr) (sptr `plusPtr` soff)+  return $! PS dfp 0 dlen+  where -- The encoding table is constructed such that the expansion of a 12bit block+        -- to a 16bit block can be done by a single Word16 copy from the correspoding+        -- table entry to the target address. The 16bit blocks are stored in big-endian+        -- order, as the indices into the table are built in big-endian order.+        encodeTable :: ForeignPtr Word16+        encodeTable = +            case table of PS fp _ _ -> castForeignPtr fp+          where+            ix    = fromIntegral . B.index alphabet+            table = B.pack $ concat $ [ [ix j, ix k] | j <- [0..63], k <- [0..63] ]+        {-# NOINLINE encodeTable #-}++-- | Efficiently intersperse a terminator string into another at+-- regular intervals, and terminate the input with it.+--+-- Examples:+--+-- > joinWith "|" 2 "----" = "--|--|"+--+-- > joinWith "\r\n" 3 "foobarbaz" = "foo\r\nbar\r\nbaz\r\n"+joinWith :: ByteString  -- ^ String to intersperse and end with+         -> Int         -- ^ Interval at which to intersperse, in bytes+         -> ByteString  -- ^ String to transform+         -> ByteString+joinWith brk@(PS bfp boff blen) every bs@(PS sfp soff slen)+    | every <= 0 = error "invalid interval"+    | blen <= 0  = bs+    | B.null bs = brk+    | otherwise =+  unsafeCreate dlen $ \dptr ->+    withForeignPtr bfp $ \bptr -> do+      withForeignPtr sfp $ \sptr -> do+          let bp = bptr `plusPtr` boff+          let dEnd = dptr `plusPtr` dlen+              loop !dp !sp | dp >= dEnd = return ()+                           | otherwise = do+                let n = min every (dEnd `minusPtr` dp)+                memcpy dp sp (fromIntegral n)+                memcpy (dp `plusPtr` n) bp (fromIntegral blen)+                loop (dp `plusPtr` (n + blen)) (sp `plusPtr` every)+          loop dptr (sptr `plusPtr` soff)+  where dlen = slen + blen * numBreaks+        numBreaks = slen `div` every++-- | Decode a base64-encoded string.  This function strictly follows+-- the specification in RFC 4648,+-- <http://www.apps.ietf.org/rfc/rfc4648.html>.+-- This function takes the decoding table (for @base64@ or @base64url@) as +-- the first paramert.+decodeWithTable :: ForeignPtr Word8 -> ByteString -> Either String ByteString+decodeWithTable decodeFP (PS sfp soff slen)+    | drem /= 0 = Left "invalid padding"+    | dlen <= 0 = Right B.empty+    | otherwise = unsafePerformIO $ do+  dfp <- mallocByteString dlen+  withForeignPtr decodeFP $ \decptr -> do+    let finish dbytes = return . Right $! if dbytes > 0+                                          then PS dfp 0 dbytes+                                          else B.empty+        bail = return . Left+    withForeignPtr sfp $ \sptr -> do+      let sEnd = sptr `plusPtr` (slen + soff)+          look p = do+            ix <- fromIntegral `fmap` peek8 p+            v <- peek8 (decptr `plusPtr` ix)+            return $! fromIntegral v :: IO Word32+          fill !dp !sp !n+            | sp >= sEnd = finish n+            | otherwise = {-# SCC "decodeWithTable/fill" #-} do+            a <- look sp+            b <- look (sp `plusPtr` 1)+            c <- look (sp `plusPtr` 2)+            d <- look (sp `plusPtr` 3)+            let w = (a `shiftL` 18) .|. (b `shiftL` 12) .|.+                    (c `shiftL` 6) .|. d+            if a == done || b == done+              then bail $ "invalid padding near offset " +++                   show (sp `minusPtr` sptr)+              else if a .|. b .|. c .|. d == x+              then bail $ "invalid base64 encoding near offset " +++                   show (sp `minusPtr` sptr)+              else do+                poke8 dp $ fromIntegral (w `shiftR` 16)+                if c == done+                  then finish $ n + 1+                  else do+                    poke8 (dp `plusPtr` 1) $ fromIntegral (w `shiftR` 8)+                    if d == done+                      then finish $! n + 2+                      else do+                        poke8 (dp `plusPtr` 2) $ fromIntegral w+                        fill (dp `plusPtr` 3) (sp `plusPtr` 4) (n+3)+      withForeignPtr dfp $ \dptr ->+        fill dptr (sptr `plusPtr` soff) 0+  where (di,drem) = slen `divMod` 4+        dlen = di * 3++data D = D { dNext :: {-# UNPACK #-} !(Ptr Word8)+           , dValue :: {-# UNPACK #-} !Word32 }++-- | Decode a base64-encoded string.  This function is lenient in+-- following the specification from RFC 4648,+-- <http://www.apps.ietf.org/rfc/rfc4648.html>, and will not generate+-- parse errors no matter how poor its input.+-- This function takes the decoding table (for @base64@ or @base64url@) as +-- the first paramert.+decodeLenientWithTable :: ForeignPtr Word8 -> ByteString -> ByteString+decodeLenientWithTable decodeFP (PS sfp soff slen)+    | dlen <= 0 = B.empty+    | otherwise = unsafePerformIO $ do+  dfp <- mallocByteString dlen+  dbytes <- withForeignPtr decodeFP $ \decptr ->+    withForeignPtr sfp $ \sptr -> do+      let sEnd = sptr `plusPtr` (slen + soff)+          fill !dp !sp !n+            | sp >= sEnd = return n+            | otherwise = {-# SCC "decodeLenientWithTable/fill" #-} do+            let look skipPad = go+                  where+                    go p | p >= sEnd = return $! D (sEnd `plusPtr` (-1)) done+                         | otherwise =  {-# SCC "decodeLenient/look" #-} do+                      ix <- fromIntegral `fmap` peek8 p+                      v <- peek8 (decptr `plusPtr` ix)+                      if v == x || (v == done && skipPad)+                        then go (p `plusPtr` 1)+                        else return $! D (p `plusPtr` 1) (fromIntegral v)+            !a <- look True  sp+            !b <- look True  (dNext a)+            !c <- look False (dNext b)+            !d <- look False (dNext c)+            let w = (dValue a `shiftL` 18) .|. (dValue b `shiftL` 12) .|.+                    (dValue c `shiftL` 6) .|. dValue d+            if dValue a == done || dValue b == done+              then return n+              else do+                poke8 dp $ fromIntegral (w `shiftR` 16)+                if dValue c == done+                  then return $! n + 1+                  else do+                    poke8 (dp `plusPtr` 1) $ fromIntegral (w `shiftR` 8)+                    if dValue d == done+                      then return $! n + 2+                      else do+                        poke8 (dp `plusPtr` 2) $ fromIntegral w+                        fill (dp `plusPtr` 3) (dNext d) (n+3)+      withForeignPtr dfp $ \dptr ->+        fill dptr (sptr `plusPtr` soff) 0+  return $! if dbytes > 0+            then PS dfp 0 dbytes+            else B.empty+  where dlen = ((slen + 3) `div` 4) * 3++x :: Integral a => a+x = 255+{-# INLINE x #-}++done :: Integral a => a+done = 99+{-# INLINE done #-}
+ Data/ByteString/Base64/URL.hs view
@@ -0,0 +1,58 @@+{-# LANGUAGE BangPatterns #-}++-- |+-- Module      : Data.ByteString.Base64.URL+-- Copyright   : (c) 2012 Deian Stefan+--+-- License     : BSD-style+-- Maintainer  : deian@cs.stanford.edu+-- Stability   : experimental+-- Portability : GHC+--+-- Fast and efficient encoding and decoding of base64url-encoded strings.++module Data.ByteString.Base64.URL+    (+      encode+    , decode+    , decodeLenient+    , joinWith+    ) where++import Data.ByteString.Base64.Internal+import qualified Data.ByteString as B+import Data.ByteString.Internal (ByteString(..))+import Data.Word (Word8)+import Foreign.ForeignPtr (ForeignPtr)++-- | Encode a string into base64url form.  The result will always be a+-- multiple of 4 bytes in length.+encode :: ByteString -> ByteString+encode = encodeWithAlphabet alphabet++-- | Decode a base64url-encoded string.  This function strictly follows+-- the specification in RFC 4648,+-- <http://www.apps.ietf.org/rfc/rfc4648.html>.+decode :: ByteString -> Either String ByteString+decode = decodeWithTable decodeFP++-- | Decode a base64url-encoded string.  This function is lenient in+-- following the specification from RFC 4648,+-- <http://www.apps.ietf.org/rfc/rfc4648.html>, and will not generate+-- parse errors no matter how poor its input.+decodeLenient :: ByteString -> ByteString+decodeLenient = decodeLenientWithTable decodeFP+++alphabet :: ByteString+alphabet = B.pack $ [65..90] ++ [97..122] ++ [48..57] ++ [45,95]+{-# NOINLINE alphabet #-}++decodeFP :: ForeignPtr Word8+PS decodeFP _ _ = B.pack $ replicate 45 x ++ [62,x,x] ++ [52..61] ++ [x,x,+  x,done,x,x,x] ++ [0..25] ++ [x,x,x,x,63,x] ++ [26..51] ++ replicate 133 x+{-# NOINLINE decodeFP #-}++x :: Integral a => a+x = 255+{-# INLINE x #-}
base64-bytestring.cabal view
@@ -1,5 +1,5 @@ name:                base64-bytestring-version:             0.1.0.3+version:             0.1.1.0 synopsis:            Fast base64 encoding and deconding for ByteStrings description:         Fast base64 encoding and deconding for ByteStrings homepage:            https://github.com/bos/base64-bytestring@@ -8,20 +8,24 @@ license-file:        LICENSE author:              Bryan O'Sullivan <bos@serpentine.com> maintainer:          Bryan O'Sullivan <bos@serpentine.com>-copyright:           2010 Bryan O'Sullivan+copyright:           2010-2011 Bryan O'Sullivan category:            Data build-type:          Simple-extra-source-files:  README.markdown+cabal-version:       >=1.8  extra-source-files:+  README.markdown   tests/Transcode.hs--Cabal-version:       >=1.6+  tests/transcode.py  library   exposed-modules:     Data.ByteString.Base64+    Data.ByteString.Base64.URL   +  other-modules:+    Data.ByteString.Base64.Internal+   build-depends:     base == 4.*,     bytestring == 0.9.*@@ -29,10 +33,29 @@   ghc-options: -Wall -funbox-strict-fields   ghc-prof-options: -auto-all +test-suite tests+  type: exitcode-stdio-1.0+  hs-source-dirs: tests+  main-is: Tests.hs++  ghc-options:+    -Wall -threaded -rtsopts++  build-depends:+    QuickCheck,+    HUnit,+    base64-bytestring,+    base,+    containers,+    bytestring,+    test-framework,+    test-framework-quickcheck2,+    test-framework-hunit+ source-repository head   type:     git-  location: http://github.com/bos/base64-bytestring+  location: git://github.com/bos/base64-bytestring  source-repository head   type:     mercurial-  location: http://bitbucket.org/bos/base64-bytestring+  location: https://bitbucket.org/bos/base64-bytestring
+ tests/transcode.py view
@@ -0,0 +1,14 @@+#!/usr/bin/env python++import binascii, sys++funcs = {+    'decode': binascii.a2b_base64,+    'encode': binascii.b2a_base64,+    'read': lambda x:x,+    }+    +f = funcs[sys.argv[1]]++for n in sys.argv[2:]:+    sys.stdout.write(f(open(n).read()))