Next: Methods for Instance Lists
Up: Linked Lists
Previous: Linked Lists
- 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: 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.