⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 util.c

📁 在VC6环境下开发
💻 C
字号:
#include "eDbInit.h"
/*
** Number of 32-bit guard words
*/
#define N_GUARD 1

int eDb_malloc_failed = 0;
/*
** Allocate new memory and set it to zero.  Return NULL if
** no memory is available.  See also eDbMallocRaw().
*/
long nMalloc = 0;
void *eDbMalloc(int n){
	void *p;
	if( (p = _MALLOC_(n))==0 ){
		if( n>0 ) eDb_malloc_failed++;
	}else{
		memset(p, 0, n);
		//fprintf(fdebug,"M %d:--%x\t",++nMalloc,p);
	}
	return p;
}

/*
** Allocate new memory but do not set it to zero.  Return NULL if
** no memory is available.  See also eDbMalloc().
*/
void *eDbMallocRaw(int n){
	void *p;
	if( (p = _MALLOC_(n))==0 ){
		if( n>0 ) eDb_malloc_failed++;
	}else{
		//fprintf(fdebug,"MR%d:--%x\t",++nMalloc,p);
	}
	return p;
}

/*
** Free memory previously obtained from eDbMalloc()
*/
long nFree = 0;
void eDbFree(void *p){
	if( p ){
		_FREE_(p);
		//fprintf(fdebug,"F %d:--%x\t",++nFree,p);
	}
}

/*
** Resize a prior allocation.  If p==0, then this routine
** works just like eDbMalloc().  If n==0, then this routine
** works just like eDbFree().
*/
void *eDbRealloc(void *p, int n){
	void *p2;
	if( p==0 ){
		return eDbMalloc(n);
	}
	if( n==0 ){
		eDbFree(p);
		return 0;
	}
	p2 = _REALLOC_(p, n);
	if( p2==0 ){
		eDb_malloc_failed++;
	}else{
		//fprintf(fdebug,"MA%d:--%x:%x\t",++nMalloc,p,p2);
	}
	return p2;
}
/*
** Make a copy of a string in memory obtained from eDbMalloc()
*/
char *eDbStrDup(const char *z){
	char *zNew;
	if( z==0 ) return 0;
	zNew = eDbMallocRaw(strlen(z)+1);
	if( zNew ) strcpy(zNew, z);
	return zNew;
}
char *eDbStrNDup(const char *z, int n){
	char *zNew;
	if( z==0 ) return 0;
	zNew = eDbMallocRaw(n+1);
	if( zNew ){
		memcpy(zNew, z, n);
		zNew[n] = 0;
	}
	return zNew;
}
/*
** Check to see if the given pointer was obtained from eDbMalloc()
** and is able to hold at least N bytes.  Raise an exception if this
** is not the case.
**
** This routine is used for testing purposes only.
*/
void eDbCheckMemory(void *p, int N){
	int *pi = p;
	int n, i, k;
	pi -= N_GUARD+1;
	for(i=0; i<N_GUARD; i++){
		assert( pi[i]==0xdead1122 );
	}
	n = pi[N_GUARD];
	assert( N>=0 && N<n );
	k = (n+sizeof(int)-1)/sizeof(int);
	for(i=0; i<N_GUARD; i++){
		assert( pi[k+N_GUARD+1+i]==0xdead3344 );
	}
}

/*
** Create a string from the 2nd and subsequent arguments (up to the
** first NULL argument), store the string in memory obtained from
** eDbMalloc() and make the pointer indicated by the 1st argument
** point to that string.  The 1st argument must either be NULL or 
** point to memory obtained from eDbMalloc().
*/
void eDbSetString(char **pz, const char *zFirst, ...){
	va_list ap;
	int nByte;
	const char *z;
	char *zResult;

	if( pz==0 ) return;
	nByte = strlen(zFirst) + 1;
	va_start(ap, zFirst);
	while( (z = va_arg(ap, const char*))!=0 ){
		nByte += strlen(z);
	}
	va_end(ap);
	eDbFree(*pz);
	*pz = zResult = eDbMallocRaw( nByte );
	if( zResult==0 ){
		return;
	}
	strcpy(zResult, zFirst);
	zResult += strlen(zResult);
	va_start(ap, zFirst);
	while( (z = va_arg(ap, const char*))!=0 ){
		strcpy(zResult, z);
		zResult += strlen(zResult);
	}
	va_end(ap);
}
/* An array to map all upper-case characters into their corresponding
** lower-case character. 
*/
static unsigned char UpperToLower[] = {
      0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17,
     18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
     36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
     54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 97, 98, 99,100,101,102,103,
    104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,
    122, 91, 92, 93, 94, 95, 96, 97, 98, 99,100,101,102,103,104,105,106,107,
    108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,
    126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
    144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,
    162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,
    180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,
    198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,
    216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,
    234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,
    252,253,254,255
};

/*
** This function computes a hash on the name of a keyword.
** Case is not significant.
*/
int eDbHashNoCase(const char *z, int n){
	int h = 0;
	if( n<=0 ) n = strlen(z);
	while( n > 0  ){
		h = (h<<3) ^ h ^ UpperToLower[(unsigned char)*z++];
		n--;
	}
	return h & 0x7fffffff;
}

/*
** Some systems have stricmp().  Others have strcasecmp().  Because
** there is no consistency, we will define our own.
*/
int eDbStrICmp(const char *zLeft, const char *zRight){
	register unsigned char *a, *b;
	a = (unsigned char *)zLeft;
	b = (unsigned char *)zRight;
	while( *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; }
	return *a - *b;
}
int eDbStrNICmp(const char *zLeft, const char *zRight, int N){
	register unsigned char *a, *b;
	a = (unsigned char *)zLeft;
	b = (unsigned char *)zRight;
	while( N-- > 0 && *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; }
	return N<0 ? 0 : *a - *b;
}

void eDbSetNString(char **pz, ...){
	va_list ap;
	int nByte;
	const char *z;
	char *zResult;
	int n;

	if( pz==0 ) return;
	nByte = 0;
	va_start(ap, pz);
	while( (z = va_arg(ap, const char*))!=0 ){
		n = va_arg(ap, int);
		if( n<=0 ) n = strlen(z);
		nByte += n;
	}
	va_end(ap);
	eDbFree(*pz);
	*pz = zResult = eDbMallocRaw( nByte + 1 );
	if( zResult==0 ) return;
	va_start(ap, pz);
	while( (z = va_arg(ap, const char*))!=0 ){
		n = va_arg(ap, int);
		if( n<=0 ) n = strlen(z);
		strncpy(zResult, z, n);
		zResult += n;
	}
	*zResult = 0;
	va_end(ap);
}
void eDbErrorMsg(Parser *pParse, const char *zfmt, ...){
	int n,nByte;
	int count;
	char *bufpt;
	const char *z;
	char c;
	char sbuf[200];
	char zInt[12];
	va_list ap;	
	pParse->nErr++;
	eDbFree(pParse->zErrMsg);
	nByte = 0;
	count = 0;
	va_start(ap, zfmt);
	for(; (c=(*zfmt))!=0; ++zfmt){
		if( c!='%' ){
		  int amt;
		  bufpt = (char *)zfmt;
		  amt = 1;
		  while( (c=(*++zfmt))!='%' && c!=0 ) amt++;
		  memcpy(&sbuf[count],bufpt,amt);
		  count += amt;
		  if( c==0 ) break;
		}
		if( c=='%' ){
			c = * ++zfmt;
			if(c==0) break;
			switch(c){
				case 'd':{
					n = va_arg(ap, int);
					itoa(n,zInt,10);
					n = strlen(zInt);
					strcpy(&sbuf[count],zInt);
					count += n;
					break;
				}
				case 's':{
					z = va_arg(ap, const char*);
					n = strlen(z);
					strcpy(&sbuf[count],z);
					count += n;
					break;
				}
			}
		}
	}
	va_end(ap);
	sbuf[count] = 0;
	n = strlen(sbuf);
	pParse->zErrMsg = eDbMalloc(n+1);
	strcpy(pParse->zErrMsg,sbuf);
	fprintf(fout,"%s\n",pParse->zErrMsg);
}
int eDbVdbeByteSwap(int x){
	union {
		char zBuf[sizeof(int)];
		int i;
	} ux;
	ux.zBuf[3] = x&0xff;
	ux.zBuf[2] = (x>>8)&0xff;
	ux.zBuf[1] = (x>>16)&0xff;
	ux.zBuf[0] = (x>>24)&0xff;
	return ux.i;
}

void eDbDequote(char *z){
	int quote;
	int i, j;
	if( z==0 ) return;
	quote = z[0];
	switch( quote ){
		case '\'':  break;
		case '"':   break;
		case '[':   quote = ']';  break;
		default:    return;
	}
	for(i=1, j=0; z[i]; i++){
		if( z[i]==quote ){
			if( z[i+1]==quote ){
				z[j++] = quote;
				i++;
		  }else{
				z[j++] = 0;
				break;
		  }
		}else{
			z[j++] = z[i];
		}
	}
}

void eDbFreeKayData(KeyData *p){
	eDbFree(p->pKey);
	eDbFree(p->pData);
	eDbFree(p);
}

void eDbFreeParseResult(ParseResult *p){
	if(p == 0) return ;
	if( p->pEList ) eDbExprListDelete(p->pEList);
	if( p->pSelect ) eDbSelectDelete(p->pSelect);
	if( p->pIdList ) eDbIdListDelete(p->pIdList);
	if( p->pSrc ) eDbSrcListDelete(p->pSrc);
	if( p->pWhere ) eDbExprDelete(p->pWhere);
	if(p->zSql) eDbFree(p->zSql);
	eDbFree(p);
}

int eDbLookupTupleByIdxKey(BtCursor *pCur,const char *zKey, int nKey, int omit,int op){
	int rc,res;
	rc = eDbBtreeMoveto(pCur, zKey,strlen(zKey)+1, &res);
	if( rc==0 && res >= omit){
		eDbBtreeKeyCompare(pCur, zKey, nKey-omit, omit, &res);
	}
	switch(op){
		case TK_LE:
			res = res <= 0;
			break;
		case TK_LT:
			res = res < 0;
			break;
		case TK_GE:
			res = res >= 0;
			break;
		case TK_GT:
			res = res > 0;
			break;
		case TK_NE:
			res = res != 0;
			break;
		case TK_EQ:
			res = res == 0;
			break;
		default:{
			res = 0;
		}
	}
	return res;
	
}
/*
** compare two strings, if they meet to op
** then return true, or else return false;
*/
int eDbStrCompareOK(int op,int type,const char *zSrc,const char *zDes){
	int rc;
	switch(type){
		case eDb_SO_NUM:{
			int iSrc = atoi(zSrc);
			int iDes = atoi(zDes);
			rc = iSrc - iDes;
			break;
		}
		case eDb_SO_DEC:{
			break;
		}
		default:{
			rc = eDbStrICmp(zSrc,zDes);
		}
	}	
	switch(op){
		case TK_LE:
			rc = rc <= 0;
			break;
		case TK_LT:
			rc = rc < 0;
			break;
		case TK_GE:
			rc = rc >= 0;
			break;
		case TK_GT:
			rc = rc > 0;
			break;
		case TK_NE:
			rc = rc != 0;
			break;
		case TK_EQ:
			rc = rc == 0;
			break;
		default:{
			rc = 0;
		}
	}
	return rc;
}

/*
** look up the name in table
** if found, return the idx in column
** else return -1
*/

int eDbLookupColName(Table *pTab,const char *name){
	int i;
	for(i=0;i<pTab->nCol;i++){	
		if(eDbStrICmp(pTab->aCol[i].zName,name) == 0){
			break;
		}
	}
	if(i >= pTab->nCol) i = -1;
	return i;
}

/*
** look up i-th column in index
** if found, return the rootpage of the index
** else return 0
*/

int eDbLookupIdxColumn(Table *pTab,int iCol){
	int i;
	Index *pIdx = pTab->pIndex;
	for(;pIdx;pIdx=pIdx->pNext){	
		for(i=0;i<pIdx->nColumn;i++){
			if( i==0 && pIdx->aiColumn[i]==iCol ){
				return pIdx->tnum;
			}
		}
	}
	return 0;
}

/*
** The string z[] is an ascii representation of a real number.
** Convert this string to a double.
**
** This routine assumes that z[] really is a valid number.  If it
** is not, the result is undefined.
**
** This routine is used instead of the library atof() function because
** the library atof() might want to use "," as the decimal point instead
** of "." depending on how locale is set.  But that would cause problems
** for SQL.  So this routine always uses "." regardless of locale.
*/
#ifndef LONGDOUBLE_TYPE
# define LONGDOUBLE_TYPE long double
#endif
double eDbAtoF(const char *z, const char **pzEnd){
  int sign = 1;
  LONGDOUBLE_TYPE v1 = 0.0;
  if( *z=='-' ){
    sign = -1;
    z++;
  }else if( *z=='+' ){
    z++;
  }
  while( isdigit(*z) ){
    v1 = v1*10.0 + (*z - '0');
    z++;
  }
  if( *z=='.' ){
    LONGDOUBLE_TYPE divisor = 1.0;
    z++;
    while( isdigit(*z) ){
      v1 = v1*10.0 + (*z - '0');
      divisor *= 10.0;
      z++;
    }
    v1 /= divisor;
  }
  if( *z=='e' || *z=='E' ){
    int esign = 1;
    int eval = 0;
    LONGDOUBLE_TYPE scale = 1.0;
    z++;
    if( *z=='-' ){
      esign = -1;
      z++;
    }else if( *z=='+' ){
      z++;
    }
    while( isdigit(*z) ){
      eval = eval*10 + *z - '0';
      z++;
    }
    while( eval>=64 ){ scale *= 1.0e+64; eval -= 64; }
    while( eval>=16 ){ scale *= 1.0e+16; eval -= 16; }
    while( eval>=4 ){ scale *= 1.0e+4; eval -= 4; }
    while( eval>=1 ){ scale *= 1.0e+1; eval -= 1; }
    if( esign<0 ){
      v1 /= scale;
    }else{
      v1 *= scale;
    }
  }
  if( pzEnd ) *pzEnd = z;
  return sign<0 ? -v1 : v1;
}

/*
** The following procedure converts a double-precision floating point
** number into a string.  The resulting string has the property that
** two such strings comparied using strcmp() or memcmp() will give the
** same results as a numeric comparison of the original floating point
** numbers.
**
** This routine is used to generate database keys from floating point
** numbers such that the keys sort in the same order as the original
** floating point numbers even though the keys are compared using
** memcmp().
**
** The calling function should have allocated at least 14 characters
** of space for the buffer z[].
*/
#define _64e3  (64.0 * 64.0 * 64.0)
#define _64e4  (64.0 * 64.0 * 64.0 * 64.0)
#define _64e15 (_64e3 * _64e4 * _64e4 * _64e4)
#define _64e16 (_64e4 * _64e4 * _64e4 * _64e4)
#define _64e63 (_64e15 * _64e16 * _64e16 * _64e16)
#define _64e64 (_64e16 * _64e16 * _64e16 * _64e16)
void eDbRealToSortable(double r, char *z){
  int neg;
  int exp;
  int cnt = 0;

  /* This array maps integers between 0 and 63 into base-64 digits.
  ** The digits must be chosen such at their ASCII codes are increasing.
  ** This means we can not use the traditional base-64 digit set. */
  static const char zDigit[] = 
     "0123456789"
     "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
     "abcdefghijklmnopqrstuvwxyz"
     "|~";
  if( r<0.0 ){
    neg = 1;
    r = -r;
    *z++ = '-';
  } else {
    neg = 0;
    *z++ = '0';
  }
  exp = 0;

  if( r==0.0 ){
    exp = -1024;
  }else if( r<(0.5/64.0) ){
    while( r < 0.5/_64e64 && exp > -961  ){ r *= _64e64;  exp -= 64; }
    while( r < 0.5/_64e16 && exp > -1009 ){ r *= _64e16;  exp -= 16; }
    while( r < 0.5/_64e4  && exp > -1021 ){ r *= _64e4;   exp -= 4; }
    while( r < 0.5/64.0   && exp > -1024 ){ r *= 64.0;    exp -= 1; }
  }else if( r>=0.5 ){
    while( r >= 0.5*_64e63 && exp < 960  ){ r *= 1.0/_64e64; exp += 64; }
    while( r >= 0.5*_64e15 && exp < 1008 ){ r *= 1.0/_64e16; exp += 16; }
    while( r >= 0.5*_64e3  && exp < 1020 ){ r *= 1.0/_64e4;  exp += 4; }
    while( r >= 0.5        && exp < 1023 ){ r *= 1.0/64.0;   exp += 1; }
  }
  if( neg ){
    exp = -exp;
    r = -r;
  }
  exp += 1024;
  r += 0.5;
  if( exp<0 ) return;
  if( exp>=2048 || r>=1.0 ){
    strcpy(z, "~~~~~~~~~~~~");
    return;
  }
  *z++ = zDigit[(exp>>6)&0x3f];
  *z++ = zDigit[exp & 0x3f];
  while( r>0.0 && cnt<10 ){
    int digit;
    r *= 64.0;
    digit = (int)r;
    assert( digit>=0 && digit<64 );
    *z++ = zDigit[digit & 0x3f];
    r -= digit;
    cnt++;
  }
  *z = 0;
}
/*
** The string zNum represents an integer.  There might be some other
** information following the integer too, but that part is ignored.
** If the integer that the prefix of zNum represents will fit in a
** 32-bit signed integer, return TRUE.  Otherwise return FALSE.
**
** This routine returns FALSE for the string -2147483648 even that
** that number will, in theory fit in a 32-bit integer.  But positive
** 2147483648 will not fit in 32 bits.  So it seems safer to return
** false.
*/
int eDbFitsIn32Bits(const char *zNum){
  int i, c;
  if( *zNum=='-' || *zNum=='+' ) zNum++;
  for(i=0; (c=zNum[i])>='0' && c<='9'; i++){}
  return i<10 || (i==10 && memcmp(zNum,"2147483647",10)<=0);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -