📄 util.c
字号:
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); sqliteFree(*pz); *pz = zResult = sqliteMallocRaw( 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;#ifdef MEMORY_DEBUG#if MEMORY_DEBUG>1 fprintf(stderr,"string at 0x%x is %s\n", (int)*pz, *pz);#endif#endif va_end(ap);}/*** Add an error message to pParse->zErrMsg and increment pParse->nErr.** The following formatting characters are allowed:**** %s Insert a string** %z A string that should be freed after use** %d Insert an integer** %T Insert a token** %S Insert the first element of a SrcList*/void sqliteErrorMsg(Parse *pParse, const char *zFormat, ...){ va_list ap; pParse->nErr++; sqliteFree(pParse->zErrMsg); va_start(ap, zFormat); pParse->zErrMsg = sqliteVMPrintf(zFormat, ap); va_end(ap);}/*** Convert an SQL-style quoted string into a normal string by removing** the quote characters. The conversion is done in-place. If the** input does not begin with a quote character, then this routine** is a no-op.**** 2002-Feb-14: This routine is extended to remove MS-Access style** brackets from around identifers. For example: "[a-b-c]" becomes** "a-b-c".*/void sqliteDequote(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]; } }}/* 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 sqliteHashNoCase(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 sqliteStrICmp(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 UpperToLower[*a] - UpperToLower[*b];}int sqliteStrNICmp(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 : UpperToLower[*a] - UpperToLower[*b];}/*** Return TRUE if z is a pure numeric string. Return FALSE if the** string contains any character which is not part of a number.**** Am empty string is considered non-numeric.*/int sqliteIsNumber(const char *z){ if( *z=='-' || *z=='+' ) z++; if( !isdigit(*z) ){ return 0; } z++; while( isdigit(*z) ){ z++; } if( *z=='.' ){ z++; if( !isdigit(*z) ) return 0; while( isdigit(*z) ){ z++; } } if( *z=='e' || *z=='E' ){ z++; if( *z=='+' || *z=='-' ) z++; if( !isdigit(*z) ) return 0; while( isdigit(*z) ){ z++; } } return *z==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.*/double sqliteAtoF(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 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 sqliteFitsIn32Bits(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);}/* This comparison routine is what we use for comparison operations** between numeric values in an SQL expression. "Numeric" is a little** bit misleading here. What we mean is that the strings have a** type of "numeric" from the point of view of SQL. The strings** do not necessarily contain numbers. They could contain text.**** If the input strings both look like actual numbers then they** compare in numerical order. Numerical strings are always less ** than non-numeric strings so if one input string looks like a** number and the other does not, then the one that looks like** a number is the smaller. Non-numeric strings compare in ** lexigraphical order (the same order as strcmp()).*/int sqliteCompare(const char *atext, const char *btext){ int result; int isNumA, isNumB; if( atext==0 ){ return -1; }else if( btext==0 ){ return 1; } isNumA = sqliteIsNumber(atext); isNumB = sqliteIsNumber(btext); if( isNumA ){ if( !isNumB ){ result = -1; }else{ double rA, rB; rA = sqliteAtoF(atext, 0); rB = sqliteAtoF(btext, 0); if( rA<rB ){ result = -1; }else if( rA>rB ){ result = +1; }else{ result = 0; } } }else if( isNumB ){ result = +1; }else { result = strcmp(atext, btext); } return result; }/*** This routine is used for sorting. Each key is a list of one or more** null-terminated elements. The list is terminated by two nulls in** a row. For example, the following text is a key with three elements**** Aone\000Dtwo\000Athree\000\000**** All elements begin with one of the characters "+-AD" and end with "\000"** with zero or more text elements in between. Except, NULL elements** consist of the special two-character sequence "N\000".**** Both arguments will have the same number of elements. This routine** returns negative, zero, or positive if the first argument is less** than, equal to, or greater than the first. (Result is a-b).**** Each element begins with one of the characters "+", "-", "A", "D".** This character determines the sort order and collating sequence:**** + Sort numerically in ascending order** - Sort numerically in descending order** A Sort as strings in ascending order** D Sort as strings in descending order.**** For the "+" and "-" sorting, pure numeric strings (strings for which the** isNum() function above returns TRUE) always compare less than strings** that are not pure numerics. Non-numeric strings compare in memcmp()** order. This is the same sort order as the sqliteCompare() function** above generates.**** The last point is a change from version 2.6.3 to version 2.7.0. In** version 2.6.3 and earlier, substrings of digits compare in numerical ** and case was used only to break a tie.**** Elements that begin with 'A' or 'D' compare in memcmp() order regardless** of whether or not they look like a number.**** Note that the sort order imposed by the rules above is the same** from the ordering defined by the "<", "<=", ">", and ">=" operators** of expressions and for indices. This was not the case for version** 2.6.3 and earlier.*/int sqliteSortCompare(const char *a, const char *b){ int res = 0; int isNumA, isNumB; int dir = 0; while( res==0 && *a && *b ){ if( a[0]=='N' || b[0]=='N' ){ if( a[0]==b[0] ){ a += 2; b += 2; continue; } if( a[0]=='N' ){ dir = b[0]; res = -1; }else{ dir = a[0]; res = +1; } break; } assert( a[0]==b[0] ); if( (dir=a[0])=='A' || a[0]=='D' ){ res = strcmp(&a[1],&b[1]); if( res ) break; }else{ isNumA = sqliteIsNumber(&a[1]); isNumB = sqliteIsNumber(&b[1]); if( isNumA ){ double rA, rB; if( !isNumB ){ res = -1; break; } rA = sqliteAtoF(&a[1], 0); rB = sqliteAtoF(&b[1], 0); if( rA<rB ){ res = -1; break; } if( rA>rB ){ res = +1; break; } }else if( isNumB ){ res = +1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -