All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Eric Salomé" <esalome@ctx.net>
To: "'The development of GRUB 2'" <grub-devel@gnu.org>
Subject: RE : a simple list
Date: Tue, 9 May 2006 01:51:41 +0200	[thread overview]
Message-ID: <003001c672fa$5adab170$0b00a8c0@yoda> (raw)
In-Reply-To: <3C2082E50F32E1459503A8E675E24EE4B0462A@icex3.ic.ac.uk>

[-- Attachment #1: Type: text/plain, Size: 4141 bytes --]

Hi,

I didn’t take a good look at current iterate functions in Grub 2, yet.

 

Most iterations needs a “init” (before treatment of first item) and a
“fini” (after treatment of last item).

Further more, one might want to make iteration functions “re-entrant”
(or recursive), or call-back other functions in a generic way.

 

One way to get to such behavior easily cost a bit more than the example
you provided : 

you may just add an argument (let’s call it the context object) to the
call of the iterate function :

 

#define grub_iterate_list(list, func, context) \
  {typeof(list) el = list; while (el) {func(context, el); el=el->next;}
func(context, NULL)}
or

#define grub_iterate_list(list, func) \
  {void * context = NULL; typeof(list) el = list; while (el)
{func(&context, el); el=el->next;} func(&context, NULL)}
but I prefer the first define as it allows transmission of a full
context to the iteration function.

 

my_struct * my_ctxt;

 

my_ctxt = NULL; grub_iterate_list(list, my_func, &my_ctxt);

 

void my_func (my_struct ** ctxt, my_item * item) {

      if (item == NULL) {

          /* End of iteration : Do any cleanup */

          if (*ctxt == NULL) return;

          free (*ctxt) ……

          …..

          return;

      }

      if (*ctxt == NULL) {

           /* First iteration : Do any initialization */

           *ctxt = malloc (sizeof (my_struct)); ….

           …..

}

/* Do the iteration stuff */

…..

return;

}

 

In grub_iterate_list_brk, you can use context to send a patern or model
object to compare each item of the list with.

 

The draw back is it makes iteration function a bit less readable, but a
lot more powerful.

                        

_________________________________________

Eric Salomé – Paris, France

 

-----Message d'origine-----
De : grub-devel-bounces+esalome=ctx.net@gnu.org
[mailto:grub-devel-bounces+esalome=ctx.net@gnu.org] De la part de
Guffens, Vincent
Envoyé : lundi 8 mai 2006 01:14
À : grub-devel@gnu.org
Objet : a simple list

 

Hi,

I need to use a simple list to register the pci devices, drivers and so
on. I notice that there are lists like that already in the code so what
would you think about having a list.h file like that ?

/* A very simple list.
 *
 * If you want a list of struct myitem
 * you do
 *
 * struct myitem *item_list;
 *
 * where myitem MUST have its next pointer as the FIRST field
 *
 * and you can then add, delete the EL item,
 * grub_add_list (&item_list, el);
 * grub_del_list (&item_list, el);
 *
 * or call HOOK(item) for each element of the list
 * grub_iterate_list (item_list, hook);
 *
 * This brk version will point el to the list item for which
 * HOOK(EL) returns a non-null value
 * grub_iterate_list_brk (item_list, hook, el);
 *
 */

struct obj {
  struct obj *next; /* MUST BE FIRST */
};

#define grub_del_list(list, el) _grub_del_list((struct obj**) list,
(struct obj*) el)
#define grub_add_list(list, el) _grub_add_list((struct obj**) list,
(struct obj*) el)
#define grub_find_list(list, el) \
  (typeof(list)) _grub_find_list((struct obj*) list, (struct obj*) el)
#define grub_iterate_list(list, func) \
  {typeof(list) el = list; while (el) {func(el); el=el->next;}}
#define grub_iterate_list_brk(list, func, it) \
  {typeof(list) el = list; it = 0; \
    while (el) {if (func(el)) {it = el; break;} el=el->next; }}

static inline struct obj*  _grub_find_list (struct obj *list, struct obj
*el)
{
  struct obj *it = list;
  for (it = list; it; it=it->next)
  {
    if (it == el) return el;
  }
  return 0;
};

static inline void _grub_add_list (struct obj **list, struct obj *el)
{
  if ( (!el) || (_grub_find_list (*list, el)) )
    return;
 
  el->next = *list;
  *list = el;
};

static inline void _grub_del_list (struct obj **list, struct obj *el)
{
  struct obj **p;
  struct obj *q;

  for (p = list, q = *p; q; p = &(q->next), q = q->next)
    if (q == el)
      {
        *p = q->next;
        break;
      }
};


[-- Attachment #2: Type: text/html, Size: 13334 bytes --]

  reply	other threads:[~2006-05-08 23:51 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-05-07 23:14 a simple list Guffens, Vincent
2006-05-08 23:51 ` Eric Salomé [this message]
2006-05-09  9:08   ` RE : " vincent guffens
2006-05-09 20:31 ` Eric Salomé
2006-05-09 21:29   ` vincent guffens

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='003001c672fa$5adab170$0b00a8c0@yoda' \
    --to=esalome@ctx.net \
    --cc=grub-devel@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.