#include "spvm_native.h"
// https://github.com/gcc-mirror/gcc/blob/master/libstdc++-v3/libsupc++/hash_bytes.cc#L72-L112
int32_t SPVM__Hash___murmur_hash(SPVM_ENV* env, SPVM_VALUE* stack) {
(void)env;
void* object = stack[0].oval;
uint32_t seed = stack[1].ival;
const char* buf = env->get_chars(env, object);
uint32_t len = env->length(env, object);
uint32_t m = 0x5bd1e995;
uint32_t hash = seed ^ len;
// Mix 4 bytes at a time into the hash.
while(len >= 4) {
uint32_t k;
memcpy(&k, buf, sizeof(k));
k *= m;
k ^= k >> 24;
k *= m;
hash *= m;
hash ^= k;
buf += 4;
len -= 4;
}
// Handle the last few bytes of the input array.
switch(len) {
case 3:
hash ^= (unsigned char)buf[2] << 16;
case 2:
hash ^= (unsigned char)buf[1] << 8;
case 1:
hash ^= (unsigned char)buf[0];
hash *= m;
};
// Do a few final mixes of the hash.
hash ^= hash >> 13;
hash *= m;
hash ^= hash >> 15;
stack[0].lval = hash; // return a long value to ensure being positive.
return 0;
}