Changeset: 8af0e497f840 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=8af0e497f840
Modified Files:
        monetdb5/modules/mal/pcre.c
Branch: Aug2018
Log Message:

Only convert pattern to wide character string once per select.


diffs (274 lines):

diff --git a/monetdb5/modules/mal/pcre.c b/monetdb5/modules/mal/pcre.c
--- a/monetdb5/modules/mal/pcre.c
+++ b/monetdb5/modules/mal/pcre.c
@@ -85,6 +85,7 @@ mal_export str ILIKEjoin1(bat *r1, bat *
 /* current implementation assumes simple %keyword% [keyw%]* */
 typedef struct RE {
        char *k;
+       wchar_t *w;
        bool search;
        ptrdiff_t len;
        struct RE *n;
@@ -163,32 +164,27 @@ my_mbsrtowcs(wchar_t *dst, const char **
 #endif
 
 static int
-mystrncasecmp(const char *s1, const char *s2, size_t n1)
+mywstrncasecmp(const char *s1, const wchar_t *s2, size_t n2)
 {
-       wchar_t c1, c2;
-       size_t n2 = n1;
+       wchar_t c1;
 
 #ifndef _MSC_VER
-       mbstate_t ps1, ps2;
+       mbstate_t ps1;
        memset(&ps1, 0, sizeof(ps1));
-       memset(&ps2, 0, sizeof(ps2));
 #endif
-       while (n1 > 0 && n2 > 0) {
-               size_t nn1 = mbrtowc(&c1, s1, n1, &ps1);
-               size_t nn2 = mbrtowc(&c2, s2, n2, &ps2);
+       while (n2 > 0) {
+               size_t nn1 = mbrtowc(&c1, s1, 1000, &ps1);
                if (nn1 == 0)
-                       return -(nn2 != 0);
-               if (nn2 == 0)
+                       return -(*s2 != 0);
+               if (*s2 == 0)
                        return 1;
-               if (nn1 == (size_t) -1 || nn1 == (size_t) -2 ||
-                       nn2 == (size_t) -1 || nn2 == (size_t) -2)
+               if (nn1 == (size_t) -1 || nn1 == (size_t) -2)
                        return 0;        /* actually an error that shouldn't 
happen */
-               if (towlower((wint_t) c1) != towlower((wint_t) c2))
-                       return towlower((wint_t) c1) - towlower((wint_t) c2);
-               n1 -= nn1;
+               if (towlower((wint_t) c1) != towlower((wint_t) *s2))
+                       return towlower((wint_t) c1) - towlower((wint_t) *s2);
                s1 += nn1;
-               n2 -= nn2;
-               s2 += nn2;
+               n2--;
+               s2++;
        }
        return 0;
 }
@@ -251,53 +247,47 @@ mywstrcasecmp(const char *s1, const wcha
 }
 
 static const char *
-mystrcasestr(const char *haystack, const char *needle)
+mywstrcasestr(const char *haystack, const wchar_t *wneedle)
 {
-       size_t nlen = strlen(needle);
+       size_t nlen = wcslen(wneedle);
 
-#ifndef _MSC_VER
-       mbstate_t ps;
-       memset(&ps, 0, sizeof(ps));
-#endif
        if (nlen == 0)
                return haystack;
-       wchar_t *wneedle = GDKmalloc((nlen + 1) * sizeof(wchar_t));
-       const char *n = needle;
-       if (wneedle == NULL || (nlen = mbsrtowcs(wneedle, &needle, nlen + 1, 
&ps)) == (size_t) -1) {
-               needle = n;                             /* start over */
-               GDKfree(wneedle);
-               nlen = strlen(needle);
-               /* fallback code */
-               for (size_t hlen = strlen(haystack); nlen <= hlen; hlen--) {
-                       if (mystrncasecmp(haystack, needle, nlen) == 0)
-                               return haystack;
-                       while ((*++haystack & 0xC0) == 0x80)
-                               hlen--;
-               }
-               return NULL;
-       }
-       for (wchar_t *w = wneedle; *w; w++)
-               *w = (wchar_t) towlower((wint_t) *w);
-       for (size_t hlen = strlen(haystack); *haystack; hlen--) {
+
+       size_t hlen = strlen(haystack);
+#ifndef _MSC_VER
+       mbstate_t ps, pss;
+       memset(&ps, 0, sizeof(ps));
+       pss = ps;
+#endif
+
+       while (*haystack) {
                size_t i;
-               for (i = 0; i < nlen; i++) {
+               size_t h;
+               size_t step = 0;
+               for (i = h = 0; i < nlen; i++) {
                        wchar_t c;
-                       size_t j = mbrtowc(&c, haystack, hlen, &ps);
-                       if (j == 0) {
-                               GDKfree(wneedle);
+                       size_t j = mbrtowc(&c, haystack + h, hlen - h, &ps);
+                       if (j == 0)
                                return NULL;
+                       if (i == 0) {
+                               step = j;
+#ifndef _MSC_VER
+                               pss = ps;
+#endif
                        }
-                       if (towlower((wint_t) c) != (wint_t) wneedle[i])
+                       if (towlower((wint_t) c) != towlower((wint_t) 
wneedle[i]))
                                break;
-               }
-               if (i == nlen) {
-                       GDKfree(wneedle);
-                       return haystack;
+                       h += j;
                }
-               while ((*++haystack & 0xC0) == 0x80)
-                       hlen--;
+               if (i == nlen)
+                       return haystack;
+#ifndef _MSC_VER
+               ps = pss;
+#endif
+               haystack += step;
+               hlen -= step;
        }
-       GDKfree(wneedle);
        return NULL;
 }
 
@@ -336,7 +326,7 @@ re_match_ignore(const char *s, RE *patte
 
        for (r = pattern; r; r = r->n) {
                if (!*s ||
-                       (r->search ? (s = mystrcasestr(s, r->k)) == NULL : 
mystrncasecmp(s, r->k, r->len) != 0))
+                       (r->search ? (s = mywstrcasestr(s, r->w)) == NULL : 
mywstrncasecmp(s, r->w, r->len) != 0))
                        return false;
                s += r->len;
        }
@@ -362,6 +352,7 @@ re_destroy(RE *p)
 {
        if (p) {
                GDKfree(p->k);
+               GDKfree(p->w);
                do {
                        RE *n = p->n;
 
@@ -371,42 +362,77 @@ re_destroy(RE *p)
        }
 }
 
-/* Create a linked list of RE structures.  The k field in the first
- * structure is allocated, whereas the k field in all subsequent
- * structures point into the allocated buffer of the first. */
+/* Create a linked list of RE structures.  Depending on the caseignore
+ * flag, the w (if true) or the k (if false) field is used.  These
+ * fields in the first structure are allocated, whereas in all
+ * subsequent structures the fields point into the allocated buffer of
+ * the first. */
 static RE *
-re_create(const char *pat, int nr)
+re_create(const char *pat, int nr, bool caseignore)
 {
        RE *r = (RE*)GDKmalloc(sizeof(RE)), *n = r;
-       char *p, *q;
 
        if (r == NULL)
                return NULL;
        r->n = NULL;
        r->search = 0;
        r->k = NULL;
+       r->w = NULL;
 
        if (*pat == '%') {
                pat++; /* skip % */
                r->search = true;
        }
-       if ((p = GDKstrdup(pat)) == NULL) {
-               GDKfree(r);
-               return NULL;
-       }
-       while ((q = strchr(p, '%')) != NULL) {
-               *q = 0;
-               n->k = p;
-               n->len = q - p;
-               if (--nr > 0) {
-                       n = n->n = (RE*)GDKmalloc(sizeof(RE));
-                       if (n == NULL)
-                               goto bailout;
-                       n->search = true;
-                       n->n = NULL;
-                       n->k = NULL;
+       if (caseignore) {
+               size_t patlen = strlen(pat);
+               wchar_t *wp = GDKmalloc(sizeof(wchar_t) * (patlen + 1));
+               wchar_t *wq;
+#ifndef _MSC_VER
+               mbstate_t ps;
+               memset(&ps, 0, sizeof(ps));
+#endif
+               if (wp == NULL) {
+                       GDKfree(r);
+                       return NULL;
                }
-               p = q + 1;
+               mbsrtowcs(wp, &pat, patlen + 1, &ps);
+               r->w = wp;
+               while ((wq = wcschr(wp, L'%')) != NULL) {
+                       *wq = 0;
+                       n->w = wp;
+                       n->len = wq - wp;
+                       if (--nr > 0) {
+                               n = n->n = (RE*)GDKmalloc(sizeof(RE));
+                               if (n == NULL)
+                                       goto bailout;
+                               n->search = true;
+                               n->n = NULL;
+                               n->k = NULL;
+                               n->w = NULL;
+                       }
+                       wp = wq + 1;
+               }
+       } else {
+               char *p, *q;
+               if ((p = GDKstrdup(pat)) == NULL) {
+                       GDKfree(r);
+                       return NULL;
+               }
+               while ((q = strchr(p, '%')) != NULL) {
+                       *q = 0;
+                       n->k = p;
+                       n->len = q - p;
+                       if (--nr > 0) {
+                               n = n->n = (RE*)GDKmalloc(sizeof(RE));
+                               if (n == NULL)
+                                       goto bailout;
+                               n->search = true;
+                               n->n = NULL;
+                               n->k = NULL;
+                               n->w = NULL;
+                       }
+                       p = q + 1;
+               }
        }
        return r;
   bailout:
@@ -616,7 +642,7 @@ re_likeselect(BAT **bnp, BAT *b, BAT *s,
 
        if (!use_strcmp) {
                nr = re_simple(pat);
-               re = re_create(pat, nr);
+               re = re_create(pat, nr, caseignore);
                if (!re)
                        throw(MAL, "pcre.likeselect", SQLSTATE(HY001) 
MAL_MALLOC_FAIL);
        }
@@ -2012,7 +2038,7 @@ pcrejoin(BAT *r1, BAT *r2, BAT *l, BAT *
                if (strcmp(vr, str_nil) == 0)
                        continue;
                if (*esc == 0 && (nr = re_simple(vr)) > 0) {
-                       re = re_create(vr, nr);
+                       re = re_create(vr, nr, caseignore);
                        if (re == NULL) {
                                msg = createException(MAL, "pcre.join", 
SQLSTATE(HY001) MAL_MALLOC_FAIL);
                                goto bailout;
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to