Merge branch 'wip/hughsie/g_ref_string_new_len' into 'master'

Add a g_ref_string_new_len() to allow creating from non-NUL byte arrays

See merge request GNOME/glib!158
This commit is contained in:
Philip Withnall 2018-07-09 17:30:12 +00:00
commit 4a53ed2073
4 changed files with 76 additions and 0 deletions

View File

@ -3497,6 +3497,7 @@ g_arc_box_get_size
<FILE>refstring</FILE>
g_ref_string_new
g_ref_string_new_intern
g_ref_string_new_len
g_ref_string_acquire
g_ref_string_release
g_ref_string_length

View File

@ -130,6 +130,39 @@ g_ref_string_new (const char *str)
return res;
}
/**
* g_ref_string_new_len:
* @str: (not nullable): a string
* @len: length of @str to use, or -1 if @str is nul-terminated
*
* Creates a new reference counted string and copies the contents of @str
* into it, up to @len bytes.
*
* Since this function does not stop at nul bytes, it is the caller's
* responsibility to ensure that @str has at least @len addressable bytes.
*
* Returns: (transfer full) (not nullable): the newly created reference counted string
*
* Since: 2.58
*/
char *
g_ref_string_new_len (const char *str, gssize len)
{
char *res;
g_return_val_if_fail (str != NULL, NULL);
if (len < 0)
return g_ref_string_new (str);
/* allocate then copy as str[len] may not be readable */
res = (char *) g_atomic_rc_box_alloc ((gsize) len + 1);
memcpy (res, str, len);
res[len] = '\0';
return res;
}
/* interned_str_equal: variant of g_str_equal() that compares
* pointers as well as contents; this avoids running strcmp()
* on arbitrarily long strings, as it's more likely to have

View File

@ -26,6 +26,9 @@ G_BEGIN_DECLS
GLIB_AVAILABLE_IN_2_58
char * g_ref_string_new (const char *str);
GLIB_AVAILABLE_IN_2_58
char * g_ref_string_new_len (const char *str,
gssize len);
GLIB_AVAILABLE_IN_2_58
char * g_ref_string_new_intern (const char *str);
GLIB_AVAILABLE_IN_2_58

View File

@ -36,6 +36,42 @@ test_refstring_base (void)
g_ref_string_release (s);
}
/* test_refstring_length: Test the _len variant */
static void
test_refstring_length (void)
{
char buf[] = {'h', 'e', 'l', 'l', 'o'}; /* no NUL */
char *s = g_ref_string_new_len (buf, 5);
g_assert_cmpstr (s, ==, "hello");
g_assert_cmpint (strlen (s), ==, strlen ("hello"));
g_assert_cmpuint (g_ref_string_length (s), ==, strlen ("hello"));
g_ref_string_release (s);
}
/* test_refstring_length: Test the _len variant with no size set */
static void
test_refstring_length_auto (void)
{
char *s = g_ref_string_new_len ("hello", -1);
g_assert_cmpstr (s, ==, "hello");
g_assert_cmpuint (g_ref_string_length (s), ==, strlen ("hello"));
g_ref_string_release (s);
}
/* test_refstring_length_nuls: Test the _len variant */
static void
test_refstring_length_nuls (void)
{
char buf[] = {'h', 'e', '\0', 'l', 'o'}; /* no NUL */
char *s = g_ref_string_new_len (buf, 5);
g_assert_cmpstr (s, ==, "he");
g_assert_cmpint (memcmp (s, "he\0lo", 5), ==, 0);
g_assert_cmpuint (g_ref_string_length (s), ==, 5);
g_ref_string_release (s);
}
/* test_refstring_intern: Test the interning API of GRefString */
static void
test_refstring_intern (void)
@ -76,6 +112,9 @@ main (int argc,
g_test_init (&argc, &argv, NULL);
g_test_add_func ("/refstring/base", test_refstring_base);
g_test_add_func ("/refstring/length", test_refstring_length);
g_test_add_func ("/refstring/length-auto", test_refstring_length_auto);
g_test_add_func ("/refstring/length-nuls", test_refstring_length_nuls);
g_test_add_func ("/refstring/intern", test_refstring_intern);
return g_test_run ();