#include "ShBFA.h"


ShBFA::ShBFA()
{
}


ShBFA::~ShBFA()
{
}

ShBFA::ShBFA(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 ShBFA::insert(const uchar* str, uint len, uint c){ //c is the set id, range from 0 to (bf_c - 1)
	uint pos;
	for (uint i = 0; i < bf_k; i++) {
		pos = bf_hfp[i](str, len) % bf_m;
		bf_base[(pos + c) / 8] |= (128 >> ((pos + c) % 8));
	}
	bf_n++;
	return 1;
}

int ShBFA::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;
	}

	for (uint i = 0; i < bf_c; i++) {
		if ((g & (1i64 << i)) != 0) {
			return (bf_c - i - 1);
		}
	}
	return -1;
}