D-Bus  1.5.8
dbus-list.c
00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
00002 /* dbus-list.c Generic linked list utility (internal to D-Bus implementation)
00003  * 
00004  * Copyright (C) 2002  Red Hat, Inc.
00005  *
00006  * Licensed under the Academic Free License version 2.1
00007  * 
00008  * This program is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * This program is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  * 
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program; if not, write to the Free Software
00020  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00021  *
00022  */
00023 
00024 #include <config.h>
00025 #include "dbus-internals.h"
00026 #include "dbus-list.h"
00027 #include "dbus-mempool.h"
00028 #include "dbus-threads-internal.h"
00029 
00038 static DBusMemPool *list_pool;
00039 _DBUS_DEFINE_GLOBAL_LOCK (list);
00040 
00051 /* the mem pool is probably a speed hit, with the thread
00052  * lock, though it does still save memory - unknown.
00053  */
00054 static DBusList*
00055 alloc_link (void *data)
00056 {
00057   DBusList *link;
00058 
00059   _DBUS_LOCK (list);
00060 
00061   if (list_pool == NULL)
00062     {      
00063       list_pool = _dbus_mem_pool_new (sizeof (DBusList), TRUE);
00064 
00065       if (list_pool == NULL)
00066         {
00067           _DBUS_UNLOCK (list);
00068           return NULL;
00069         }
00070 
00071       link = _dbus_mem_pool_alloc (list_pool);
00072       if (link == NULL)
00073         {
00074           _dbus_mem_pool_free (list_pool);
00075           list_pool = NULL;
00076           _DBUS_UNLOCK (list);
00077           return NULL;
00078         }
00079     }
00080   else
00081     {
00082       link = _dbus_mem_pool_alloc (list_pool);
00083     }
00084 
00085   if (link)
00086     link->data = data;
00087   
00088   _DBUS_UNLOCK (list);
00089 
00090   return link;
00091 }
00092 
00093 static void
00094 free_link (DBusList *link)
00095 {  
00096   _DBUS_LOCK (list);
00097   if (_dbus_mem_pool_dealloc (list_pool, link))
00098     {
00099       _dbus_mem_pool_free (list_pool);
00100       list_pool = NULL;
00101     }
00102   
00103   _DBUS_UNLOCK (list);
00104 }
00105 
00106 static void
00107 link_before (DBusList **list,
00108              DBusList  *before_this_link,
00109              DBusList  *link)
00110 {
00111   if (*list == NULL)
00112     {
00113       link->prev = link;
00114       link->next = link;
00115       *list = link;
00116     }
00117   else
00118     {      
00119       link->next = before_this_link;
00120       link->prev = before_this_link->prev;
00121       before_this_link->prev = link;
00122       link->prev->next = link;
00123       
00124       if (before_this_link == *list)
00125         *list = link;
00126     }
00127 }
00128 
00129 static void
00130 link_after (DBusList **list,
00131             DBusList  *after_this_link,
00132             DBusList  *link)
00133 {
00134   if (*list == NULL)
00135     {
00136       link->prev = link;
00137       link->next = link;
00138       *list = link;
00139     }
00140   else
00141     {
00142       link->prev = after_this_link;
00143       link->next = after_this_link->next;
00144       after_this_link->next = link;
00145       link->next->prev = link;
00146     }
00147 }
00148 
00149 #ifdef DBUS_ENABLE_STATS
00150 void
00151 _dbus_list_get_stats     (dbus_uint32_t *in_use_p,
00152                           dbus_uint32_t *in_free_list_p,
00153                           dbus_uint32_t *allocated_p)
00154 {
00155   _DBUS_LOCK (list);
00156   _dbus_mem_pool_get_stats (list_pool, in_use_p, in_free_list_p, allocated_p);
00157   _DBUS_UNLOCK (list);
00158 }
00159 #endif
00160 
00230 DBusList*
00231 _dbus_list_alloc_link (void *data)
00232 {
00233   return alloc_link (data);
00234 }
00235 
00242 void
00243 _dbus_list_free_link (DBusList *link)
00244 {
00245   free_link (link);
00246 }
00247 
00248 
00258 dbus_bool_t
00259 _dbus_list_append (DBusList **list,
00260                    void      *data)
00261 {
00262   if (!_dbus_list_prepend (list, data))
00263     return FALSE;
00264 
00265   /* Now cycle the list forward one so the prepended node is the tail */
00266   *list = (*list)->next;
00267 
00268   return TRUE;
00269 }
00270 
00280 dbus_bool_t
00281 _dbus_list_prepend (DBusList **list,
00282                     void      *data)
00283 {
00284   DBusList *link;
00285 
00286   link = alloc_link (data);
00287   if (link == NULL)
00288     return FALSE;
00289 
00290   link_before (list, *list, link);
00291 
00292   return TRUE;
00293 }
00294 
00303 void
00304 _dbus_list_append_link (DBusList **list,
00305                         DBusList *link)
00306 {
00307   _dbus_list_prepend_link (list, link);
00308 
00309   /* Now cycle the list forward one so the prepended node is the tail */
00310   *list = (*list)->next;
00311 }
00312 
00321 void
00322 _dbus_list_prepend_link (DBusList **list,
00323                          DBusList *link)
00324 {
00325   link_before (list, *list, link);
00326 }
00327 
00328 #ifdef DBUS_BUILD_TESTS
00329 
00337 dbus_bool_t
00338 _dbus_list_insert_before (DBusList **list,
00339                           DBusList  *before_this_link,
00340                           void      *data)
00341 {
00342   DBusList *link;
00343   
00344   if (before_this_link == NULL)
00345     return _dbus_list_append (list, data);
00346   else
00347     {
00348       link = alloc_link (data);
00349       if (link == NULL)
00350         return FALSE;
00351   
00352       link_before (list, before_this_link, link);
00353     }
00354   
00355   return TRUE;
00356 }
00357 #endif /* DBUS_BUILD_TESTS */
00358 
00367 dbus_bool_t
00368 _dbus_list_insert_after (DBusList **list,
00369                          DBusList  *after_this_link,
00370                          void      *data)
00371 {
00372   DBusList *link;  
00373 
00374   if (after_this_link == NULL)
00375     return _dbus_list_prepend (list, data);
00376   else
00377     {
00378       link = alloc_link (data);
00379       if (link == NULL)
00380         return FALSE;
00381   
00382       link_after (list, after_this_link, link);
00383     }
00384   
00385   return TRUE;
00386 }
00387 
00395 void
00396 _dbus_list_insert_before_link (DBusList **list,
00397                                DBusList  *before_this_link,
00398                                DBusList  *link)
00399 {
00400   if (before_this_link == NULL)
00401     _dbus_list_append_link (list, link);
00402   else
00403     link_before (list, before_this_link, link);
00404 }
00405 
00413 void
00414 _dbus_list_insert_after_link (DBusList **list,
00415                               DBusList  *after_this_link,
00416                               DBusList  *link)
00417 {
00418   if (after_this_link == NULL)
00419     _dbus_list_prepend_link (list, link);
00420   else  
00421     link_after (list, after_this_link, link);
00422 }
00423 
00434 dbus_bool_t
00435 _dbus_list_remove (DBusList **list,
00436                    void      *data)
00437 {
00438   DBusList *link;
00439 
00440   link = *list;
00441   while (link != NULL)
00442     {
00443       if (link->data == data)
00444         {
00445           _dbus_list_remove_link (list, link);
00446           return TRUE;
00447         }
00448       
00449       link = _dbus_list_get_next_link (list, link);
00450     }
00451 
00452   return FALSE;
00453 }
00454 
00465 dbus_bool_t
00466 _dbus_list_remove_last (DBusList **list,
00467                         void      *data)
00468 {
00469   DBusList *link;
00470 
00471   link = _dbus_list_find_last (list, data);
00472   if (link)
00473     {
00474       _dbus_list_remove_link (list, link);
00475       return TRUE;
00476     }
00477   else
00478     return FALSE;
00479 }
00480 
00491 DBusList*
00492 _dbus_list_find_last (DBusList **list,
00493                       void      *data)
00494 {
00495   DBusList *link;
00496 
00497   link = _dbus_list_get_last_link (list);
00498 
00499   while (link != NULL)
00500     {
00501       if (link->data == data)
00502         return link;
00503       
00504       link = _dbus_list_get_prev_link (list, link);
00505     }
00506 
00507   return NULL;
00508 }
00509 
00518 void
00519 _dbus_list_unlink (DBusList **list,
00520                    DBusList  *link)
00521 {
00522   if (link->next == link)
00523     {
00524       /* one-element list */
00525       *list = NULL;
00526     }
00527   else
00528     {      
00529       link->prev->next = link->next;
00530       link->next->prev = link->prev;
00531       
00532       if (*list == link)
00533         *list = link->next;
00534     }
00535 
00536   link->next = NULL;
00537   link->prev = NULL;
00538 }
00539 
00546 void
00547 _dbus_list_remove_link (DBusList **list,
00548                         DBusList  *link)
00549 {
00550   _dbus_list_unlink (list, link);
00551   free_link (link);
00552 }
00553 
00561 void
00562 _dbus_list_clear (DBusList **list)
00563 {
00564   DBusList *link;
00565 
00566   link = *list;
00567   while (link != NULL)
00568     {
00569       DBusList *next = _dbus_list_get_next_link (list, link);
00570       
00571       free_link (link);
00572       
00573       link = next;
00574     }
00575 
00576   *list = NULL;
00577 }
00578 
00586 DBusList*
00587 _dbus_list_get_first_link (DBusList **list)
00588 {
00589   return *list;
00590 }
00591 
00599 DBusList*
00600 _dbus_list_get_last_link (DBusList **list)
00601 {
00602   if (*list == NULL)
00603     return NULL;
00604   else
00605     return (*list)->prev;
00606 }
00607 
00615 void*
00616 _dbus_list_get_last (DBusList **list)
00617 {
00618   if (*list == NULL)
00619     return NULL;
00620   else
00621     return (*list)->prev->data;
00622 }
00623 
00631 void*
00632 _dbus_list_get_first (DBusList **list)
00633 {
00634   if (*list == NULL)
00635     return NULL;
00636   else
00637     return (*list)->data;
00638 }
00639 
00647 DBusList*
00648 _dbus_list_pop_first_link (DBusList **list)
00649 {
00650   DBusList *link;
00651   
00652   link = _dbus_list_get_first_link (list);
00653   if (link == NULL)
00654     return NULL;
00655 
00656   _dbus_list_unlink (list, link);
00657 
00658   return link;
00659 }
00660 
00668 void*
00669 _dbus_list_pop_first (DBusList **list)
00670 {
00671   DBusList *link;
00672   void *data;
00673   
00674   link = _dbus_list_get_first_link (list);
00675   if (link == NULL)
00676     return NULL;
00677   
00678   data = link->data;
00679   _dbus_list_remove_link (list, link);
00680 
00681   return data;
00682 }
00683 
00691 void*
00692 _dbus_list_pop_last (DBusList **list)
00693 {
00694   DBusList *link;
00695   void *data;
00696   
00697   link = _dbus_list_get_last_link (list);
00698   if (link == NULL)
00699     return NULL;
00700   
00701   data = link->data;
00702   _dbus_list_remove_link (list, link);
00703 
00704   return data;
00705 }
00706 
00707 #ifdef DBUS_BUILD_TESTS
00708 
00715 DBusList*
00716 _dbus_list_pop_last_link (DBusList **list)
00717 {
00718   DBusList *link;
00719   
00720   link = _dbus_list_get_last_link (list);
00721   if (link == NULL)
00722     return NULL;
00723 
00724   _dbus_list_unlink (list, link);
00725 
00726   return link;
00727 }
00728 #endif /* DBUS_BUILD_TESTS */
00729 
00739 dbus_bool_t
00740 _dbus_list_copy (DBusList **list,
00741                  DBusList **dest)
00742 {
00743   DBusList *link;
00744 
00745   _dbus_assert (list != dest);
00746 
00747   *dest = NULL;
00748   
00749   link = *list;
00750   while (link != NULL)
00751     {
00752       if (!_dbus_list_append (dest, link->data))
00753         {
00754           /* free what we have so far */
00755           _dbus_list_clear (dest);
00756           return FALSE;
00757         }
00758       
00759       link = _dbus_list_get_next_link (list, link);
00760     }
00761 
00762   return TRUE;
00763 }
00764 
00772 int
00773 _dbus_list_get_length (DBusList **list)
00774 {
00775   DBusList *link;
00776   int length;
00777 
00778   length = 0;
00779   
00780   link = *list;
00781   while (link != NULL)
00782     {
00783       ++length;
00784       
00785       link = _dbus_list_get_next_link (list, link);
00786     }
00787 
00788   return length;
00789 }
00790 
00801 void
00802 _dbus_list_foreach (DBusList          **list,
00803                     DBusForeachFunction function,
00804                     void               *data)
00805 {
00806   DBusList *link;
00807 
00808   link = *list;
00809   while (link != NULL)
00810     {
00811       DBusList *next = _dbus_list_get_next_link (list, link);
00812       
00813       (* function) (link->data, data);
00814       
00815       link = next;
00816     }
00817 }
00818 
00825 dbus_bool_t
00826 _dbus_list_length_is_one (DBusList **list)
00827 {
00828   return (*list != NULL &&
00829           (*list)->next == *list);
00830 }
00831 
00834 #ifdef DBUS_BUILD_TESTS
00835 #include "dbus-test.h"
00836 #include <stdio.h>
00837 
00838 static void
00839 verify_list (DBusList **list)
00840 {
00841   DBusList *link;
00842   int length;
00843   
00844   link = *list;
00845 
00846   if (link == NULL)
00847     return;
00848 
00849   if (link->next == link)
00850     {
00851       _dbus_assert (link->prev == link);
00852       _dbus_assert (*list == link);
00853       return;
00854     }
00855 
00856   length = 0;
00857   do
00858     {
00859       length += 1;
00860       _dbus_assert (link->prev->next == link);
00861       _dbus_assert (link->next->prev == link);
00862       link = link->next;
00863     }
00864   while (link != *list);
00865 
00866   _dbus_assert (length == _dbus_list_get_length (list));
00867 
00868   if (length == 1)
00869     _dbus_assert (_dbus_list_length_is_one (list));
00870   else
00871     _dbus_assert (!_dbus_list_length_is_one (list));
00872 }
00873 
00874 static dbus_bool_t
00875 is_ascending_sequence (DBusList **list)
00876 {
00877   DBusList *link;
00878   int prev;
00879 
00880   prev = _DBUS_INT_MIN;
00881   
00882   link = _dbus_list_get_first_link (list);
00883   while (link != NULL)
00884     {
00885       int v = _DBUS_POINTER_TO_INT (link->data);
00886       
00887       if (v <= prev)
00888         return FALSE;
00889 
00890       prev = v;
00891       
00892       link = _dbus_list_get_next_link (list, link);
00893     }
00894 
00895   return TRUE;
00896 }
00897 
00898 static dbus_bool_t
00899 is_descending_sequence (DBusList **list)
00900 {
00901   DBusList *link;
00902   int prev;
00903 
00904   prev = _DBUS_INT_MAX;
00905   
00906   link = _dbus_list_get_first_link (list);
00907   while (link != NULL)
00908     {
00909       int v = _DBUS_POINTER_TO_INT (link->data);
00910 
00911       if (v >= prev)
00912         return FALSE;
00913 
00914       prev = v;
00915       
00916       link = _dbus_list_get_next_link (list, link);
00917     }
00918 
00919   return TRUE;
00920 }
00921 
00922 static dbus_bool_t
00923 all_even_values (DBusList **list)
00924 {
00925   DBusList *link;
00926   
00927   link = _dbus_list_get_first_link (list);
00928   while (link != NULL)
00929     {
00930       int v = _DBUS_POINTER_TO_INT (link->data);
00931 
00932       if ((v % 2) != 0)
00933         return FALSE;
00934       
00935       link = _dbus_list_get_next_link (list, link);
00936     }
00937 
00938   return TRUE;
00939 }
00940 
00941 static dbus_bool_t
00942 all_odd_values (DBusList **list)
00943 {
00944   DBusList *link;
00945   
00946   link = _dbus_list_get_first_link (list);
00947   while (link != NULL)
00948     {
00949       int v = _DBUS_POINTER_TO_INT (link->data);
00950 
00951       if ((v % 2) == 0)
00952         return FALSE;
00953       
00954       link = _dbus_list_get_next_link (list, link);
00955     }
00956 
00957   return TRUE;
00958 }
00959 
00960 static dbus_bool_t
00961 lists_equal (DBusList **list1,
00962              DBusList **list2)
00963 {
00964   DBusList *link1;
00965   DBusList *link2;
00966   
00967   link1 = _dbus_list_get_first_link (list1);
00968   link2 = _dbus_list_get_first_link (list2);
00969   while (link1 && link2)
00970     {
00971       if (link1->data != link2->data)
00972         return FALSE;
00973       
00974       link1 = _dbus_list_get_next_link (list1, link1);
00975       link2 = _dbus_list_get_next_link (list2, link2);
00976     }
00977 
00978   if (link1 || link2)
00979     return FALSE;
00980 
00981   return TRUE;
00982 }
00983 
00989 dbus_bool_t
00990 _dbus_list_test (void)
00991 {
00992   DBusList *list1;
00993   DBusList *list2;
00994   DBusList *link1;
00995   DBusList *link2;
00996   DBusList *copy1;
00997   DBusList *copy2;
00998   int i;
00999   
01000   list1 = NULL;
01001   list2 = NULL;
01002 
01003   /* Test append and prepend */
01004   
01005   i = 0;
01006   while (i < 10)
01007     {
01008       if (!_dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i)))
01009         _dbus_assert_not_reached ("could not allocate for append");
01010       
01011       if (!_dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i)))
01012         _dbus_assert_not_reached ("count not allocate for prepend");
01013       ++i;
01014 
01015       verify_list (&list1);
01016       verify_list (&list2);
01017       
01018       _dbus_assert (_dbus_list_get_length (&list1) == i);
01019       _dbus_assert (_dbus_list_get_length (&list2) == i);
01020     }
01021 
01022   _dbus_assert (is_ascending_sequence (&list1));
01023   _dbus_assert (is_descending_sequence (&list2));
01024 
01025   /* Test list clear */
01026   _dbus_list_clear (&list1);
01027   _dbus_list_clear (&list2);
01028 
01029   verify_list (&list1);
01030   verify_list (&list2);
01031 
01032   /* Test get_first, get_last, pop_first, pop_last */
01033   
01034   i = 0;
01035   while (i < 10)
01036     {
01037       _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i));
01038       _dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i));
01039       ++i;
01040     }
01041 
01042   --i;
01043   while (i >= 0)
01044     {
01045       void *got_data1;
01046       void *got_data2;
01047       
01048       void *data1;
01049       void *data2;
01050 
01051       got_data1 = _dbus_list_get_last (&list1);
01052       got_data2 = _dbus_list_get_first (&list2);
01053       
01054       data1 = _dbus_list_pop_last (&list1);
01055       data2 = _dbus_list_pop_first (&list2);
01056 
01057       _dbus_assert (got_data1 == data1);
01058       _dbus_assert (got_data2 == data2);
01059       
01060       _dbus_assert (_DBUS_POINTER_TO_INT (data1) == i);
01061       _dbus_assert (_DBUS_POINTER_TO_INT (data2) == i);
01062 
01063       verify_list (&list1);
01064       verify_list (&list2);
01065 
01066       _dbus_assert (is_ascending_sequence (&list1));
01067       _dbus_assert (is_descending_sequence (&list2));
01068       
01069       --i;
01070     }
01071 
01072   _dbus_assert (list1 == NULL);
01073   _dbus_assert (list2 == NULL);
01074 
01075   /* Test get_first_link, get_last_link, pop_first_link, pop_last_link */
01076   
01077   i = 0;
01078   while (i < 10)
01079     {
01080       _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i));
01081       _dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i));
01082       ++i;
01083     }
01084 
01085   --i;
01086   while (i >= 0)
01087     {
01088       DBusList *got_link1;
01089       DBusList *got_link2;
01090 
01091       DBusList *link1;
01092       DBusList *link2;
01093       
01094       void *data1;
01095       void *data2;
01096       
01097       got_link1 = _dbus_list_get_last_link (&list1);
01098       got_link2 = _dbus_list_get_first_link (&list2);
01099       
01100       link1 = _dbus_list_pop_last_link (&list1);
01101       link2 = _dbus_list_pop_first_link (&list2);
01102 
01103       _dbus_assert (got_link1 == link1);
01104       _dbus_assert (got_link2 == link2);
01105 
01106       data1 = link1->data;
01107       data2 = link2->data;
01108 
01109       _dbus_list_free_link (link1);
01110       _dbus_list_free_link (link2);
01111       
01112       _dbus_assert (_DBUS_POINTER_TO_INT (data1) == i);
01113       _dbus_assert (_DBUS_POINTER_TO_INT (data2) == i);
01114 
01115       verify_list (&list1);
01116       verify_list (&list2);
01117 
01118       _dbus_assert (is_ascending_sequence (&list1));
01119       _dbus_assert (is_descending_sequence (&list2));
01120       
01121       --i;
01122     }
01123 
01124   _dbus_assert (list1 == NULL);
01125   _dbus_assert (list2 == NULL);
01126   
01127   /* Test iteration */
01128   
01129   i = 0;
01130   while (i < 10)
01131     {
01132       _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i));
01133       _dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i));
01134       ++i;
01135 
01136       verify_list (&list1);
01137       verify_list (&list2);
01138       
01139       _dbus_assert (_dbus_list_get_length (&list1) == i);
01140       _dbus_assert (_dbus_list_get_length (&list2) == i);
01141     }
01142 
01143   _dbus_assert (is_ascending_sequence (&list1));
01144   _dbus_assert (is_descending_sequence (&list2));
01145 
01146   --i;
01147   link2 = _dbus_list_get_first_link (&list2);
01148   while (link2 != NULL)
01149     {
01150       verify_list (&link2); /* pretend this link is the head */
01151       
01152       _dbus_assert (_DBUS_POINTER_TO_INT (link2->data) == i);
01153       
01154       link2 = _dbus_list_get_next_link (&list2, link2);
01155       --i;
01156     }
01157 
01158   i = 0;
01159   link1 = _dbus_list_get_first_link (&list1);
01160   while (link1 != NULL)
01161     {
01162       verify_list (&link1); /* pretend this link is the head */
01163       
01164       _dbus_assert (_DBUS_POINTER_TO_INT (link1->data) == i);
01165       
01166       link1 = _dbus_list_get_next_link (&list1, link1);
01167       ++i;
01168     }
01169 
01170   --i;
01171   link1 = _dbus_list_get_last_link (&list1);
01172   while (link1 != NULL)
01173     {
01174       verify_list (&link1); /* pretend this link is the head */
01175 
01176       _dbus_assert (_DBUS_POINTER_TO_INT (link1->data) == i);
01177       
01178       link1 = _dbus_list_get_prev_link (&list1, link1);
01179       --i;
01180     }
01181 
01182   _dbus_list_clear (&list1);
01183   _dbus_list_clear (&list2);
01184 
01185   /* Test remove */
01186   
01187   i = 0;
01188   while (i < 10)
01189     {
01190       _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i));
01191       _dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i));
01192       ++i;
01193     }
01194 
01195   --i;
01196   while (i >= 0)
01197     {
01198       if ((i % 2) == 0)
01199         {
01200           if (!_dbus_list_remove (&list1, _DBUS_INT_TO_POINTER (i)))
01201             _dbus_assert_not_reached ("element should have been in list");
01202           if (!_dbus_list_remove (&list2, _DBUS_INT_TO_POINTER (i)))
01203             _dbus_assert_not_reached ("element should have been in list");
01204 
01205           verify_list (&list1);
01206           verify_list (&list2);
01207         }
01208       --i;
01209     }
01210 
01211   _dbus_assert (all_odd_values (&list1));
01212   _dbus_assert (all_odd_values (&list2));
01213 
01214   _dbus_list_clear (&list1);
01215   _dbus_list_clear (&list2);
01216 
01217   /* test removing the other half of the elements */
01218   
01219   i = 0;
01220   while (i < 10)
01221     {
01222       _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i));
01223       _dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i));
01224       ++i;
01225     }
01226 
01227   --i;
01228   while (i >= 0)
01229     {
01230       if ((i % 2) != 0)
01231         {
01232           if (!_dbus_list_remove (&list1, _DBUS_INT_TO_POINTER (i)))
01233             _dbus_assert_not_reached ("element should have been in list");
01234           if (!_dbus_list_remove (&list2, _DBUS_INT_TO_POINTER (i)))
01235             _dbus_assert_not_reached ("element should have been in list");
01236 
01237           verify_list (&list1);
01238           verify_list (&list2);
01239         }
01240       --i;
01241     }
01242 
01243   _dbus_assert (all_even_values (&list1));
01244   _dbus_assert (all_even_values (&list2));
01245 
01246   /* clear list using remove_link */
01247   while (list1 != NULL)
01248     {
01249       _dbus_list_remove_link (&list1, list1);
01250       verify_list (&list1);
01251     }
01252   while (list2 != NULL)
01253     {
01254       _dbus_list_remove_link (&list2, list2);
01255       verify_list (&list2);
01256     }
01257 
01258   /* Test remove link more generally */
01259   i = 0;
01260   while (i < 10)
01261     {
01262       _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i));
01263       _dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i));
01264       ++i;
01265     }
01266 
01267   --i;
01268   link2 = _dbus_list_get_first_link (&list2);
01269   while (link2 != NULL)
01270     {
01271       DBusList *next = _dbus_list_get_next_link (&list2, link2);
01272       
01273       _dbus_assert (_DBUS_POINTER_TO_INT (link2->data) == i);
01274 
01275       if ((i % 2) == 0)
01276         _dbus_list_remove_link (&list2, link2);
01277 
01278       verify_list (&list2);
01279       
01280       link2 = next;
01281       --i;
01282     }
01283 
01284   _dbus_assert (all_odd_values (&list2));  
01285   _dbus_list_clear (&list2);
01286   
01287   i = 0;
01288   link1 = _dbus_list_get_first_link (&list1);
01289   while (link1 != NULL)
01290     {
01291       DBusList *next = _dbus_list_get_next_link (&list1, link1);
01292 
01293       _dbus_assert (_DBUS_POINTER_TO_INT (link1->data) == i);
01294 
01295       if ((i % 2) != 0)
01296         _dbus_list_remove_link (&list1, link1);
01297 
01298       verify_list (&list1);
01299       
01300       link1 = next;
01301       ++i;
01302     }
01303 
01304   _dbus_assert (all_even_values (&list1));
01305   _dbus_list_clear (&list1);
01306 
01307   /* Test copying a list */
01308   i = 0;
01309   while (i < 10)
01310     {
01311       _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i));
01312       _dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i));
01313       ++i;
01314     }
01315 
01316   /* bad pointers, because they are allowed in the copy dest */
01317   copy1 = _DBUS_INT_TO_POINTER (0x342234);
01318   copy2 = _DBUS_INT_TO_POINTER (23);
01319   
01320   _dbus_list_copy (&list1, &copy1);
01321   verify_list (&list1);
01322   verify_list (&copy1);
01323   _dbus_assert (lists_equal (&list1, &copy1));
01324   
01325   _dbus_list_copy (&list2, &copy2);
01326   verify_list (&list2);
01327   verify_list (&copy2);
01328   _dbus_assert (lists_equal (&list2, &copy2));
01329 
01330   /* Now test copying empty lists */
01331   _dbus_list_clear (&list1);
01332   _dbus_list_clear (&list2);
01333   _dbus_list_clear (&copy1);
01334   _dbus_list_clear (&copy2);
01335   
01336   /* bad pointers, because they are allowed in the copy dest */
01337   copy1 = _DBUS_INT_TO_POINTER (0x342234);
01338   copy2 = _DBUS_INT_TO_POINTER (23);
01339   
01340   _dbus_list_copy (&list1, &copy1);
01341   verify_list (&list1);
01342   verify_list (&copy1);
01343   _dbus_assert (lists_equal (&list1, &copy1));
01344   
01345   _dbus_list_copy (&list2, &copy2);
01346   verify_list (&list2);
01347   verify_list (&copy2);
01348   _dbus_assert (lists_equal (&list2, &copy2));
01349 
01350   _dbus_list_clear (&list1);
01351   _dbus_list_clear (&list2);
01352   
01353   /* insert_before on empty list */
01354   _dbus_list_insert_before (&list1, NULL,
01355                             _DBUS_INT_TO_POINTER (0));
01356   verify_list (&list1);
01357 
01358   /* inserting before first element */
01359   _dbus_list_insert_before (&list1, list1,
01360                             _DBUS_INT_TO_POINTER (2));
01361   verify_list (&list1);
01362   _dbus_assert (is_descending_sequence (&list1));
01363 
01364   /* inserting in the middle */
01365   _dbus_list_insert_before (&list1, list1->next,
01366                             _DBUS_INT_TO_POINTER (1));
01367   verify_list (&list1);
01368   _dbus_assert (is_descending_sequence (&list1));  
01369 
01370   /* using insert_before to append */
01371   _dbus_list_insert_before (&list1, NULL,
01372                             _DBUS_INT_TO_POINTER (-1));
01373   verify_list (&list1);
01374   _dbus_assert (is_descending_sequence (&list1));
01375   
01376   _dbus_list_clear (&list1);
01377 
01378   /* insert_after on empty list */
01379   _dbus_list_insert_after (&list1, NULL,
01380                            _DBUS_INT_TO_POINTER (0));
01381   verify_list (&list1);
01382 
01383   /* inserting after first element */
01384   _dbus_list_insert_after (&list1, list1,
01385                            _DBUS_INT_TO_POINTER (1));
01386   verify_list (&list1);
01387   _dbus_assert (is_ascending_sequence (&list1));
01388 
01389   /* inserting at the end */
01390   _dbus_list_insert_after (&list1, list1->next,
01391                            _DBUS_INT_TO_POINTER (2));
01392   verify_list (&list1);
01393   _dbus_assert (is_ascending_sequence (&list1));
01394 
01395   /* using insert_after to prepend */
01396   _dbus_list_insert_after (&list1, NULL,
01397                            _DBUS_INT_TO_POINTER (-1));
01398   verify_list (&list1);
01399   _dbus_assert (is_ascending_sequence (&list1));
01400   
01401   _dbus_list_clear (&list1);
01402 
01403   /* using remove_last */
01404   _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (2));
01405   _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (1));
01406   _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (3));
01407 
01408   _dbus_list_remove_last (&list1, _DBUS_INT_TO_POINTER (2));
01409   
01410   verify_list (&list1);
01411   _dbus_assert (is_ascending_sequence (&list1));
01412   
01413   _dbus_list_clear (&list1);
01414   
01415   return TRUE;
01416 }
01417 
01418 #endif