packages feed

cityhash 0.1.0.1 → 0.2.0.0

raw patch · 7 files changed

+155/−66 lines, 7 filesdep ~QuickCheckdep ~bytestringdep ~largewordPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: QuickCheck, bytestring, largeword, test-framework, test-framework-quickcheck2

API changes (from Hackage documentation)

+ Data.Digest.CityHash: cityHash128WithSeed :: ByteString -> Word128 -> Word128
+ Data.Digest.CityHash: cityHash64WithSeed :: ByteString -> Word64 -> Word64
+ Data.Digest.CityHash: cityHash64WithSeeds :: ByteString -> Word64 -> Word64 -> Word64

Files

Data/Digest/CityHash.hs view
@@ -1,60 +1,94 @@ {-# LANGUAGE ForeignFunctionInterface #-} -- | -- Module      : Data.Digest.CityHash--- Copyright   : (c) Austin Seipp 2011--- License     : BSD3+-- Copyright   : (c) Austin Seipp 2011-2012+-- License     : MIT -- --- Maintainer  : as@hacks.yi.org+-- Maintainer  : mad.one@gmail.com -- Stability   : experimental -- Portability : portable (FFI) --  -- This module implements a binding to the CityHash family of hashing -- functions. You can find more information here: -- <http://code.google.com/p/cityhash/>. It implements both the 64-bit--- and 128-bit interfaces.--- --- Note that CityHash was designed to work on architectures where--- unaligned reads do not have a large penalty. In practice, it is--- only used at Google on little-endian Intel/AMD CPUs, and has not--- been tested on big-endian architectures.+-- and 128-bit interfaces, with seed functionality. --  module Data.Digest.CityHash-( -- * Hashing values -  cityHash64  -- :: ByteString -> Word64-, cityHash128 -- :: ByteString -> Word128-) where+      ( -- * 64-bit hashes+        cityHash64          -- :: ByteString -> Word64+      , cityHash64WithSeed  -- :: ByteString -> Word64 -> Word64+      , cityHash64WithSeeds -- :: ByteString -> Word64 -> Word64 -> Word64+        -- * 128-bit hashes+      , cityHash128         -- :: ByteString -> Word128+      , cityHash128WithSeed -- :: ByteString -> Word128 -> Word128+      ) where import Foreign import Foreign.C import Control.Monad (liftM)-+import System.IO.Unsafe as U (unsafePerformIO) import Data.LargeWord  import qualified Data.ByteString as S import qualified Data.ByteString.Unsafe as U --- | Hash a value into a 64bit result.+-- | Hash function for a byte array. cityHash64 :: S.ByteString -> Word64 cityHash64 bs-  = unsafePerformIO . U.unsafeUseAsCStringLen bs $ \(cstr,clen) -> do+  = unsafeUseBS bs $ \(cstr, clen) -> do       return $ c_CityHash64 cstr clen {-# INLINEABLE cityHash64 #-} --- | Hash a value into a 128bit result. Per the documentation, this is--- probably only faster for inputs with a length greater than--- approximately 200 bytes. Alternatively, use this when you wish--- to have minimal collisions.+-- | Hash function for a byte array.  For convenience, a 64-bit seed is also+-- hashed into the result.+cityHash64WithSeed :: S.ByteString -> Word64 -> Word64+cityHash64WithSeed bs seed+  = unsafeUseBS bs $ \(cstr, clen) -> do+      return $ c_CityHash64WithSeed cstr clen seed+{-# INLINEABLE cityHash64WithSeed #-}++-- | Hash function for a byte array.  For convenience, two seeds are also+-- hashed into the result.+cityHash64WithSeeds :: S.ByteString -> Word64 -> Word64 -> Word64+cityHash64WithSeeds bs seed0 seed1+  = unsafeUseBS bs $ \(cstr, clen) -> do+      return $ c_CityHash64WithSeeds cstr clen seed0 seed1+{-# INLINEABLE cityHash64WithSeeds #-}+++-- | Hash function for a byte array. cityHash128 :: S.ByteString -> Word128 cityHash128 bs-  = unsafePerformIO . U.unsafeUseAsCStringLen bs $ \(cstr,clen) ->+  = unsafeUseBS bs $ \(cstr,clen) ->       allocaBytes w64s $ \lo ->          allocaBytes w64s $ \hi -> do           c_CityHash128 cstr clen lo hi-          lo' <- fromIntegral `liftM` peek lo-          hi' <- fromIntegral `liftM` peek hi+          lo' <- (fromIntegral `liftM` peek lo) :: IO Word128+          hi' <- (fromIntegral `liftM` peek hi) :: IO Word128           return $ (hi' `shiftL` 64) .|. lo'   where w64s = sizeOf (undefined :: Word64) {-# INLINEABLE cityHash128 #-} +-- | Hash function for a byte array.  For convenience, a 128-bit seed is also+-- hashed into the result.+cityHash128WithSeed :: S.ByteString -> Word128 -> Word128+cityHash128WithSeed bs seed+  = unsafeUseBS bs $ \(cstr,clen) ->+      allocaBytes w64s $ \lo -> +        allocaBytes w64s $ \hi -> do+          c_CityHash128WithSeed cstr clen (loHalf seed) (hiHalf seed) lo hi+          lo' <- (fromIntegral `liftM` peek lo) :: IO Word128+          hi' <- (fromIntegral `liftM` peek hi) :: IO Word128+          return $ (hi' `shiftL` 64) .|. lo'+  where w64s = sizeOf (undefined :: Word64)+{-# INLINEABLE cityHash128WithSeed #-}++-- +-- Utils+-- ++unsafeUseBS :: S.ByteString -> ((CString, Int) -> IO a) -> a+unsafeUseBS bs = U.unsafePerformIO . U.unsafeUseAsCStringLen bs+ -- -- FFI bindings -- @@ -62,5 +96,15 @@ foreign import ccall unsafe "hs_city.h hs_CityHash64"   c_CityHash64 :: CString -> Int -> Word64 +foreign import ccall unsafe "hs_city.h hs_CityHash64WithSeed"+  c_CityHash64WithSeed :: CString -> Int -> Word64 -> Word64++foreign import ccall unsafe "hs_city.h hs_CityHash64WithSeeds"+  c_CityHash64WithSeeds :: CString -> Int -> Word64 -> Word64 -> Word64+ foreign import ccall unsafe "hs_city.h hs_CityHash128"   c_CityHash128 :: CString -> Int -> Ptr Word64 -> Ptr Word64 -> IO ()++foreign import ccall unsafe "hs_city.h hs_CityHash128WithSeed"+  c_CityHash128WithSeed :: CString -> Int -> Word64 -> Word64 +                        -> Ptr Word64 -> Ptr Word64 -> IO ()
− LICENSE
@@ -1,30 +0,0 @@-Copyright Austin Seipp 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:--    * Redistributions of source code must retain the above copyright-      notice, this list of conditions and the following disclaimer.--    * 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.--    * Neither the name of Austin Seipp nor the names of other-      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 COPYRIGHT-OWNER 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.
+ LICENSE.txt view
@@ -0,0 +1,20 @@+Copyright (c) 2011-2012 Austin Seipp++Permission is hereby granted, free of charge, to any person obtaining+a copy of this software and associated documentation files (the+"Software"), to deal in the Software without restriction, including+without limitation the rights to use, copy, modify, merge, publish,+distribute, sublicense, and/or sell copies of the Software, and to+permit persons to whom the Software is furnished to do so, subject to+the following conditions:++The above copyright notice and this permission notice shall be+included in all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
cbits/hs_city.cc view
@@ -5,8 +5,27 @@   return CityHash64(buf,len); } +uint64_t hs_CityHash64WithSeed(const char *buf, size_t len, uint64_t seed) {+  return CityHash64WithSeed(buf,len,seed);+}++uint64_t hs_CityHash64WithSeeds(const char *buf, size_t len,+                                uint64 seed0, uint64 seed1) {+  return CityHash64WithSeeds(buf,len,seed0,seed1);+}+ void hs_CityHash128(const char* buf, size_t len, uint64_t* lo, uint64_t* hi) {   uint128 res = CityHash128(buf,len);   *lo = Uint128Low64(res);   *hi = Uint128High64(res);+}++void hs_CityHash128WithSeed(const char* buf, size_t len, uint64_t in1, uint64_t in2,+                            uint64_t* lo, uint64_t* hi) {+  uint128 seed;+  seed.first = in1; seed.second = in2;++  uint128 r = CityHash128WithSeed(buf, len, seed);+  *lo = Uint128Low64(r);+  *hi = Uint128High64(r); }
cbits/hs_city.h view
@@ -4,8 +4,13 @@ extern "C" {  uint64_t hs_CityHash64(const char* buf, size_t len);-void hs_CityHash128(const char* buf, size_t len, uint64_t* lo, uint64_t* hi);+uint64_t hs_CityHash64WithSeed(const char *buf, size_t len, uint64_t seed);+uint64_t hs_CityHash64WithSeeds(const char *buf, size_t len,+                                uint64 seed0, uint64 seed1); +void hs_CityHash128(const char* buf, size_t len, uint64_t* lo, uint64_t* hi);+void hs_CityHash128WithSeed(const char* buf, size_t len, uint64_t in1, uint64_t in2,+                            uint64_t* lo, uint64_t* hi); }  #endif
cityhash.cabal view
@@ -1,5 +1,5 @@ name:                cityhash-version:             0.1.0.1+version:             0.2.0.0 synopsis:            Bindings to CityHash description:   This package implements a binding to the CityHash family of hashing functions (implemented in C++.)@@ -7,8 +7,8 @@   See <http://code.google.com/p/cityhash/> for more information. homepage:            http://github.com/thoughtpolice/hs-cityhash bug-reports:         https://github.com/thoughtpolice/hs-cityhash/issues-license:             BSD3-license-file:        LICENSE+license:             MIT+license-file:        LICENSE.txt author:              Austin Seipp <mad.one@gmail.com> maintainer:          Austin Seipp <mad.one@gmail.com> category:            Codec@@ -28,9 +28,9 @@ library   exposed-modules: Data.Digest.CityHash   build-depends:-    base    >= 3 && < 5,-    bytestring == 0.9.*,-    largeword  >= 1.0.0+    base       >= 3 && < 5,+    bytestring >= 0.9,+    largeword  >= 1.0   c-sources:       cbits/city.cc, cbits/hs_city.cc   include-dirs:    cbits   extra-libraries: stdc++@@ -45,12 +45,13 @@   type:           exitcode-stdio-1.0    build-depends:-    base    >= 3 && < 5,-    bytestring     == 0.9.*,-    QuickCheck     == 2.4.*,-    test-framework == 0.4.*,-    test-framework-quickcheck2 == 0.2.*,+    base           >= 3 && < 5,+    bytestring     >= 0.9,+    largeword      >= 1.0,+    QuickCheck     >= 2.4,+    test-framework >= 0.5,+    test-framework-quickcheck2 >= 0.2,     cityhash -  ghc-options:      -fno-cse+  ghc-options:      -fno-cse -fno-warn-orphans   default-language: Haskell98
tests/Properties.hs view
@@ -1,21 +1,51 @@ {-# LANGUAGE ViewPatterns #-}+{-# LANGUAGE TypeSynonymInstances #-}+{-# LANGUAGE FlexibleInstances #-} module Main (main) where +import Data.Bits+import Data.Word import qualified Data.ByteString as S+import Control.Monad (liftM)+import Data.LargeWord import Data.Digest.CityHash +import Test.QuickCheck import Test.Framework (defaultMain, testGroup) import Test.Framework.Providers.QuickCheck2 (testProperty)  main :: IO () main = defaultMain [ testGroup "simple" [                        testProperty "cityhash64 is pure" prop_city64_pure+                     , testProperty "cityhash64WithSeed is pure" prop_city64WithSeed_pure+                     , testProperty "cityhash64WithSeeds is pure" prop_city64WithSeeds_pure                      , testProperty "cityhash128 is pure" prop_city128_pure+                     , testProperty "cityhash128WithSeed is pure" prop_city128WithSeed_pure                      ]                    ] +instance Arbitrary Word128 where+  arbitrary = do+    lo <- cast `liftM` arbitrary+    hi <- cast `liftM` arbitrary+    return ((hi `shiftL` 64) .|. lo)+	    where+        cast :: Word64 -> Word128+        cast = fromIntegral++ prop_city64_pure (S.pack -> xs)   = cityHash64 xs == cityHash64 xs +prop_city64WithSeed_pure (S.pack -> xs) seed+  = cityHash64WithSeed xs seed == cityHash64WithSeed xs seed++prop_city64WithSeeds_pure (S.pack -> xs) seed0 seed1+  = cityHash64WithSeeds xs seed0 seed1 == cityHash64WithSeeds xs seed0 seed1+ prop_city128_pure (S.pack -> xs)   = cityHash128 xs == cityHash128 xs++prop_city128WithSeed_pure (S.pack -> xs) seed+  = cityHash128WithSeed xs seed == cityHash128WithSeed xs seed+