diff options
Diffstat (limited to 'ext/misc/rot13.c')
-rw-r--r-- | ext/misc/rot13.c | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/ext/misc/rot13.c b/ext/misc/rot13.c new file mode 100644 index 0000000..05b4a18 --- /dev/null +++ b/ext/misc/rot13.c @@ -0,0 +1,115 @@ +/* +** 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; +} |