mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-25 11:42:10 +01:00
gdatalist: rework g_data_remove_internal() to use datalist_shrink()
The main point here is to reuse datalist_remove() and datalist_shrink(). Especially, datalist_shrink() will become more interesting next, when it actually shrinks the buffer. Also, I find the previous implementation with "data_end" confusing. Instead, only use index "i_data" to iterate over the data.
This commit is contained in:
parent
927075277c
commit
6c0d4c884f
@ -200,6 +200,11 @@ datalist_remove (GData *data, guint32 idx)
|
|||||||
g_assert (idx < data->len);
|
g_assert (idx < data->len);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* g_data_remove_internal() relies on the fact, that this function removes
|
||||||
|
* the entry similar to g_array_remove_index_fast(). That is, the entries up
|
||||||
|
* to @idx are left unchanged, and the last entry at moved to position @idx.
|
||||||
|
* */
|
||||||
|
|
||||||
data->len--;
|
data->len--;
|
||||||
|
|
||||||
if (idx != data->len)
|
if (idx != data->len)
|
||||||
@ -481,10 +486,10 @@ g_data_remove_internal (GData **datalist,
|
|||||||
GData *d;
|
GData *d;
|
||||||
GDataElt *old;
|
GDataElt *old;
|
||||||
GDataElt *old_to_free = NULL;
|
GDataElt *old_to_free = NULL;
|
||||||
GDataElt *data;
|
GData *d_to_free;
|
||||||
GDataElt *data_end;
|
|
||||||
gsize found_keys;
|
gsize found_keys;
|
||||||
gboolean free_d = FALSE;
|
gsize i_keys;
|
||||||
|
guint32 i_data;
|
||||||
|
|
||||||
d = g_datalist_lock_and_get (datalist);
|
d = g_datalist_lock_and_get (datalist);
|
||||||
|
|
||||||
@ -510,68 +515,50 @@ g_data_remove_internal (GData **datalist,
|
|||||||
old = old_to_free;
|
old = old_to_free;
|
||||||
}
|
}
|
||||||
|
|
||||||
data = d->data;
|
i_data = 0;
|
||||||
data_end = data + d->len;
|
|
||||||
found_keys = 0;
|
found_keys = 0;
|
||||||
|
while (i_data < d->len && found_keys < n_keys)
|
||||||
while (data < data_end && found_keys < n_keys)
|
|
||||||
{
|
{
|
||||||
|
GDataElt *data = &d->data[i_data];
|
||||||
gboolean remove = FALSE;
|
gboolean remove = FALSE;
|
||||||
|
|
||||||
for (gsize i = 0; i < n_keys; i++)
|
for (i_keys = 0; i_keys < n_keys; i_keys++)
|
||||||
{
|
{
|
||||||
if (data->key == keys[i])
|
if (data->key == keys[i_keys])
|
||||||
{
|
{
|
||||||
old[i] = *data;
|
/* We must invoke the destroy notifications in the order of @keys.
|
||||||
|
* Hence, build up the list @old at index @i_keys. */
|
||||||
|
old[i_keys] = *data;
|
||||||
|
found_keys++;
|
||||||
remove = TRUE;
|
remove = TRUE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (remove)
|
if (!remove)
|
||||||
{
|
{
|
||||||
GDataElt *data_last = data_end - 1;
|
i_data++;
|
||||||
|
continue;
|
||||||
found_keys++;
|
|
||||||
|
|
||||||
if (data < data_last)
|
|
||||||
*data = *data_last;
|
|
||||||
|
|
||||||
data_end--;
|
|
||||||
d->len--;
|
|
||||||
|
|
||||||
/* We don't bother to shrink, but if all data are now gone
|
|
||||||
* we at least free the memory
|
|
||||||
*/
|
|
||||||
if (d->len == 0)
|
|
||||||
{
|
|
||||||
free_d = TRUE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
data++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (free_d)
|
datalist_remove (d, i_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found_keys > 0 && datalist_shrink (&d, &d_to_free))
|
||||||
{
|
{
|
||||||
g_datalist_unlock_and_set (datalist, NULL);
|
g_datalist_unlock_and_set (datalist, d);
|
||||||
g_free (d);
|
if (d_to_free)
|
||||||
|
g_free (d_to_free);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
g_datalist_unlock (datalist);
|
g_datalist_unlock (datalist);
|
||||||
|
|
||||||
if (found_keys > 0)
|
if (found_keys > 0)
|
||||||
{
|
{
|
||||||
for (gsize i = 0; i < n_keys; i++)
|
for (i_keys = 0; i_keys < n_keys; i_keys++)
|
||||||
{
|
{
|
||||||
/* If keys[i] was not found, then old[i].destroy is NULL.
|
if (old[i_keys].destroy)
|
||||||
* Call old[i].destroy() only if keys[i] was found, and
|
old[i_keys].destroy (old[i_keys].data);
|
||||||
* is associated with a destroy notifier: */
|
|
||||||
if (old[i].destroy)
|
|
||||||
old[i].destroy (old[i].data);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user