| /* |
| ** 2013-05-15 |
| ** |
| ** The author disclaims copyright to this source code. In place of |
| ** a legal notice, here is a blessing: |
| ** |
| ** May you do good and not evil. |
| ** May you find forgiveness for yourself and forgive others. |
| ** May you share freely, never taking more than you give. |
| ** |
| ****************************************************************************** |
| ** |
| ** This SQLite extension implements a rot13() function and a rot13 |
| ** collating sequence. |
| */ |
| #include "sqlite3ext.h" |
| SQLITE_EXTENSION_INIT1 |
| #include <assert.h> |
| #include <string.h> |
| |
| /* |
| ** Perform rot13 encoding on a single ASCII character. |
| */ |
| static unsigned char rot13(unsigned char c){ |
| if( c>='a' && c<='z' ){ |
| c += 13; |
| if( c>'z' ) c -= 26; |
| }else if( c>='A' && c<='Z' ){ |
| c += 13; |
| if( c>'Z' ) c -= 26; |
| } |
| return c; |
| } |
| |
| /* |
| ** Implementation of the rot13() function. |
| ** |
| ** Rotate ASCII alphabetic characters by 13 character positions. |
| ** Non-ASCII characters are unchanged. rot13(rot13(X)) should always |
| ** equal X. |
| */ |
| static void rot13func( |
| sqlite3_context *context, |
| int argc, |
| sqlite3_value **argv |
| ){ |
| const unsigned char *zIn; |
| int nIn; |
| unsigned char *zOut; |
| unsigned char *zToFree = 0; |
| int i; |
| unsigned char zTemp[100]; |
| assert( argc==1 ); |
| if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; |
| zIn = (const unsigned char*)sqlite3_value_text(argv[0]); |
| nIn = sqlite3_value_bytes(argv[0]); |
| if( nIn<sizeof(zTemp)-1 ){ |
| zOut = zTemp; |
| }else{ |
| zOut = zToFree = (unsigned char*)sqlite3_malloc64( nIn+1 ); |
| if( zOut==0 ){ |
| sqlite3_result_error_nomem(context); |
| return; |
| } |
| } |
| for(i=0; i<nIn; i++) zOut[i] = rot13(zIn[i]); |
| zOut[i] = 0; |
| sqlite3_result_text(context, (char*)zOut, i, SQLITE_TRANSIENT); |
| sqlite3_free(zToFree); |
| } |
| |
| /* |
| ** Implement the rot13 collating sequence so that if |
| ** |
| ** x=y COLLATE rot13 |
| ** |
| ** Then |
| ** |
| ** rot13(x)=rot13(y) COLLATE binary |
| */ |
| static int rot13CollFunc( |
| void *notUsed, |
| int nKey1, const void *pKey1, |
| int nKey2, const void *pKey2 |
| ){ |
| const char *zA = (const char*)pKey1; |
| const char *zB = (const char*)pKey2; |
| int i, x; |
| for(i=0; i<nKey1 && i<nKey2; i++){ |
| x = (int)rot13(zA[i]) - (int)rot13(zB[i]); |
| if( x!=0 ) return x; |
| } |
| return nKey1 - nKey2; |
| } |
| |
| |
| #ifdef _WIN32 |
| __declspec(dllexport) |
| #endif |
| int sqlite3_rot_init( |
| sqlite3 *db, |
| char **pzErrMsg, |
| const sqlite3_api_routines *pApi |
| ){ |
| int rc = SQLITE_OK; |
| SQLITE_EXTENSION_INIT2(pApi); |
| (void)pzErrMsg; /* Unused parameter */ |
| rc = sqlite3_create_function(db, "rot13", 1, |
| SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC, |
| 0, rot13func, 0, 0); |
| if( rc==SQLITE_OK ){ |
| rc = sqlite3_create_collation(db, "rot13", SQLITE_UTF8, 0, rot13CollFunc); |
| } |
| return rc; |
| } |