#include "sqliteInt.h"
#define BITVEC_SZ 512
#define BITVEC_USIZE \
(((BITVEC_SZ-(3*sizeof(u32)))/sizeof(Bitvec*))*sizeof(Bitvec*))
#define BITVEC_TELEM u8
#define BITVEC_SZELEM 8
#define BITVEC_NELEM (BITVEC_USIZE/sizeof(BITVEC_TELEM))
#define BITVEC_NBIT (BITVEC_NELEM*BITVEC_SZELEM)
#define BITVEC_NINT (BITVEC_USIZE/sizeof(u32))
#define BITVEC_MXHASH (BITVEC_NINT/2)
#define BITVEC_HASH(X) (((X)*1)%BITVEC_NINT)
#define BITVEC_NPTR (BITVEC_USIZE/sizeof(Bitvec *))
struct Bitvec {
u32 iSize;
u32 nSet;
u32 iDivisor;
union {
BITVEC_TELEM aBitmap[BITVEC_NELEM];
u32 aHash[BITVEC_NINT];
Bitvec *apSub[BITVEC_NPTR];
} u;
};
Bitvec *sqlite3BitvecCreate(u32 iSize){
Bitvec *p;
assert( sizeof(*p)==BITVEC_SZ );
p = sqlite3MallocZero( sizeof(*p) );
if( p ){
p->iSize = iSize;
}
return p;
}
int sqlite3BitvecTestNotNull(Bitvec *p, u32 i){
assert( p!=0 );
i--;
if( i>=p->iSize ) return 0;
while( p->iDivisor ){
u32 bin = i/p->iDivisor;
i = i%p->iDivisor;
p = p->u.apSub[bin];
if (!p) {
return 0;
}
}
if( p->iSize<=BITVEC_NBIT ){
return (p->u.aBitmap[i/BITVEC_SZELEM] & (1<<(i&(BITVEC_SZELEM-1))))!=0;
} else{
u32 h = BITVEC_HASH(i++);
while( p->u.aHash[h] ){
if( p->u.aHash[h]==i ) return 1;
h = (h+1) % BITVEC_NINT;
}
return 0;
}
}
int sqlite3BitvecTest(Bitvec *p, u32 i){
return p!=0 && sqlite3BitvecTestNotNull(p,i);
}
int sqlite3BitvecSet(Bitvec *p, u32 i){
u32 h;
if( p==0 ) return SQLITE_OK;
assert( i>0 );
assert( i<=p->iSize );
i--;
while((p->iSize > BITVEC_NBIT) && p->iDivisor) {
u32 bin = i/p->iDivisor;
i = i%p->iDivisor;
if( p->u.apSub[bin]==0 ){
p->u.apSub[bin] = sqlite3BitvecCreate( p->iDivisor );
if( p->u.apSub[bin]==0 ) return SQLITE_NOMEM_BKPT;
}
p = p->u.apSub[bin];
}
if( p->iSize<=BITVEC_NBIT ){
p->u.aBitmap[i/BITVEC_SZELEM] |= 1 << (i&(BITVEC_SZELEM-1));
return SQLITE_OK;
}
h = BITVEC_HASH(i++);
if( !p->u.aHash[h] ){
if (p->nSet<(BITVEC_NINT-1)) {
goto bitvec_set_end;
} else {
goto bitvec_set_rehash;
}
}
do {
if( p->u.aHash[h]==i ) return SQLITE_OK;
h++;
if( h>=BITVEC_NINT ) h = 0;
} while( p->u.aHash[h] );
bitvec_set_rehash:
if( p->nSet>=BITVEC_MXHASH ){
unsigned int j;
int rc;
u32 *aiValues = sqlite3StackAllocRaw(0, sizeof(p->u.aHash));
if( aiValues==0 ){
return SQLITE_NOMEM_BKPT;
}else{
memcpy(aiValues, p->u.aHash, sizeof(p->u.aHash));
memset(p->u.apSub, 0, sizeof(p->u.apSub));
p->iDivisor = (p->iSize + BITVEC_NPTR - 1)/BITVEC_NPTR;
rc = sqlite3BitvecSet(p, i);
for(j=0; j<BITVEC_NINT; j++){
if( aiValues[j] ) rc |= sqlite3BitvecSet(p, aiValues[j]);
}
sqlite3StackFree(0, aiValues);
return rc;
}
}
bitvec_set_end:
p->nSet++;
p->u.aHash[h] = i;
return SQLITE_OK;
}
void sqlite3BitvecClear(Bitvec *p, u32 i, void *pBuf){
if( p==0 ) return;
assert( i>0 );
i--;
while( p->iDivisor ){
u32 bin = i/p->iDivisor;
i = i%p->iDivisor;
p = p->u.apSub[bin];
if (!p) {
return;
}
}
if( p->iSize<=BITVEC_NBIT ){
p->u.aBitmap[i/BITVEC_SZELEM] &= ~(1 << (i&(BITVEC_SZELEM-1)));
}else{
unsigned int j;
u32 *aiValues = pBuf;
memcpy(aiValues, p->u.aHash, sizeof(p->u.aHash));
memset(p->u.aHash, 0, sizeof(p->u.aHash));
p->nSet = 0;
for(j=0; j<BITVEC_NINT; j++){
if( aiValues[j] && aiValues[j]!=(i+1) ){
u32 h = BITVEC_HASH(aiValues[j]-1);
p->nSet++;
while( p->u.aHash[h] ){
h++;
if( h>=BITVEC_NINT ) h = 0;
}
p->u.aHash[h] = aiValues[j];
}
}
}
}
void sqlite3BitvecDestroy(Bitvec *p){
if( p==0 ) return;
if( p->iDivisor ){
unsigned int i;
for(i=0; i<BITVEC_NPTR; i++){
sqlite3BitvecDestroy(p->u.apSub[i]);
}
}
sqlite3_free(p);
}
u32 sqlite3BitvecSize(Bitvec *p){
return p->iSize;
}
#ifndef SQLITE_UNTESTABLE
#define SETBIT(V,I) V[I>>3] |= (1<<(I&7))
#define CLEARBIT(V,I) V[I>>3] &= ~(1<<(I&7))
#define TESTBIT(V,I) (V[I>>3]&(1<<(I&7)))!=0
int sqlite3BitvecBuiltinTest(int sz, int *aOp){
Bitvec *pBitvec = 0;
unsigned char *pV = 0;
int rc = -1;
int i, nx, pc, op;
void *pTmpSpace;
pBitvec = sqlite3BitvecCreate( sz );
pV = sqlite3MallocZero( (sz+7)/8 + 1 );
pTmpSpace = sqlite3_malloc64(BITVEC_SZ);
if( pBitvec==0 || pV==0 || pTmpSpace==0 ) goto bitvec_end;
sqlite3BitvecSet(0, 1);
sqlite3BitvecClear(0, 1, pTmpSpace);
pc = i = 0;
while( (op = aOp[pc])!=0 ){
switch( op ){
case 1:
case 2:
case 5: {
nx = 4;
i = aOp[pc+2] - 1;
aOp[pc+2] += aOp[pc+3];
break;
}
case 3:
case 4:
default: {
nx = 2;
sqlite3_randomness(sizeof(i), &i);
break;
}
}
if( (--aOp[pc+1]) > 0 ) nx = 0;
pc += nx;
i = (i & 0x7fffffff)%sz;
if( (op & 1)!=0 ){
SETBIT(pV, (i+1));
if( op!=5 ){
if( sqlite3BitvecSet(pBitvec, i+1) ) goto bitvec_end;
}
}else{
CLEARBIT(pV, (i+1));
sqlite3BitvecClear(pBitvec, i+1, pTmpSpace);
}
}
rc = sqlite3BitvecTest(0,0) + sqlite3BitvecTest(pBitvec, sz+1)
+ sqlite3BitvecTest(pBitvec, 0)
+ (sqlite3BitvecSize(pBitvec) - sz);
for(i=1; i<=sz; i++){
if( (TESTBIT(pV,i))!=sqlite3BitvecTest(pBitvec,i) ){
rc = i;
break;
}
}
bitvec_end:
sqlite3_free(pTmpSpace);
sqlite3_free(pV);
sqlite3BitvecDestroy(pBitvec);
return rc;
}
#endif