mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-03 09:46:17 +01:00
Merge branch 'g_str_has_optimization' into 'main'
Optimize g_str_has_*() functions to detect static arguments Closes #24 See merge request GNOME/glib!2859
This commit is contained in:
commit
f8674c1d4c
@ -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);
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <string.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>
|
||||||
@ -139,12 +140,50 @@ gchar * g_strrstr_len (const gchar *haystack,
|
|||||||
const gchar *needle);
|
const gchar *needle);
|
||||||
|
|
||||||
GLIB_AVAILABLE_IN_ALL
|
GLIB_AVAILABLE_IN_ALL
|
||||||
gboolean g_str_has_suffix (const gchar *str,
|
gboolean (g_str_has_suffix) (const gchar *str,
|
||||||
const gchar *suffix);
|
const gchar *suffix);
|
||||||
GLIB_AVAILABLE_IN_ALL
|
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 G_GNUC_CHECK_VERSION (2, 0)
|
||||||
|
|
||||||
|
/* A note on the 'x + !x' terms: These are added to workaround a false
|
||||||
|
* warning in gcc 10< which is ignoring the check 'x != NULL' that is
|
||||||
|
* set outside of the G_GNUC_EXTENSION scope. Without 'x + !x' it
|
||||||
|
* would complain that x may be NULL where strlen() and memcmp()
|
||||||
|
* both require non-null arguments. */
|
||||||
|
|
||||||
|
#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 + !__str); \
|
||||||
|
const size_t __prefix_len = strlen (__prefix + !__prefix); \
|
||||||
|
(__str_len >= __prefix_len) ? \
|
||||||
|
memcmp (__str + !__str, \
|
||||||
|
__prefix + !__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 + !__str); \
|
||||||
|
const size_t __suffix_len = strlen (__suffix + !__suffix); \
|
||||||
|
(__str_len >= __suffix_len) ? \
|
||||||
|
memcmp (__str + !__str + __str_len - __suffix_len, \
|
||||||
|
__suffix + !__suffix, __suffix_len) == 0 : FALSE; \
|
||||||
|
}) \
|
||||||
|
: \
|
||||||
|
(g_str_has_suffix) (STR, SUFFIX))
|
||||||
|
|
||||||
|
#endif /* G_GNUC_CHECK_VERSION (2, 0) */
|
||||||
|
|
||||||
/* String to/from double conversion functions */
|
/* String to/from double conversion functions */
|
||||||
|
|
||||||
GLIB_AVAILABLE_IN_ALL
|
GLIB_AVAILABLE_IN_ALL
|
||||||
|
@ -1200,89 +1200,132 @@ test_strdelimit (void)
|
|||||||
g_free (string);
|
g_free (string);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Testing g_str_has_prefix() */
|
/* Testing g_str_has_prefix() function avoiding the optimizing macro */
|
||||||
static void
|
static void
|
||||||
test_has_prefix (void)
|
test_has_prefix (void)
|
||||||
{
|
{
|
||||||
gboolean res;
|
|
||||||
|
|
||||||
if (g_test_undefined ())
|
if (g_test_undefined ())
|
||||||
{
|
{
|
||||||
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
|
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
|
||||||
"*assertion*!= NULL*");
|
"*assertion*!= NULL*");
|
||||||
res = g_str_has_prefix ("foo", NULL);
|
g_assert_false ((g_str_has_prefix) ("foo", NULL));
|
||||||
g_test_assert_expected_messages ();
|
g_test_assert_expected_messages ();
|
||||||
g_assert_false (res);
|
|
||||||
|
|
||||||
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
|
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
|
||||||
"*assertion*!= NULL*");
|
"*assertion*!= NULL*");
|
||||||
res = g_str_has_prefix (NULL, "foo");
|
g_assert_false ((g_str_has_prefix) (NULL, "foo"));
|
||||||
g_test_assert_expected_messages ();
|
g_test_assert_expected_messages ();
|
||||||
g_assert_false (res);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
res = g_str_has_prefix ("foo", "bar");
|
/* Having a string smaller than the prefix */
|
||||||
g_assert_cmpint (res, ==, FALSE);
|
g_assert_false ((g_str_has_prefix) ("aa", "aaa"));
|
||||||
|
|
||||||
res = g_str_has_prefix ("foo", "foobar");
|
/* Negative tests */
|
||||||
g_assert_cmpint (res, ==, FALSE);
|
g_assert_false ((g_str_has_prefix) ("foo", "bar"));
|
||||||
|
g_assert_false ((g_str_has_prefix) ("foo", "foobar"));
|
||||||
|
g_assert_false ((g_str_has_prefix) ("foobar", "bar"));
|
||||||
|
|
||||||
res = g_str_has_prefix ("foobar", "bar");
|
/* Positive tests */
|
||||||
g_assert_cmpint (res, ==, FALSE);
|
g_assert_true ((g_str_has_prefix) ("foobar", "foo"));
|
||||||
|
g_assert_true ((g_str_has_prefix) ("foo", ""));
|
||||||
res = g_str_has_prefix ("foobar", "foo");
|
g_assert_true ((g_str_has_prefix) ("foo", "foo"));
|
||||||
g_assert_cmpint (res, ==, TRUE);
|
g_assert_true ((g_str_has_prefix) ("", ""));
|
||||||
|
|
||||||
res = g_str_has_prefix ("foo", "");
|
|
||||||
g_assert_cmpint (res, ==, TRUE);
|
|
||||||
|
|
||||||
res = g_str_has_prefix ("foo", "foo");
|
|
||||||
g_assert_cmpint (res, ==, TRUE);
|
|
||||||
|
|
||||||
res = g_str_has_prefix ("", "");
|
|
||||||
g_assert_cmpint (res, ==, TRUE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Testing g_str_has_prefix() optimized macro */
|
||||||
|
static void
|
||||||
|
test_has_prefix_macro (void)
|
||||||
|
{
|
||||||
|
if (g_test_undefined ())
|
||||||
|
{
|
||||||
|
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
|
||||||
|
"*assertion*!= NULL*");
|
||||||
|
g_assert_false (g_str_has_prefix ("foo", NULL));
|
||||||
|
g_test_assert_expected_messages ();
|
||||||
|
|
||||||
|
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
|
||||||
|
"*assertion*!= NULL*");
|
||||||
|
g_assert_false (g_str_has_prefix (NULL, "foo"));
|
||||||
|
g_test_assert_expected_messages ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Having a string smaller than the prefix */
|
||||||
|
g_assert_false (g_str_has_prefix ("aa", "aaa"));
|
||||||
|
|
||||||
|
/* Negative tests */
|
||||||
|
g_assert_false (g_str_has_prefix ("foo", "bar"));
|
||||||
|
g_assert_false (g_str_has_prefix ("foo", "foobar"));
|
||||||
|
g_assert_false (g_str_has_prefix ("foobar", "bar"));
|
||||||
|
|
||||||
|
/* Positive tests */
|
||||||
|
g_assert_true (g_str_has_prefix ("foobar", "foo"));
|
||||||
|
g_assert_true (g_str_has_prefix ("foo", ""));
|
||||||
|
g_assert_true (g_str_has_prefix ("foo", "foo"));
|
||||||
|
g_assert_true (g_str_has_prefix ("", ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Testing g_str_has_suffix() function avoiding the optimizing macro */
|
||||||
static void
|
static void
|
||||||
test_has_suffix (void)
|
test_has_suffix (void)
|
||||||
{
|
{
|
||||||
gboolean res;
|
|
||||||
|
|
||||||
if (g_test_undefined ())
|
if (g_test_undefined ())
|
||||||
{
|
{
|
||||||
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
|
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
|
||||||
"*assertion*!= NULL*");
|
"*assertion*!= NULL*");
|
||||||
res = g_str_has_suffix ("foo", NULL);
|
g_assert_false ((g_str_has_suffix) ("foo", NULL));
|
||||||
g_test_assert_expected_messages ();
|
g_test_assert_expected_messages ();
|
||||||
g_assert_false (res);
|
|
||||||
|
|
||||||
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
|
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
|
||||||
"*assertion*!= NULL*");
|
"*assertion*!= NULL*");
|
||||||
res = g_str_has_suffix (NULL, "foo");
|
g_assert_false ((g_str_has_suffix) (NULL, "foo"));
|
||||||
g_test_assert_expected_messages ();
|
g_test_assert_expected_messages ();
|
||||||
g_assert_false (res);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
res = g_str_has_suffix ("foo", "bar");
|
/* Having a string smaller than the suffix */
|
||||||
g_assert_false (res);
|
g_assert_false ((g_str_has_suffix) ("aa", "aaa"));
|
||||||
|
|
||||||
res = g_str_has_suffix ("bar", "foobar");
|
/* Negative tests */
|
||||||
g_assert_false (res);
|
g_assert_false ((g_str_has_suffix) ("foo", "bar"));
|
||||||
|
g_assert_false ((g_str_has_suffix) ("bar", "foobar"));
|
||||||
|
g_assert_false ((g_str_has_suffix) ("foobar", "foo"));
|
||||||
|
|
||||||
res = g_str_has_suffix ("foobar", "foo");
|
/* Positive tests */
|
||||||
g_assert_false (res);
|
g_assert_true ((g_str_has_suffix) ("foobar", "bar"));
|
||||||
|
g_assert_true ((g_str_has_suffix) ("foo", ""));
|
||||||
|
g_assert_true ((g_str_has_suffix) ("foo", "foo"));
|
||||||
|
g_assert_true ((g_str_has_suffix) ("", ""));
|
||||||
|
}
|
||||||
|
|
||||||
res = g_str_has_suffix ("foobar", "bar");
|
/* Testing g_str_has_prefix() optimized macro */
|
||||||
g_assert_true (res);
|
static void
|
||||||
|
test_has_suffix_macro (void)
|
||||||
|
{
|
||||||
|
if (g_test_undefined ())
|
||||||
|
{
|
||||||
|
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
|
||||||
|
"*assertion*!= NULL*");
|
||||||
|
g_assert_false (g_str_has_suffix ("foo", NULL));
|
||||||
|
g_test_assert_expected_messages ();
|
||||||
|
|
||||||
res = g_str_has_suffix ("foo", "");
|
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
|
||||||
g_assert_true (res);
|
"*assertion*!= NULL*");
|
||||||
|
g_assert_false (g_str_has_suffix (NULL, "foo"));
|
||||||
|
g_test_assert_expected_messages ();
|
||||||
|
}
|
||||||
|
|
||||||
res = g_str_has_suffix ("foo", "foo");
|
/* Having a string smaller than the suffix */
|
||||||
g_assert_true (res);
|
g_assert_false (g_str_has_suffix ("aa", "aaa"));
|
||||||
|
|
||||||
res = g_str_has_suffix ("", "");
|
/* Negative tests */
|
||||||
g_assert_true (res);
|
g_assert_false (g_str_has_suffix ("foo", "bar"));
|
||||||
|
g_assert_false (g_str_has_suffix ("bar", "foobar"));
|
||||||
|
g_assert_false (g_str_has_suffix ("foobar", "foo"));
|
||||||
|
|
||||||
|
/* Positive tests */
|
||||||
|
g_assert_true (g_str_has_suffix ("foobar", "bar"));
|
||||||
|
g_assert_true (g_str_has_suffix ("foo", ""));
|
||||||
|
g_assert_true (g_str_has_suffix ("foo", "foo"));
|
||||||
|
g_assert_true (g_str_has_suffix ("", ""));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -2587,7 +2630,9 @@ main (int argc,
|
|||||||
g_test_add_func ("/strfuncs/ascii_strtod", test_ascii_strtod);
|
g_test_add_func ("/strfuncs/ascii_strtod", test_ascii_strtod);
|
||||||
g_test_add_func ("/strfuncs/bounds-check", test_bounds);
|
g_test_add_func ("/strfuncs/bounds-check", test_bounds);
|
||||||
g_test_add_func ("/strfuncs/has-prefix", test_has_prefix);
|
g_test_add_func ("/strfuncs/has-prefix", test_has_prefix);
|
||||||
|
g_test_add_func ("/strfuncs/has-prefix-macro", test_has_prefix_macro);
|
||||||
g_test_add_func ("/strfuncs/has-suffix", test_has_suffix);
|
g_test_add_func ("/strfuncs/has-suffix", test_has_suffix);
|
||||||
|
g_test_add_func ("/strfuncs/has-suffix-macro", test_has_suffix_macro);
|
||||||
g_test_add_func ("/strfuncs/memdup", test_memdup);
|
g_test_add_func ("/strfuncs/memdup", test_memdup);
|
||||||
g_test_add_func ("/strfuncs/memdup2", test_memdup2);
|
g_test_add_func ("/strfuncs/memdup2", test_memdup2);
|
||||||
g_test_add_func ("/strfuncs/set_str", test_set_str);
|
g_test_add_func ("/strfuncs/set_str", test_set_str);
|
||||||
|
Loading…
Reference in New Issue
Block a user