LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/sqlite - ogrsqliteregexp.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 72 62 86.1 %
Date: 2013-03-30 Functions: 3 3 100.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: ogrsqliteregexp.cpp 25406 2012-12-30 20:07:19Z rouault $
       3                 :  *
       4                 :  * Project:  OpenGIS Simple Features Reference Implementation
       5                 :  * Purpose:  SQLite REGEXP function
       6                 :  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2012, Even Rouault <even dot rouault at mines dash paris dot org>
      10                 :  *
      11                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      12                 :  * copy of this software and associated documentation files (the "Software"),
      13                 :  * to deal in the Software without restriction, including without limitation
      14                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15                 :  * and/or sell copies of the Software, and to permit persons to whom the
      16                 :  * Software is furnished to do so, subject to the following conditions:
      17                 :  *
      18                 :  * The above copyright notice and this permission notice shall be included
      19                 :  * in all copies or substantial portions of the Software.
      20                 :  *
      21                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27                 :  * DEALINGS IN THE SOFTWARE.
      28                 :  ****************************************************************************/
      29                 : 
      30                 : /* WARNING: VERY IMPORTANT NOTE: This file MUST not be directly compiled as */
      31                 : /* a standalone object. It must be included from ogrsqlitevirtualogr.cpp */
      32                 : /* (actually from ogrsqlitesqlfunctions.cpp) */
      33                 : #ifndef COMPILATION_ALLOWED
      34                 : #error See comment in file
      35                 : #endif
      36                 : 
      37                 : /* This code originates from pcre.c from the sqlite3-pcre extension */
      38                 : /* from http://laltromondo.dynalias.net/~iki/informatica/soft/sqlite3-pcre/ */
      39                 : /* whose header is : */
      40                 : /*
      41                 :  * Written by Alexey Tourbin <at@altlinux.org>.
      42                 :  *
      43                 :  * The author has dedicated the code to the public domain.  Anyone is free
      44                 :  * to copy, modify, publish, use, compile, sell, or distribute the original
      45                 :  * code, either in source code form or as a compiled binary, for any purpose,
      46                 :  * commercial or non-commercial, and by any means.
      47                 :  */
      48                 : 
      49                 : 
      50                 : #include "ogrsqliteregexp.h"
      51                 : 
      52                 : #ifdef HAVE_PCRE
      53                 : 
      54                 : #include <pcre.h>
      55                 : 
      56                 : typedef struct {
      57                 :     char *s;
      58                 :     pcre *p;
      59                 :     pcre_extra *e;
      60                 : } cache_entry;
      61                 : 
      62                 : #ifndef CACHE_SIZE
      63                 : #define CACHE_SIZE 16
      64                 : #endif
      65                 : 
      66                 : /************************************************************************/
      67                 : /*                         OGRSQLiteREGEXPFunction()                    */
      68                 : /************************************************************************/
      69                 : 
      70                 : static
      71              80 : void OGRSQLiteREGEXPFunction(sqlite3_context *ctx, int argc, sqlite3_value **argv)
      72                 : {
      73                 :     const char *re, *str;
      74                 :     pcre *p;
      75                 :     pcre_extra *e;
      76                 : 
      77              80 :     CPLAssert(argc == 2);
      78                 : 
      79              80 :     re = (const char *) sqlite3_value_text(argv[0]);
      80              80 :     if (!re) {
      81               2 :         sqlite3_result_error(ctx, "no regexp", -1);
      82               2 :         return;
      83                 :     }
      84                 : 
      85              78 :     if( sqlite3_value_type(argv[1]) == SQLITE_NULL )
      86                 :     {
      87               2 :         sqlite3_result_int(ctx, 0);
      88               2 :         return;
      89                 :     }
      90                 : 
      91              76 :     str = (const char *) sqlite3_value_text(argv[1]);
      92              76 :     if (!str) {
      93               0 :         sqlite3_result_error(ctx, "no string", -1);
      94               0 :         return;
      95                 :     }
      96                 : 
      97                 :     /* simple LRU cache */
      98                 :     int i;
      99              76 :     int found = 0;
     100              76 :     cache_entry *cache = (cache_entry*) sqlite3_user_data(ctx);
     101                 : 
     102              76 :     CPLAssert(cache);
     103                 : 
     104             898 :     for (i = 0; i < CACHE_SIZE && cache[i].s; i++)
     105                 :     {
     106             828 :         if (strcmp(re, cache[i].s) == 0) {
     107               6 :             found = 1;
     108               6 :             break;
     109                 :         }
     110                 :     }
     111                 : 
     112              76 :     if (found)
     113                 :     {
     114               6 :         if (i > 0)
     115                 :         {
     116               4 :             cache_entry c = cache[i];
     117               4 :             memmove(cache + 1, cache, i * sizeof(cache_entry));
     118               4 :             cache[0] = c;
     119                 :         }
     120                 :     }
     121                 :     else
     122                 :     {
     123                 :         cache_entry c;
     124                 :         const char *err;
     125                 :         int pos;
     126              70 :         c.p = pcre_compile(re, 0, &err, &pos, NULL);
     127              70 :         if (!c.p)
     128                 :         {
     129               2 :             char *e2 = sqlite3_mprintf("%s: %s (offset %d)", re, err, pos);
     130               2 :             sqlite3_result_error(ctx, e2, -1);
     131               2 :             sqlite3_free(e2);
     132               2 :             return;
     133                 :         }
     134              68 :         c.e = pcre_study(c.p, 0, &err);
     135              68 :         c.s = VSIStrdup(re);
     136              68 :         if (!c.s)
     137                 :         {
     138               0 :             sqlite3_result_error(ctx, "strdup: ENOMEM", -1);
     139               0 :             pcre_free(c.p);
     140               0 :             pcre_free(c.e);
     141               0 :             return;
     142                 :         }
     143              68 :         i = CACHE_SIZE - 1;
     144              68 :         if (cache[i].s)
     145                 :         {
     146              36 :             CPLFree(cache[i].s);
     147              36 :             CPLAssert(cache[i].p);
     148              36 :             pcre_free(cache[i].p);
     149              36 :             pcre_free(cache[i].e);
     150                 :         }
     151              68 :         memmove(cache + 1, cache, i * sizeof(cache_entry));
     152              68 :         cache[0] = c;
     153                 :     }
     154              74 :     p = cache[0].p;
     155              74 :     e = cache[0].e;
     156                 : 
     157                 :     int rc;
     158              74 :     CPLAssert(p);
     159              74 :     rc = pcre_exec(p, e, str, strlen(str), 0, 0, NULL, 0);
     160              74 :     sqlite3_result_int(ctx, rc >= 0);
     161                 : }
     162                 : 
     163                 : #endif // HAVE_PCRE
     164                 : 
     165                 : /************************************************************************/
     166                 : /*                        OGRSQLiteRegisterRegExpFunction()             */
     167                 : /************************************************************************/
     168                 : 
     169                 : static
     170             751 : void* OGRSQLiteRegisterRegExpFunction(sqlite3* hDB)
     171                 : {
     172                 : #ifdef HAVE_PCRE
     173                 : 
     174                 :     /* For debugging purposes mostly */
     175             751 :     if( !CSLTestBoolean(CPLGetConfigOption("OGR_SQLITE_REGEXP", "YES")) )
     176               0 :         return NULL;
     177                 : 
     178                 :     /* Check if we really need to define our own REGEXP function */
     179             751 :     int rc = sqlite3_exec(hDB, "SELECT 'a' REGEXP 'a'", NULL, NULL, NULL);
     180             751 :     if( rc == SQLITE_OK )
     181                 :     {
     182               0 :         CPLDebug("SQLITE", "REGEXP already available");
     183               0 :         return NULL;
     184                 :     }
     185                 : 
     186             751 :     cache_entry *cache = (cache_entry*) CPLCalloc(CACHE_SIZE, sizeof(cache_entry));
     187                 :     sqlite3_create_function(hDB, "REGEXP", 2, SQLITE_UTF8, cache,
     188             751 :                             OGRSQLiteREGEXPFunction, NULL, NULL);
     189                 : 
     190                 :     /* To clear the error flag */
     191             751 :     sqlite3_exec(hDB, "SELECT 1", NULL, NULL, NULL);
     192                 : 
     193             751 :     return cache;
     194                 : #else // HAVE_PCRE
     195                 :     return NULL;
     196                 : #endif // HAVE_PCRE
     197                 : }
     198                 : 
     199                 : /************************************************************************/
     200                 : /*                         OGRSQLiteFreeRegExpCache()                   */
     201                 : /************************************************************************/
     202                 : 
     203                 : static
     204             751 : void OGRSQLiteFreeRegExpCache(void* hRegExpCache)
     205                 : {
     206                 : #ifdef HAVE_PCRE
     207             751 :     if( hRegExpCache == NULL )
     208               0 :         return;
     209                 : 
     210             751 :     cache_entry *cache = (cache_entry*) hRegExpCache;
     211                 :     int i;
     212             783 :     for (i = 0; i < CACHE_SIZE && cache[i].s; i++)
     213                 :     {
     214              32 :         CPLFree(cache[i].s);
     215              32 :         CPLAssert(cache[i].p);
     216              32 :         pcre_free(cache[i].p);
     217              32 :         pcre_free(cache[i].e);
     218                 :     }
     219             751 :     CPLFree(cache);
     220                 : #endif // HAVE_PCRE
     221                 : }

Generated by: LCOV version 1.7