|
|
- #include <stdint.h>
- #include <string.h>
- #include "erl_nif.h"
-
- typedef struct {
- size_t keySize;
- size_t bblSize_1;
- size_t bblSize_2;
- struct _bbl **arrayPtr;
- } hashb;
-
- typedef struct _bbl {
- struct _node *head;
- } bbl;
-
- typedef struct _node {
- struct _node *next;
- ErlNifBinary Key;
- ErlNifBinary Value;
- } node;
-
- #define BBLSIZE_1 128
- #define BBLSIZE_2 128
-
- static ErlNifResourceType *ResType = NULL;
- static ERL_NIF_TERM undefined;
- static ERL_NIF_TERM ok;
-
- ///////////////////////////////hash 函数 /////////////////////////////
- static uint32_t fnv_hash(const unsigned char *data, size_t size, uint32_t salt) {
- uint32_t i;
- uint64_t hashv;
- const unsigned char *_hf_key = (const unsigned char *) (data);
- hashv = 2166136261;
- for (i = 0; i < size; i++) {
- hashv = hashv ^ _hf_key[i];
- hashv = hashv * 16777619;
- }
- //enif_fprintf(stdout, "IMY************get %T \n", argv[1]);
- return hashv;
- }
-
- static uint32_t murmurhash(const unsigned char *key, uint32_t len, uint32_t seed) {
- //uint32_t c1 = 0xcc9e2d51;
- //uint32_t c2 = 0x1b873593;
- //uint32_t r1 = 15;
- //uint32_t r2 = 13;
- //uint32_t m = 5;
- //uint32_t n = 0xe6546b64;
- uint32_t h = 0;
- uint32_t k = 0;
- uint8_t *d = (uint8_t *) key; // 32 bit extract from `key'
- const uint32_t *chunks = NULL;
- const uint8_t *tail = NULL; // tail - last 8 bytes
- int i = 0;
- int l = len / 4; // chunk length
-
- h = seed;
-
- chunks = (const uint32_t *) (d + l * 4); // body
- tail = (const uint8_t *) (d + l * 4); // last 8 byte chunk of `key'
-
- // for each 4 byte chunk of `key'
- for (i = -l; i != 0; ++i) {
- // next 4 byte chunk of `key'
- k = chunks[i];
-
- // encode next 4 byte chunk of `key'
- k *= 0xcc9e2d51;
- k = (k << 15) | (k >> (32 - 15));
- k *= 0x1b873593;
-
- // append to hash
- h ^= k;
- h = (h << 13) | (h >> (32 - 13));
- h = h * 5 + 0xe6546b64;
- }
-
- k = 0;
-
- // remainder
- switch (len & 3) { // `len % 4'
- case 3:
- k ^= (tail[2] << 16);
- case 2:
- k ^= (tail[1] << 8);
- case 1:
- k ^= tail[0];
- k *= 0xcc9e2d51;
- k = (k << 15) | (k >> (32 - 15));
- k *= 0x1b873593;
- h ^= k;
- }
-
- h ^= len;
-
- h ^= (h >> 16);
- h *= 0x85ebca6b;
- h ^= (h >> 13);
- h *= 0xc2b2ae35;
- h ^= (h >> 16);
-
- return h;
- }
-
- //////////////////////////////////hash 函数测试///////////////////////////
- static ERL_NIF_TERM hash1(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
- ErlNifBinary Value;
- if (!enif_term_to_binary(env, argv[0], &Value))
- return enif_make_badarg(env);
-
- uint32_t Salt;
- if (!enif_get_uint(env, argv[1], &Salt)) {
- return enif_make_badarg(env);
- }
-
- Salt = fnv_hash(Value.data, Value.size, Salt);
- enif_release_binary(&Value);
- return ok;
-
- };
-
- static ERL_NIF_TERM hash2(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
- ErlNifUInt64 Salt;
- if (!enif_get_uint64(env, argv[1], &Salt))
- return enif_make_badarg(env);
-
- ErlNifBinary Value;
- if (!enif_term_to_binary(env, argv[0], &Value))
- return enif_make_badarg(env);
- enif_release_binary(&Value);
- Salt = enif_hash(ERL_NIF_INTERNAL_HASH, argv[1], 2423432432);
- return ok;
- };
-
- static ERL_NIF_TERM hash3(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
- ErlNifUInt64 Salt;
- if (!enif_get_uint64(env, argv[1], &Salt))
- return enif_make_badarg(env);
-
- ErlNifBinary Value;
- if (!enif_term_to_binary(env, argv[0], &Value))
- return enif_make_badarg(env);
- Salt = murmurhash(Value.data, Value.size, 0);
- enif_release_binary(&Value);
- return ok;
- };
-
- static uint8_t compareChar1(const unsigned char *src, const unsigned char *dst, size_t Size) {
-
- // int j = 0;
- // unsigned char *tsrc, *tdst;
- // tsrc = src;
- // tdst = dst;
- // for(j = 0; j <= Size; j++)
- // {
- // enif_fprintf(stdout, "IMY************get9999111 src %d dst %d \n", *tsrc, *tdst);
- // tsrc++;
- // tdst++;
- // }
- uint8_t i = 0;
- while (i < Size-1 && (*src == *dst)) {
- // enif_fprintf(stdout, "IMY************get99992222 %d %d \n", *src, *dst);
- src++;
- dst++;
- i++;
- }
- //enif_fprintf(stdout, "IMY************get9999while end %d %d \n", *src, *dst);
- if (*src != *dst) {
- //enif_fprintf(stdout, "IMY************get99993333 %d %d \n", *src, *dst);
- return 1;
- } else {
- //enif_fprintf(stdout, "IMY************get99995555 %d %d \n", *src, *dst);
- return 0;
- }
- }
-
- static uint8_t compareChar2(const unsigned char *src, const unsigned char *dst, size_t Size) {
- const uint32_t *intSrc = NULL;
- const uint32_t *intDst = NULL;
- const uint8_t *tailSrc = NULL; // tail - last 8 bytes
- const uint8_t *tailDst = NULL; // tail - last 8 bytes
- int l = Size / 4; // chunk length
-
- intSrc = (const uint32_t *) src; // body
- intDst = (const uint32_t *) dst; // body
- tailSrc = (const uint8_t *) (src + l * 4); // last 8 byte chunk of `key'
- tailDst = (const uint8_t *) (dst + l * 4); // last 8 byte chunk of `key'
-
- // for each 4 byte chunk of `key'
- int i = 0;
- for (i = 0; i < l; i++) {
- if (intSrc[i] != intDst[i])
- return 1;
- }
- // remainder
- switch (Size & 3) {
- case 3:
- if (tailSrc[0] != tailDst[0] || tailSrc[1] != tailDst[1] || tailSrc[2] != tailDst[2]) {
- return 1;
- }
- break;
- case 2:
- if (tailSrc[0] != tailDst[0] || tailSrc[1] != tailDst[1]) {
- return 1;
- }
- break;
- case 1:
- if (tailSrc[0] != tailDst[0]) {
- return 1;
- }
- break;
- }
- return 0;
- }
-
- static ERL_NIF_TERM compareBin1(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
- ErlNifBinary src, dst;
-
- if (!(enif_inspect_binary(env, argv[0], &src) && enif_inspect_binary(env, argv[1], &dst)))
- return enif_make_badarg(env);
-
- if (src.size != dst.size) {
- return enif_make_int(env, 1);
- }
- int Ret = compareChar1(src.data, dst.data, src.size);
- return enif_make_int(env, Ret);
- }
-
- static ERL_NIF_TERM compareBin2(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
- ErlNifBinary src, dst;
- if (!(enif_inspect_binary(env, argv[0], &src) && enif_inspect_binary(env, argv[1], &dst)))
- return enif_make_badarg(env);
-
- if (src.size != dst.size) {
- return enif_make_int(env, 1);
- }
- int Ret = compareChar2(src.data, dst.data, src.size);
- return enif_make_int(env, Ret);
- }
-
- /////////////////////////////////////////////////////////////////////
-
- static int load(ErlNifEnv *env, void **priv, ERL_NIF_TERM load_info) {
- ErlNifResourceFlags flags = ERL_NIF_RT_CREATE | ERL_NIF_RT_TAKEOVER;
- ResType = enif_open_resource_type(env, NULL, "_nifHashb_", NULL, flags, NULL);
- if (NULL == ResType)
- return -1;
- undefined = enif_make_atom(env, "undefined");
- ok = enif_make_atom(env, "ok");
- return 0;
- }
-
- static ERL_NIF_TERM new(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
- hashb *ResPtr = (hashb *) enif_alloc_resource(ResType, sizeof(hashb));
- ResPtr->keySize = 0;
- ResPtr->bblSize_1 = BBLSIZE_1;
- ResPtr->bblSize_2 = BBLSIZE_2;
- ResPtr->arrayPtr = enif_alloc(sizeof(bbl *) * BBLSIZE_1);
- int i, j;
- bbl NullBbl;
- NullBbl.head = NULL;
- for (i = 0; i < BBLSIZE_1; i++) {
- ResPtr->arrayPtr[i] = enif_alloc(sizeof(bbl) * BBLSIZE_2);
- for (j = 0; j < BBLSIZE_2; j++) {
- ResPtr->arrayPtr[i][j] = NullBbl;
- }
- }
- ERL_NIF_TERM Res = enif_make_resource(env, ResPtr);
- enif_release_resource(ResPtr);
- return Res;
- }
-
- static uint8_t compareChar(const unsigned char *src, const unsigned char *dst, size_t Size) {
- const uint32_t *intSrc = NULL;
- const uint32_t *intDst = NULL;
- const uint8_t *tailSrc = NULL; // tail - last 8 bytes
- const uint8_t *tailDst = NULL; // tail - last 8 bytes
- int l = Size / 4; // chunk length
-
- intSrc = (const uint32_t *) src; // body
- intDst = (const uint32_t *) dst; // body
- tailSrc = (const uint8_t *) (src + l * 4); // last 8 byte chunk of `key'
- tailDst = (const uint8_t *) (dst + l * 4); // last 8 byte chunk of `key'
-
- // for each 4 byte chunk of `key'
- int i = 0;
- for (i = 0; i < l; i++) {
- if (intSrc[i] != intDst[i])
- return 1;
- }
- // remainder
- switch (Size & 3) {
- case 3:
- if (tailSrc[0] != tailDst[0] || tailSrc[1] != tailDst[1] || tailSrc[2] != tailDst[2]) {
- return 1;
- }
- break;
- case 2:
- if (tailSrc[0] != tailDst[0] || tailSrc[1] != tailDst[1]) {
- return 1;
- }
- break;
- case 1:
- if (tailSrc[0] != tailDst[0]) {
- return 1;
- }
- break;
- }
- return 0;
- }
-
- static uint8_t compareBin(ErlNifBinary src, ErlNifBinary dst) {
- if (src.size != dst.size) {
- //enif_fprintf(stdout, "IMY************get8888\n");
- return 1;
- }
- //enif_fprintf(stdout, "IMY************get8888111 %d \n", src.size);
- return compareChar(src.data, dst.data, src.size);
- }
-
- static ERL_NIF_TERM get(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
- hashb *ResPtr;
-
- if (!enif_get_resource(env, argv[0], ResType, (void **) &ResPtr)) {
- return enif_make_badarg(env);
- }
- //enif_fprintf(stdout, "IMY************get1111\n");
-
-
- uint32_t BblIndex_1, BblIndex_2;
- if(!enif_get_uint(env, argv[1], &BblIndex_1)) {
- return enif_make_badarg(env);
- }
-
- //enif_fprintf(stdout, "IMY************get22221111\n");
-
- if(!enif_get_uint(env, argv[2], &BblIndex_2)) {
- return enif_make_badarg(env);
- }
- //enif_fprintf(stdout, "IMY************get2222\n");
- BblIndex_1 = BblIndex_1 % ResPtr->bblSize_1;
- BblIndex_2 = BblIndex_2 % ResPtr->bblSize_2;
- //enif_fprintf(stdout, "IMY************get3333\n");
- if (NULL == ResPtr->arrayPtr[BblIndex_1][BblIndex_2].head) {
- //enif_fprintf(stdout, "IMY************get4444\n");
- return undefined;
- } else {
- //enif_fprintf(stdout, "IMY************get55555\n");
- ErlNifBinary getKey;
- if (!enif_inspect_binary(env, argv[3], &getKey))
- return enif_make_badarg(env);
- node *Head = ResPtr->arrayPtr[BblIndex_1][BblIndex_2].head;
- while (Head) {
- //enif_fprintf(stdout, "IMY************get7777\n");
- if (compareBin(getKey, Head->Key) == 0) {
- ERL_NIF_TERM Ret;
- enif_binary_to_term(env, Head->Value.data, Head->Value.size, &Ret, 0);
- //enif_fprintf(stdout, "IMY************get5555\n");
- return Ret;
- }
- Head = Head->next;
- }
- //enif_fprintf(stdout, "IMY************get6666\n");
- return undefined;
- }
- }
-
- static ERL_NIF_TERM put(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
- hashb *ResPtr;
-
- if (!enif_get_resource(env, argv[0], ResType, (void **) &ResPtr)) {
- return enif_make_badarg(env);
- }
- //enif_fprintf(stdout, "IMY************put111 \n");
-
- uint32_t BblIndex_1, BblIndex_2;
- if(!enif_get_uint(env, argv[1], &BblIndex_1)) {
- return enif_make_badarg(env);
- }
- if(!enif_get_uint(env, argv[2], &BblIndex_2)) {
- return enif_make_badarg(env);
- }
-
- BblIndex_1 = BblIndex_1 % ResPtr->bblSize_1;
- BblIndex_2 = BblIndex_2 % ResPtr->bblSize_2;
-
- ErlNifBinary Key, Value;
- if (!enif_inspect_binary(env, argv[3], &Key))
- return enif_make_badarg(env);
-
- if (!enif_inspect_binary(env, argv[4], &Value))
- return enif_make_badarg(env);
-
- //enif_fprintf(stdout, "IMY************put222 %d %d \n", BblIndex_1, BblIndex_2);
-
- //enif_fprintf(stdout, "IMY************put3333 \n");
- if (NULL == ResPtr->arrayPtr[BblIndex_1][BblIndex_2].head) {
- node *NewNode = enif_alloc(sizeof(node));
- enif_alloc_binary(Key.size, &NewNode->Key);
- enif_alloc_binary(Value.size, &NewNode->Value);
- memcpy(NewNode->Key.data, Key.data, Key.size);
- memcpy(NewNode->Value.data, Value.data, Value.size);
- NewNode->next = NULL;
- ResPtr->arrayPtr[BblIndex_1][BblIndex_2].head = NewNode;
- ResPtr->keySize = ResPtr->keySize + 1;
- //enif_fprintf(stdout, "IMY************put4444 \n");
- return ok;
- } else {
- node *Head = ResPtr->arrayPtr[BblIndex_1][BblIndex_2].head;
- while (Head) {
- if (compareBin(Key, Head->Key) == 0) {
- //ERL_NIF_TERM Ret;
- ErlNifBinary OldValue = Head->Value;
- enif_release_binary(&OldValue);
- //enif_binary_to_term(env, OldValue.data, OldValue.size, &Ret, 0);
- ErlNifBinary NewValue;
- enif_alloc_binary(Value.size, &NewValue);
- memcpy(NewValue.data, Value.data, Value.size);
- Head->Value = NewValue;
- //enif_fprintf(stdout, "IMY************put55555 \n");
- //return Ret;
- return ok;
- }
- Head = Head->next;
- }
- node *NewNode = enif_alloc(sizeof(node));
- enif_alloc_binary(Key.size, &NewNode->Key);
- enif_alloc_binary(Value.size, &NewNode->Value);
- memcpy(NewNode->Key.data, Key.data, Key.size);
- memcpy(NewNode->Value.data, Value.data, Value.size);
- NewNode->next = ResPtr->arrayPtr[BblIndex_1][BblIndex_2].head;
- ResPtr->arrayPtr[BblIndex_1][BblIndex_2].head = NewNode;
- ResPtr->keySize = ResPtr->keySize + 1;
- //enif_fprintf(stdout, "IMY************put6666\n");
- return ok;
- }
- }
- /////////////////////////////////////////////////////////////////////////
-
- static ErlNifFunc nifFuns[] = {
- {"new", 0, new},
- {"get", 4, get},
- {"put", 5, put},
- {"hash1", 2, hash1},
- {"hash2", 2, hash2},
- {"hash3", 2, hash3},
- {"compareBin1", 2, compareBin1},
- {"compareBin2", 2, compareBin2},
- };
-
- ERL_NIF_INIT(nifHashb, nifFuns,
- &load, NULL, NULL, NULL)
-
-
|