LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/sqlite - ogrsqliteregexp.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 72 65 90.3 %
Date: 2012-12-26 Functions: 3 3 100.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: ogrsqliteregexp.cpp 25052 2012-10-05 23:30:16Z 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                 : /* This code originates from pcre.c from the sqlite3-pcre extension */
      31                 : /* from http://laltromondo.dynalias.net/~iki/informatica/soft/sqlite3-pcre/ */
      32                 : /* whose header is : */
      33                 : /*
      34                 :  * Written by Alexey Tourbin <at@altlinux.org>.
      35                 :  *
      36                 :  * The author has dedicated the code to the public domain.  Anyone is free
      37                 :  * to copy, modify, publish, use, compile, sell, or distribute the original
      38                 :  * code, either in source code form or as a compiled binary, for any purpose,
      39                 :  * commercial or non-commercial, and by any means.
      40                 :  */
      41                 : 
      42                 : 
      43                 : #include "ogrsqliteregexp.h"
      44                 : 
      45                 : #ifdef HAVE_PCRE
      46                 : 
      47                 : #include <pcre.h>
      48                 : 
      49                 : typedef struct {
      50                 :     char *s;
      51                 :     pcre *p;
      52                 :     pcre_extra *e;
      53                 : } cache_entry;
      54                 : 
      55                 : #ifndef CACHE_SIZE
      56                 : #define CACHE_SIZE 16
      57                 : #endif
      58                 : 
      59                 : /************************************************************************/
      60                 : /*                         OGRSQLiteREGEXPFunction()                    */
      61                 : /************************************************************************/
      62                 : 
      63                 : static
      64              95 : void OGRSQLiteREGEXPFunction(sqlite3_context *ctx, int argc, sqlite3_value **argv)
      65                 : {
      66                 :     const char *re, *str;
      67                 :     pcre *p;
      68                 :     pcre_extra *e;
      69                 : 
      70              95 :     CPLAssert(argc == 2);
      71                 : 
      72              95 :     re = (const char *) sqlite3_value_text(argv[0]);
      73              95 :     if (!re) {
      74               2 :         sqlite3_result_error(ctx, "no regexp", -1);
      75               2 :         return;
      76                 :     }
      77                 : 
      78              93 :     if( sqlite3_value_type(argv[1]) == SQLITE_NULL )
      79                 :     {
      80               2 :         sqlite3_result_int(ctx, 0);
      81               2 :         return;
      82                 :     }
      83                 : 
      84              91 :     str = (const char *) sqlite3_value_text(argv[1]);
      85              91 :     if (!str) {
      86               0 :         sqlite3_result_error(ctx, "no string", -1);
      87               0 :         return;
      88                 :     }
      89                 : 
      90                 :     /* simple LRU cache */
      91                 :     int i;
      92              91 :     int found = 0;
      93              91 :     cache_entry *cache = (cache_entry*) sqlite3_user_data(ctx);
      94                 : 
      95              91 :     CPLAssert(cache);
      96                 : 
      97             913 :     for (i = 0; i < CACHE_SIZE && cache[i].s; i++)
      98                 :     {
      99             828 :         if (strcmp(re, cache[i].s) == 0) {
     100               6 :             found = 1;
     101               6 :             break;
     102                 :         }
     103                 :     }
     104                 : 
     105              91 :     if (found)
     106                 :     {
     107               6 :         if (i > 0)
     108                 :         {
     109               4 :             cache_entry c = cache[i];
     110               4 :             memmove(cache + 1, cache, i * sizeof(cache_entry));
     111               4 :             cache[0] = c;
     112                 :         }
     113                 :     }
     114                 :     else
     115                 :     {
     116                 :         cache_entry c;
     117                 :         const char *err;
     118                 :         int pos;
     119              85 :         c.p = pcre_compile(re, 0, &err, &pos, NULL);
     120              85 :         if (!c.p)
     121                 :         {
     122               2 :             char *e2 = sqlite3_mprintf("%s: %s (offset %d)", re, err, pos);
     123               2 :             sqlite3_result_error(ctx, e2, -1);
     124               2 :             sqlite3_free(e2);
     125               2 :             return;
     126                 :         }
     127              83 :         c.e = pcre_study(c.p, 0, &err);
     128              83 :         c.s = VSIStrdup(re);
     129              83 :         if (!c.s)
     130                 :         {
     131               0 :             sqlite3_result_error(ctx, "strdup: ENOMEM", -1);
     132               0 :             pcre_free(c.p);
     133               0 :             pcre_free(c.e);
     134               0 :             return;
     135                 :         }
     136              83 :         i = CACHE_SIZE - 1;
     137              83 :         if (cache[i].s)
     138                 :         {
     139              36 :             CPLFree(cache[i].s);
     140              36 :             CPLAssert(cache[i].p);
     141              36 :             pcre_free(cache[i].p);
     142              36 :             pcre_free(cache[i].e);
     143                 :         }
     144              83 :         memmove(cache + 1, cache, i * sizeof(cache_entry));
     145              83 :         cache[0] = c;
     146                 :     }
     147              89 :     p = cache[0].p;
     148              89 :     e = cache[0].e;
     149                 : 
     150                 :     int rc;
     151              89 :     CPLAssert(p);
     152              89 :     rc = pcre_exec(p, e, str, strlen(str), 0, 0, NULL, 0);
     153              89 :     sqlite3_result_int(ctx, rc >= 0);
     154                 : }
     155                 : 
     156                 : #endif // HAVE_PCRE
     157                 : 
     158                 : /************************************************************************/
     159                 : /*                        OGRSQLiteRegisterRegExpFunction()             */
     160                 : /************************************************************************/
     161                 : 
     162             634 : void* OGRSQLiteRegisterRegExpFunction(sqlite3* hDB)
     163                 : {
     164                 : #ifdef HAVE_PCRE
     165                 : 
     166                 :     /* For debugging purposes mostly */
     167             634 :     if( !CSLTestBoolean(CPLGetConfigOption("OGR_SQLITE_REGEXP", "YES")) )
     168               0 :         return NULL;
     169                 : 
     170                 :     /* Check if we really need to define our own REGEXP function */
     171             634 :     int rc = sqlite3_exec(hDB, "SELECT 'a' REGEXP 'a'", NULL, NULL, NULL);
     172             634 :     if( rc == SQLITE_OK )
     173                 :     {
     174              15 :         CPLDebug("SQLITE", "REGEXP already available");
     175              15 :         return NULL;
     176                 :     }
     177                 : 
     178             619 :     cache_entry *cache = (cache_entry*) CPLCalloc(CACHE_SIZE, sizeof(cache_entry));
     179                 :     sqlite3_create_function(hDB, "REGEXP", 2, SQLITE_UTF8, cache,
     180             619 :                             OGRSQLiteREGEXPFunction, NULL, NULL);
     181                 : 
     182                 :     /* To clear the error flag */
     183             619 :     sqlite3_exec(hDB, "SELECT 1", NULL, NULL, NULL);
     184                 : 
     185             619 :     return cache;
     186                 : #else // HAVE_PCRE
     187                 :     return NULL;
     188                 : #endif // HAVE_PCRE
     189                 : }
     190                 : 
     191                 : /************************************************************************/
     192                 : /*                         OGRSQLiteFreeRegExpCache()                   */
     193                 : /************************************************************************/
     194                 : 
     195             874 : void OGRSQLiteFreeRegExpCache(void* hRegExpCache)
     196                 : {
     197                 : #ifdef HAVE_PCRE
     198             874 :     if( hRegExpCache == NULL )
     199             255 :         return;
     200                 : 
     201             619 :     cache_entry *cache = (cache_entry*) hRegExpCache;
     202                 :     int i;
     203             666 :     for (i = 0; i < CACHE_SIZE && cache[i].s; i++)
     204                 :     {
     205              47 :         CPLFree(cache[i].s);
     206              47 :         CPLAssert(cache[i].p);
     207              47 :         pcre_free(cache[i].p);
     208              47 :         pcre_free(cache[i].e);
     209                 :     }
     210             619 :     CPLFree(cache);
     211                 : #endif // HAVE_PCRE
     212                 : }

Generated by: LCOV version 1.7