Skip to content

Commit 3a6f2b6

Browse files
committed
Rebase on master, make test suite pass once more
1 parent 432ac53 commit 3a6f2b6

File tree

3 files changed

+90
-109
lines changed

3 files changed

+90
-109
lines changed

src/Data/Hashable/Class.hs

Lines changed: 2 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,6 @@ import qualified Data.Sequence as Seq
9494
import qualified Data.Set as Set
9595
import qualified Data.Tree as Tree
9696

97-
import qualified Data.Text.Internal.Lazy as TL
98-
9997
#if __GLASGOW_HASKELL__ >= 703
10098
import Foreign.C (CSize(..))
10199
#else
@@ -670,13 +668,7 @@ instance Hashable B.ByteString where
670668
hashPtrWithSalt p (fromIntegral len) (hashWithSalt salt len)
671669

672670
instance Hashable BL.ByteString where
673-
hashWithSalt salt = finalise . BL.foldlChunks step (SP salt 0)
674-
where
675-
finalise (SP s l) = hashWithSalt s l
676-
step (SP s l) bs = unsafeDupablePerformIO $
677-
B.unsafeUseAsCStringLen bs $ \(p, len) -> do
678-
s' <- hashPtrWithSalt p (fromIntegral len) s
679-
return (SP s' (l + len))
671+
hashWithSalt = hashLazyByteStringWithSalt
680672

681673
#if MIN_VERSION_bytestring(0,10,4)
682674
instance Hashable BSI.ShortByteString where
@@ -690,12 +682,7 @@ instance Hashable T.Text where
690682
(hashWithSalt salt len)
691683

692684
instance Hashable TL.Text where
693-
hashWithSalt salt = finalise . TL.foldlChunks step (SP salt 0)
694-
where
695-
finalise (SP s l) = hashWithSalt s l
696-
step (SP s l) (T.Text arr off len) = SP
697-
(hashByteArrayWithSalt (TA.aBA arr) (off `shiftL` 1) (len `shiftL` 1) s)
698-
(l + len)
685+
hashWithSalt = hashLazyTextWithSalt
699686

700687
-- | Compute the hash of a ThreadId.
701688
hashThreadId :: ThreadId -> Int
@@ -781,20 +768,6 @@ hashPtr :: Ptr a -- ^ pointer to the data to hash
781768
-> IO Int -- ^ hash value
782769
hashPtr p len = hashPtrWithSalt p len defaultSalt
783770

784-
-- | Compute a hash value for the content of this pointer, using an
785-
-- initial salt.
786-
--
787-
-- This function can for example be used to hash non-contiguous
788-
-- segments of memory as if they were one contiguous segment, by using
789-
-- the output of one hash as the salt for the next.
790-
hashPtrWithSalt :: Ptr a -- ^ pointer to the data to hash
791-
-> Int -- ^ length, in bytes
792-
-> Int -- ^ salt
793-
-> IO Int -- ^ hash value
794-
hashPtrWithSalt p len salt =
795-
fromIntegral `fmap` c_siphash24 k0 (fromSalt salt) (castPtr p)
796-
(fromIntegral len)
797-
798771
-- | Compute a hash value for the content of this 'ByteArray#',
799772
-- beginning at the specified offset, using specified number of bytes.
800773
hashByteArray :: ByteArray# -- ^ data to hash
@@ -804,37 +777,6 @@ hashByteArray :: ByteArray# -- ^ data to hash
804777
hashByteArray ba0 off len = hashByteArrayWithSalt ba0 off len defaultSalt
805778
{-# INLINE hashByteArray #-}
806779

807-
-- | Compute a hash value for the content of this 'ByteArray#', using
808-
-- an initial salt.
809-
--
810-
-- This function can for example be used to hash non-contiguous
811-
-- segments of memory as if they were one contiguous segment, by using
812-
-- the output of one hash as the salt for the next.
813-
hashByteArrayWithSalt
814-
:: ByteArray# -- ^ data to hash
815-
-> Int -- ^ offset, in bytes
816-
-> Int -- ^ length, in bytes
817-
-> Int -- ^ salt
818-
-> Int -- ^ hash value
819-
hashByteArrayWithSalt ba !off !len !h =
820-
fromIntegral $
821-
c_siphash24_offset k0 (fromSalt h) ba (fromIntegral off) (fromIntegral len)
822-
823-
k0 :: Word64
824-
k0 = 0x56e2b8a0aee1721a
825-
{-# INLINE k0 #-}
826-
827-
fromSalt :: Int -> Word64
828-
#if WORD_SIZE_IN_BITS == 64
829-
fromSalt = fromIntegral
830-
#else
831-
fromSalt v = fromIntegral v `xor` k1
832-
833-
k1 :: Word64
834-
k1 = 0x7654954208bdfef9
835-
{-# INLINE k1 #-}
836-
#endif
837-
838780
-- | Combine two given hash values. 'combine' has zero as a left
839781
-- identity.
840782
combine :: Int -> Int -> Int
@@ -1078,8 +1020,6 @@ instance Hashable IntSet.IntSet where
10781020
instance Hashable1 Seq.Seq where
10791021
liftHashWithSalt h s x = F.foldl' h (hashWithSalt s (Seq.length x)) x
10801022

1081-
foreign import ccall unsafe "hashable_siphash24_offset" c_siphash24_offset
1082-
:: Word64 -> Word64 -> ByteArray# -> CSize -> CSize -> Word64
10831023

10841024
-- | @since 1.3.4.0
10851025
instance Hashable v => Hashable (Seq.Seq v) where
@@ -1092,44 +1032,3 @@ instance Hashable1 Tree.Tree where
10921032
-- | @since 1.3.4.0
10931033
instance Hashable v => Hashable (Tree.Tree v) where
10941034
hashWithSalt = hashWithSalt1
1095-
foreign import ccall unsafe "hashable_siphash24" c_siphash24
1096-
:: Word64 -> Word64 -> Ptr Word8 -> CSize -> IO Word64
1097-
<<<<<<< variant A
1098-
>>>>>>> variant B
1099-
1100-
hashLazyByteStringWithSalt :: Int -> BL.ByteString -> Int
1101-
hashLazyByteStringWithSalt salt cs0 = unsafePerformIO . allocaArray 5 $ \v -> do
1102-
c_siphash_init k0 (fromSalt salt) v
1103-
let go !buffered !totallen (BL.Chunk c cs) =
1104-
B.unsafeUseAsCStringLen c $ \(ptr, len) -> do
1105-
let len' = fromIntegral len
1106-
buffered' <- c_siphash24_chunk buffered v (castPtr ptr) len' (-1)
1107-
go buffered' (totallen + len') cs
1108-
go buffered totallen _ = do
1109-
_ <- c_siphash24_chunk buffered v nullPtr 0 totallen
1110-
fromIntegral `fmap` peek (v `advancePtr` 4)
1111-
go 0 0 cs0
1112-
1113-
foreign import ccall unsafe "hashable_siphash24_chunk" c_siphash24_chunk
1114-
:: CInt -> Ptr Word64 -> Ptr Word8 -> CSize -> CSize -> IO CInt
1115-
1116-
foreign import ccall unsafe "hashable_siphash_init" c_siphash_init
1117-
:: Word64 -> Word64 -> Ptr Word64 -> IO ()
1118-
1119-
hashLazyTextWithSalt :: Int -> TL.Text -> Int
1120-
hashLazyTextWithSalt salt cs0 = unsafePerformIO . allocaArray 5 $ \v -> do
1121-
c_siphash_init k0 (fromSalt salt) v
1122-
let go !buffered !totallen (TL.Chunk (T.Text arr off len) cs) = do
1123-
let len' = fromIntegral (len `shiftL` 1)
1124-
buffered' <- c_siphash24_chunk_offset buffered v (TA.aBA arr)
1125-
(fromIntegral (off `shiftL` 1)) len' (-1)
1126-
go buffered' (totallen + len') cs
1127-
go buffered totallen _ = do
1128-
_ <- c_siphash24_chunk buffered v nullPtr 0 totallen
1129-
fromIntegral `fmap` peek (v `advancePtr` 4)
1130-
go 0 0 cs0
1131-
1132-
foreign import ccall unsafe "hashable_siphash24_chunk_offset"
1133-
c_siphash24_chunk_offset
1134-
:: CInt -> Ptr Word64 -> ByteArray# -> CSize -> CSize -> CSize -> IO CInt
1135-
======= end

src/Data/Hashable/LowLevel.hs

Lines changed: 87 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,35 @@ module Data.Hashable.LowLevel (
99
hashWord64,
1010
hashPtrWithSalt,
1111
hashByteArrayWithSalt,
12+
hashLazyTextWithSalt,
13+
hashLazyByteStringWithSalt
1214
) where
1315

1416
#include "MachDeps.h"
1517

1618
import Data.Bits (xor)
1719
import Data.Int (Int64)
18-
import Data.Word (Word64)
20+
import Data.Word (Word64, Word8)
1921
import Foreign.C (CString)
2022
import Foreign.Ptr (Ptr, castPtr)
2123
import GHC.Base (ByteArray#)
24+
import Foreign.C.Types (CInt(..))
25+
import qualified Data.Text.Array as TA
26+
import qualified Data.Text.Internal as T
27+
import qualified Data.Text as T
28+
import qualified Data.Text.Lazy as TL
29+
import qualified Data.Text.Internal.Lazy as TL
30+
import qualified Data.ByteString as B
31+
import qualified Data.ByteString.Unsafe as B
32+
import qualified Data.ByteString.Lazy as BL
33+
import Foreign.Marshal.Array(advancePtr, allocaArray)
34+
import System.IO.Unsafe(unsafePerformIO)
35+
import Foreign.Storable (alignment, peek, sizeOf)
36+
import Foreign.Ptr(nullPtr)
37+
import Data.Bits (shiftL, shiftR, xor)
38+
#if (MIN_VERSION_bytestring(0,10,0))
39+
import qualified Data.ByteString.Lazy.Internal as BL -- foldlChunks
40+
#endif
2241

2342
#ifdef HASHABLE_RANDOM_SEED
2443
import System.IO.Unsafe (unsafePerformIO)
@@ -27,6 +46,11 @@ import System.IO.Unsafe (unsafePerformIO)
2746
#if WORD_SIZE_IN_BITS != 64
2847
import Data.Bits (shiftR)
2948
#endif
49+
#if __GLASGOW_HASKELL__ >= 703
50+
import Foreign.C (CSize(..))
51+
#else
52+
import Foreign.C (CSize)
53+
#endif
3054

3155
-------------------------------------------------------------------------------
3256
-- Initial seed
@@ -96,8 +120,8 @@ hashPtrWithSalt :: Ptr a -- ^ pointer to the data to hash
96120
-> Salt -- ^ salt
97121
-> IO Salt -- ^ hash value
98122
hashPtrWithSalt p len salt =
99-
fromIntegral `fmap` c_hashCString (castPtr p) (fromIntegral len)
100-
(fromIntegral salt)
123+
fromIntegral `fmap` c_siphash24 k0 (fromSalt salt) (castPtr p)
124+
(fromIntegral len)
101125

102126
-- | Compute a hash value for the content of this 'ByteArray#', using
103127
-- an initial salt.
@@ -112,8 +136,23 @@ hashByteArrayWithSalt
112136
-> Salt -- ^ salt
113137
-> Salt -- ^ hash value
114138
hashByteArrayWithSalt ba !off !len !h =
115-
fromIntegral $ c_hashByteArray ba (fromIntegral off) (fromIntegral len)
116-
(fromIntegral h)
139+
fromIntegral $
140+
c_siphash24_offset k0 (fromSalt h) ba (fromIntegral off) (fromIntegral len)
141+
142+
k0 :: Word64
143+
k0 = 0x56e2b8a0aee1721a
144+
{-# INLINE k0 #-}
145+
146+
fromSalt :: Int -> Word64
147+
#if WORD_SIZE_IN_BITS == 64
148+
fromSalt = fromIntegral
149+
#else
150+
fromSalt v = fromIntegral v `xor` k1
151+
152+
k1 :: Word64
153+
k1 = 0x7654954208bdfef9
154+
{-# INLINE k1 #-}
155+
#endif
117156

118157
foreign import capi unsafe "HsHashable.h hashable_fnv_hash" c_hashCString
119158
#if WORD_SIZE_IN_BITS == 64
@@ -132,3 +171,46 @@ foreign import ccall unsafe "hashable_fnv_hash_offset" c_hashByteArray
132171
#else
133172
:: ByteArray# -> Int32 -> Int32 -> Int32 -> Word32
134173
#endif
174+
175+
foreign import ccall unsafe "hashable_siphash24_offset" c_siphash24_offset
176+
:: Word64 -> Word64 -> ByteArray# -> CSize -> CSize -> Word64
177+
178+
foreign import ccall unsafe "hashable_siphash24" c_siphash24
179+
:: Word64 -> Word64 -> Ptr Word8 -> CSize -> IO Word64
180+
181+
182+
hashLazyByteStringWithSalt :: Int -> BL.ByteString -> Int
183+
hashLazyByteStringWithSalt salt cs0 = unsafePerformIO . allocaArray 5 $ \v -> do
184+
c_siphash_init k0 (fromSalt salt) v
185+
let go !buffered !totallen (BL.Chunk c cs) =
186+
B.unsafeUseAsCStringLen c $ \(ptr, len) -> do
187+
let len' = fromIntegral len
188+
buffered' <- c_siphash24_chunk buffered v (castPtr ptr) len' (-1)
189+
go buffered' (totallen + len') cs
190+
go buffered totallen _ = do
191+
_ <- c_siphash24_chunk buffered v nullPtr 0 totallen
192+
fromIntegral `fmap` peek (v `advancePtr` 4)
193+
go 0 0 cs0
194+
195+
foreign import ccall unsafe "hashable_siphash24_chunk" c_siphash24_chunk
196+
:: CInt -> Ptr Word64 -> Ptr Word8 -> CSize -> CSize -> IO CInt
197+
198+
foreign import ccall unsafe "hashable_siphash_init" c_siphash_init
199+
:: Word64 -> Word64 -> Ptr Word64 -> IO ()
200+
201+
hashLazyTextWithSalt :: Int -> TL.Text -> Int
202+
hashLazyTextWithSalt salt cs0 = unsafePerformIO . allocaArray 5 $ \v -> do
203+
c_siphash_init k0 (fromSalt salt) v
204+
let go !buffered !totallen (TL.Chunk (T.Text arr off len) cs) = do
205+
let len' = fromIntegral (len `shiftL` 1)
206+
buffered' <- c_siphash24_chunk_offset buffered v (TA.aBA arr)
207+
(fromIntegral (off `shiftL` 1)) len' (-1)
208+
go buffered' (totallen + len') cs
209+
go buffered totallen _ = do
210+
_ <- c_siphash24_chunk buffered v nullPtr 0 totallen
211+
fromIntegral `fmap` peek (v `advancePtr` 4)
212+
go 0 0 cs0
213+
214+
foreign import ccall unsafe "hashable_siphash24_chunk_offset"
215+
c_siphash24_chunk_offset
216+
:: CInt -> Ptr Word64 -> ByteArray# -> CSize -> CSize -> CSize -> IO CInt

tests/Regress.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ regressions = [] ++
4949
#if WORD_SIZE_IN_BITS == 64
5050
, testCase "64 bit Text" $ do
5151
hash ("hello world" :: Text) @=?
52-
2930784640930823038 -- siphash
52+
(-4389506060771033211) -- siphash
5353
-- -3875242662334356092 -- FNV
5454
#endif
5555
, F.testGroup "concatenation"

0 commit comments

Comments
 (0)