Bryan O'Sullivan avatar Bryan O'Sullivan committed 5c297dc

Initial commit.

Comments (0)

Files changed (6)

+^dist$
+\.(?:aux|eventlog|h[ip]|log|[oa]|orig|prof|ps|swp)$
+~$
+syntax: glob
+.\#*

Data/ByteString/Base16.hs

+{-# 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
+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.
+# 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>.
+import Distribution.Simple
+main = defaultMain

base16-bytestring.cabal

+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
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.