/* Copyright (c) 2005 Dirk Jagdmann This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ /* Usage: To use the sqlite function pcre() you have to call sqlite3_pcre_init(sqlite3 *DB) somewhere in your startup code of your application. The pcre function takes two arguments. The first one is the regular expression (as a string), the second argument is the string to match. If the regex matches the string pcre() returns an integer > 0. If pcre() returns 0 either no match was found or the pcre library could not compile/use your regex. Errors in compiling the regex are printed to stderr. Example: create table test ( s text ); insert into test values('this is a test'); insert into test values('foobar'); select * from test where pcre('i', s) > 0; -- will return the row with 'this is a test' */ #include #include #include #include #include /* TODO: - support UTF-16 mode of sqlite - give access to additional options/flags of pcre */ #if defined(__linux__) && ( (__GNUC__ >= 4) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 4))) #define TLS __thread #else #define TLS #warning thread local storage not configured for your platform. sqlite3_pcre is therefore not thread safe. #endif #define ARGUMENTS 2 static TLS pcre *p=0; static TLS pcre_extra *extra=0; static TLS int extraflag=0; static TLS char *oldregexp=0; static void cleanup() { if(p) pcre_free(p), p=0; if(extra) pcre_free(extra), extra=0; if(oldregexp) free(oldregexp), oldregexp=0; } static void sqlite3_pcre(sqlite3_context *DB, int argc, sqlite3_value **argv) { int ret=0; int ovector[10*3]; const char *error=0; int erroroffset=-1; const char *regexp; const char *str; if(argc!=ARGUMENTS) goto out; regexp=(const char*)sqlite3_value_text(argv[0]); if(!regexp) goto out; str=(const char*)sqlite3_value_text(argv[1]); if(!str) goto out; /* if we encountered a new regexp we compile it */ if((oldregexp==0) || strcmp(oldregexp,regexp)) { cleanup(); oldregexp=strdup(regexp); p=pcre_compile(regexp, 0 /*options*/, &error, &erroroffset, NULL /*tableptr*/); if(!p) { fputs("sqlite3_pcre(): ", stderr); if(error) fputs(error, stderr); if(erroroffset>=0) { int i; fputs("\n", stderr); fputs(regexp, stderr); fputs("\n", stderr); for(i=0; i