Optimize g_str_has_*() functions to detect const arguments at compile-time

Compilers can emit optimized code for str|strn|mem)cmp(str,"literal")
at compile-time. This commit use the preprocessor to introduce this
kind of optimization for the functions g_str_has_prefix() and
g_str_has_suffix().

Original work by Ben @bdejean

Closes issue #24
This commit is contained in:
Emmanuel Fleury 2022-08-19 18:00:19 +02:00
parent 90ae06a9f6
commit 0f4be1429d
2 changed files with 34 additions and 10 deletions

View File

@ -2928,8 +2928,7 @@ g_strrstr_len (const gchar *haystack,
* *
* Since: 2.2 * Since: 2.2
*/ */
gboolean gboolean (g_str_has_suffix) (const gchar *str,
g_str_has_suffix (const gchar *str,
const gchar *suffix) const gchar *suffix)
{ {
gsize str_len; gsize str_len;
@ -2958,8 +2957,7 @@ g_str_has_suffix (const gchar *str,
* *
* Since: 2.2 * Since: 2.2
*/ */
gboolean gboolean (g_str_has_prefix) (const gchar *str,
g_str_has_prefix (const gchar *str,
const gchar *prefix) const gchar *prefix)
{ {
g_return_val_if_fail (str != NULL, FALSE); g_return_val_if_fail (str != NULL, FALSE);

View File

@ -32,6 +32,8 @@
#endif #endif
#include <stdarg.h> #include <stdarg.h>
#include <string.h>
#include <glib/gmacros.h> #include <glib/gmacros.h>
#include <glib/gtypes.h> #include <glib/gtypes.h>
#include <glib/gerror.h> #include <glib/gerror.h>
@ -143,6 +145,30 @@ GLIB_AVAILABLE_IN_ALL
gboolean g_str_has_prefix (const gchar *str, gboolean g_str_has_prefix (const gchar *str,
const gchar *prefix); const gchar *prefix);
#if defined(__GNUC__) && (__GNUC__ > 2)
#define g_str_has_prefix(STR, PREFIX) \
((STR != NULL && PREFIX != NULL && __builtin_constant_p (PREFIX)) ? G_GNUC_EXTENSION ({ \
const char *const __str = STR; \
const char *const __prefix = PREFIX; \
const size_t __str_len = strlen (__str); \
const size_t __prefix_len = strlen (__prefix); \
(__str_len >= __prefix_len) ? memcmp (__str, __prefix, __prefix_len) == 0 : FALSE; \
}) \
: (g_str_has_prefix) (STR, PREFIX))
#define g_str_has_suffix(STR, SUFFIX) \
((STR != NULL && SUFFIX != NULL && __builtin_constant_p (SUFFIX)) ? G_GNUC_EXTENSION ({ \
const char *const __str = STR; \
const char *const __suffix = SUFFIX; \
const size_t __str_len = strlen (__str); \
const size_t __suffix_len = strlen (__suffix); \
(__str_len >= __suffix_len) ? memcmp (__str + __str_len - __suffix_len, __suffix, __suffix_len) == 0 : FALSE; \
}) \
: (g_str_has_suffix) (STR, SUFFIX))
#endif
/* String to/from double conversion functions */ /* String to/from double conversion functions */
GLIB_AVAILABLE_IN_ALL GLIB_AVAILABLE_IN_ALL