diff --git a/docs/reference/glib/glib-sections.txt.in b/docs/reference/glib/glib-sections.txt.in index 60e87af5b..d9e7ac3d6 100644 --- a/docs/reference/glib/glib-sections.txt.in +++ b/docs/reference/glib/glib-sections.txt.in @@ -2625,6 +2625,7 @@ g_str_hash strings GString g_string_new +g_string_new_take g_string_new_len g_string_sized_new g_string_assign diff --git a/glib/garray.c b/glib/garray.c index 118360ca1..4e8c8c309 100644 --- a/glib/garray.c +++ b/glib/garray.c @@ -204,8 +204,10 @@ g_array_new (gboolean zero_terminated, * reference count of 1. * * This avoids having to copy the data manually, when it can just be - * inherited. @data will eventually be freed using g_free(), so must - * have been allocated with a suitable allocator. + * inherited. + * After this call, @data belongs to the #GArray and may no longer be + * modified by the caller. The memory of @data has to be dynamically + * allocated and will eventually be freed with g_free(). * * In case the elements need to be cleared when the array is freed, use * g_array_set_clear_func() to set a #GDestroyNotify function to perform @@ -252,8 +254,10 @@ g_array_new_take (gpointer data, * and setting the reference count to 1. * * This avoids having to copy the data manually, when it can just be - * inherited. @data will eventually be freed using g_free(), so must - * have been allocated with a suitable allocator. + * inherited. + * After this call, @data belongs to the #GArray and may no longer be + * modified by the caller. The memory of @data has to be dynamically + * allocated and will eventually be freed with g_free(). * * The length is calculated by iterating through @data until the first %NULL * element is found. @@ -1275,8 +1279,10 @@ g_ptr_array_new (void) * Creates a new #GPtrArray with @data as pointers, @len as length and a * reference count of 1. * - * This avoids having to copy such data manually. @data will eventually be - * freed using g_free(), so must have been allocated with a suitable allocator. + * This avoids having to copy such data manually. + * After this call, @data belongs to the #GPtrArray and may no longer be + * modified by the caller. The memory of @data has to be dynamically + * allocated and will eventually be freed with g_free(). * * It also sets @element_free_func for freeing each element when the array is * destroyed either via g_ptr_array_unref(), when g_ptr_array_free() is called @@ -1321,8 +1327,10 @@ g_ptr_array_new_take (gpointer *data, * Creates a new #GPtrArray with @data as pointers, computing the length of it * and setting the reference count to 1. * - * This avoids having to copy such data manually. @data will eventually be - * freed using g_free(), so must have been allocated with a suitable allocator. + * This avoids having to copy such data manually. + * After this call, @data belongs to the #GPtrArray and may no longer be + * modified by the caller. The memory of @data has to be dynamically + * allocated and will eventually be freed with g_free(). * * The length is calculated by iterating through @data until the first %NULL * element is found. @@ -2845,8 +2853,10 @@ g_byte_array_steal (GByteArray *array, * @data: (transfer full) (array length=len): byte data for the array * @len: length of @data * - * Create byte array containing the data. The data will be owned by the array - * and will be freed with g_free(), i.e. it could be allocated using g_strdup(). + * Creates a byte array containing the @data. + * After this call, @data belongs to the #GByteArray and may no longer be + * modified by the caller. The memory of @data has to be dynamically + * allocated and will eventually be freed with g_free(). * * Do not use it if @len is greater than %G_MAXUINT. #GByteArray * stores the length of its data in #guint, which may be shorter than diff --git a/glib/gbytes.c b/glib/gbytes.c index e4d269710..380e39f96 100644 --- a/glib/gbytes.c +++ b/glib/gbytes.c @@ -108,11 +108,9 @@ g_bytes_new (gconstpointer data, * * Creates a new #GBytes from @data. * - * After this call, @data belongs to the bytes and may no longer be - * modified by the caller. g_free() will be called on @data when the - * bytes is no longer in use. Because of this @data must have been created by - * a call to g_malloc(), g_malloc0() or g_realloc() or by one of the many - * functions that wrap these calls (such as g_new(), g_strdup(), etc). + * After this call, @data belongs to the #GBytes and may no longer be + * modified by the caller. The memory of @data has to be dynamically + * allocated and will eventually be freed with g_free(). * * For creating #GBytes with memory from other allocators, see * g_bytes_new_with_free_func(). diff --git a/glib/gstring.c b/glib/gstring.c index ad6b92231..77448f2f1 100644 --- a/glib/gstring.c +++ b/glib/gstring.c @@ -155,6 +155,39 @@ g_string_new (const gchar *init) return string; } +/** + * g_string_new_take: (constructor) + * @init: (nullable) (transfer full): initial text used as the string. + * Ownership of the string is transferred to the #GString. + * Passing %NULL creates an empty string. + * + * Creates a new #GString, initialized with the given string. + * + * After this call, @init belongs to the #GString and may no longer be + * modified by the caller. The memory of @data has to be dynamically + * allocated and will eventually be freed with g_free(). + * + * Returns: (transfer full): the new #GString + */ +GString * +g_string_new_take (gchar *init) +{ + GString *string; + + if (init == NULL) + { + return g_string_new (NULL); + } + + string = g_slice_new (GString); + + string->str = init; + string->len = strlen (string->str); + string->allocated_len = string->len + 1; + + return string; +} + /** * g_string_new_len: (constructor) * @init: initial contents of the string diff --git a/glib/gstring.h b/glib/gstring.h index 859668716..b4ccb34a9 100644 --- a/glib/gstring.h +++ b/glib/gstring.h @@ -51,6 +51,8 @@ struct _GString GLIB_AVAILABLE_IN_ALL GString* g_string_new (const gchar *init); +GLIB_AVAILABLE_IN_2_78 +GString* g_string_new_take (gchar *init); GLIB_AVAILABLE_IN_ALL GString* g_string_new_len (const gchar *init, gssize len); diff --git a/glib/gvariant.c b/glib/gvariant.c index 40cda9c9d..b7e42413c 100644 --- a/glib/gvariant.c +++ b/glib/gvariant.c @@ -1282,8 +1282,9 @@ g_variant_new_string (const gchar *string) * @string must be valid UTF-8, and must not be %NULL. To encode * potentially-%NULL strings, use this with g_variant_new_maybe(). * - * This function consumes @string. g_free() will be called on @string - * when it is no longer required. + * After this call, @string belongs to the #GVariant and may no longer be + * modified by the caller. The memory of @data has to be dynamically + * allocated and will eventually be freed with g_free(). * * You must not modify or access @string in any other way after passing * it to this function. It is even possible that @string is immediately diff --git a/glib/tests/string.c b/glib/tests/string.c index a2225189f..932a311de 100644 --- a/glib/tests/string.c +++ b/glib/tests/string.c @@ -709,6 +709,40 @@ test_string_steal (void) g_free (str); } +static void +test_string_new_take (void) +{ + const char *test_str_const = "test_test"; + const char *replaced_str_const = "test__test"; + char *test_str = malloc (10 * sizeof (*test_str_const)); + GString *string; + + strcpy (test_str, test_str_const); + g_assert_cmpstr (test_str, ==, test_str_const); + + string = g_string_new_take (g_steal_pointer (&test_str)); + g_assert_null (test_str); + g_assert_nonnull (string); + + g_string_replace (string, "_", "__", 0); + g_assert_cmpstr (string->str, ==, replaced_str_const); + + test_str = g_string_free_and_steal (g_steal_pointer (&string)); + g_assert_cmpstr (test_str, ==, replaced_str_const); + + g_free (test_str); +} + +static void +test_string_new_take_null (void) +{ + GString *string = g_string_new_take (NULL); + + g_assert_cmpstr (string->str, ==, ""); + + g_string_free (g_steal_pointer (&string), TRUE); +} + int main (int argc, char *argv[]) @@ -736,6 +770,8 @@ main (int argc, g_test_add_func ("/string/test-string-to-bytes", test_string_to_bytes); g_test_add_func ("/string/test-string-replace", test_string_replace); g_test_add_func ("/string/test-string-steal", test_string_steal); + g_test_add_func ("/string/test-string-new-take", test_string_new_take); + g_test_add_func ("/string/test-string-new-take/null", test_string_new_take_null); return g_test_run(); }