diff --git a/docs/reference/glib/glib-sections.txt b/docs/reference/glib/glib-sections.txt index d2e985e68..583b12765 100644 --- a/docs/reference/glib/glib-sections.txt +++ b/docs/reference/glib/glib-sections.txt @@ -2326,6 +2326,7 @@ g_string_erase g_string_truncate g_string_set_size g_string_free +g_string_free_to_bytes g_string_up diff --git a/glib/glib.symbols b/glib/glib.symbols index d5c1fc6a9..7f7a5ced3 100644 --- a/glib/glib.symbols +++ b/glib/glib.symbols @@ -1084,6 +1084,7 @@ g_string_chunk_new g_string_equal g_string_erase g_string_free +g_string_free_to_bytes g_string_hash g_string_insert g_string_insert_c diff --git a/glib/gstring.c b/glib/gstring.c index 9fac86cbd..9473f0109 100644 --- a/glib/gstring.c +++ b/glib/gstring.c @@ -50,12 +50,17 @@ * @short_description: text buffers which grow automatically * as text is added * - * A #GString is an object that handles the memory management - * of a C string for you. You can think of it as similar to a - * Java StringBuffer. In addition to the string itself, GString - * stores the length of the string, so can be used for binary - * data with embedded nul bytes. To access the C string managed - * by the GString @string, simply use @string->str. + * A #GString is an object that handles the memory management of a C + * string for you. The emphasis of #GString is on text, typically + * UTF-8. Crucially, the "str" member of a #GString is guaranteed to + * have a trailing nul character, and it is therefore always safe to + * call functions such as strchr() or g_strdup() on it. + * + * However, a #GString can also hold arbitrary binary data, because it + * has a "len" member, which includes any possible embedded nul + * characters in the data. Conceptually then, #GString is like a + * #GByteArray with the addition of many convenience methods for text, + * and a guaranteed nul terminator. */ /** @@ -226,6 +231,37 @@ g_string_free (GString *string, return segment; } +/** + * g_string_free_to_bytes: + * @string: (transfer full): a #GString + * + * Transfers ownership of the contents of @string to a newly allocated + * #GBytes. The #GString structure itself is deallocated, and it is + * therefore invalid to use @string after invoking this function. + * + * Note that while #GString ensures that its buffer always has a + * trailing nul character (not reflected in its "len"), the returned + * #GBytes does not include this extra nul; i.e. it has length exactly + * equal to the "len" member. + * + * Returns: A newly allocated #GBytes containing contents of @string; @string itself is freed + * Since: 2.34 + */ +GBytes* +g_string_free_to_bytes (GString *string) +{ + gsize len; + gchar *buf; + + g_return_val_if_fail (string != NULL, NULL); + + len = string->len; + + buf = g_string_free (string, FALSE); + + return g_bytes_new_take (buf, len); +} + /** * g_string_equal: * @v: a #GString diff --git a/glib/gstring.h b/glib/gstring.h index 079734343..75434908a 100644 --- a/glib/gstring.h +++ b/glib/gstring.h @@ -33,6 +33,7 @@ #include #include +#include #include /* for G_CAN_INLINE */ G_BEGIN_DECLS @@ -52,6 +53,8 @@ GString* g_string_new_len (const gchar *init, GString* g_string_sized_new (gsize dfl_size); gchar* g_string_free (GString *string, gboolean free_segment); +GLIB_AVAILABLE_IN_2_34 +GBytes* g_string_free_to_bytes (GString *string); gboolean g_string_equal (const GString *v, const GString *v2); guint g_string_hash (const GString *str); diff --git a/glib/tests/string.c b/glib/tests/string.c index 19cb8316d..11c8da7d8 100644 --- a/glib/tests/string.c +++ b/glib/tests/string.c @@ -472,6 +472,26 @@ test_string_set_size (void) g_string_free (s, TRUE); } +static void +test_string_to_bytes (void) +{ + GString *s; + GBytes *bytes; + gconstpointer byte_data; + gsize byte_len; + + s = g_string_new ("foo"); + g_string_append (s, "-bar"); + + bytes = g_string_free_to_bytes (s); + + byte_data = g_bytes_get_data (bytes, &byte_len); + + g_assert_cmpint (byte_len, ==, 7); + + g_assert_cmpint (memcmp (byte_data, "foo-bar", byte_len), ==, 0); +} + int main (int argc, char *argv[]) @@ -495,6 +515,7 @@ main (int argc, g_test_add_func ("/string/test-string-nul-handling", test_string_nul_handling); g_test_add_func ("/string/test-string-up-down", test_string_up_down); g_test_add_func ("/string/test-string-set-size", test_string_set_size); + g_test_add_func ("/string/test-string-to-bytes", test_string_to_bytes); return g_test_run(); }