Last active
September 16, 2020 23:46
-
-
Save SilkyPants/b6249bd9f042537b32bc758167cf4930 to your computer and use it in GitHub Desktop.
Murmur3 ported to Dart - using https://github.com/darrenkopp/murmurhash-net as a base
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import 'dart:core'; | |
| import 'dart:typed_data'; | |
| import 'dart:convert'; | |
| class Murmur32 | |
| { | |
| int c1 = 0xcc9e2d51.toUnsigned(32); | |
| int c2 = 0x1b873593.toUnsigned(32); | |
| int _seed; | |
| Murmur32(int seed) | |
| { | |
| _seed = seed.toUnsigned(32); | |
| _reset(); | |
| } | |
| int get seed => _seed; | |
| int h1; | |
| int length; | |
| void _reset() | |
| { | |
| h1 = seed; | |
| length = 0; | |
| } | |
| ByteData computeHashFromString(String source) { | |
| Uint8List buffer = Uint8List.fromList(utf8.encode(source)); | |
| return computeHash(buffer, 0, buffer.length); | |
| } | |
| ByteData computeHash(Uint8List buffer, int offset, int count) | |
| { | |
| _reset(); | |
| hashCore(buffer, 0, buffer.length); | |
| h1 = fMix((h1 ^ length).toUnsigned(32)); | |
| return ByteData(4)..buffer.asByteData().setUint32(0, h1); | |
| } | |
| int fMix(int h) { | |
| // pipelining friendly algorithm | |
| h = ((h ^ (h >> 16)) * 0x85ebca6b).toUnsigned(32); | |
| h = ((h ^ (h >> 13)) * 0xc2b2ae35).toUnsigned(32); | |
| return (h ^ (h >> 16)).toUnsigned(32); | |
| } | |
| int rotateLeft(int x, int r) { | |
| return ((x << r) | (x >> (32 - r))).toUnsigned(32); | |
| } | |
| int toUint32(Uint8List data, int start) { | |
| return Endian.host == Endian.little | |
| ? (data[start] | data[start + 1] << 8 | data[start + 2] << 16 | data[start + 3] << 24) | |
| : (data[start] << 24 | data[start + 1] << 16 | data[start + 2] << 8 | data[start + 3]); | |
| } | |
| void hashCore(Uint8List buffer, int start, int count) { | |
| length += count.toUnsigned(32); | |
| int remainder = count & 3; | |
| int alignedLength = (start + (count - remainder)).toUnsigned(32); | |
| for (int i = start; i < alignedLength; i += 4) { | |
| var v1 = (toUint32(buffer, i) * c1).toUnsigned(32); | |
| var v2 = rotateLeft(v1, 15); | |
| var v3 = (v2 * c2).toUnsigned(32); | |
| var v4 = (h1 ^ v3).toUnsigned(32); | |
| var v5 = rotateLeft(v4, 13); | |
| var v6 = (v5 * 5).toUnsigned(32); | |
| h1 = (v6 + 0xe6546b64).toUnsigned(32); | |
| } | |
| if (remainder > 0) { | |
| // create our keys and initialize to 0 | |
| int k1 = 0; | |
| // determine how many bytes we have left to work with based on length | |
| switch (remainder) | |
| { | |
| case 3: | |
| k1 ^= (buffer[alignedLength + 2] << 16).toUnsigned(32); | |
| continue case2; | |
| case2: | |
| case 2: | |
| k1 ^= (buffer[alignedLength + 1] << 8).toUnsigned(32); | |
| continue case1; | |
| case1: | |
| case 1: | |
| k1 ^= buffer[alignedLength]; | |
| break; | |
| } | |
| h1 ^= (rotateLeft((k1 * c1).toUnsigned(32), 15) * c2).toUnsigned(32); | |
| } | |
| } | |
| } | |
| void main() { | |
| var key = '布瑞恩氏 大型短管磁轨炮'; | |
| var seed = 2538058380; | |
| Uint8List buffer = Uint8List.fromList(utf8.encode(key)); | |
| var mmh = Murmur32(seed); | |
| var val = mmh.computeHashFromString(key); | |
| var byteData = ByteData.sublistView(val); | |
| print("$key = $val = ${byteData.getUint32(0)} (expecting 2170369764L)"); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment