Skip to content
Browse files

Merge pull request #8 from ToJans/master

Murmur3AUnsafeHash respects byte array boundaries during hashing. Fixes #6 .
  • Loading branch information...
2 parents 1d633b2 + c5a5f94 commit 984860df8acf108eb67af2bff9d6a484fda059fa @gregoryyoung gregoryyoung committed Oct 10, 2012
View
1 src/EventStore/EventStore.Core.Tests/EventStore.Core.Tests.csproj
@@ -83,6 +83,7 @@
<Compile Include="Fakes\NoopPublisher.cs" />
<Compile Include="Index\adding_four_items_to_empty_index_map_with_two_tables_per_level_causes_double_merge.cs" />
<Compile Include="Index\adding_two_items_to_empty_index_map_with_two_tables_per_level_causes_merge.cs" />
+ <Compile Include="Index\create_hashcode_from_byte_arrays.cs" />
<Compile Include="Index\create_index_map_from_non_existing_file.cs" />
<Compile Include="Index\adding_four_items_to_empty_index_map_with_four_tables_per_level_causes_merge.cs" />
<Compile Include="Index\adding_item_to_empty_index_map.cs" />
View
51 src/EventStore/EventStore.Core.Tests/Index/create_hashcode_from_byte_arrays.cs
@@ -0,0 +1,51 @@
+// Copyright (c) 2012, Event Store LLP
+// 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 the Event Store LLP nor the names of its
+// 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
+// HOLDER 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.
+//
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using NUnit.Framework;
+using EventStore.Core.Index.Hashes;
+
+namespace EventStore.Core.Tests.Index
+{
+ [TestFixture]
+ class create_hashcode_from_byte_arrays
+ {
+ [Test]
+ public void Murmur32Unsafe_works_with_byte_arrays_with_length_not_divisable_by_4()
+ {
+ var byte_array_with_length_not_divisable_by_4 = new byte[]{0, 1, 2, 3, 4, 5, 6};
+ var SUT = new Murmur3AUnsafe();
+ unsafe
+ {
+ Assert.AreEqual((uint)0x7B5DE42E, SUT.Hash(byte_array_with_length_not_divisable_by_4));
+ }
+ }
+ }
+}
View
20 src/EventStore/EventStore.Core/Index/Hashes/Murmur3AUnsafe.cs
@@ -29,7 +29,7 @@
namespace EventStore.Core.Index.Hashes
{
- public class Murmur3AUnsafe: IHasher
+ public class Murmur3AUnsafe : IHasher
{
private const uint Seed = 0xc58f1a7b;
@@ -57,12 +57,12 @@ private unsafe static uint Hash(byte* data, uint len, uint seed)
{
UInt32 nblocks = len / 4;
UInt32 h1 = seed;
-
+
//----------
// body
UInt32 k1;
- UInt32* block = (UInt32*) data;
+ UInt32* block = (UInt32*)data;
for (UInt32 i = nblocks; i > 0; --i, ++block)
{
k1 = *block;
@@ -73,20 +73,22 @@ private unsafe static uint Hash(byte* data, uint len, uint seed)
h1 ^= k1;
h1 = Rotl32(h1, 13);
- h1 = h1*5 + 0xe6546b64;
+ h1 = h1 * 5 + 0xe6546b64;
}
//----------
// tail
- k1 = 0;
uint rem = len & 3;
- if (rem >= 3)
- k1 ^= block[2] << 16;
- if (rem >= 2)
- k1 ^= block[1] << 8;
if (rem > 0)
{
+ k1 = 0;
+ byte* lastbytes = (byte*)block;
+ while (rem-- > 0)
+ {
+ k1 <<= 8;
+ k1 ^= lastbytes++[0];
+ }
k1 ^= block[0];
k1 *= c1;
k1 = Rotl32(k1, 15);

0 comments on commit 984860d

Please sign in to comment.
Something went wrong with that request. Please try again.