Permalink
Browse files

Initial commit.

  • Loading branch information...
bos committed Jan 25, 2011
0 parents commit 405a2b79b98c4fc437c422ed61ae87dc563a84a8
Showing with 194 additions and 0 deletions.
  1. +5 −0 .hgignore
  2. +81 −0 Data/ByteString/Base16.hs
  3. +30 −0 LICENSE
  4. +37 −0 README.markdown
  5. +2 −0 Setup.hs
  6. +39 −0 base16-bytestring.cabal
@@ -0,0 +1,5 @@
+^dist$
+\.(?:aux|eventlog|h[ip]|log|[oa]|orig|prof|ps|swp)$
+~$
+syntax: glob
+.\#*
@@ -0,0 +1,81 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+-- |
+-- Module : Data.ByteString.Base16
+-- Copyright : (c) 2011 MailRank, Inc.
+--
+-- License : BSD
+-- Maintainer : bos@mailrank.com
+-- Stability : experimental
+-- Portability : GHC
+--
+-- Fast and efficient encoding and decoding of base16-encoded strings.
+
+module Data.ByteString.Base16
+ (
+ encode
+ , decode
+ ) where
+
+import Data.Bits ((.&.), shiftL, shiftR)
+import Data.ByteString.Char8 (empty)
+import Data.ByteString.Internal (ByteString(..), createAndTrim', unsafeCreate)
+import Data.ByteString.Unsafe (unsafeIndex)
+import Data.Word (Word8)
+import Foreign.ForeignPtr (ForeignPtr, withForeignPtr)
+import Foreign.Ptr (Ptr, minusPtr, plusPtr)
+import Foreign.Storable (peek, poke)
+import System.IO.Unsafe (unsafePerformIO)
+
+digits :: ByteString
+digits = "0123456789abcdef"
+{-# NOINLINE digits #-}
+
+encode :: ByteString -> ByteString
+encode (PS sfp soff slen)
+ | slen > maxBound `div` 2 = error "Data.ByteString.Base16.encode: input too large"
+ | otherwise = unsafeCreate (slen*2) $ \dptr ->
+ withForeignPtr sfp $ \sptr ->
+ enc (sptr `plusPtr` soff) dptr
+ where
+ enc sptr = go sptr where
+ e = sptr `plusPtr` slen
+ go s d | s == e = return ()
+ | otherwise = do
+ x <- peek8 s
+ poke d . unsafeIndex digits $ x `shiftR` 4
+ poke (d `plusPtr` 1) . unsafeIndex digits $ x .&. 0xf
+ go (s `plusPtr` 1) (d `plusPtr` 2)
+
+decode :: ByteString -> (ByteString, ByteString)
+decode (PS sfp soff slen) =
+ unsafePerformIO . createAndTrim' (slen `div` 2) $ \dptr ->
+ withForeignPtr sfp $ \sptr ->
+ dec (sptr `plusPtr` soff) dptr
+ where
+ dec sptr = go sptr where
+ e = sptr `plusPtr` if odd slen then slen - 1 else slen
+ go s d | s == e = let len = e `minusPtr` sptr
+ in return (0, len `div` 2, ps sfp (soff+len) (slen-len))
+ | otherwise = do
+ let hex w
+ | w >= 48 && w <= 57 = w - 48
+ | w >= 97 && w <= 102 = w - 97 + 10
+ | w >= 65 && w <= 70 = w - 65 + 10
+ | otherwise = 0xff
+ hi <- hex `fmap` peek8 s
+ lo <- hex `fmap` peek8 (s `plusPtr` 1)
+ if lo == 0xff || hi == 0xff
+ then let len = s `minusPtr` sptr
+ in return (0, len `div` 2, ps sfp (soff+len) (slen-len))
+ else do
+ poke d . fromIntegral $ lo + (hi `shiftL` 4)
+ go (s `plusPtr` 2) (d `plusPtr` 1)
+
+peek8 :: Ptr Word8 -> IO Int
+peek8 p = fromIntegral `fmap` peek p
+
+ps :: ForeignPtr Word8 -> Int -> Int -> ByteString
+ps fp off len
+ | len <= 0 = empty
+ | otherwise = PS fp off len
30 LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2011 MailRank, Inc.
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the author nor the names of his contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS
+OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,37 @@
+# Fast base16 support
+
+This package provides a Haskell library for working with base16-encoded
+data quickly and efficiently, using the ByteString type.
+
+
+# Performance
+
+This library is written in pure Haskell, and it's fast:
+
+* 250 MB/sec encoding
+
+* 200 MB/sec strict decoding (per RFC 4648)
+
+* 100 MB/sec lenient decoding
+
+
+# Get involved!
+
+Please report bugs via the
+[bitbucket issue tracker](http://github.com/mailrank/base16-bytestring).
+
+Master [github repository](http://github.com/mailrank/base16-bytestring):
+
+* `git clone git://github.com/mailrank/base16-bytestring.git`
+
+There's also a [Mercurial mirror](http://bitbucket.org/bos/base16-bytestring):
+
+* `hg clone http://bitbucket.org/bos/base16-bytestring`
+
+(You can create and contribute changes using either git or Mercurial.)
+
+
+# Authors
+
+This library is written and maintained by Bryan O'Sullivan,
+<bos@mailrank.com>.
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
@@ -0,0 +1,39 @@
+name: base16-bytestring
+version: 0.1.0.0
+synopsis: Fast base16 (hex) encoding and deconding for ByteStrings
+description: Fast base16 (hex) encoding and deconding for ByteStrings
+homepage: http://github.com/mailrank/base16-bytestring
+bug-reports: http://girhub.co/mailrank/base16-bytestring/issues
+license: BSD3
+license-file: LICENSE
+copyright: Copyright 2011 MailRank, Inc.
+author: Bryan O'Sullivan <bos@serpentine.com>
+maintainer: Bryan O'Sullivan <bos@serpentine.com>
+copyright: 2010 Bryan O'Sullivan
+category: Data
+build-type: Simple
+extra-source-files: README.markdown
+
+extra-source-files:
+ tests/Transcode.hs
+
+Cabal-version: >=1.6
+
+library
+ exposed-modules:
+ Data.ByteString.Base16
+
+ build-depends:
+ base == 4.*,
+ bytestring == 0.9.*
+
+ ghc-options: -Wall -funbox-strict-fields
+ ghc-prof-options: -auto-all
+
+source-repository head
+ type: git
+ location: http://github.com/mailrank/base16-bytestring
+
+source-repository head
+ type: mercurial
+ location: http://bitbucket.org/bos/base16-bytestring

0 comments on commit 405a2b7

Please sign in to comment.