#include "ShBFC.h"


ShBFC::ShBFC()
{
}


ShBFC::~ShBFC()
{
}

ShBFC::ShBFC(uint m, uint k, uint c) {
	bf_m = m;
	bf_k = k;
	bf_c = c;
	bf_n = 0;

	uint size = (bf_m >> 3) + 8; //Support offset <= 56
	bf_base = new uchar[size];
	memset(bf_base, 0, sizeof(uchar)* size);

	this->queryMemAccNum = 0;

	unsigned int(*tmp_ptr[18])(const unsigned char * str, unsigned int len) =
	{ JSHash, OCaml, OAAT, PJWHash, RSHash, SBOX, SDBM, Simple, SML, STL,
	APHash, BKDR, BOB, CRC32, DEKHash, DJBHash, FNV32, Hsieh };
	for (int i = 0; i < 18; i++){
		bf_hfp[i] = tmp_ptr[i];
	}
}

uint ShBFC::insert(const uchar* str, uint len, uint num){ //num is the times an element will insert

	uint tmp = num - 1;
	if (tmp >= bf_c) //Error!
		return 0; 

	uint pos;
	for (uint i = 0; i < bf_k; i++) {
		pos = bf_hfp[i](str, len) % bf_m;
		bf_base[(pos + tmp) / 8] |= (128 >> ((pos + tmp) % 8));
	}
	bf_n++;
	return 1;
}

uint ShBFC::query(const uchar* str, uint len) {
	uint fhv, slot;
	uint64 g = (1i64 << bf_c) - 1;

	for (uint i = 0; i < bf_k; i++) {
		fhv = bf_hfp[i](str, len) % bf_m;
		slot = (fhv >> 3);

		this->queryMemAccNum++;
		uint64 *p = (uint64 *)(&bf_base[slot]);

		g &= ((htonll(*p) << (fhv & 7)) >> (64 - bf_c));

		if (g == 0) break;
	}

	uint c = 0;
	for (uint d = 0; d < bf_c; d++) {
		if ((g & ((uint64)1 << d)) != 0) {
			c = bf_c - d;
			break;
		}
	}
	return c;
}