diff --git a/dbus/dbus-string-util.c b/dbus/dbus-string-util.c index aed9487..f2d1d69 100644 --- a/dbus/dbus-string-util.c +++ b/dbus/dbus-string-util.c @@ -512,7 +512,38 @@ _dbus_string_test (void) _dbus_assert (_dbus_string_get_length (&other) == i * 2 - 1); _dbus_assert (_dbus_string_equal_c_str (&other, "HelloHello WorldWorle")); - + + if (!_dbus_string_replace_len (&str, 0, 5, + &other, + _dbus_string_get_length (&other) - 5, + 5)) + _dbus_assert_not_reached ("could not replace same length"); + + _dbus_assert (_dbus_string_get_length (&str) == i); + _dbus_assert (_dbus_string_get_length (&other) == i * 2 - 1); + _dbus_assert (_dbus_string_equal_c_str (&other, + "HelloHello WorldHello")); + + if (!_dbus_string_replace_len (&str, 0, 5, + &other, + _dbus_string_get_length (&other) - 10, + 10)) + _dbus_assert_not_reached ("could not replace different length"); + + _dbus_assert (_dbus_string_get_length (&str) == i); + _dbus_assert (_dbus_string_get_length (&other) == 16); + _dbus_assert (_dbus_string_equal_c_str (&other, + "HelloHello Hello")); + + if (!_dbus_string_replace_len (&str, 6, 5, + &other, 1, 2)) + _dbus_assert_not_reached ("could not replace different length"); + + _dbus_assert (_dbus_string_get_length (&str) == i); + _dbus_assert (_dbus_string_get_length (&other) == 19); + _dbus_assert (_dbus_string_equal_c_str (&other, + "HWorldloHello Hello")); + _dbus_string_free (&str); _dbus_string_free (&other); diff --git a/dbus/dbus-string.c b/dbus/dbus-string.c index 6b9b2bf..ce6919b 100644 --- a/dbus/dbus-string.c +++ b/dbus/dbus-string.c @@ -1668,11 +1668,33 @@ _dbus_string_replace_len (const DBusString *source, _dbus_assert (replace_at <= real_dest->len); _dbus_assert (replace_len <= real_dest->len - replace_at); - if (!copy (real_source, start, len, - real_dest, replace_at)) - return FALSE; + if (len == replace_len) + memmove (real_dest->str + replace_at, + real_source->str + start, len); + else if (len < replace_len) + { + memmove (real_dest->str + replace_at, + real_source->str + start, len); + delete (real_dest, replace_at + len, + replace_len - len); + } + else /* if (len > replace_len) */ + { + int diff; + + diff = len - replace_len; - delete (real_dest, replace_at + len, replace_len); + /* First of all we check if destination string can be enlarged as + * required, then we overwrite previous bytes + */ + + if (!copy (real_source, start + replace_len, diff, + real_dest, replace_at + replace_len)) + return FALSE; + + memmove (real_dest->str + replace_at, + real_source->str + start, replace_len); + } return TRUE; }