Merge branch 'gstrdup-inline' into 'main'

gstrfuncs: Add inline version of g_strdup()

See merge request GNOME/glib!3209
This commit is contained in:
Marco Trevisan 2023-01-26 18:38:37 +00:00
commit 5e40004bdb
5 changed files with 186 additions and 8 deletions

View File

@ -21,8 +21,47 @@
#include <gio/gio.h>
int
main ()
static void
test_name (void)
{
return 0;
GTask *task = NULL;
char *orig = g_strdup ("some task");
task = g_task_new (NULL, NULL, NULL, NULL);
(g_task_set_name) (task, orig);
g_assert_cmpstr (g_task_get_name (task), ==, "some task");
(g_task_set_name) (task, "some other name");
g_assert_cmpstr (g_task_get_name (task), ==, "some other name");
g_clear_object (&task);
g_free (orig);
}
static void
test_name_macro_wrapper (void)
{
GTask *task = NULL;
char *orig = g_strdup ("some task");
task = g_task_new (NULL, NULL, NULL, NULL);
g_task_set_name (task, orig);
g_assert_cmpstr (g_task_get_name (task), ==, "some task");
g_task_set_name (task, "some other name");
g_assert_cmpstr (g_task_get_name (task), ==, "some other name");
g_clear_object (&task);
g_free (orig);
}
int
main (int argc, char **argv)
{
g_test_init (&argc, &argv, NULL);
g_test_add_func ("/gtask/name", test_name);
g_test_add_func ("/gtask/name/macro-wrapper", test_name_macro_wrapper);
return g_test_run ();
}

View File

@ -352,12 +352,12 @@ get_C_locale (void)
* Returns: a newly-allocated copy of @str
*/
gchar*
g_strdup (const gchar *str)
(g_strdup) (const gchar *str)
{
gchar *new_str;
gsize length;
if (str)
if G_LIKELY (str)
{
length = strlen (str) + 1;
new_str = g_new (char, length);

View File

@ -147,12 +147,13 @@ gboolean (g_str_has_prefix) (const gchar *str,
const gchar *prefix);
#if G_GNUC_CHECK_VERSION (2, 0)
#if !defined (__GTK_DOC_IGNORE__) && !defined (__GI_SCANNER__)
/* This macro is defeat a false -Wnonnull warning in GCC.
* Without it, it thinks strlen and memcmp may be getting passed NULL
* despite the explicit check for NULL right above the calls.
*/
#define _G_STR_NONNULL(x) (x + !x)
#define _G_STR_NONNULL(x) ((x) + !(x))
#define g_str_has_prefix(STR, PREFIX) \
(__builtin_constant_p (PREFIX)? \
@ -202,6 +203,24 @@ gboolean (g_str_has_prefix) (const gchar *str,
(g_str_has_suffix) (STR, SUFFIX) \
)
#define g_strdup(STR) \
(__builtin_constant_p ((STR)) ? \
(G_LIKELY ((STR) != NULL) ? \
G_GNUC_EXTENSION ({ \
const char *const ___str = ((STR)); \
const char *const __str = _G_STR_NONNULL (___str); \
const size_t __str_len = strlen (__str) + 1; \
char *__dup_str = (char *) g_malloc (__str_len); \
(char *) memcpy (__dup_str, __str, __str_len); \
}) \
: \
(char *) (NULL) \
) \
: \
(g_strdup) ((STR)) \
)
#endif /* !defined (__GTK_DOC_IGNORE__) && !defined (__GI_SCANNER__) */
#endif /* G_GNUC_CHECK_VERSION (2, 0) */
/* String to/from double conversion functions */
@ -277,7 +296,7 @@ gchar* g_strup (gchar *string);
* ought to be freed with g_free from the caller at some point.
*/
GLIB_AVAILABLE_IN_ALL
gchar* g_strdup (const gchar *str) G_GNUC_MALLOC;
gchar* (g_strdup) (const gchar *str) G_GNUC_MALLOC;
GLIB_AVAILABLE_IN_ALL
gchar* g_strdup_printf (const gchar *format,
...) G_GNUC_PRINTF (1, 2) G_GNUC_MALLOC;

View File

@ -304,6 +304,7 @@ test_str_equal (void)
{
const char *str_a = "a";
char *str_b = g_strdup ("b");
char *str_null = g_strdup (NULL);
gconstpointer str_a_ptr = str_a, str_b_ptr = str_b;
const unsigned char *str_c = (const unsigned char *) "c";
@ -317,10 +318,60 @@ test_str_equal (void)
g_assert_true (g_str_equal (str_a, str_a_ptr));
g_assert_false (g_str_equal (str_a_ptr, str_b_ptr));
g_assert_false (g_str_equal (str_c, str_b));
g_assert_cmpstr (str_b, !=, str_null);
g_free (str_b);
}
static void
test_strdup (void)
{
gchar *str;
g_assert_null ((g_strdup) (NULL));
str = (g_strdup) ("C++ is cool too!");
g_assert_nonnull (str);
g_assert_cmpstr (str, ==, "C++ is cool too!");
g_free (str);
}
static void
test_strdup_macro (void)
{
gchar *str;
g_assert_null (g_strdup (NULL));
str = g_strdup ("C++ is cool too!");
g_assert_nonnull (str);
g_assert_cmpstr (str, ==, "C++ is cool too!");
g_free (str);
}
static void
test_str_has_prefix (void)
{
g_assert_true ((g_str_has_prefix) ("C++ is cool!", "C++"));
}
static void
test_str_has_prefix_macro (void)
{
g_assert_true (g_str_has_prefix ("C++ is cool!", "C++"));
}
static void
test_str_has_suffix (void)
{
g_assert_true ((g_str_has_suffix) ("C++ is cool!", "cool!"));
}
static void
test_str_has_suffix_macro (void)
{
g_assert_true (g_str_has_suffix ("C++ is cool!", "cool!"));
}
static void
test_string_append (void)
@ -444,6 +495,12 @@ main (int argc, char *argv[])
g_test_add_func ("/C++/clear-pointer", test_clear_pointer);
g_test_add_func ("/C++/steal-pointer", test_steal_pointer);
g_test_add_func ("/C++/str-equal", test_str_equal);
g_test_add_func ("/C++/strdup", test_strdup);
g_test_add_func ("/C++/strdup/macro", test_strdup_macro);
g_test_add_func ("/C++/str-has-prefix", test_str_has_prefix);
g_test_add_func ("/C++/str-has-prefix/macro", test_str_has_prefix_macro);
g_test_add_func ("/C++/str-has-suffix", test_str_has_suffix);
g_test_add_func ("/C++/str-has-suffix/macro", test_str_has_suffix_macro);
g_test_add_func ("/C++/string-append", test_string_append);
return g_test_run ();

View File

@ -499,12 +499,58 @@ test_strdup (void)
{
gchar *str;
g_assert_null ((g_strdup) (NULL));
str = (g_strdup) (GLIB_TEST_STRING);
g_assert_nonnull (str);
g_assert_cmpstr (str, ==, GLIB_TEST_STRING);
char *other_str = (g_strdup) (str);
g_free (str);
g_assert_nonnull (other_str);
g_assert_cmpstr (other_str, ==, GLIB_TEST_STRING);
g_clear_pointer (&other_str, g_free);
str = (g_strdup) ("");
g_assert_cmpint (str[0], ==, '\0');
g_assert_cmpstr (str, ==, "");
g_clear_pointer (&str, g_free);
}
static void
test_strdup_inline (void)
{
gchar *str;
#if G_GNUC_CHECK_VERSION (2, 0)
#ifndef g_strdup
#error g_strdup() should be defined as a macro in this platform!
#endif
#else
g_test_incomplete ("g_strdup() is not inlined in this platform");
#endif
/* Testing inline version of g_strdup() function with various positive and
* negative cases */
g_assert_null (g_strdup (NULL));
str = g_strdup (GLIB_TEST_STRING);
g_assert_nonnull (str);
g_assert_cmpstr (str, ==, GLIB_TEST_STRING);
g_free (str);
char *other_str = g_strdup (str);
g_clear_pointer (&str, g_free);
g_assert_nonnull (other_str);
g_assert_cmpstr (other_str, ==, GLIB_TEST_STRING);
g_clear_pointer (&other_str, g_free);
str = g_strdup ("");
g_assert_cmpint (str[0], ==, '\0');
g_assert_cmpstr (str, ==, "");
g_clear_pointer (&str, g_free);
}
/* Testing g_strndup() function with various positive and negative cases */
@ -1238,6 +1284,14 @@ test_has_prefix (void)
static void
test_has_prefix_macro (void)
{
#if G_GNUC_CHECK_VERSION (2, 0)
#ifndef g_str_has_prefix
#error g_str_has_prefix() should be defined as a macro in this platform!
#endif
#else
g_test_incomplete ("g_str_has_prefix() is not inlined in this platform");
#endif
if (g_test_undefined ())
{
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
@ -1305,6 +1359,14 @@ test_has_suffix (void)
static void
test_has_suffix_macro (void)
{
#if G_GNUC_CHECK_VERSION (2, 0)
#ifndef g_str_has_suffix
#error g_str_has_suffix() should be defined as a macro in this platform!
#endif
#else
g_test_incomplete ("g_str_has_suffix() is not inlined in this platform");
#endif
if (g_test_undefined ())
{
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
@ -2677,6 +2739,7 @@ main (int argc,
g_test_add_func ("/strfuncs/strconcat", test_strconcat);
g_test_add_func ("/strfuncs/strdelimit", test_strdelimit);
g_test_add_func ("/strfuncs/strdup", test_strdup);
g_test_add_func ("/strfuncs/strdup/inline", test_strdup_inline);
g_test_add_func ("/strfuncs/strdup-printf", test_strdup_printf);
g_test_add_func ("/strfuncs/strdupv", test_strdupv);
g_test_add_func ("/strfuncs/strerror", test_strerror);