[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
RE : a simple list
From: |
Eric Salomé |
Subject: |
RE : a simple list |
Date: |
Tue, 9 May 2006 22:31:30 +0200 |
Hi Vincent,
I picked up your email from the archive as I didn't received it yet.
As you see, it's very easy with a simple #define to create simple code
for simple cases and yet be powerful for more complex cases :
#define grub_iterate_list_brk(list, func, context, it) \
{typeof(list) el = list; it = 0; \
while (el) {if (func(context, el)) {it = el; break;} el=el->next; }}
that you can call with
grub_iterate_list_brk(grub_devices, compare, dev, it);
with the simpliest compare function between two devices, and you get
in-line functions nearly as simpler as the one you wrote.
But let's try this :
item * grub_iterate_list_brk (item * start,
void * (*fct) (void * a, void * b), void * search) {
while (start && fct(search, (void *) start)) start =
start->next;
return start ? start : (item *) fct(search, NULL);
}
that you can call with :
it = (dev *) grub_iterate_list_brk((item *) grub_devices,
devcompare, device);
You are not in-lining functions (that makes the code smaller) and this
is a simple devcompare function to see how it works :
void * devcompare (dev * a, dev * b) {
if (b == NULL) return NULL;
if (a == NULL) return NULL;
return (void *) strcmp (a->name, b->name);
}
Which is 3 line long but still is readable ... and yet powerful :
If (b == NULL) return NULL;
You have ended the list and didn't find a match ? grub_iterate_list_brk
let the compare function choose what it likes to return as a result :
Can be NULL (not found)
Can be a default value
Can be the "best" item picked out of the iteration process that matches
best the criteria; as you like :-)
If (a == NULL) return NULL;
What happens then ? if you call grub_iterate_list_brk with no criteria
(device == NULL), than it assumes you want any item and returns the
first item in the list. That's good behaviour and only a small overhead
in devcompare.
Return (void *) strcmp (a->name, b->name);
Grub_iterate_list_brk return the item for which the compare function
returns 0 (or NULL), so that you can easily write :
Return (void *) (
a->id - b->id
|| a->magic - b-> magic
|| strcmp(a->name, b->name) );
Is that what you were looking for ?
PS: Sorry folks for my previous emails sent in html : it sent lots of
useless blank lines for nothing.
________________________________________
Eric Salomé Paris, France
From:
vincent guffens
Subject:
Re: RE : a simple list
Date:
Tue, 09 May 2006 10:08:24 +0100
User-agent:
Debian Thunderbird 1.0.7 (X11/20051017)
Thank you for this information. Adding the concept of context is indeed
the right idea. I was doing it as follows
void function (grub_device_t dev)
{
grub_device_t it;
auto int look_for_dev (grub_device_t);
int look_for_dev (grub_device_t grub_device_t other_dev)
{
return compare (dev, other_dev)
}
grub_iterate_list_brk (grub_devices, look_for_dev, it);
}
but it has to be compared with something like
void function (grub_device_t dev)
{
grub_device_t it = grub_devices;
while (it)
{
if ( compare (dev, it) )
break;
}
}
which is obviously simpler. Maybe the only two functions that are really
needed are add and del ?