1 /* 2 ** 2020-04-14 3 ** 4 ** The author disclaims copyright to this source code. In place of 5 ** a legal notice, here is a blessing: 6 ** 7 ** May you do good and not evil. 8 ** May you find forgiveness for yourself and forgive others. 9 ** May you share freely, never taking more than you give. 10 ** 11 ****************************************************************************** 12 ** 13 ** This SQLite extension implements the UINT collating sequence. 14 ** 15 ** UINT works like BINARY for text, except that embedded strings 16 ** of digits compare in numeric order. 17 ** 18 ** * Leading zeros are handled properly, in the sense that 19 ** they do not mess of the maginitude comparison of embedded 20 ** strings of digits. "x00123y" is equal to "x123y". 21 ** 22 ** * Only unsigned integers are recognized. Plus and minus 23 ** signs are ignored. Decimal points and exponential notation 24 ** are ignored. 25 ** 26 ** * Embedded integers can be of arbitrary length. Comparison 27 ** is *not* limited integers that can be expressed as a 28 ** 64-bit machine integer. 29 */ 30 #include "sqlite3ext.h" 31 SQLITE_EXTENSION_INIT1 32 #include <assert.h> 33 #include <string.h> 34 #include <ctype.h> 35 36 /* 37 ** Compare text in lexicographic order, except strings of digits 38 ** compare in numeric order. 39 */ 40 static int uintCollFunc( 41 void *notUsed, 42 int nKey1, const void *pKey1, 43 int nKey2, const void *pKey2 44 ){ 45 const unsigned char *zA = (const unsigned char*)pKey1; 46 const unsigned char *zB = (const unsigned char*)pKey2; 47 int i=0, j=0, x; 48 (void)notUsed; 49 while( i<nKey1 && j<nKey2 ){ 50 x = zA[i] - zB[j]; 51 if( isdigit(zA[i]) ){ 52 int k; 53 if( !isdigit(zB[j]) ) return x; 54 while( i<nKey1 && zA[i]=='0' ){ i++; } 55 while( j<nKey2 && zB[j]=='0' ){ j++; } 56 k = 0; 57 while( i+k<nKey1 && isdigit(zA[i+k]) 58 && j+k<nKey2 && isdigit(zB[j+k]) ){ 59 k++; 60 } 61 if( i+k<nKey1 && isdigit(zA[i+k]) ){ 62 return +1; 63 }else if( j+k<nKey2 && isdigit(zB[j+k]) ){ 64 return -1; 65 }else{ 66 x = memcmp(zA+i, zB+j, k); 67 if( x ) return x; 68 i += k; 69 j += k; 70 } 71 }else if( x ){ 72 return x; 73 }else{ 74 i++; 75 j++; 76 } 77 } 78 return (nKey1 - i) - (nKey2 - j); 79 } 80 81 #ifdef _WIN32 82 __declspec(dllexport) 83 #endif 84 int sqlite3_uint_init( 85 sqlite3 *db, 86 char **pzErrMsg, 87 const sqlite3_api_routines *pApi 88 ){ 89 SQLITE_EXTENSION_INIT2(pApi); 90 (void)pzErrMsg; /* Unused parameter */ 91 return sqlite3_create_collation(db, "uint", SQLITE_UTF8, 0, uintCollFunc); 92 } 93