mirror of
https://gitlab.freedesktop.org/dbus/dbus.git
synced 2026-05-09 06:08:01 +02:00
DBusString: Add _DBUS_STRING_INIT_INVALID and allow "freeing" it
This means we can finally use patterns like this:
DBusString buffer = _DBUS_STRING_INIT_INVALID;
dbus_bool_t ret = FALSE;
... some long setup ...
if (!_dbus_string_init (&buffer))
goto out;
... some long operation ...
ret = TRUE;
out:
... free things ...
_dbus_string_free (&buffer);
... free more things ...
return ret;
without having to have a separate boolean to track whether buffer has
been initialized.
One observable difference is that if s is a "const" (borrowed pointer)
string, _dbus_string_free (&s) now sets it to be invalid. Previously,
it would have kept its (borrowed pointer) contents, which seems like
a violation of least-astonishment.
Signed-off-by: Simon McVittie <smcv@collabora.com>
Reviewed-by: Philip Withnall <withnall@endlessm.com>
Bug: https://bugs.freedesktop.org/show_bug.cgi?id=89104
This commit is contained in:
parent
608a453b73
commit
e49a21e357
3 changed files with 45 additions and 4 deletions
|
|
@ -228,7 +228,7 @@ _DBUS_STRING_DEFINE_STATIC (test_static_string, "hello");
|
||||||
dbus_bool_t
|
dbus_bool_t
|
||||||
_dbus_string_test (void)
|
_dbus_string_test (void)
|
||||||
{
|
{
|
||||||
DBusString str;
|
DBusString str = _DBUS_STRING_INIT_INVALID;
|
||||||
DBusString other;
|
DBusString other;
|
||||||
int i, a, end;
|
int i, a, end;
|
||||||
long v;
|
long v;
|
||||||
|
|
@ -245,6 +245,11 @@ _dbus_string_test (void)
|
||||||
_dbus_assert (real_test_static_string->valid);
|
_dbus_assert (real_test_static_string->valid);
|
||||||
_dbus_assert (real_test_static_string->align_offset == 0);
|
_dbus_assert (real_test_static_string->align_offset == 0);
|
||||||
|
|
||||||
|
/* Test that _DBUS_STRING_INIT_INVALID has the desired effect */
|
||||||
|
_dbus_string_free (&str);
|
||||||
|
_dbus_string_free (&str);
|
||||||
|
_dbus_string_free (&str);
|
||||||
|
|
||||||
/* Test shortening and setting length */
|
/* Test shortening and setting length */
|
||||||
i = 0;
|
i = 0;
|
||||||
while (i < _DBUS_N_ELEMENTS (lens))
|
while (i < _DBUS_N_ELEMENTS (lens))
|
||||||
|
|
@ -270,6 +275,9 @@ _dbus_string_test (void)
|
||||||
}
|
}
|
||||||
|
|
||||||
_dbus_string_free (&str);
|
_dbus_string_free (&str);
|
||||||
|
/* Test that a cleared string is effectively _DBUS_STRING_INIT_INVALID */
|
||||||
|
_dbus_string_free (&str);
|
||||||
|
_dbus_string_free (&str);
|
||||||
|
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -251,7 +251,12 @@ _dbus_string_init_from_string(DBusString *str,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Frees a string created by _dbus_string_init().
|
* Frees a string created by _dbus_string_init(), and fills it with the
|
||||||
|
* same contents as #_DBUS_STRING_INIT_INVALID.
|
||||||
|
*
|
||||||
|
* Unlike all other #DBusString API, it is also valid to call this function
|
||||||
|
* for a string that was filled with #_DBUS_STRING_INIT_INVALID.
|
||||||
|
* This is convenient for error rollback.
|
||||||
*
|
*
|
||||||
* @param str memory where the string is stored.
|
* @param str memory where the string is stored.
|
||||||
*/
|
*/
|
||||||
|
|
@ -259,20 +264,32 @@ void
|
||||||
_dbus_string_free (DBusString *str)
|
_dbus_string_free (DBusString *str)
|
||||||
{
|
{
|
||||||
DBusRealString *real = (DBusRealString*) str;
|
DBusRealString *real = (DBusRealString*) str;
|
||||||
|
/* DBusRealString and DBusString have the same members in the same order,
|
||||||
|
* just differently-named */
|
||||||
|
DBusRealString invalid = _DBUS_STRING_INIT_INVALID;
|
||||||
|
|
||||||
|
/* Allow for the _DBUS_STRING_INIT_INVALID case */
|
||||||
|
if (real->str == NULL && real->len == 0 && real->allocated == 0 &&
|
||||||
|
!real->constant && !real->locked && !real->valid &&
|
||||||
|
real->align_offset == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
DBUS_GENERIC_STRING_PREAMBLE (real);
|
DBUS_GENERIC_STRING_PREAMBLE (real);
|
||||||
|
|
||||||
if (real->constant)
|
if (real->constant)
|
||||||
return;
|
goto wipe;
|
||||||
|
|
||||||
/* so it's safe if @p str returned by a failed
|
/* so it's safe if @p str returned by a failed
|
||||||
* _dbus_string_init call
|
* _dbus_string_init call
|
||||||
* Bug: https://bugs.freedesktop.org/show_bug.cgi?id=65959
|
* Bug: https://bugs.freedesktop.org/show_bug.cgi?id=65959
|
||||||
*/
|
*/
|
||||||
if (real->str == NULL)
|
if (real->str == NULL)
|
||||||
return;
|
goto wipe;
|
||||||
|
|
||||||
dbus_free (real->str - real->align_offset);
|
dbus_free (real->str - real->align_offset);
|
||||||
|
|
||||||
|
wipe:
|
||||||
|
*real = invalid;
|
||||||
real->valid = FALSE;
|
real->valid = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,22 @@ struct DBusString
|
||||||
unsigned int dummy_bits : 3; /**< placeholder */
|
unsigned int dummy_bits : 3; /**< placeholder */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Content for a DBusString that is considered invalid for all
|
||||||
|
* operations, except that it is valid to call _dbus_string_free()
|
||||||
|
* during error handling.
|
||||||
|
*/
|
||||||
|
#define _DBUS_STRING_INIT_INVALID \
|
||||||
|
{ \
|
||||||
|
NULL, /* dummy1 */ \
|
||||||
|
0, /* dummy2 */ \
|
||||||
|
0, /* dummy3 */ \
|
||||||
|
0, /* dummy_bit1 */ \
|
||||||
|
0, /* dummy_bit2 */ \
|
||||||
|
0, /* dummy_bit3 */ \
|
||||||
|
0 /* dummy_bits */ \
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef DBUS_DISABLE_ASSERT
|
#ifdef DBUS_DISABLE_ASSERT
|
||||||
/* Some simple inlining hacks; the current linker is not smart enough
|
/* Some simple inlining hacks; the current linker is not smart enough
|
||||||
* to inline non-exported symbols across files in the library.
|
* to inline non-exported symbols across files in the library.
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue