Skip to content

Commit 41d8587

Browse files
committed
Initial commit, with fast working encode
0 parents  commit 41d8587

File tree

5 files changed

+127
-0
lines changed

5 files changed

+127
-0
lines changed

.hgignore

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
^dist$
2+
\.(?:aux|eventlog|h[ip]|log|[oa]|orig|prof|ps|swp)$
3+
~$

Data/ByteString/Base64.hs

+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
{-# LANGUAGE BangPatterns, OverloadedStrings #-}
2+
3+
module Data.ByteString.Base64
4+
(
5+
encode
6+
, decode
7+
) where
8+
9+
import Data.Bits ((.|.), (.&.), shiftL, shiftR)
10+
import Data.ByteString.Char8 (ByteString, pack)
11+
import Data.ByteString.Internal
12+
import Data.ByteString.Unsafe
13+
import Data.Word (Word8, Word16, Word32)
14+
import Foreign.ForeignPtr (ForeignPtr, mallocForeignPtrArray, withForeignPtr)
15+
import Foreign.Ptr (Ptr, castPtr, plusPtr)
16+
import Foreign.Storable (peek, peekElemOff, poke, pokeElemOff)
17+
import System.IO.Unsafe (unsafePerformIO)
18+
19+
peek8 :: Ptr Word8 -> IO Word8
20+
peek8 = peek
21+
22+
encode :: ByteString -> ByteString
23+
encode (PS sary soff slen) = unsafePerformIO $ do
24+
let dlen = (((slen + 2) `div` 3) * 4)
25+
dary <- mallocByteString dlen
26+
withForeignPtr encTable $ \ep ->
27+
withForeignPtr sary $ \sptr ->
28+
withForeignPtr dary $ \dptr -> do
29+
let pp p = (fromIntegral `fmap` peek8 p) :: IO Word32
30+
sEnd = sptr `plusPtr` slen
31+
fill !dp !sp
32+
| sp `plusPtr` 2 >= sEnd = complete (castPtr dp) sp
33+
| otherwise = do
34+
i <- pp sp
35+
j <- pp (sp `plusPtr` 1)
36+
k <- pp (sp `plusPtr` 2)
37+
let w = (i `shiftL` 16) .|. (j `shiftL` 8) .|. k
38+
enc = peekElemOff ep . fromIntegral
39+
poke dp =<< enc (w `shiftR` 12)
40+
poke (dp `plusPtr` 2) =<< enc (w .&. 0xfff)
41+
fill (dp `plusPtr` 4) (sp `plusPtr` 3)
42+
complete dp sp
43+
| sp == sEnd = return ()
44+
| otherwise = do
45+
let peekSP n f = (f . fromIntegral) `fmap` peek8 (sp `plusPtr` n)
46+
twoMore = sp `plusPtr` 2 == sEnd
47+
equals = 0x3d :: Word8
48+
a <- peekSP 0 ((`shiftR` 2) . (.&. 0xfc))
49+
b <- peekSP 0 ((`shiftL` 4) . (.&. 0x03))
50+
b' <- if twoMore
51+
then peekSP 1 ((.|. b) . (`shiftR` 4) . (.&. 0xf0))
52+
else return b
53+
poke dp (unsafeIndex alphabet a)
54+
poke (dp `plusPtr` 1) (unsafeIndex alphabet b')
55+
c <- if twoMore
56+
then peekSP 1 ((`shiftL` 2) . (.&. 0x0f))
57+
else return equals
58+
poke (dp `plusPtr` 2) c
59+
poke (dp `plusPtr` 3) equals
60+
fill (castPtr dptr) (sptr `plusPtr` soff)
61+
return $! PS dary 0 dlen
62+
63+
decode :: ByteString -> ByteString
64+
decode = undefined
65+
66+
alphabet :: ByteString
67+
alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
68+
{-# NOINLINE alphabet #-}
69+
70+
encTable :: ForeignPtr Word16
71+
encTable = unsafePerformIO $ do
72+
fp <- mallocForeignPtrArray 4096
73+
let ix = fromIntegral . unsafeIndex alphabet
74+
withForeignPtr fp $ \p ->
75+
sequence_ [ pokeElemOff p (j*64+k) ((ix k `shiftL` 8) .|. ix j)
76+
| j <- [0..64], k <- [0..64] ]
77+
return fp
78+
{-# NOINLINE encTable #-}

LICENSE

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
Permission is hereby granted, free of charge, to any person obtaining a copy
2+
of this software and associated documentation files (the "Software"), to deal
3+
in the Software without restriction, including without limitation the rights
4+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
5+
copies of the Software, and to permit persons to whom the Software is
6+
furnished to do so, subject to the following conditions:
7+
8+
The above copyright notice and this permission notice shall be included in
9+
all copies or substantial portions of the Software.
10+
11+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
12+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
14+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
15+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
16+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
17+
THE SOFTWARE.

Setup.hs

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
import Distribution.Simple
2+
main = defaultMain

base64-bytestring.cabal

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
name: base64-bytestring
2+
version: 0.1.0.0
3+
synopsis: Fast base64 encoding and deconding for ByteStrings
4+
description: Fast base64 encoding and deconding for ByteStrings
5+
homepage: http://bitbucket.org/bos/base64-bytestring
6+
license: MIT
7+
license-file: LICENSE
8+
author: Bryan O'Sullivan <[email protected]>
9+
maintainer: Bryan O'Sullivan <[email protected]>
10+
copyright: 2010 Bryan O'Sullivan
11+
category: Data
12+
build-type: Simple
13+
14+
-- Extra files to be distributed with the package, such as examples or
15+
-- a README.
16+
-- Extra-source-files:
17+
18+
Cabal-version: >=1.2
19+
20+
21+
library
22+
exposed-modules:
23+
Data.ByteString.Base64
24+
25+
build-depends:
26+
base == 4.*,
27+
bytestring == 0.9.*

0 commit comments

Comments
 (0)