Changeset: 6ea95a92719f for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=6ea95a92719f
Modified Files:
monetdb5/modules/mal/pcre.c
Branch: Aug2018
Log Message:
Avoid mbstowcs (thread-safety); convert pattern to wide string only once.
diffs (187 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
@@ -95,7 +95,7 @@ typedef struct RE {
#ifdef _MSC_VER
/* on Windows, we cannot set the UTF-8 locale, so we need to implement
- * our own version of mbrtowc and mbstowcs */
+ * our own version of mbrtowc and mbsrtowcs */
static size_t
my_mbrtowc(wchar_t *dst, const char *src, size_t len)
@@ -128,34 +128,38 @@ my_mbrtowc(wchar_t *dst, const char *src
}
static size_t
-my_mbstowcs(wchar_t *dst, const char *src, size_t len)
+my_mbsrtowcs(wchar_t *dst, const char **src, size_t len)
{
size_t i;
+ const char *s = *src;
for (i = 0; i < len; i++) {
- if ((src[0] & 0x80) == 0) {
- *dst = src[0];
- src += 1;
- } else if ((src[0] & 0xE0) == 0xC0) {
- *dst = ((src[0] & 0x1F) << 6) | (src[1] & 0x3F);
- src += 2;
- } else if ((src[0] & 0xF0) == 0xE0) {
- *dst = ((src[0] & 0x0F) << 12) | ((src[1] & 0x3F) << 6)
| (src[2] & 0x3F);
- src += 3;
- } else if ((src[0] & 0xF8) == 0xF0) {
- *dst = ((src[0] & 0x0F) << 18) | ((src[1] & 0x3F) <<
12) | ((src[2] & 0x3F) << 6) | (src[3] & 0x3F);
- src += 4;
+ if ((s[0] & 0x80) == 0) {
+ dst[i] = s[0];
+ s += 1;
+ } else if ((s[0] & 0xE0) == 0xC0) {
+ dst[i] = ((s[0] & 0x1F) << 6) | (s[1] & 0x3F);
+ s += 2;
+ } else if ((s[0] & 0xF0) == 0xE0) {
+ dst[i] = ((s[0] & 0x0F) << 12) | ((s[1] & 0x3F) << 6) |
(s[2] & 0x3F);
+ s += 3;
+ } else if ((s[0] & 0xF8) == 0xF0) {
+ dst[i] = ((s[0] & 0x0F) << 18) | ((s[1] & 0x3F) << 12)
| ((s[2] & 0x3F) << 6) | (s[3] & 0x3F);
+ s += 4;
} else {
+ *src = s;
return (size_t) -1;
}
- if (*dst == 0)
+ if (dst[i] == 0) {
+ *src = NULL;
return i;
- dst++;
+ }
}
+ *src = s;
return i;
}
-#define mbrtowc(dst, src, len, ps) my_mbrtowc(dst, src, len)
-#define mbstowcs(dst, src, len) my_mbstowcs(dst, src, len)
+#define mbrtowc(dst, src, len, ps) my_mbrtowc(dst, src, len)
+#define mbsrtowcs(dst, src, len, ps) my_mbsrtowcs(dst, src, len)
#endif
static int
@@ -219,15 +223,48 @@ mystrcasecmp(const char *s1, const char
}
}
+static int
+mywstrcasecmp(const char *s1, const wchar_t *s2)
+{
+ wchar_t c1;
+
+#ifndef _MSC_VER
+ mbstate_t ps1;
+ memset(&ps1, 0, sizeof(ps1));
+#endif
+ for (;;) {
+ /* use some ridiculously high number as the length of the
+ * input strings: we will still not go beyond the terminating
+ * '\0' */
+ size_t nn1 = mbrtowc(&c1, s1, 1000, &ps1);
+ if (nn1 == 0)
+ return -(*s2 != 0);
+ if (*s2 == 0)
+ return 1;
+ 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) *s2))
+ return towlower((wint_t) c1) - towlower((wint_t) *s2);
+ s1 += nn1;
+ s2++;
+ }
+}
+
static const char *
mystrcasestr(const char *haystack, const char *needle)
{
size_t nlen = strlen(needle);
+#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));
- if (wneedle == NULL || (nlen = mbstowcs(wneedle, needle, nlen + 1)) ==
(size_t) -1) {
+ 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 */
@@ -241,10 +278,6 @@ mystrcasestr(const char *haystack, const
}
for (wchar_t *w = wneedle; *w; w++)
*w = (wchar_t) towlower((wint_t) *w);
-#ifndef _MSC_VER
- mbstate_t ps;
- memset(&ps, 0, sizeof(ps));
-#endif
for (size_t hlen = strlen(haystack); *haystack; hlen--) {
size_t i;
for (i = 0; i < nlen; i++) {
@@ -590,7 +623,6 @@ re_likeselect(BAT **bnp, BAT *b, BAT *s,
if (s && !BATtdense(s)) {
const oid *candlist;
BUN r;
-
assert(s->ttype == TYPE_oid || s->ttype == TYPE_void);
assert(s->tsorted);
assert(s->tkey);
@@ -602,12 +634,22 @@ re_likeselect(BAT **bnp, BAT *b, BAT *s,
candlist = (const oid *) Tloc(s, p);
if (use_strcmp) {
if (caseignore) {
+ size_t patlen = strlen(pat);
+ wchar_t *wpat = GDKmalloc(sizeof(wchar_t) *
(patlen + 1));
+#ifndef _MSC_VER
+ mbstate_t ps;
+ memset(&ps, 0, sizeof(ps));
+#endif
+ if (wpat == NULL)
+ throw(MAL, "pcre.likeselect",
SQLSTATE(HY001) MAL_MALLOC_FAIL);
+ mbsrtowcs(wpat, &pat, patlen + 1, &ps);
if (anti)
candscanloop(v && *v != '\200' &&
-
mystrcasecmp(v, pat) != 0);
+
mywstrcasecmp(v, wpat) != 0);
else
candscanloop(v && *v != '\200' &&
-
mystrcasecmp(v, pat) == 0);
+
mywstrcasecmp(v, wpat) == 0);
+ GDKfree(wpat);
} else {
if (anti)
candscanloop(v && *v != '\200' &&
@@ -648,12 +690,22 @@ re_likeselect(BAT **bnp, BAT *b, BAT *s,
}
if (use_strcmp) {
if (caseignore) {
+ size_t patlen = strlen(pat);
+ wchar_t *wpat = GDKmalloc(sizeof(wchar_t) *
(patlen + 1));
+#ifndef _MSC_VER
+ mbstate_t ps;
+ memset(&ps, 0, sizeof(ps));
+#endif
+ if (wpat == NULL)
+ throw(MAL, "pcre.likeselect",
SQLSTATE(HY001) MAL_MALLOC_FAIL);
+ mbsrtowcs(wpat, &pat, patlen + 1, &ps);
if (anti)
scanloop(v && *v != '\200' &&
- mystrcasecmp(v, pat)
!= 0);
+ mywstrcasecmp(v, wpat)
!= 0);
else
scanloop(v && *v != '\200' &&
- mystrcasecmp(v, pat)
== 0);
+ mywstrcasecmp(v, wpat)
== 0);
+ GDKfree(wpat);
} else {
if (anti)
scanloop(v && *v != '\200' &&
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list