mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-03-30 04:13:06 +02:00
Merge branch 'wip/chergert/insertbeforelink' into 'master'
Add pre-allocated link helpers for GList and GQueue See merge request GNOME/glib!476
This commit is contained in:
commit
375fa65b24
@ -2268,6 +2268,7 @@ g_list_append
|
|||||||
g_list_prepend
|
g_list_prepend
|
||||||
g_list_insert
|
g_list_insert
|
||||||
g_list_insert_before
|
g_list_insert_before
|
||||||
|
g_list_insert_before_link
|
||||||
g_list_insert_sorted
|
g_list_insert_sorted
|
||||||
g_list_remove
|
g_list_remove
|
||||||
g_list_remove_link
|
g_list_remove_link
|
||||||
@ -2389,7 +2390,9 @@ g_queue_index
|
|||||||
g_queue_remove
|
g_queue_remove
|
||||||
g_queue_remove_all
|
g_queue_remove_all
|
||||||
g_queue_insert_before
|
g_queue_insert_before
|
||||||
|
g_queue_insert_before_link
|
||||||
g_queue_insert_after
|
g_queue_insert_after
|
||||||
|
g_queue_insert_after_link
|
||||||
g_queue_insert_sorted
|
g_queue_insert_sorted
|
||||||
g_queue_push_head_link
|
g_queue_push_head_link
|
||||||
g_queue_push_tail_link
|
g_queue_push_tail_link
|
||||||
|
68
glib/glist.c
68
glib/glist.c
@ -367,6 +367,64 @@ g_list_insert (GList *list,
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_list_insert_before_link:
|
||||||
|
* @list: a pointer to a #GList, this must point to the top of the list
|
||||||
|
* @sibling: (nullable): the list element before which the new element
|
||||||
|
* is inserted or %NULL to insert at the end of the list
|
||||||
|
* @link_: the list element to be added, which must not be part of
|
||||||
|
* any other list
|
||||||
|
*
|
||||||
|
* Inserts @link_ into the list before the given position.
|
||||||
|
*
|
||||||
|
* Returns: the (possibly changed) start of the #GList
|
||||||
|
*
|
||||||
|
* Since: 2.62
|
||||||
|
*/
|
||||||
|
GList *
|
||||||
|
g_list_insert_before_link (GList *list,
|
||||||
|
GList *sibling,
|
||||||
|
GList *link_)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (link_ != NULL, list);
|
||||||
|
g_return_val_if_fail (link_->prev == NULL, list);
|
||||||
|
g_return_val_if_fail (link_->next == NULL, list);
|
||||||
|
|
||||||
|
if (list == NULL)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (sibling == NULL, list);
|
||||||
|
return link_;
|
||||||
|
}
|
||||||
|
else if (sibling != NULL)
|
||||||
|
{
|
||||||
|
link_->prev = sibling->prev;
|
||||||
|
link_->next = sibling;
|
||||||
|
sibling->prev = link_;
|
||||||
|
if (link_->prev != NULL)
|
||||||
|
{
|
||||||
|
link_->prev->next = link_;
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (sibling == list, link_);
|
||||||
|
return link_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GList *last;
|
||||||
|
|
||||||
|
for (last = list; last->next != NULL; last = last->next) {}
|
||||||
|
|
||||||
|
last->next = link_;
|
||||||
|
last->next->prev = last;
|
||||||
|
last->next->next = NULL;
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* g_list_insert_before:
|
* g_list_insert_before:
|
||||||
* @list: a pointer to a #GList, this must point to the top of the list
|
* @list: a pointer to a #GList, this must point to the top of the list
|
||||||
@ -383,14 +441,14 @@ g_list_insert_before (GList *list,
|
|||||||
GList *sibling,
|
GList *sibling,
|
||||||
gpointer data)
|
gpointer data)
|
||||||
{
|
{
|
||||||
if (!list)
|
if (list == NULL)
|
||||||
{
|
{
|
||||||
list = g_list_alloc ();
|
list = g_list_alloc ();
|
||||||
list->data = data;
|
list->data = data;
|
||||||
g_return_val_if_fail (sibling == NULL, list);
|
g_return_val_if_fail (sibling == NULL, list);
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
else if (sibling)
|
else if (sibling != NULL)
|
||||||
{
|
{
|
||||||
GList *node;
|
GList *node;
|
||||||
|
|
||||||
@ -399,7 +457,7 @@ g_list_insert_before (GList *list,
|
|||||||
node->prev = sibling->prev;
|
node->prev = sibling->prev;
|
||||||
node->next = sibling;
|
node->next = sibling;
|
||||||
sibling->prev = node;
|
sibling->prev = node;
|
||||||
if (node->prev)
|
if (node->prev != NULL)
|
||||||
{
|
{
|
||||||
node->prev->next = node;
|
node->prev->next = node;
|
||||||
return list;
|
return list;
|
||||||
@ -414,9 +472,7 @@ g_list_insert_before (GList *list,
|
|||||||
{
|
{
|
||||||
GList *last;
|
GList *last;
|
||||||
|
|
||||||
last = list;
|
for (last = list; last->next != NULL; last = last->next) {}
|
||||||
while (last->next)
|
|
||||||
last = last->next;
|
|
||||||
|
|
||||||
last->next = _g_list_alloc ();
|
last->next = _g_list_alloc ();
|
||||||
last->next->data = data;
|
last->next->data = data;
|
||||||
|
@ -78,6 +78,10 @@ GLIB_AVAILABLE_IN_ALL
|
|||||||
GList* g_list_insert_before (GList *list,
|
GList* g_list_insert_before (GList *list,
|
||||||
GList *sibling,
|
GList *sibling,
|
||||||
gpointer data) G_GNUC_WARN_UNUSED_RESULT;
|
gpointer data) G_GNUC_WARN_UNUSED_RESULT;
|
||||||
|
GLIB_AVAILABLE_IN_2_62
|
||||||
|
GList* g_list_insert_before_link (GList *list,
|
||||||
|
GList *sibling,
|
||||||
|
GList *link_) G_GNUC_WARN_UNUSED_RESULT;
|
||||||
GLIB_AVAILABLE_IN_ALL
|
GLIB_AVAILABLE_IN_ALL
|
||||||
GList* g_list_concat (GList *list1,
|
GList* g_list_concat (GList *list1,
|
||||||
GList *list2) G_GNUC_WARN_UNUSED_RESULT;
|
GList *list2) G_GNUC_WARN_UNUSED_RESULT;
|
||||||
|
@ -1047,6 +1047,44 @@ g_queue_insert_before (GQueue *queue,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_queue_insert_before_link:
|
||||||
|
* @queue: a #GQueue
|
||||||
|
* @sibling: (nullable): a #GList link that must be part of @queue, or %NULL to
|
||||||
|
* push at the tail of the queue.
|
||||||
|
* @link_: a #GList link to insert which must not be part of any other list.
|
||||||
|
*
|
||||||
|
* Inserts @link_ into @queue before @sibling.
|
||||||
|
*
|
||||||
|
* @sibling must be part of @queue.
|
||||||
|
*
|
||||||
|
* Since: 2.62
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
g_queue_insert_before_link (GQueue *queue,
|
||||||
|
GList *sibling,
|
||||||
|
GList *link_)
|
||||||
|
{
|
||||||
|
g_return_if_fail (queue != NULL);
|
||||||
|
g_return_if_fail (link_ != NULL);
|
||||||
|
g_return_if_fail (link_->prev == NULL);
|
||||||
|
g_return_if_fail (link_->next == NULL);
|
||||||
|
|
||||||
|
if G_UNLIKELY (sibling == NULL)
|
||||||
|
{
|
||||||
|
/* We don't use g_list_insert_before_link() with a NULL sibling because it
|
||||||
|
* would be a O(n) operation and we would need to update manually the tail
|
||||||
|
* pointer.
|
||||||
|
*/
|
||||||
|
g_queue_push_tail_link (queue, link_);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
queue->head = g_list_insert_before_link (queue->head, sibling, link_);
|
||||||
|
queue->length++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* g_queue_insert_after:
|
* g_queue_insert_after:
|
||||||
* @queue: a #GQueue
|
* @queue: a #GQueue
|
||||||
@ -1074,6 +1112,35 @@ g_queue_insert_after (GQueue *queue,
|
|||||||
g_queue_insert_before (queue, sibling->next, data);
|
g_queue_insert_before (queue, sibling->next, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_queue_insert_after_link:
|
||||||
|
* @queue: a #GQueue
|
||||||
|
* @sibling: (nullable): a #GList link that must be part of @queue, or %NULL to
|
||||||
|
* push at the head of the queue.
|
||||||
|
* @link_: a #GList link to insert which must not be part of any other list.
|
||||||
|
*
|
||||||
|
* Inserts @link_ into @queue after @sibling.
|
||||||
|
*
|
||||||
|
* @sibling must be part of @queue.
|
||||||
|
*
|
||||||
|
* Since: 2.62
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
g_queue_insert_after_link (GQueue *queue,
|
||||||
|
GList *sibling,
|
||||||
|
GList *link_)
|
||||||
|
{
|
||||||
|
g_return_if_fail (queue != NULL);
|
||||||
|
g_return_if_fail (link_ != NULL);
|
||||||
|
g_return_if_fail (link_->prev == NULL);
|
||||||
|
g_return_if_fail (link_->next == NULL);
|
||||||
|
|
||||||
|
if G_UNLIKELY (sibling == NULL)
|
||||||
|
g_queue_push_head_link (queue, link_);
|
||||||
|
else
|
||||||
|
g_queue_insert_before_link (queue, sibling->next, link_);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* g_queue_insert_sorted:
|
* g_queue_insert_sorted:
|
||||||
* @queue: a #GQueue
|
* @queue: a #GQueue
|
||||||
|
@ -144,10 +144,20 @@ GLIB_AVAILABLE_IN_ALL
|
|||||||
void g_queue_insert_before (GQueue *queue,
|
void g_queue_insert_before (GQueue *queue,
|
||||||
GList *sibling,
|
GList *sibling,
|
||||||
gpointer data);
|
gpointer data);
|
||||||
|
GLIB_AVAILABLE_IN_2_62
|
||||||
|
void g_queue_insert_before_link
|
||||||
|
(GQueue *queue,
|
||||||
|
GList *sibling,
|
||||||
|
GList *link_);
|
||||||
GLIB_AVAILABLE_IN_ALL
|
GLIB_AVAILABLE_IN_ALL
|
||||||
void g_queue_insert_after (GQueue *queue,
|
void g_queue_insert_after (GQueue *queue,
|
||||||
GList *sibling,
|
GList *sibling,
|
||||||
gpointer data);
|
gpointer data);
|
||||||
|
GLIB_AVAILABLE_IN_2_62
|
||||||
|
void g_queue_insert_after_link
|
||||||
|
(GQueue *queue,
|
||||||
|
GList *sibling,
|
||||||
|
GList *link_);
|
||||||
GLIB_AVAILABLE_IN_ALL
|
GLIB_AVAILABLE_IN_ALL
|
||||||
void g_queue_insert_sorted (GQueue *queue,
|
void g_queue_insert_sorted (GQueue *queue,
|
||||||
gpointer data,
|
gpointer data,
|
||||||
|
@ -548,6 +548,72 @@ test_double_free (void)
|
|||||||
g_test_trap_assert_stderr ("*corrupted double-linked list detected*");
|
g_test_trap_assert_stderr ("*corrupted double-linked list detected*");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_list_insert_before_link (void)
|
||||||
|
{
|
||||||
|
GList a = {0};
|
||||||
|
GList b = {0};
|
||||||
|
GList c = {0};
|
||||||
|
GList d = {0};
|
||||||
|
GList e = {0};
|
||||||
|
GList *list;
|
||||||
|
|
||||||
|
list = g_list_insert_before_link (NULL, NULL, &a);
|
||||||
|
g_assert_nonnull (list);
|
||||||
|
g_assert_true (list == &a);
|
||||||
|
g_assert_null (a.prev);
|
||||||
|
g_assert_null (a.next);
|
||||||
|
g_assert_cmpint (g_list_length (list), ==, 1);
|
||||||
|
|
||||||
|
list = g_list_insert_before_link (list, &a, &b);
|
||||||
|
g_assert_nonnull (list);
|
||||||
|
g_assert_true (list == &b);
|
||||||
|
g_assert_null (b.prev);
|
||||||
|
g_assert_true (b.next == &a);
|
||||||
|
g_assert_true (a.prev == &b);
|
||||||
|
g_assert_null (a.next);
|
||||||
|
g_assert_cmpint (g_list_length (list), ==, 2);
|
||||||
|
|
||||||
|
list = g_list_insert_before_link (list, &a, &c);
|
||||||
|
g_assert_nonnull (list);
|
||||||
|
g_assert_true (list == &b);
|
||||||
|
g_assert_null (b.prev);
|
||||||
|
g_assert_true (b.next == &c);
|
||||||
|
g_assert_true (c.next == &a);
|
||||||
|
g_assert_true (c.prev == &b);
|
||||||
|
g_assert_true (a.prev == &c);
|
||||||
|
g_assert_null (a.next);
|
||||||
|
g_assert_cmpint (g_list_length (list), ==, 3);
|
||||||
|
|
||||||
|
list = g_list_insert_before_link (list, &b, &d);
|
||||||
|
g_assert_nonnull (list);
|
||||||
|
g_assert_true (list == &d);
|
||||||
|
g_assert_null (d.prev);
|
||||||
|
g_assert_true (b.prev == &d);
|
||||||
|
g_assert_true (c.prev == &b);
|
||||||
|
g_assert_true (a.prev == &c);
|
||||||
|
g_assert_true (d.next == &b);
|
||||||
|
g_assert_true (b.next == &c);
|
||||||
|
g_assert_true (c.next == &a);
|
||||||
|
g_assert_null (a.next);
|
||||||
|
g_assert_cmpint (g_list_length (list), ==, 4);
|
||||||
|
|
||||||
|
list = g_list_insert_before_link (list, NULL, &e);
|
||||||
|
g_assert_nonnull (list);
|
||||||
|
g_assert_true (list == &d);
|
||||||
|
g_assert_null (d.prev);
|
||||||
|
g_assert_true (b.prev == &d);
|
||||||
|
g_assert_true (c.prev == &b);
|
||||||
|
g_assert_true (a.prev == &c);
|
||||||
|
g_assert_true (d.next == &b);
|
||||||
|
g_assert_true (b.next == &c);
|
||||||
|
g_assert_true (c.next == &a);
|
||||||
|
g_assert_true (a.next == &e);
|
||||||
|
g_assert_true (e.prev == &a);
|
||||||
|
g_assert_null (e.next);
|
||||||
|
g_assert_cmpint (g_list_length (list), ==, 5);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main (int argc, char *argv[])
|
main (int argc, char *argv[])
|
||||||
{
|
{
|
||||||
@ -562,6 +628,7 @@ main (int argc, char *argv[])
|
|||||||
g_test_add_func ("/list/sort", test_list_sort);
|
g_test_add_func ("/list/sort", test_list_sort);
|
||||||
g_test_add_func ("/list/sort-with-data", test_list_sort_with_data);
|
g_test_add_func ("/list/sort-with-data", test_list_sort_with_data);
|
||||||
g_test_add_func ("/list/sort/stable", test_list_sort_stable);
|
g_test_add_func ("/list/sort/stable", test_list_sort_stable);
|
||||||
|
g_test_add_func ("/list/insert-before-link", test_list_insert_before_link);
|
||||||
g_test_add_func ("/list/insert-sorted", test_list_insert_sorted);
|
g_test_add_func ("/list/insert-sorted", test_list_insert_sorted);
|
||||||
g_test_add_func ("/list/insert-sorted-with-data", test_list_insert_sorted_with_data);
|
g_test_add_func ("/list/insert-sorted-with-data", test_list_insert_sorted_with_data);
|
||||||
g_test_add_func ("/list/reverse", test_list_reverse);
|
g_test_add_func ("/list/reverse", test_list_reverse);
|
||||||
|
@ -1117,6 +1117,40 @@ test_free_full (void)
|
|||||||
g_slice_free (QueueItem, three);
|
g_slice_free (QueueItem, three);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_insert_sibling_link (void)
|
||||||
|
{
|
||||||
|
GQueue q = G_QUEUE_INIT;
|
||||||
|
GList a = {0};
|
||||||
|
GList b = {0};
|
||||||
|
GList c = {0};
|
||||||
|
GList d = {0};
|
||||||
|
GList e = {0};
|
||||||
|
|
||||||
|
g_queue_push_head_link (&q, &a);
|
||||||
|
g_queue_insert_after_link (&q, &a, &d);
|
||||||
|
g_queue_insert_before_link (&q, &d, &b);
|
||||||
|
g_queue_insert_after_link (&q, &b, &c);
|
||||||
|
g_queue_insert_after_link (&q, NULL, &e);
|
||||||
|
|
||||||
|
g_assert_true (q.head == &e);
|
||||||
|
g_assert_true (q.tail == &d);
|
||||||
|
|
||||||
|
g_assert_null (e.prev);
|
||||||
|
g_assert_true (e.next == &a);
|
||||||
|
|
||||||
|
g_assert_true (a.prev == &e);
|
||||||
|
g_assert_true (a.next == &b);
|
||||||
|
|
||||||
|
g_assert_true (b.prev == &a);
|
||||||
|
g_assert_true (b.next == &c);
|
||||||
|
|
||||||
|
g_assert_true (c.prev == &b);
|
||||||
|
g_assert_true (c.next == &d);
|
||||||
|
|
||||||
|
g_assert_true (d.prev == &c);
|
||||||
|
g_assert_null (d.next);
|
||||||
|
}
|
||||||
|
|
||||||
int main (int argc, char *argv[])
|
int main (int argc, char *argv[])
|
||||||
{
|
{
|
||||||
@ -1133,6 +1167,7 @@ int main (int argc, char *argv[])
|
|||||||
g_test_add_func ("/queue/clear", test_clear);
|
g_test_add_func ("/queue/clear", test_clear);
|
||||||
g_test_add_func ("/queue/free-full", test_free_full);
|
g_test_add_func ("/queue/free-full", test_free_full);
|
||||||
g_test_add_func ("/queue/clear-full", test_clear_full);
|
g_test_add_func ("/queue/clear-full", test_clear_full);
|
||||||
|
g_test_add_func ("/queue/insert-sibling-link", test_insert_sibling_link);
|
||||||
|
|
||||||
seed = g_test_rand_int_range (0, G_MAXINT);
|
seed = g_test_rand_int_range (0, G_MAXINT);
|
||||||
path = g_strdup_printf ("/queue/random/seed:%u", seed);
|
path = g_strdup_printf ("/queue/random/seed:%u", seed);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user