Complete.Org: Mailing Lists: Archives: freeciv-dev: January 2005:
[Freeciv-Dev] (PR#11990) New genlist code
Home

[Freeciv-Dev] (PR#11990) New genlist code

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
Subject: [Freeciv-Dev] (PR#11990) New genlist code
From: "Per I. Mathisen" <per@xxxxxxxxxxx>
Date: Sat, 22 Jan 2005 11:59:33 -0800
Reply-to: bugs@xxxxxxxxxxx

<URL: http://bugs.freeciv.org/Ticket/Display.html?id=11990 >

Now that the API change has been done, the new genlist code itself is a
rather small patch. Here it is.

But before I commit this, I want to make section lookups in registry.c
into a hashtable lookup instead of a genlist search.

  - Per

Index: client/helpdata.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/helpdata.c,v
retrieving revision 1.94
diff -u -r1.94 helpdata.c
--- client/helpdata.c   22 Jan 2005 19:45:39 -0000      1.94
+++ client/helpdata.c   22 Jan 2005 19:56:42 -0000
@@ -468,7 +468,7 @@
 void help_iter_start(void)
 {
   check_help_nodes_init();
-  help_nodes_iterator = help_nodes->list->head_link;
+  help_nodes_iterator = help_nodes->list->head;
 }
 
 /****************************************************************
Index: utility/genlist.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/utility/genlist.c,v
retrieving revision 1.17
diff -u -r1.17 genlist.c
--- utility/genlist.c   22 Jan 2005 19:45:45 -0000      1.17
+++ utility/genlist.c   22 Jan 2005 19:56:42 -0000
@@ -1,265 +1,289 @@
-/********************************************************************** 
- Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
+/**********************************************************************
+ Freeciv - Copyright (C) 2003 - The Freeciv Team
    This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
-
+   it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1, or (at
+   your option) any later version.
+                                                                               
 
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
+   GNU Lesser General Public License for more details.
 ***********************************************************************/
 
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 #endif
 
+#include <assert.h>
 #include <stdlib.h>
 
+#include "log.h"
 #include "mem.h"
+#include "shared.h"
+#include "support.h"
 
 #include "genlist.h"
 
-static struct genlist_link *find_genlist_position(const struct genlist 
*pgenlist,
-                                                 int pos);
-
-/************************************************************************
-  Create a new empty genlist.
-************************************************************************/
-struct genlist *genlist_new(void)
-{
-  struct genlist *pgenlist = fc_malloc(sizeof(*pgenlist));
+/* Tracker is a list of pointers to lists that we will prune when
+ * the time is right. */
+static struct genlist *tracker;
 
-  pgenlist->nelements=0;
-  pgenlist->head_link = NULL;
-  pgenlist->tail_link = NULL;
+static void genlist_prune(struct genlist *plist);
 
-  return pgenlist;
+/**************************************************************************
+  Initialize genlist module.
+**************************************************************************/
+void genlists_init()
+{
+  tracker = genlist_new();
 }
 
-/************************************************************************
-  Remove a genlist.  The list must be empty first!
-************************************************************************/
-void genlist_free(struct genlist *pgenlist)
+/**************************************************************************
+  Quit genlist module.  Returns FALSE if memory was not cleaned up
+  properly.
+**************************************************************************/
+void genlists_free()
 {
-  free(pgenlist);
+  genlist_free(tracker);
 }
 
-/************************************************************************
-  Returns the number of elements stored in the genlist.
-************************************************************************/
-int genlist_size(const struct genlist *pgenlist)
+/**************************************************************************
+  Create a genlist and insert it into the genlist tracker.
+**************************************************************************/
+struct genlist *genlist_new()
 {
-  return pgenlist->nelements;
-}
+  struct genlist *plist = calloc(sizeof(struct genlist), 1);
 
+  plist->nelements = 0;
+  plist->ndeleted = 0;
+  plist->head = NULL;
+  plist->tail = NULL;
+  plist->track = NULL;
 
-/************************************************************************
-  Returns the user-data pointer stored in the genlist at the position
-  given by 'idx'.  For idx out of range (including an empty list),
-  returns NULL.
-  Recall 'idx' can be -1 meaning the last element.
-************************************************************************/
-void *genlist_get(const struct genlist *pgenlist, int idx)
-{
-  struct genlist_link *link=find_genlist_position(pgenlist, idx);
+  if (tracker) {
+    struct genlist_link *plink;
 
-  if (link) {
-    return link->dataptr;
-  } else {
-    return NULL;
-  }
-}
+    /* Insert list into tracker, unless we _are_ the tracker. */
+    genlist_prepend(tracker, plist);
 
+    /* Find our position in the tracker */
+    for (plink = tracker->head; plink->dataptr != plist; plink = plink->next);
 
-/************************************************************************
-  Frees all the internal data used by the genlist (but doesn't touch
-  the user-data).  At the end the state of the genlist will be the
-  same as when genlist_init() is called on a new genlist.
-************************************************************************/
-void genlist_unlink_all(struct genlist *pgenlist)
-{
-  if(pgenlist->nelements > 0) {
-    struct genlist_link *plink=pgenlist->head_link, *plink2;
+    /* Point plist->track at ourselves in the tracker */
+    plist->track = plink;
+  }
 
-    do {
-      plink2=plink->next;
-      free(plink);
-    } while ((plink = plink2) != NULL);
+  return plist;
+}
 
-    pgenlist->head_link = NULL;
-    pgenlist->tail_link = NULL;
+/**************************************************************************
+  Get data from given position. -1 gives us last position.
+**************************************************************************/
+void *genlist_get(const struct genlist *plist, int idx)
+{
+  struct genlist_link *plink = plist->head;
+  int i = 0;
 
-    pgenlist->nelements=0;
+  if (idx == -1) {
+    idx = genlist_size(plist);
   }
-}
 
+  if (!plist->head || genlist_size(plist) == 0) {
+    /* List is empty */
+    return NULL;
+  } else if (idx == genlist_size(plist) && !plist->tail->deleted) {
+    /* Last item */
+    return plist->tail->dataptr;
+  } else if (idx > genlist_size(plist) || idx < -1) {
+    /* Trying to fetch out of bounds item */
+    return NULL;
+  }
 
-/************************************************************************
-  Remove an element of the genlist with the specified user-data pointer
-  given by 'punlink'.  If there is no such element, does nothing.
-  If there are multiple such elements, removes the first one.
-************************************************************************/
-void genlist_unlink(struct genlist *pgenlist, void *punlink)
-{
-  if(pgenlist->nelements > 0) {
-    struct genlist_link *plink=pgenlist->head_link;
-    
-    while (plink != NULL && plink->dataptr != punlink) {
-      plink = plink->next;
+  /* Ok, we have to search */
+  for (;; plink = plink->next) {
+    if (plink->deleted) {
+      continue;
     }
-    
-    if (plink) {
-      if(pgenlist->head_link==plink)
-        pgenlist->head_link=plink->next;
-      else
-        plink->prev->next=plink->next;
-
-      if(pgenlist->tail_link==plink)
-        pgenlist->tail_link=plink->prev;
-      else
-        plink->next->prev=plink->prev;
-      free(plink);
-      pgenlist->nelements--;
+    if (i == idx) {
+      break;
     }
+    i++;
   }
+  return plink->dataptr;
 }
 
-
-/************************************************************************
-  Insert a new element in the list, at position 'pos', with the specified
-  user-data pointer 'data'.  Existing elements at >= pos are moved one
-  space to the "right".  Recall 'pos' can be -1 meaning add at the
-  end of the list.  For an empty list pos has no effect.
-  A bad 'pos' value for a non-empty list is treated as -1 (is this
-  a good idea?)
-************************************************************************/
-static void genlist_insert(struct genlist *pgenlist, void *data, int pos)
-{
-  if(pgenlist->nelements == 0) { /*list is empty, ignore pos */
-    
-    struct genlist_link *plink = fc_malloc(sizeof(*plink));
-
-    plink->dataptr=data;
-    plink->next = NULL;
-    plink->prev = NULL;
-
-    pgenlist->head_link=plink;
-    pgenlist->tail_link=plink;
-
-  }
-  else {
-    struct genlist_link *plink = fc_malloc(sizeof(*plink));
-    plink->dataptr=data;
-
-    if(pos==0) {
-      plink->next=pgenlist->head_link;
-      plink->prev = NULL;
-      pgenlist->head_link->prev=plink;
-      pgenlist->head_link=plink;
-    }
-    else if(pos<=-1 || pos>=pgenlist->nelements) {
-      plink->next = NULL;
-      plink->prev=pgenlist->tail_link;
-      pgenlist->tail_link->next=plink;
-      pgenlist->tail_link=plink;
-    }
-    else {
-      struct genlist_link *left, *right;     /* left and right of new element 
*/
-      right = find_genlist_position(pgenlist, pos);
-      left = right->prev;
-      plink->next = right;
-      plink->prev = left;
-      right->prev = plink;
-      left->next = plink;
-    }
+/**************************************************************************
+  Free list. Does not touch data inside the list. Calling this function
+  while such data is still in the list is an error.
+**************************************************************************/
+void genlist_free(struct genlist *plist)
+{
+  /* Remove our entry in the tracker list. */
+  if (plist->track) {
+    plist->track->deleted = TRUE;
+    tracker->nelements--;
   }
+  /* assert(plist->nelements == 0); */
 
-  pgenlist->nelements++;
+  free(plist);
 }
 
-
-/************************************************************************
-  Insert an item at the start of the list.
-************************************************************************/
-void genlist_prepend(struct genlist *pgenlist, void *data)
+/**************************************************************************
+  Remove first link from the list where the data pointers match.
+**************************************************************************/
+void genlist_unlink(struct genlist *plist, void *punlink)
 {
-  genlist_insert(pgenlist, data, 0); /* beginning */
+  struct genlist_link *next = plist->head;
+
+  while (next) {
+    if (!next->deleted && next->dataptr == punlink) {
+      next->deleted = TRUE;
+      plist->nelements--;
+      plist->ndeleted++;
+      break;
+    }
+    next = next->next;
+  }
 }
 
+/**************************************************************************
+  Empty the list.
+**************************************************************************/
+void genlist_unlink_all(struct genlist *plist)
+{
+  struct genlist_link *next = plist->head;
+
+  while (next) {
+    if (!next->deleted) {
+      next->deleted = TRUE;
+      plist->nelements--;
+      plist->ndeleted++;
+    }
+    next = next->next;
+  }
+  assert(plist->nelements == 0);
+}
 
-/************************************************************************
-  Insert an item at the end of the list.
-************************************************************************/
-void genlist_append(struct genlist *pgenlist, void *data)
-{
-  genlist_insert(pgenlist, data, -1); /* end */
+/**************************************************************************
+  Insert data at beginning of list.
+**************************************************************************/
+void genlist_prepend(struct genlist *plist, void *data)
+{
+  struct genlist_link *new_link = fc_malloc(sizeof(struct genlist_link));
+
+  new_link->dataptr = data;
+  new_link->deleted = FALSE;
+  new_link->next = plist->head;
+  plist->head = new_link;
+  if (plist->tail == NULL) {
+    plist->tail = new_link;
+  }
+  plist->nelements++;
 }
 
-/************************************************************************
-  Returns a pointer to the genlist link structure at the specified
-  position.  Recall 'pos' -1 refers to the last position.
-  For pos out of range returns NULL.
-  Traverses list either forwards or backwards for best efficiency.
-************************************************************************/
-static struct genlist_link *find_genlist_position(const struct genlist 
*pgenlist,
-                                                 int pos)
+/**************************************************************************
+  Insert data at end of list.
+**************************************************************************/
+void genlist_append(struct genlist *plist, void *data)
 {
-  struct genlist_link *plink;
+  struct genlist_link *new_link = fc_malloc(sizeof(struct genlist_link));
 
-  if (pos == 0) {
-    return pgenlist->head_link;
-  } else if (pos == -1) {
-    return pgenlist->tail_link;
-  } else if (pos < -1 || pos >= pgenlist->nelements) {
-    return NULL;
+  new_link->dataptr = data;
+  new_link->deleted = FALSE;
+  new_link->next = NULL;
+  if (plist->tail) {
+    plist->tail->next = new_link;
+  } else {
+    plist->head = new_link;
   }
+  plist->tail = new_link;
+  plist->nelements++;
+}
 
-  if(pos<pgenlist->nelements/2)   /* fastest to do forward search */
-    for(plink=pgenlist->head_link; pos != 0; pos--)
-      plink=plink->next;
- 
-  else                           /* fastest to do backward search */
-    for(plink=pgenlist->tail_link,pos=pgenlist->nelements-pos-1; pos != 0; 
pos--)
-      plink=plink->prev;
- 
-  return plink;
+/**************************************************************************
+  Free all unused memory in all genlists.
+**************************************************************************/
+void genlists_prune()
+{
+  struct genlist_link *plink = tracker->head;
+
+  for (; plink != NULL; plink = plink->next) {
+    if (!plink->deleted
+        && plink->dataptr != NULL
+        && ((struct genlist *)(plink->dataptr))->ndeleted > 0) {
+      genlist_prune(plink->dataptr);
+    }
+  }
+  genlist_prune(tracker);
 }
 
+/**************************************************************************
+  Free unused memory. Call some time when we are certain that no calling 
+  code uses the list.
+**************************************************************************/
+static void genlist_prune(struct genlist *plist)
+{
+  struct genlist_link *plink = plist->head;
+  struct genlist_link *plink_prev = NULL;
+
+  while (plink && plist->ndeleted > 0) {
+    if (plink->deleted) {
+      struct genlist_link *remove = plink;
+
+      if (plist->head == plink) {
+        plist->head = plink->next;
+      }
+      if (plist->tail == plink) {
+        plist->tail = plink_prev;
+      }
+      if (plink_prev) {
+        plink_prev->next = plink->next;
+      }
+      plink = plink->next;
+      free(remove);
+      plist->ndeleted--;
+    } else {
+      plink_prev = plink;
+      plink = plink->next;
+    }
+  }
+}
 
-/************************************************************************
- Sort the elements of a genlist.
- 
- The comparison function should be a function usable by qsort; note
- that the const void * arguments to compar should really be "pointers to
- void*", where the void* being pointed to are the genlist dataptrs.
- That is, there are two levels of indirection.
- To do the sort we first construct an array of pointers corresponding
- the the genlist dataptrs, then sort those and put them back into
- the genlist.
-************************************************************************/
-void genlist_sort(struct genlist *pgenlist,
-                 int (*compar)(const void *, const void *))
-{
-  const int n = genlist_size(pgenlist);
-  void *sortbuf[n];
-  struct genlist_link *myiter;
+/**************************************************************************
+  Generic sort function. Hand over a comparison function that can be 
+  used by qsort. The arguments to this helper function are pointers to
+  void*, which is a pointer to the list dataptr. Note, two levels of
+  indirection.
+**************************************************************************/
+void genlist_sort(struct genlist *plist, int (*compar)(const void *, 
+                                                       const void *))
+{
+  struct genlist_link *plink = plist->head;
   int i;
+  void *buffer[genlist_size(plist)];
+
+  if (compar == NULL || !plink || !plink->next || genlist_size(plist) <= 1) {
+    return; /* Nothing to do */
+  }
 
-  if (n <= 1) {
-    return;
+  /* Copy pointers into buffer */
+  for (i = 0; plink; plink = plink->next) {
+    if (!plink->deleted) {
+      buffer[i] = plink->dataptr;
+      i++;
+    }
   }
 
-  myiter = find_genlist_position(pgenlist, 0);  
-  for(i=0; i<n; i++, ITERATOR_NEXT(myiter)) {
-    sortbuf[i] = ITERATOR_PTR(myiter);
-  }
-  
-  qsort(sortbuf, n, sizeof(*sortbuf), compar);
-  
-  myiter = find_genlist_position(pgenlist, 0);  
-  for(i=0; i<n; i++, ITERATOR_NEXT(myiter)) {
-    myiter->dataptr = sortbuf[i];
+  /* Sort the array */
+  qsort(&buffer, genlist_size(plist), sizeof(void*), compar);
+
+  /* Copy pointers back from buffer */
+  plink = plist->head;
+  for (i = 0; plink; plink = plink->next) {
+    if (!plink->deleted) {
+      plink->dataptr = buffer[i];
+      i++;
+    }
   }
 }
Index: utility/genlist.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/utility/genlist.h,v
retrieving revision 1.13
diff -u -r1.13 genlist.h
--- utility/genlist.h   22 Jan 2005 19:45:45 -0000      1.13
+++ utility/genlist.h   22 Jan 2005 19:56:42 -0000
@@ -1,116 +1,81 @@
-/********************************************************************** 
- Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
+/**********************************************************************
+ Freeciv - Copyright (C) 2003 - The Freeciv Team
    This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
+   it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1, or (at
+   your option) any later version.
 
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
+   GNU Lesser General Public License for more details.
 ***********************************************************************/
 #ifndef FC__GENLIST_H
 #define FC__GENLIST_H
 
-/********************************************************************** 
-  MODULE: genlist
+#undef DEBUG_LISTS
+#ifdef DEBUG_LISTS
+#define DEBUG_INFO(p) __FILE__, __LINE__
+#else
+#define DEBUG_INFO(p)
+#endif
 
-  A "genlist" is a generic doubly-linked list.  That is:
-    generic:        stores (void*) pointers to arbitrary user data;
-    doubly-linked:  can be efficiently traversed both "forwards"
-                    and "backwards".
-                   
-  The list data structures are allocated dynamically, and list
-  elements can be added or removed at arbitrary positions.
-  
-  Positions in the list are specified starting from 0, up to n-1
-  for a list with n elements.  The position -1 can be used to
-  refer to the last element (that is, the same as n-1, or n when
-  adding a new element), but other negative numbers are not
-  meaningful.
-
-  There are two memory management issues:
-  
-  - The user-data pointed to by the genlist elements; these are
-    entirely the user's responsibility, and the genlist code just
-    treats these as opaque data, not doing any allocation or freeing.
-    
-  - The data structures used internally by the genlist to store
-    data for the links etc.  These are allocated by genlist_insert(),
-    and freed by genlist_unlink() and genlist_unlink_all().  That is,
-    it is the responsibility of the user to call the unlink functions
-    as necessary to avoid memory leaks.
-
-  A trap to beware of with iterators is modifying the list while the 
-  iterator is active, in particular removing the next element pointed 
-  to by the iterator (see further comments below).
+#include "shared.h"
 
-  See also the speclist module.
-***********************************************************************/
-
-/* A single element of a genlist, storing the pointer to user
-   data, and pointers to the next and previous elements:
-*/
+/* A single list link. The last link's next is NULL. */
 struct genlist_link {
-  struct genlist_link *next, *prev; 
+  struct genlist_link *next;
   void *dataptr;
+  bool deleted;
 };
 
-
-/* A genlist, storing the number of elements (for quick retrieval and
-   testing for empty lists), and pointers to the first and last elements
-   of the list.
-*/
+/* The nelements parameter contains the number of links in the list, while
+ * head and tail point to first and last link, respectively. The track 
+ * variable points to our entry in the tracker, if we are there. */
 struct genlist {
   int nelements;
-  struct genlist_link *head_link;
-  struct genlist_link *tail_link;
+  int ndeleted;
+  struct genlist_link *head;
+  struct genlist_link *tail;
+  struct genlist_link *track;
 };
 
-int genlist_size(const struct genlist *pgenlist);
-void *genlist_get(const struct genlist *pgenlist, int idx);
-struct genlist *genlist_new(void);
-void genlist_unlink_all(struct genlist *pgenlist);
-void genlist_free(struct genlist *pgenlist);
-void genlist_append(struct genlist *pgenlist, void *data);
-void genlist_prepend(struct genlist *pgenlist, void *data);
-void genlist_unlink(struct genlist *pgenlist, void *punlink);
+/* Operations on all lists */
+void genlists_init(void);
+void genlists_free(void);
+void genlists_prune(void);
 
-void genlist_sort(struct genlist *pgenlist,
-                 int (*compar)(const void *, const void *));
+/* Operations on a single list */
+struct genlist *genlist_new(void);
+#define genlist_size(plist) ((plist)->nelements)
+void *genlist_get(const struct genlist *plist, int idx);
+void genlist_prepend(struct genlist *plist, void *data);
+void genlist_append(struct genlist *plist, void *data);
+void genlist_unlink(struct genlist *plist, void *punlink);
+void genlist_unlink_all(struct genlist *plist);
+void genlist_free(struct genlist *plist);
+void genlist_sort(struct genlist *plist,
+                  int (*compar)(const void *, const void *));
 
-#define ITERATOR_PTR(iter) ((iter) ? ((iter)->dataptr) : NULL)
+#define ITERATOR_PTR(iter) ((iter)->dataptr)
 #define ITERATOR_NEXT(iter) (iter = (iter)->next)
 #define ITERATOR_PREV(iter) (iter = (iter)->prev)
 
-
 /* This is to iterate for a type defined like:
      struct unit_list { struct genlist list; };
    where the pointers in the list are really pointers to "atype".
    Eg, see speclist.h, which is what this is really for.
 */
-#define TYPED_LIST_ITERATE(atype, typed_list, var) {       \
-  struct genlist_link *myiter = (typed_list)->list->head_link;\
-  atype *var;                                              \
-  for(; ITERATOR_PTR(myiter);) {                           \
-    var = ITERATOR_PTR(myiter);                                   \
-    ITERATOR_NEXT(myiter);
-
-/* Balance for above: */ 
-#define LIST_ITERATE_END  }}
-
-
-/* Same, but iterate backwards: */
-#define TYPED_LIST_ITERATE_REV(atype, typed_list, var) {   \
-  struct genlist_link *myiter = (typed_list)->list->tail_link;\
-  atype *var;                                              \
-  for(; ITERATOR_PTR(myiter);) {                           \
-    var = ITERATOR_PTR(myiter);                                   \
-    ITERATOR_PREV(myiter);
- 
-/* Balance for above: */ 
-#define LIST_ITERATE_REV_END  }}
+#define TYPED_LIST_ITERATE(atype, typed_list, var) {         \
+  struct genlist_link *link = (typed_list)->list->head;      \
+  atype *var;                                                \
+  while (link && ITERATOR_PTR(link)) {                       \
+    bool deleted = link->deleted;                            \
+    var = (atype *)ITERATOR_PTR(link);                       \
+    ITERATOR_NEXT(link);                                     \
+    if (!deleted) {
 
+/* Balance for above: */
+#define LIST_ITERATE_END  }}}
 
-#endif  /* FC__GENLIST_H */
+#endif
Index: utility/registry.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/utility/registry.c,v
retrieving revision 1.69
diff -u -r1.69 registry.c
--- utility/registry.c  22 Jan 2005 19:45:45 -0000      1.69
+++ utility/registry.c  22 Jan 2005 19:56:42 -0000
@@ -210,10 +210,6 @@
        TYPED_LIST_ITERATE(struct section, seclist, psection)
 #define section_list_iterate_end  LIST_ITERATE_END
 
-#define section_list_iterate_rev(seclist, psection) \
-       TYPED_LIST_ITERATE_REV(struct section, seclist, psection)
-#define section_list_iterate_rev_end  LIST_ITERATE_REV_END
-
 /* The hash table and some extra data: */
 struct hash_data {
   struct hash_table *htbl;
@@ -360,17 +356,14 @@
                                            const char *name)
 {
   /*
-   * Search backwards since on insertion the requested section is most
-   * likely at the end (on lookup it doesn't matter).
-   *
-   * Nonetheless this is slow if there are lots of sections.  We could have
+   * This is slow if there are lots of sections.  We could have
    * a hash on section names to speed it up.
    */
-  section_list_iterate_rev(sf->sections, psection) {
+  section_list_iterate(sf->sections, psection) {
     if (strcmp(psection->name, name) == 0) {
       return psection;
     }
-  } section_list_iterate_rev_end;
+  } section_list_iterate_end;
 
   return NULL;
 }      
@@ -657,7 +650,7 @@
     /* Following doesn't use entry_list_iterate() because we want to do
      * tricky things with the iterators...
      */
-    for(ent_iter = psection->entries->list->head_link;
+    for(ent_iter = psection->entries->list->head;
         ent_iter && (pentry = ITERATOR_PTR(ent_iter));
        ITERATOR_NEXT(ent_iter)) {
 

[Prev in Thread] Current Thread [Next in Thread]