packages feed

spool (empty) → 0.1

raw patch · 6 files changed

+199/−0 lines, 6 filesdep +basedep +bytestringdep +vectorsetup-changed

Dependencies added: base, bytestring, vector

Files

+ Data/Vector/Storable/ByteString.hs view
@@ -0,0 +1,36 @@+-- | Convert between @ByteString@ and @Vector.Storable@+-- without copying.+module Data.Vector.Storable.ByteString+    ( -- | See also the caveats mentioned in the package's+      -- top-level documentation.+      byteStringToVector+    , vectorToByteString+    ) where++import qualified Data.ByteString          as BS+import qualified Data.ByteString.Internal as BS+import qualified Data.Vector.Storable     as V++import Foreign.Storable+import Foreign.ForeignPtr++sizeOfElem :: (Storable a) => V.Vector a -> Int+sizeOfElem vec = sizeOf (undefined `asTypeOf` V.head vec)++-- | Convert a @'BS.ByteString'@ to a @'V.Vector'@.+--+-- This function can produce @'Vector'@s which do not obey+-- architectural alignment requirements.  On @x86@ this should+-- not be an issue.+byteStringToVector :: (Storable a) => BS.ByteString -> V.Vector a+byteStringToVector bs = vec where+    vec = V.unsafeFromForeignPtr (castForeignPtr fptr) (scale off) (scale len)+    (fptr, off, len) = BS.toForeignPtr bs+    scale = (`div` sizeOfElem vec)++-- | Convert a @'V.Vector'@ to a @'BS.ByteString'@.+vectorToByteString :: (Storable a) => V.Vector a -> BS.ByteString+vectorToByteString vec+  = BS.fromForeignPtr (castForeignPtr fptr) (scale off) (scale len) where+    (fptr, off, len) = V.unsafeToForeignPtr vec+    scale = (* sizeOfElem vec)
+ LICENSE view
@@ -0,0 +1,26 @@+Copyright (c) Keegan McAllister 2011++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 COPYRIGHT HOLDERS AND 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.
+ README view
@@ -0,0 +1,10 @@+spool provides conversion between ByteString and Vector.Storable without+copying the underlying data.++Documentation is hosted at http://hackage.haskell.org/package/spool++To build the documentation yourself, run++  $ cabal configure && cabal haddock --hyperlink-source++This will produce HTML documentation under dist/doc/html/spool.
+ Setup.hs view
@@ -0,0 +1,4 @@+#! /usr/bin/runhaskell++import Distribution.Simple+main = defaultMain
+ spool.cabal view
@@ -0,0 +1,38 @@+name:                spool+version:             0.1+license:             BSD3+license-file:        LICENSE+synopsis:            Convert between ByteString and Vector.Storable without copying+category:            Data Structures+author:              Keegan McAllister <mcallister.keegan@gmail.com>+maintainer:          Keegan McAllister <mcallister.keegan@gmail.com>+build-type:          Simple+cabal-version:       >=1.6+description:+  This library allows conversion between the types from @Data.ByteString@+  (package @bytestring@) and @Data.Vector.Storable@ (package @vector@) without+  copying the underlying data.  This is useful, for example, when @ByteString@+  IO produces or consumes vectors of numbers in native byte order.+  .+  This trick relies on the fact that @ByteString@ and @Vector@ use their+  respective @ForeignPtr@s in compatible ways.  It works with+  @bytestring-0.9.1.10@ and @vector-0.9@ on GHC 7.0.  It may break with future+  releases of these packages.  Depending on this library should be seen as a+  way to document and standardize an existing hack, and not as an absolute+  guarantee of correct behavior.++extra-source-files:+    test/test.hs+  , README++library+  exposed-modules:  Data.Vector.Storable.ByteString+  ghc-options:      -Wall+  build-depends:+      base       >= 3 && < 5+    , bytestring >= 0.9+    , vector     >= 0.7++source-repository head+    type:     git+    location: git://github.com/kmcallister/spool.git
+ test/test.hs view
@@ -0,0 +1,85 @@+{-# LANGUAGE+    ScopedTypeVariables #-}++module Main(main) where++import qualified Data.ByteString      as B+import qualified Data.Vector.Storable as V++import Data.Word+import System.ByteOrder   -- package 'byteorder'+import Test.QuickCheck+import Foreign.Storable++import Data.Vector.Storable.ByteString+++arbList :: (Bounded a, Integral a) => Gen [a]+arbList = choose (0, 16384) >>= flip vectorOf arbitraryBoundedIntegral++instance Arbitrary B.ByteString where+    arbitrary = fmap B.pack arbList++instance (Bounded a, Integral a, Storable a) => Arbitrary (V.Vector a) where+    arbitrary = fmap V.fromList arbList+++-- Reference implementations++fromBE, fromHost :: (Integral a) => [Word8] -> a+fromBE = foldl (\n x -> n*256 + fromIntegral x) 0+fromHost = case byteOrder of+    LittleEndian -> fromBE . reverse+    BigEndian    -> fromBE++toLE, toHost :: (Integral a) => Int -> a -> [Word8]+toLE sz = take sz . map (fromIntegral . (`mod` 256)) . iterate (`div` 256)+toHost = case byteOrder of+    LittleEndian -> toLE+    BigEndian    -> \sz -> reverse . toLE sz++data Rep a = Rep Int ([Word8] -> a) (a -> [Word8])++rep8 :: Rep Word8+rep8 = Rep 1 (\[x] -> x) return++repN :: forall a. (Storable a, Integral a) => Rep a+repN = let n = sizeOf (undefined :: a) in Rep n fromHost (toHost n)++ref_byteStringToVector :: (Storable a) => Rep a -> B.ByteString -> V.Vector a+ref_byteStringToVector (Rep n f _) = V.fromList . go where+    go bs = case B.splitAt n bs of+        (x, xs) | B.length x == n -> f (B.unpack x) : go xs+        _ -> []++ref_vectorToByteString :: (Storable a) => Rep a -> V.Vector a -> B.ByteString+ref_vectorToByteString (Rep _ _ f) = B.pack . concatMap f . V.toList+++-- Properties++mkProp_inv      _ x = byteStringToVector (vectorToByteString x) == x+mkProp_inv_ref  r x = ref_byteStringToVector r (ref_vectorToByteString r x) == x++mkProp_inv_ref1 r x = ref_byteStringToVector r (vectorToByteString x) == x+mkProp_inv_ref2 r x = byteStringToVector (ref_vectorToByteString r x) == x++mkProp_eq_BV r x = ref_byteStringToVector r x == byteStringToVector x+mkProp_eq_VB r x = ref_vectorToByteString r x == vectorToByteString x+++-- Test runner++runFor :: (Integral a, Bounded a, Storable a) => Rep a -> IO ()+runFor r = do+    mapM_ (quickCheck . ($r))+        [mkProp_inv, mkProp_inv_ref, mkProp_inv_ref1,+         mkProp_inv_ref2, mkProp_eq_VB]+    quickCheck (mkProp_eq_BV r)++main :: IO ()+main = do+    runFor rep8+    runFor (repN :: Rep Word16)+    runFor (repN :: Rep Word32)+    runFor (repN :: Rep Word64)