next up previous contents index
Next: Methods for Instance Lists Up: Linked Lists Previous: Linked Lists

Basic List Methods and Functions

 

   

GRAPE(G_List, "new-instance")(name)
CLASS *G_List
char *name
Create an empty G_List instance named name. Nodes are created by the insert functions as required.

   

GRAPE(glist, "free")()
G_LIST *glist
Free all nodes and delete the list. The objects are not freed, therefore any object that is no longer needed should be removed from the list and freed before "delete" is called (see insert and remove functions below for an example).

   

GRAPE(glist, "append")(alist)
G_LIST *glist, *alist
Append the nodes of alist to glist. The nodes are removed from alist which will be empty afterwards.

   

GRAPE(glist, "remove-all")()
G_LIST *glist
Remove all nodes from glist which will be empty afterwards. As GRAPE(glist, free")() this method will not free the objects.

       

GRAPE(glist, "apply")(function)
GRAPE(glist, "apply-method")(method)
G_LIST *glist
void (*function)(void *obj)
char *method
Apply a function or a method to all objects of the list. The function is called with the object as (the only) parameter, for "apply-method" it is assumed that the objects are instances, the (parameterless) method is called on them. For example if all instances in a list should be displayed this can be done with
GRAPE(glist, "apply-method")("display");
If you need to apply some more complex operation to all list objects you should use the functions g_list_first, g_list_last and g_list_next, g_list_previous (see below).

       

GRAPE(glist, "is-empty")()
GRAPE(glist, "contains")(obj)
G_LIST *glist
void *obj
Test if the list is empty or if it contains the given object.

int g_list_add_head(glist, obj)
int g_list_add_tail(glist, obj)
int g_list_add_pre(glist, obj)
int g_list_add_post(glist, obj)
int g_list_insert(glist, obj, prev)
G_LIST *glist
void *obj, *prev
Insert an object into the list. g_list_add_head inserts the object as the first and g_list_add_tail as the last element, g_list_insert inserts it after the given prev object, g_list_add_pre and g_list_add_post before and behind the current position respectively. The functions return FALSE if an error occurs, in this case it was not possible to allocate the memory for the node or the object prev was not found in the list.

Because the objects of G_Lists are of arbitrary type no reference counting can be done by these functions -- even if the objects are instances. Therefore you have to be carefull when you insert instances in a list, the reference counter should be incremented when necessary:

if(g_list_add_head(glist, inst))
  inst->refcount++;
else
  fprintf(stderr, "can't insert instance %s\n", inst->name);
In this case the instances have to be deleted from the list before the list itself is deleted:
GRAPE(glist, "apply-method")("delete");
GRAPE(glist, "delete")();

void *g_list_rem_head(glist)
void *g_list_rem_tail(glist)
void *g_list_rem_curr(glist)
void *g_list_remove(glist, obj)
G_LIST *glist
void *obj
Remove an object from the list. g_list_rem_head, g_list_rem_tail and g_list_rem_curr remove the first resp. last resp. current element from the list and return it, a return value of NULL indicates that the list is empty. g_list_remove tries to remove the given object from the list, a return value of NULL indicates that the object was not found in the list.

The g_list_rem_head or g_list_rem_tail function can for example be used to clear a list. If the list contains items which were assigned to the list and added to the manager the list can be cleared with

while(inst = g_list_rem_head(glist)) {
  GRAPE(mgr, "remove-inter")(inst);
  GRAPE(inst, "delete")();
}

void *g_list_first(glist)
void *g_list_last(glist)
void *g_list_next(glist)
void *g_list_previous(glist)
void *g_list_current(glist)
void *g_list_set_current(glist, obj)
G_LIST *glist
void *obj
Iteration functions for walking through the list. The methods "apply" and "apply-method" can only be used to apply parameterless functions or methods to all elements of the list. For more complex operation on the list elements these functions can be used.

Each list has a current object which can be obtained by g_list_current and set by g_list_set_current. A NULL return value of g_list_current indicates that no current object was set before or that the current object was removed from the list, g_list_set_current returns NULL if obj was not found in the list.

g_list_first and g_list_last set the fist resp. last object of the list as current object and return it, NULL as return value indicates that the list is empty. g_list_next and g_list_previous set the next resp. previous object as current object and return it, they return NULL if there is no next or previous object, that is the current object was the last resp. first object of the list.

These functions are for example used by the "apply" method to call the given function on all objects:

G_LIST *g_list_apply(void (*func)(void *))
{
  G_LIST *self;
  void *obj;

  self = (G_LIST *)START_METHOD(G_INSTANCE);
  ASSURE(self, "", END_METHOD(NULL));

  for(obj = g_list_first(self); obj; obj = g_list_next(self))
    func(obj);

  END_METHOD(self);
}

int g_list_count_entries(glist)
G_LIST *glist
g_list_count_entries returns the number of nodes in the list.

int g_list_push_iter(glist)
int g_list_dup_iter(glist, depth)
int g_list_xchg_iter(glist, depth)
int g_list_pop_iter(glist, depth)
int g_list_get_curr_iter(glist)
void *g_list_first_for(glist, depth)
void *g_list_last_for(glist, depth)
void *g_list_current_for(glist, depth)
void *g_list_next_for(glist, depth)
void *g_list_previous_for(glist, depth)
G_LIST *glist
int depth
Finding an object in a G_List is a slow operation. Nevertheless in some situation you need nested loops with two or more iterators for the same list. There are functions for management of an iterator stack, pushed iterators will be updated if the node they are pointing to is deleted by an operation on another level. Only the top iterator allows read/write operations using the normal G_List-functions, the others are read only (if not brought onto the top). Note that the stack is currently designed for local operation only, it is not handled by the "xdr" method, though not read/written to/from files.

The depth argument can be positive or 0, meaning the absolute (non-changing) position on the stack, or negative, meaning the distance from the top, where -1 is the top (default or current) iterator.

g_list_push_iter, g_list_dup_iter, g_list_xchg_iter, g_list_pop_iter and g_list_get_curr_iter are the stack management, g_list_push_iter, g_list_dup_iter push the current resp. the given iterator, g_list_xchg_iter exchanges the current with a given one, g_list_pop_iter pops all entries up to the given one with the special meaning that depth == 0 is equivalent to -1 and pops everything but the standard iterator. g_list_get_curr_iter, g_list_push_iter, g_list_dup_iter return the absolute depth of the current iterator, which will always be positive, or 0 to indicate an error. g_list_pop_iter and g_list_xchg_iter return 0 or a nonzero value in case of an error resp. successful operation.

g_list_first_for, g_list_last_for, g_list_current_for, g_list_next_for and g_list_previous_for do the same as their form without _for, except that they require a stack depth argument.

An example:

type *g_list_test (G_LIST *list, int (*remove)(type *, type *, type *))
{
  type *a, *b, *c;
  int depth;

  for (a = g_list_first (list); a; a = g_list_next (list)) {
    depth = g_list_push_iter (list);
    for (b = g_list_first (list); b; b = g_list_next (list)) {
      g_list_push_iter (list);
      for (c = g_list_first (list); c; c = g_list_next (list)) {
        if (remove(a,b,c)) {
          /* unconditionally pop to the "a" */
          g_list_pop_iter (list, depth);
          /* remove "a" from the list */
          g_list_rem_curr (list);
          return a;
        }
      }
      /* pop one stack entry: back to "b" */
      g_list_pop_iter (list, 0);
    }
    g_list_pop_iter (list, 0);
  }
  return NULL;
}

next up previous contents index
Next: Methods for Instance Lists Up: Linked Lists Previous: Linked Lists

SFB 256 Universität Bonn and IAM Universität Freiburg

Copyright © by the Sonderforschungsbereich 256 at the Institut für Angewandte Mathematik, Universität Bonn.