#include /* rand() and friends */ #include #include #include /* sprintf() */ #include /** A simple example of writing a custom SQL function for sqlite3. It provides results of a so-called Fudge-dice roll. Fudge dice (dF) are used by the Fudge roleplaying system (http://fudgerpg.com). Call it with 0, 1 or 2 arguments: 0 args: same as calling dF(4). 1 arg: arg1 is an integer telling how many dice to roll. 2 args: arg2 is any value. The TYPE of the value is used to dynamically set the return type. If arg2 is an INTEGER (the default) or DOUBLE then a number of the appropriate type is returned to the caller via sqlite_result_xxx(context,...). If arg2 is a string then a description showing the results of each die roll of the set, plus the total, is sent back. You may bind this function to your db by calling something like: sqlite3_create_function( myDb, "dF", -1, SQLITE_ANY, 0, sqlite_func_dF, 0, 0 ); Author: stephan at wanderinghorse dot net License: Public Domain */ void sqlite_func_dF( sqlite3_context *context, int argc, sqlite3_value **argv ) { static char seeded = 0; enum {BufLen = 128}; char buf[BufLen+1] = {0}; char * bPos = buf; int count = 0; int returnT; int reti = 0; if( !seeded && (seeded=1) ){ srand( time(NULL) ); } if( argc > 2 ){ sqlite3_result_error( context, "dF() function requires 0, 1, or 2 arguments: " "(0==roll 4dF and return int), " "(1==roll [ARG0]dF and return int), " "(2=roll [ARG0]dF and return result as TYPEOF(ARG1))", -1 ); return; } returnT = (argc<2) ? SQLITE_INTEGER : sqlite3_value_type(argv[1]); if( 0 == argc ){ count = 4; } else{ count = sqlite3_value_int(argv[0]); if( count < 1 ) count = 4; } if(count > BufLen/2+20){ sqlite3_result_error( context, "dF() can't buffer that many dice.", -1 ); return; } if( SQLITE_TEXT == returnT ){ /*bPos += sprintf(bPos, "dF: ");*/ } { int rnd; char marker; while( count-- ){ rnd = rand() % 3 - 1; if( SQLITE_TEXT == returnT ) { marker = ((0==rnd) ? '0' : ((rnd>0) ? '+' : '-')); *bPos++ = marker; *bPos++ = ' '; } reti += rnd; } } if( SQLITE_TEXT == returnT ){ bPos += sprintf(bPos, "= %d", reti); *bPos = 0; sqlite3_result_text( context, buf, strlen(buf), SQLITE_TRANSIENT ); } else if( SQLITE_FLOAT == returnT ){ sqlite3_result_double(context, 1.0 * reti); } else{ sqlite3_result_int(context, reti); } return; }