Changeset: 822bcb77f1da for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=822bcb77f1da
Modified Files:
        monetdb5/modules/atoms/str.c
        sql/backends/monet5/UDF/udf/udf.c
Branch: Nov2019
Log Message:

Backported recent string function fixes from Jun2020 into Nov2019


diffs (truncated from 513 to 300 lines):

diff --git a/monetdb5/modules/atoms/str.c b/monetdb5/modules/atoms/str.c
--- a/monetdb5/modules/atoms/str.c
+++ b/monetdb5/modules/atoms/str.c
@@ -3156,68 +3156,123 @@ UTF8_strtail(const char *s, int pos)
        return (str) s;
 }
 
+static inline str
+UTF8_strncpy(char *restrict dst, const char *restrict s, int n)
+{
+       UTF8_assert(s);
+       while (*s && n) {
+               if ((*s & 0xF8) == 0xF0) {
+                       /* 4 byte UTF-8 sequence */
+                       *dst++ = *s++;
+                       *dst++ = *s++;
+                       *dst++ = *s++;
+                       *dst++ = *s++;
+               } else if ((*s & 0xF0) == 0xE0) {
+                       /* 3 byte UTF-8 sequence */
+                       *dst++ = *s++;
+                       *dst++ = *s++;
+                       *dst++ = *s++;
+               } else if ((*s & 0xE0) == 0xC0) {
+                       /* 2 byte UTF-8 sequence */
+                       *dst++ = *s++;
+                       *dst++ = *s++;
+               } else {
+                       /* 1 byte UTF-8 "sequence" */
+                       *dst++ = *s++;
+               }
+               n--;
+       }
+       *dst = '\0';
+       return dst;
+}
+
+static inline str
+UTF8_offset(char *restrict s, int n)
+{
+       UTF8_assert(s);
+       while (*s && n) {
+               if ((*s & 0xF8) == 0xF0) {
+                       /* 4 byte UTF-8 sequence */
+                       s += 4;
+               } else if ((*s & 0xF0) == 0xE0) {
+                       /* 3 byte UTF-8 sequence */
+                       s += 3;
+               } else if ((*s & 0xE0) == 0xC0) {
+                       /* 2 byte UTF-8 sequence */
+                       s += 2;
+               } else {
+                       /* 1 byte UTF-8 "sequence" */
+                       s++;
+               }
+               n--;
+       }
+       return s;
+}
+
 static str
 convertCase(BAT *from, BAT *to, str *res, const char *src, const char *malfunc)
 {
-       BATiter toi = bat_iterator(to);
-       BATiter fromi = bat_iterator(from);
        size_t len = strlen(src);
        char *dst;
        const char *end = src + len;
-       BUN UTF8_CONV_r;
        bool lower_to_upper = from == UTF8_toUpperFrom;
 
-       if (strNil(src)) {
+       if (GDK_STRNIL(src)) {
                *res = GDKstrdup(str_nil);
        } else {
-               *res = GDKmalloc(len + 1);
-               if (*res != NULL) {
-                       dst = *res;
-                       while (src < end) {
-                               int c;
+               if (BAThash(from) != GDK_SUCCEED ||
+                       (*res = GDKmalloc(len + 1)) == NULL) {
+                       throw(MAL, malfunc, SQLSTATE(HY013) MAL_MALLOC_FAIL);
+               }
+               Hash *h = from->thash;
+               dst = *res;
+               while (src < end) {
+                       int c;
 
-                               UTF8_GETCHAR(c, src);
-                               if ((c & 0x80) == 0) {
-                                       /* for ASCII characters we don't need 
to do a hash
-                                        * lookup */
-                                       if (lower_to_upper) {
-                                               if ('a' <= c && c <= 'z')
-                                                       c += 'A' - 'a';
-                                       } else {
-                                               if ('A' <= c && c <= 'Z')
-                                                       c += 'a' - 'A';
-                                       }
+                       UTF8_GETCHAR(c, src);
+                       if ((c & 0x80) == 0) {
+                               /* for ASCII characters we don't need to do a 
hash
+                                * lookup */
+                               if (lower_to_upper) {
+                                       if ('a' <= c && c <= 'z')
+                                               c += 'A' - 'a';
                                } else {
-                                       /* use hash, even though BAT is sorted 
*/
-                                       HASHfnd_int(UTF8_CONV_r, fromi, &c);
-                                       if (UTF8_CONV_r != BUN_NONE)
-                                               c = *(int*) BUNtloc(toi, 
UTF8_CONV_r);
+                                       if ('A' <= c && c <= 'Z')
+                                               c += 'a' - 'A';
                                }
-                               if (dst + UTF8_CHARLEN(c) > *res + len) {
-                                       /* doesn't fit, so allocate more space;
-                                        * also allocate enough for the rest of 
the
-                                        * source */
-                                       size_t off = dst - *res;
+                       } else {
+                               /* use hash, even though BAT is sorted */
+                               for (BUN hb = HASHget(h, hash_int(h, &c));
+                                        hb != HASHnil(h);
+                                        hb = HASHgetlink(h, hb)) {
+                                       if (c == ((int *) 
from->theap.base)[hb]) {
+                                               c = ((int *) 
to->theap.base)[hb];
+                                               break;
+                                       }
+                               }
+                       }
+                       if (dst + UTF8_CHARLEN(c) > *res + len) {
+                               /* doesn't fit, so allocate more space;
+                                * also allocate enough for the rest of the
+                                * source */
+                               size_t off = dst - *res;
 
-                                       dst = GDKrealloc(*res, (len += 4 + (end 
- src)) + 1);
-                                       if (dst == NULL) {
-                                               /* if realloc fails, original 
buffer is still
-                                                * allocated, so free it */
-                                               GDKfree(*res);
-                                               goto hashfnd_failed;
-                                       }
-                                       *res = dst;
-                                       dst = *res + off;
+                               dst = GDKrealloc(*res, (len += 4 + (end - src)) 
+ 1);
+                               if (dst == NULL) {
+                                       /* if realloc fails, original buffer is 
still
+                                        * allocated, so free it */
+                                       GDKfree(*res);
+                                       throw(MAL, malfunc, SQLSTATE(HY013) 
MAL_MALLOC_FAIL);
                                }
-                               UTF8_PUTCHAR(c, dst);
+                               *res = dst;
+                               dst = *res + off;
                        }
-                       *dst = 0;
+                       UTF8_PUTCHAR(c, dst);
                }
+               *dst = 0;
        }
        if (*res != NULL)
                return MAL_SUCCEED;
-  hashfnd_failed:
-       throw(MAL, malfunc, SQLSTATE(HY013) MAL_MALLOC_FAIL);
   illegal:
        throw(MAL, malfunc, SQLSTATE(42000) "Illegal Unicode code point");
 }
@@ -3301,7 +3356,7 @@ STRConcat(str *res, const str *val1, con
        const char *s1 = *val1;
        const char *s2 = *val2;
 
-       if (strNil(s1) || strNil(s2)) {
+       if (GDK_STRNIL(s1) || GDK_STRNIL(s2)) {
                *res = GDKstrdup(str_nil);
        } else {
                l1 = strlen(s1);
@@ -3323,7 +3378,7 @@ STRLength(int *res, const str *arg1)
        size_t l;
        const char *s = *arg1;
 
-       if (strNil(s)) {
+       if (GDK_STRNIL(s)) {
                *res = int_nil;
                return MAL_SUCCEED;
        }
@@ -3341,7 +3396,7 @@ STRBytes(int *res, const str *arg1)
        size_t l;
        const char *s = *arg1;
 
-       if (strNil(s)) {
+       if (GDK_STRNIL(s)) {
                *res = int_nil;
                return MAL_SUCCEED;
        }
@@ -3357,7 +3412,7 @@ STRTail(str *res, const str *arg1, const
        int off = *offset;
        const char *s = *arg1;
 
-       if (strNil(s) || is_int_nil(off)) {
+       if (GDK_STRNIL(s) || is_int_nil(off)) {
                *res = GDKstrdup(str_nil);
        } else {
                if (off < 0) {
@@ -3382,7 +3437,7 @@ STRSubString(str *res, const str *arg1, 
        int off = *offset, l = *length;
        const char *s = *arg1;
 
-       if (strNil(s) || is_int_nil(off) || is_int_nil(l)) {
+       if (GDK_STRNIL(s) || is_int_nil(off) || is_int_nil(l)) {
                *res = GDKstrdup(str_nil);
                if (*res == NULL)
                        throw(MAL, "str.substring", SQLSTATE(HY013) 
MAL_MALLOC_FAIL);
@@ -3447,7 +3502,7 @@ STRWChrAt(int *res, const str *arg1, con
 /* 64bit: should have lng arg */
        const char *s = *arg1;
 
-       if (strNil(s) || is_int_nil(*at) || *at < 0) {
+       if (GDK_STRNIL(s) || is_int_nil(*at) || *at < 0) {
                *res = int_nil;
                return MAL_SUCCEED;
        }
@@ -3469,7 +3524,7 @@ STRPrefix(bit *res, const str *arg1, con
        const char *s = *arg1;
        const char *prefix = *arg2;
 
-       if (strNil(s) || strNil(prefix)) {
+       if (GDK_STRNIL(s) || GDK_STRNIL(prefix)) {
                *res = bit_nil;
                return MAL_SUCCEED;
        }
@@ -3485,7 +3540,7 @@ STRSuffix(bit *res, const str *arg1, con
        const char *s = *arg1;
        const char *suffix = *arg2;
 
-       if (strNil(s) || strNil(suffix)) {
+       if (GDK_STRNIL(s) || GDK_STRNIL(suffix)) {
                *res = bit_nil;
                return MAL_SUCCEED;
        }
@@ -3519,7 +3574,7 @@ STRstrSearch(int *res, const str *haysta
        const char *s = *haystack;
        const char *s2 = *needle;
 
-       if (strNil(s) || strNil(s2)) {
+       if (GDK_STRNIL(s) || GDK_STRNIL(s2)) {
                *res = int_nil;
                return MAL_SUCCEED;
        }
@@ -3539,7 +3594,7 @@ STRReverseStrSearch(int *res, const str 
        const char *s = *arg1;
        const char *s2 = *arg2;
 
-       if (strNil(s) || strNil(s2)) {
+       if (GDK_STRNIL(s) || GDK_STRNIL(s2)) {
                *res = int_nil;
                return MAL_SUCCEED;
        }
@@ -3564,11 +3619,11 @@ STRsplitpart(str *res, str *haystack, st
 {
        size_t len;
        int f = *field;
-       char *p;
+       char *p = NULL;
        const char *s = *haystack;
        const char *s2 = *needle;
 
-       if (strNil(s) || strNil(s2) || is_int_nil(*field)) {
+       if (GDK_STRNIL(s) || GDK_STRNIL(s2) || is_int_nil(*field)) {
                *res = GDKstrdup(str_nil);
                if (*res == NULL)
                        throw(MAL, "str.splitpart", SQLSTATE(HY013) 
MAL_MALLOC_FAIL);
@@ -3580,10 +3635,11 @@ STRsplitpart(str *res, str *haystack, st
        }
 
        len = strlen(s2);
-
-       while ((p = strstr(s, s2)) != NULL && f > 1) {
-               s = p + len;
-               f--;
+       if (len) {
+               while ((p = strstr(s, s2)) != NULL && f > 1) {
+                       s = p + len;
+                       f--;
+               }
        }
 
        if (f != 1) {
@@ -3744,10 +3800,10 @@ STRRtrim(str *res, const str *arg1)
 
 /* return a list of codepoints in s */
 static int *
-trimchars(const char *s, size_t *n)
+trimchars(const char *s, size_t *n, size_t len_s)
 {
        size_t len = 0;
-       int *chars = GDKmalloc(strlen(s) * sizeof(int));
+       int *chars = GDKmalloc(len_s * sizeof(int));
        int c;
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to