diff options
author | Matthias Clasen <mclasen@redhat.com> | 2023-01-17 17:56:41 -0500 |
---|---|---|
committer | Matthias Clasen <mclasen@redhat.com> | 2023-01-17 20:56:08 -0500 |
commit | 1e38e6f53f0c0549d3d75ba76899f53b7b28f2ea (patch) | |
tree | ddc27248e3944fe4af718e2ef4e909afe7d7aee2 /glib/gstring.c | |
parent | 1aa530410990efbf23a108a51b62afd2d4ed9b20 (diff) | |
download | glib-g-string-on-stack.tar.gz |
GString: Support on-stack useg-string-on-stack
Move the preallocation into the GString struct,
and add g_string_init and g_string_clear to
enable on-stack use of GString.
Diffstat (limited to 'glib/gstring.c')
-rw-r--r-- | glib/gstring.c | 73 |
1 files changed, 59 insertions, 14 deletions
diff --git a/glib/gstring.c b/glib/gstring.c index 8967ce12b..86869d950 100644 --- a/glib/gstring.c +++ b/glib/gstring.c @@ -59,6 +59,10 @@ * 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. + * + * GString can be used as a heap-allocated object, using g_string_new() + * and g_string_free(), or as a stack-allocated struct, using g_string_init() + * and g_string_clear(). */ /** @@ -70,6 +74,7 @@ * terminating nul byte. * @allocated_len: the number of bytes that can be stored in the * string before it needs to be reallocated. May be larger than @len. + * @buf: preallocated memory for @str * * The GString struct contains the public fields of a GString. */ @@ -82,6 +87,9 @@ g_string_expand (GString *string, if G_UNLIKELY ((G_MAXSIZE - string->len - 1) < len) g_error ("adding %" G_GSIZE_FORMAT " to string would overflow", len); + if (string->str == NULL) + g_string_init (string); + string->allocated_len = g_nearest_pow (string->len + len + 1); /* If the new size is bigger than G_MAXSIZE / 2, only allocate enough * memory for this string and don't over-allocate. @@ -89,7 +97,14 @@ g_string_expand (GString *string, if (string->allocated_len == 0) string->allocated_len = string->len + len + 1; - string->str = g_realloc (string->str, string->allocated_len); + if (string->str != string->buf) + string->str = g_realloc (string->str, string->allocated_len); + else + { + string->str = g_malloc (string->allocated_len); + memcpy (string->str, string->buf, string->len); + string->str[string->len] = 0; + } } static inline void @@ -101,6 +116,23 @@ g_string_maybe_expand (GString *string, } /** + * g_string_init: + * @string: an uninitialized #GString + * + * Initializes @string. + * + * This function should be used to initialize a stack-allocated + * GString struct. + * + * Since: 2.76 + */ +void +(g_string_init) (GString *string) +{ + g_string_init_inline (string); +} + +/** * g_string_sized_new: (constructor) * @dfl_size: the default size of the space allocated to hold the string * @@ -116,12 +148,8 @@ g_string_sized_new (gsize dfl_size) { GString *string = g_slice_new (GString); - string->allocated_len = 0; - string->len = 0; - string->str = NULL; - - g_string_expand (string, MAX (dfl_size, 64)); - string->str[0] = 0; + g_string_init (string); + g_string_maybe_expand (string, dfl_size); return string; } @@ -190,6 +218,29 @@ g_string_new_len (const gchar *init, } /** + * g_string_clear: + * @string: (transfer full): a #GString + * @free_segment: if %TRUE, the actual character data is freed as well + * + * Clears a stack-allocated GString struct. + * + * If @free_segment is %TRUE it also frees the character data. + * If it's %FALSE, the caller gains ownership of the buffer and + * must free it after use with g_free(). + * + * Returns: (nullable): the character data of @string + * (i.e. %NULL if @free_segment is %TRUE) + * + * Since: 2.76 + */ +char * +(g_string_clear) (GString *string, + gboolean free_segment) +{ + return g_string_clear_inline (string, free_segment); +} + +/** * g_string_free: * @string: (transfer full): a #GString * @free_segment: if %TRUE, the actual character data is freed as well @@ -210,13 +261,7 @@ g_string_free (GString *string, g_return_val_if_fail (string != NULL, NULL); - if (free_segment) - { - g_free (string->str); - segment = NULL; - } - else - segment = string->str; + segment = g_string_clear (string, free_segment); g_slice_free (GString, string); |