From: Jay Krell Date: Wed, 3 Jul 2019 02:55:10 +0000 (-0700) Subject: Cleanup and augment string handling based on https://github.com/mono/mono/pull/15522. X-Git-Tag: submit/tizen/20210909.063632~10331^2~5^2~591 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=0bae068a92d5df3d5274c1d9b78a16f94dce0cbd;p=platform%2Fupstream%2Fdotnet%2Fruntime.git Cleanup and augment string handling based on https://github.com/mono/mono/pull/15522. 1. When comparing strings, check pointer equality. Faster when they match, slower when they do not. 2. Provide string lowercasing into a provided buffer, which can equal the input, to avoid extra malloc/free. 3. define G_STRING_CONSTANT_AND_LENGTH(x) (x), G_N_ELEMENTS (x) - 1 e.g. strncmp (foo, G_STRING_CONSTANT_AND_LENGTH ("version")) Commit migrated from https://github.com/mono/mono/commit/8c288f06664c65050b153da0a8952209adc958a0 --- diff --git a/src/mono/mono/eglib/eglib-remap.h b/src/mono/mono/eglib/eglib-remap.h index 43d6543..0bbbcab 100644 --- a/src/mono/mono/eglib/eglib-remap.h +++ b/src/mono/mono/eglib/eglib-remap.h @@ -16,6 +16,7 @@ #define g_array_set_size monoeg_g_array_set_size #define g_array_sized_new monoeg_g_array_sized_new #define g_ascii_strdown monoeg_g_ascii_strdown +#define g_ascii_strdown_no_alloc monoeg_g_ascii_strdown_no_alloc #define g_ascii_strncasecmp monoeg_g_ascii_strncasecmp #define g_ascii_tolower monoeg_g_ascii_tolower #define g_ascii_xdigit_value monoeg_g_ascii_xdigit_value diff --git a/src/mono/mono/eglib/glib.h b/src/mono/mono/eglib/glib.h index 01dc664..2fc5fb9 100644 --- a/src/mono/mono/eglib/glib.h +++ b/src/mono/mono/eglib/glib.h @@ -212,6 +212,9 @@ typedef guint32 gunichar; */ #define G_N_ELEMENTS(s) (sizeof(s) / sizeof ((s) [0])) +// e.g. strncmp (foo, G_STRING_CONSTANT_AND_LENGTH ("version")) +#define G_STRING_CONSTANT_AND_LENGTH(x) (x), G_N_ELEMENTS (x) - 1 + #define FALSE 0 #define TRUE 1 @@ -400,6 +403,7 @@ gchar *g_stpcpy (gchar *dest, const char *src); gchar g_ascii_tolower (gchar c); gchar g_ascii_toupper (gchar c); gchar *g_ascii_strdown (const gchar *str, gssize len); +void g_ascii_strdown_no_alloc (char* dst, const char* src, gsize len); gchar *g_ascii_strup (const gchar *str, gssize len); gint g_ascii_strncasecmp (const gchar *s1, const gchar *s2, gsize n); gint g_ascii_strcasecmp (const gchar *s1, const gchar *s2); diff --git a/src/mono/mono/eglib/gstr.c b/src/mono/mono/eglib/gstr.c index 758aeb0..f028501 100644 --- a/src/mono/mono/eglib/gstr.c +++ b/src/mono/mono/eglib/gstr.c @@ -821,11 +821,20 @@ g_ascii_tolower (gchar c) return c >= 'A' && c <= 'Z' ? c + ('a' - 'A') : c; } +void +g_ascii_strdown_no_alloc (char* dst, const char* src, gsize len) +{ + // dst can equal src. no_alloc means this function does no + // allocation; caller may very well. + + for (gsize i = 0; i < len; ++i) + dst [i] = g_ascii_tolower (src [i]); +} + gchar * g_ascii_strdown (const gchar *str, gssize len) { char *ret; - int i; g_return_val_if_fail (str != NULL, NULL); @@ -833,9 +842,8 @@ g_ascii_strdown (const gchar *str, gssize len) len = strlen (str); ret = g_malloc (len + 1); - for (i = 0; i < len; i++) - ret [i] = (guchar) g_ascii_tolower (str [i]); - ret [i] = 0; + g_ascii_strdown_no_alloc (ret, str, len); + ret [len] = 0; return ret; } @@ -859,26 +867,50 @@ g_ascii_strup (const gchar *str, gssize len) ret = g_malloc (len + 1); for (i = 0; i < len; i++) - ret [i] = (guchar) g_ascii_toupper (str [i]); + ret [i] = g_ascii_toupper (str [i]); ret [i] = 0; return ret; } +static +int +g_ascii_charcmp (char c1, char c2) +{ + // Do not subtract, to avoid overflow. + // Use unsigned to mimic strcmp, and so + // shorter strings compare as less. + + const guchar u1 = (guchar)c1; + const guchar u2 = (guchar)c2; + return (u1 < u2) ? -1 : (u1 > u2) ? 1 : 0; +} + +static +int +g_ascii_charcasecmp (char c1, char c2) +{ + return g_ascii_charcmp (g_ascii_tolower (c1), g_ascii_tolower (c2)); +} + gint g_ascii_strncasecmp (const gchar *s1, const gchar *s2, gsize n) { + // Unlike strncmp etc. this function does not stop at nul, + // unless there is a mismatch. + + if (s1 == s2) + return 0; + gsize i; - + g_return_val_if_fail (s1 != NULL, 0); g_return_val_if_fail (s2 != NULL, 0); for (i = 0; i < n; i++) { - gchar c1 = g_ascii_tolower (*s1++); - gchar c2 = g_ascii_tolower (*s2++); - - if (c1 != c2) - return c1 - c2; + const int j = g_ascii_charcasecmp (*s1++, *s2++); + if (j) + return j; } return 0; @@ -887,21 +919,22 @@ g_ascii_strncasecmp (const gchar *s1, const gchar *s2, gsize n) gint g_ascii_strcasecmp (const gchar *s1, const gchar *s2) { - const char *sp1 = s1; - const char *sp2 = s2; - + if (s1 == s2) + return 0; + g_return_val_if_fail (s1 != NULL, 0); g_return_val_if_fail (s2 != NULL, 0); - - while (*sp1 != '\0') { - char c1 = g_ascii_tolower (*sp1++); - char c2 = g_ascii_tolower (*sp2++); - - if (c1 != c2) - return c1 - c2; + + char c1; + + while ((c1 = *s1)) { + ++s1; + const int j = g_ascii_charcasecmp (c1, *s2++); + if (j) + return j; } - - return (*sp1) - (*sp2); + + return g_ascii_charcmp (0, *s2); } gboolean