1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* dbus-list.c Generic linked list utility (internal to D-Bus implementation)
4 * Copyright (C) 2002 Red Hat, Inc.
6 * Licensed under the Academic Free License version 2.1
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 #include "dbus-internals.h"
26 #include "dbus-list.h"
27 #include "dbus-mempool.h"
28 #include "dbus-threads-internal.h"
31 * @defgroup DBusList Linked list
32 * @ingroup DBusInternals
33 * @brief DBusList data structure
35 * Types and functions related to DBusList.
38 static DBusMemPool *list_pool;
39 _DBUS_DEFINE_GLOBAL_LOCK (list);
42 * @defgroup DBusListInternals Linked list implementation details
43 * @ingroup DBusInternals
44 * @brief DBusList implementation details
46 * The guts of DBusList.
51 /* the mem pool is probably a speed hit, with the thread
52 * lock, though it does still save memory - unknown.
55 alloc_link (void *data)
61 if (list_pool == NULL)
63 list_pool = _dbus_mem_pool_new (sizeof (DBusList), TRUE);
65 if (list_pool == NULL)
71 link = _dbus_mem_pool_alloc (list_pool);
74 _dbus_mem_pool_free (list_pool);
82 link = _dbus_mem_pool_alloc (list_pool);
94 free_link (DBusList *link)
97 if (_dbus_mem_pool_dealloc (list_pool, link))
99 _dbus_mem_pool_free (list_pool);
107 link_before (DBusList **list,
108 DBusList *before_this_link,
119 link->next = before_this_link;
120 link->prev = before_this_link->prev;
121 before_this_link->prev = link;
122 link->prev->next = link;
124 if (before_this_link == *list)
130 link_after (DBusList **list,
131 DBusList *after_this_link,
142 link->prev = after_this_link;
143 link->next = after_this_link->next;
144 after_this_link->next = link;
145 link->next->prev = link;
149 #ifdef DBUS_ENABLE_STATS
151 _dbus_list_get_stats (dbus_uint32_t *in_use_p,
152 dbus_uint32_t *in_free_list_p,
153 dbus_uint32_t *allocated_p)
156 _dbus_mem_pool_get_stats (list_pool, in_use_p, in_free_list_p, allocated_p);
164 * @addtogroup DBusList
171 * A node in a linked list.
173 * DBusList is a circular list; that is, the tail of the list
174 * points back to the head of the list. The empty list is
175 * represented by a #NULL pointer.
179 * @def _dbus_list_get_next_link
181 * Gets the next link in the list, or #NULL if
182 * there are no more links. Used for iteration.
186 * link = _dbus_list_get_first_link (&list);
187 * while (link != NULL)
189 * printf ("value is %p\n", link->data);
190 * link = _dbus_list_get_next_link (&link);
194 * @param list address of the list head.
195 * @param link current link.
196 * @returns the next link, or %NULL if none.
201 * @def _dbus_list_get_prev_link
203 * Gets the previous link in the list, or #NULL if
204 * there are no more links. Used for iteration.
208 * link = _dbus_list_get_last_link (&list);
209 * while (link != NULL)
211 * printf ("value is %p\n", link->data);
212 * link = _dbus_list_get_prev_link (&link);
216 * @param list address of the list head.
217 * @param link current link.
218 * @returns the previous link, or %NULL if none.
223 * Allocates a linked list node. Useful for preallocating
224 * nodes and using _dbus_list_append_link() to avoid
227 * @param data the value to store in the link.
228 * @returns a newly allocated link.
231 _dbus_list_alloc_link (void *data)
233 return alloc_link (data);
237 * Frees a linked list node allocated with _dbus_list_alloc_link.
238 * Does not free the data in the node.
240 * @param link the list node
243 _dbus_list_free_link (DBusList *link)
250 * Appends a value to the list. May return #FALSE
251 * if insufficient memory exists to add a list link.
252 * This is a constant-time operation.
254 * @param list address of the list head.
255 * @param data the value to append.
256 * @returns #TRUE on success.
259 _dbus_list_append (DBusList **list,
262 if (!_dbus_list_prepend (list, data))
265 /* Now cycle the list forward one so the prepended node is the tail */
266 *list = (*list)->next;
272 * Prepends a value to the list. May return #FALSE
273 * if insufficient memory exists to add a list link.
274 * This is a constant-time operation.
276 * @param list address of the list head.
277 * @param data the value to prepend.
278 * @returns #TRUE on success.
281 _dbus_list_prepend (DBusList **list,
286 link = alloc_link (data);
290 link_before (list, *list, link);
296 * Appends a link to the list.
297 * Cannot fail due to out of memory.
298 * This is a constant-time operation.
300 * @param list address of the list head.
301 * @param link the link to append.
304 _dbus_list_append_link (DBusList **list,
307 _dbus_list_prepend_link (list, link);
309 /* Now cycle the list forward one so the prepended node is the tail */
310 *list = (*list)->next;
314 * Prepends a link to the list.
315 * Cannot fail due to out of memory.
316 * This is a constant-time operation.
318 * @param list address of the list head.
319 * @param link the link to prepend.
322 _dbus_list_prepend_link (DBusList **list,
325 link_before (list, *list, link);
328 #ifdef DBUS_BUILD_TESTS
330 * Inserts data into the list before the given existing link.
332 * @param list the list to modify
333 * @param before_this_link existing link to insert before, or #NULL to append
334 * @param data the value to insert
335 * @returns #TRUE on success, #FALSE if memory allocation fails
338 _dbus_list_insert_before (DBusList **list,
339 DBusList *before_this_link,
344 if (before_this_link == NULL)
345 return _dbus_list_append (list, data);
348 link = alloc_link (data);
352 link_before (list, before_this_link, link);
357 #endif /* DBUS_BUILD_TESTS */
360 * Inserts data into the list after the given existing link.
362 * @param list the list to modify
363 * @param after_this_link existing link to insert after, or #NULL to prepend
364 * @param data the value to insert
365 * @returns #TRUE on success, #FALSE if memory allocation fails
368 _dbus_list_insert_after (DBusList **list,
369 DBusList *after_this_link,
374 if (after_this_link == NULL)
375 return _dbus_list_prepend (list, data);
378 link = alloc_link (data);
382 link_after (list, after_this_link, link);
389 * Inserts a link into the list before the given existing link.
391 * @param list the list to modify
392 * @param before_this_link existing link to insert before, or #NULL to append
393 * @param link the link to insert
396 _dbus_list_insert_before_link (DBusList **list,
397 DBusList *before_this_link,
400 if (before_this_link == NULL)
401 _dbus_list_append_link (list, link);
403 link_before (list, before_this_link, link);
407 * Inserts a link into the list after the given existing link.
409 * @param list the list to modify
410 * @param after_this_link existing link to insert after, or #NULL to prepend
411 * @param link the link to insert
414 _dbus_list_insert_after_link (DBusList **list,
415 DBusList *after_this_link,
418 if (after_this_link == NULL)
419 _dbus_list_prepend_link (list, link);
421 link_after (list, after_this_link, link);
425 * Removes a value from the list. Only removes the
426 * first value equal to the given data pointer,
427 * even if multiple values exist which match.
428 * This is a linear-time operation.
430 * @param list address of the list head.
431 * @param data the value to remove.
432 * @returns #TRUE if a value was found to remove.
435 _dbus_list_remove (DBusList **list,
443 if (link->data == data)
445 _dbus_list_remove_link (list, link);
449 link = _dbus_list_get_next_link (list, link);
456 * Removes a value from the list. Only removes the
457 * last value equal to the given data pointer,
458 * even if multiple values exist which match.
459 * This is a linear-time operation.
461 * @param list address of the list head.
462 * @param data the value to remove.
463 * @returns #TRUE if a value was found to remove.
466 _dbus_list_remove_last (DBusList **list,
471 link = _dbus_list_find_last (list, data);
474 _dbus_list_remove_link (list, link);
482 * Finds a value in the list. Returns the last link
483 * with value equal to the given data pointer.
484 * This is a linear-time operation.
485 * Returns #NULL if no value found that matches.
487 * @param list address of the list head.
488 * @param data the value to find.
489 * @returns the link if found
492 _dbus_list_find_last (DBusList **list,
497 link = _dbus_list_get_last_link (list);
501 if (link->data == data)
504 link = _dbus_list_get_prev_link (list, link);
511 * Removes the given link from the list, but doesn't
512 * free it. _dbus_list_remove_link() both removes the
513 * link and also frees it.
515 * @param list the list
516 * @param link the link in the list
519 _dbus_list_unlink (DBusList **list,
522 if (link->next == link)
524 /* one-element list */
529 link->prev->next = link->next;
530 link->next->prev = link->prev;
541 * Removes a link from the list. This is a constant-time operation.
543 * @param list address of the list head.
544 * @param link the list link to remove.
547 _dbus_list_remove_link (DBusList **list,
550 _dbus_list_unlink (list, link);
555 * Frees all links in the list and sets the list head to #NULL. Does
556 * not free the data in each link, for obvious reasons. This is a
557 * linear-time operation.
559 * @param list address of the list head.
562 _dbus_list_clear (DBusList **list)
569 DBusList *next = _dbus_list_get_next_link (list, link);
580 * Gets the first link in the list.
581 * This is a constant-time operation.
583 * @param list address of the list head.
584 * @returns the first link, or #NULL for an empty list.
587 _dbus_list_get_first_link (DBusList **list)
593 * Gets the last link in the list.
594 * This is a constant-time operation.
596 * @param list address of the list head.
597 * @returns the last link, or #NULL for an empty list.
600 _dbus_list_get_last_link (DBusList **list)
605 return (*list)->prev;
609 * Gets the last data in the list.
610 * This is a constant-time operation.
612 * @param list address of the list head.
613 * @returns the last data in the list, or #NULL for an empty list.
616 _dbus_list_get_last (DBusList **list)
621 return (*list)->prev->data;
625 * Gets the first data in the list.
626 * This is a constant-time operation.
628 * @param list address of the list head.
629 * @returns the first data in the list, or #NULL for an empty list.
632 _dbus_list_get_first (DBusList **list)
637 return (*list)->data;
641 * Removes the first link in the list and returns it. This is a
642 * constant-time operation.
644 * @param list address of the list head.
645 * @returns the first link in the list, or #NULL for an empty list.
648 _dbus_list_pop_first_link (DBusList **list)
652 link = _dbus_list_get_first_link (list);
656 _dbus_list_unlink (list, link);
662 * Removes the first value in the list and returns it. This is a
663 * constant-time operation.
665 * @param list address of the list head.
666 * @returns the first data in the list, or #NULL for an empty list.
669 _dbus_list_pop_first (DBusList **list)
674 link = _dbus_list_get_first_link (list);
679 _dbus_list_remove_link (list, link);
685 * Removes the last value in the list and returns it. This is a
686 * constant-time operation.
688 * @param list address of the list head.
689 * @returns the last data in the list, or #NULL for an empty list.
692 _dbus_list_pop_last (DBusList **list)
697 link = _dbus_list_get_last_link (list);
702 _dbus_list_remove_link (list, link);
707 #ifdef DBUS_BUILD_TESTS
709 * Removes the last link in the list and returns it. This is a
710 * constant-time operation.
712 * @param list address of the list head.
713 * @returns the last link in the list, or #NULL for an empty list.
716 _dbus_list_pop_last_link (DBusList **list)
720 link = _dbus_list_get_last_link (list);
724 _dbus_list_unlink (list, link);
728 #endif /* DBUS_BUILD_TESTS */
731 * Copies a list. This is a linear-time operation. If there isn't
732 * enough memory to copy the entire list, the destination list will be
735 * @param list address of the head of the list to copy.
736 * @param dest address where the copied list should be placed.
737 * @returns #TRUE on success, #FALSE if not enough memory.
740 _dbus_list_copy (DBusList **list,
745 _dbus_assert (list != dest);
752 if (!_dbus_list_append (dest, link->data))
754 /* free what we have so far */
755 _dbus_list_clear (dest);
759 link = _dbus_list_get_next_link (list, link);
766 * Gets the length of a list. This is a linear-time
769 * @param list address of the head of the list
770 * @returns number of elements in the list.
773 _dbus_list_get_length (DBusList **list)
785 link = _dbus_list_get_next_link (list, link);
792 * Calls the given function for each element in the list. The
793 * function is passed the list element as its first argument, and the
794 * given data as its second argument.
796 * @param list address of the head of the list.
797 * @param function function to call for each element.
798 * @param data extra data for the function.
802 _dbus_list_foreach (DBusList **list,
803 DBusForeachFunction function,
811 DBusList *next = _dbus_list_get_next_link (list, link);
813 (* function) (link->data, data);
820 * Check whether length is exactly one.
822 * @param list the list
823 * @returns #TRUE if length is exactly one
826 _dbus_list_length_is_one (DBusList **list)
828 return (*list != NULL &&
829 (*list)->next == *list);
834 #ifdef DBUS_BUILD_TESTS
835 #include "dbus-test.h"
839 verify_list (DBusList **list)
849 if (link->next == link)
851 _dbus_assert (link->prev == link);
852 _dbus_assert (*list == link);
860 _dbus_assert (link->prev->next == link);
861 _dbus_assert (link->next->prev == link);
864 while (link != *list);
866 _dbus_assert (length == _dbus_list_get_length (list));
869 _dbus_assert (_dbus_list_length_is_one (list));
871 _dbus_assert (!_dbus_list_length_is_one (list));
875 is_ascending_sequence (DBusList **list)
880 prev = _DBUS_INT_MIN;
882 link = _dbus_list_get_first_link (list);
885 int v = _DBUS_POINTER_TO_INT (link->data);
892 link = _dbus_list_get_next_link (list, link);
899 is_descending_sequence (DBusList **list)
904 prev = _DBUS_INT_MAX;
906 link = _dbus_list_get_first_link (list);
909 int v = _DBUS_POINTER_TO_INT (link->data);
916 link = _dbus_list_get_next_link (list, link);
923 all_even_values (DBusList **list)
927 link = _dbus_list_get_first_link (list);
930 int v = _DBUS_POINTER_TO_INT (link->data);
935 link = _dbus_list_get_next_link (list, link);
942 all_odd_values (DBusList **list)
946 link = _dbus_list_get_first_link (list);
949 int v = _DBUS_POINTER_TO_INT (link->data);
954 link = _dbus_list_get_next_link (list, link);
961 lists_equal (DBusList **list1,
967 link1 = _dbus_list_get_first_link (list1);
968 link2 = _dbus_list_get_first_link (list2);
969 while (link1 && link2)
971 if (link1->data != link2->data)
974 link1 = _dbus_list_get_next_link (list1, link1);
975 link2 = _dbus_list_get_next_link (list2, link2);
985 * @ingroup DBusListInternals
986 * Unit test for DBusList
987 * @returns #TRUE on success.
990 _dbus_list_test (void)
1003 /* Test append and prepend */
1008 if (!_dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i)))
1009 _dbus_assert_not_reached ("could not allocate for append");
1011 if (!_dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i)))
1012 _dbus_assert_not_reached ("count not allocate for prepend");
1015 verify_list (&list1);
1016 verify_list (&list2);
1018 _dbus_assert (_dbus_list_get_length (&list1) == i);
1019 _dbus_assert (_dbus_list_get_length (&list2) == i);
1022 _dbus_assert (is_ascending_sequence (&list1));
1023 _dbus_assert (is_descending_sequence (&list2));
1025 /* Test list clear */
1026 _dbus_list_clear (&list1);
1027 _dbus_list_clear (&list2);
1029 verify_list (&list1);
1030 verify_list (&list2);
1032 /* Test get_first, get_last, pop_first, pop_last */
1037 _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i));
1038 _dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i));
1051 got_data1 = _dbus_list_get_last (&list1);
1052 got_data2 = _dbus_list_get_first (&list2);
1054 data1 = _dbus_list_pop_last (&list1);
1055 data2 = _dbus_list_pop_first (&list2);
1057 _dbus_assert (got_data1 == data1);
1058 _dbus_assert (got_data2 == data2);
1060 _dbus_assert (_DBUS_POINTER_TO_INT (data1) == i);
1061 _dbus_assert (_DBUS_POINTER_TO_INT (data2) == i);
1063 verify_list (&list1);
1064 verify_list (&list2);
1066 _dbus_assert (is_ascending_sequence (&list1));
1067 _dbus_assert (is_descending_sequence (&list2));
1072 _dbus_assert (list1 == NULL);
1073 _dbus_assert (list2 == NULL);
1075 /* Test get_first_link, get_last_link, pop_first_link, pop_last_link */
1080 _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i));
1081 _dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i));
1088 DBusList *got_link1;
1089 DBusList *got_link2;
1097 got_link1 = _dbus_list_get_last_link (&list1);
1098 got_link2 = _dbus_list_get_first_link (&list2);
1100 link1 = _dbus_list_pop_last_link (&list1);
1101 link2 = _dbus_list_pop_first_link (&list2);
1103 _dbus_assert (got_link1 == link1);
1104 _dbus_assert (got_link2 == link2);
1106 data1 = link1->data;
1107 data2 = link2->data;
1109 _dbus_list_free_link (link1);
1110 _dbus_list_free_link (link2);
1112 _dbus_assert (_DBUS_POINTER_TO_INT (data1) == i);
1113 _dbus_assert (_DBUS_POINTER_TO_INT (data2) == i);
1115 verify_list (&list1);
1116 verify_list (&list2);
1118 _dbus_assert (is_ascending_sequence (&list1));
1119 _dbus_assert (is_descending_sequence (&list2));
1124 _dbus_assert (list1 == NULL);
1125 _dbus_assert (list2 == NULL);
1127 /* Test iteration */
1132 _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i));
1133 _dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i));
1136 verify_list (&list1);
1137 verify_list (&list2);
1139 _dbus_assert (_dbus_list_get_length (&list1) == i);
1140 _dbus_assert (_dbus_list_get_length (&list2) == i);
1143 _dbus_assert (is_ascending_sequence (&list1));
1144 _dbus_assert (is_descending_sequence (&list2));
1147 link2 = _dbus_list_get_first_link (&list2);
1148 while (link2 != NULL)
1150 verify_list (&link2); /* pretend this link is the head */
1152 _dbus_assert (_DBUS_POINTER_TO_INT (link2->data) == i);
1154 link2 = _dbus_list_get_next_link (&list2, link2);
1159 link1 = _dbus_list_get_first_link (&list1);
1160 while (link1 != NULL)
1162 verify_list (&link1); /* pretend this link is the head */
1164 _dbus_assert (_DBUS_POINTER_TO_INT (link1->data) == i);
1166 link1 = _dbus_list_get_next_link (&list1, link1);
1171 link1 = _dbus_list_get_last_link (&list1);
1172 while (link1 != NULL)
1174 verify_list (&link1); /* pretend this link is the head */
1176 _dbus_assert (_DBUS_POINTER_TO_INT (link1->data) == i);
1178 link1 = _dbus_list_get_prev_link (&list1, link1);
1182 _dbus_list_clear (&list1);
1183 _dbus_list_clear (&list2);
1190 _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i));
1191 _dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i));
1200 if (!_dbus_list_remove (&list1, _DBUS_INT_TO_POINTER (i)))
1201 _dbus_assert_not_reached ("element should have been in list");
1202 if (!_dbus_list_remove (&list2, _DBUS_INT_TO_POINTER (i)))
1203 _dbus_assert_not_reached ("element should have been in list");
1205 verify_list (&list1);
1206 verify_list (&list2);
1211 _dbus_assert (all_odd_values (&list1));
1212 _dbus_assert (all_odd_values (&list2));
1214 _dbus_list_clear (&list1);
1215 _dbus_list_clear (&list2);
1217 /* test removing the other half of the elements */
1222 _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i));
1223 _dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i));
1232 if (!_dbus_list_remove (&list1, _DBUS_INT_TO_POINTER (i)))
1233 _dbus_assert_not_reached ("element should have been in list");
1234 if (!_dbus_list_remove (&list2, _DBUS_INT_TO_POINTER (i)))
1235 _dbus_assert_not_reached ("element should have been in list");
1237 verify_list (&list1);
1238 verify_list (&list2);
1243 _dbus_assert (all_even_values (&list1));
1244 _dbus_assert (all_even_values (&list2));
1246 /* clear list using remove_link */
1247 while (list1 != NULL)
1249 _dbus_list_remove_link (&list1, list1);
1250 verify_list (&list1);
1252 while (list2 != NULL)
1254 _dbus_list_remove_link (&list2, list2);
1255 verify_list (&list2);
1258 /* Test remove link more generally */
1262 _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i));
1263 _dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i));
1268 link2 = _dbus_list_get_first_link (&list2);
1269 while (link2 != NULL)
1271 DBusList *next = _dbus_list_get_next_link (&list2, link2);
1273 _dbus_assert (_DBUS_POINTER_TO_INT (link2->data) == i);
1276 _dbus_list_remove_link (&list2, link2);
1278 verify_list (&list2);
1284 _dbus_assert (all_odd_values (&list2));
1285 _dbus_list_clear (&list2);
1288 link1 = _dbus_list_get_first_link (&list1);
1289 while (link1 != NULL)
1291 DBusList *next = _dbus_list_get_next_link (&list1, link1);
1293 _dbus_assert (_DBUS_POINTER_TO_INT (link1->data) == i);
1296 _dbus_list_remove_link (&list1, link1);
1298 verify_list (&list1);
1304 _dbus_assert (all_even_values (&list1));
1305 _dbus_list_clear (&list1);
1307 /* Test copying a list */
1311 _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i));
1312 _dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i));
1316 /* bad pointers, because they are allowed in the copy dest */
1317 copy1 = _DBUS_INT_TO_POINTER (0x342234);
1318 copy2 = _DBUS_INT_TO_POINTER (23);
1320 _dbus_list_copy (&list1, ©1);
1321 verify_list (&list1);
1322 verify_list (©1);
1323 _dbus_assert (lists_equal (&list1, ©1));
1325 _dbus_list_copy (&list2, ©2);
1326 verify_list (&list2);
1327 verify_list (©2);
1328 _dbus_assert (lists_equal (&list2, ©2));
1330 /* Now test copying empty lists */
1331 _dbus_list_clear (&list1);
1332 _dbus_list_clear (&list2);
1333 _dbus_list_clear (©1);
1334 _dbus_list_clear (©2);
1336 /* bad pointers, because they are allowed in the copy dest */
1337 copy1 = _DBUS_INT_TO_POINTER (0x342234);
1338 copy2 = _DBUS_INT_TO_POINTER (23);
1340 _dbus_list_copy (&list1, ©1);
1341 verify_list (&list1);
1342 verify_list (©1);
1343 _dbus_assert (lists_equal (&list1, ©1));
1345 _dbus_list_copy (&list2, ©2);
1346 verify_list (&list2);
1347 verify_list (©2);
1348 _dbus_assert (lists_equal (&list2, ©2));
1350 _dbus_list_clear (&list1);
1351 _dbus_list_clear (&list2);
1353 /* insert_before on empty list */
1354 _dbus_list_insert_before (&list1, NULL,
1355 _DBUS_INT_TO_POINTER (0));
1356 verify_list (&list1);
1358 /* inserting before first element */
1359 _dbus_list_insert_before (&list1, list1,
1360 _DBUS_INT_TO_POINTER (2));
1361 verify_list (&list1);
1362 _dbus_assert (is_descending_sequence (&list1));
1364 /* inserting in the middle */
1365 _dbus_list_insert_before (&list1, list1->next,
1366 _DBUS_INT_TO_POINTER (1));
1367 verify_list (&list1);
1368 _dbus_assert (is_descending_sequence (&list1));
1370 /* using insert_before to append */
1371 _dbus_list_insert_before (&list1, NULL,
1372 _DBUS_INT_TO_POINTER (-1));
1373 verify_list (&list1);
1374 _dbus_assert (is_descending_sequence (&list1));
1376 _dbus_list_clear (&list1);
1378 /* insert_after on empty list */
1379 _dbus_list_insert_after (&list1, NULL,
1380 _DBUS_INT_TO_POINTER (0));
1381 verify_list (&list1);
1383 /* inserting after first element */
1384 _dbus_list_insert_after (&list1, list1,
1385 _DBUS_INT_TO_POINTER (1));
1386 verify_list (&list1);
1387 _dbus_assert (is_ascending_sequence (&list1));
1389 /* inserting at the end */
1390 _dbus_list_insert_after (&list1, list1->next,
1391 _DBUS_INT_TO_POINTER (2));
1392 verify_list (&list1);
1393 _dbus_assert (is_ascending_sequence (&list1));
1395 /* using insert_after to prepend */
1396 _dbus_list_insert_after (&list1, NULL,
1397 _DBUS_INT_TO_POINTER (-1));
1398 verify_list (&list1);
1399 _dbus_assert (is_ascending_sequence (&list1));
1401 _dbus_list_clear (&list1);
1403 /* using remove_last */
1404 _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (2));
1405 _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (1));
1406 _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (3));
1408 _dbus_list_remove_last (&list1, _DBUS_INT_TO_POINTER (2));
1410 verify_list (&list1);
1411 _dbus_assert (is_ascending_sequence (&list1));
1413 _dbus_list_clear (&list1);