--- Add new FOREACH_FROM variants of the queue(3) FOREACH macros which can --- optionally start the traversal from a previously found element by passing --- the element in as "var". Passing a NULL "var" retains the same semantics as --- the regular FOREACH macros. --- --- Reviewed by: ? --- MFC after: 1 week --- Index: sys/sys/queue.h =================================================================== --- sys/sys/queue.h (revision 250136) +++ sys/sys/queue.h (working copy) @@ -88,8 +88,10 @@ * _PREV - + - + * _LAST - - + + * _FOREACH + + + + + * _FOREACH_FROM + + + + * _FOREACH_SAFE + + + + * _FOREACH_REVERSE - - - + + * _FOREACH_REVERSE_FROM - - - + * _FOREACH_REVERSE_SAFE - - - + * _INSERT_HEAD + + + + * _INSERT_BEFORE - + - + @@ -167,6 +169,11 @@ (var); \ (var) = SLIST_NEXT((var), field)) +#define SLIST_FOREACH_FROM(var, head, field) \ + for ((var) = ((var) ? (var) : SLIST_FIRST((head))); \ + (var); \ + (var) = SLIST_NEXT((var), field)) + #define SLIST_FOREACH_SAFE(var, head, field, tvar) \ for ((var) = SLIST_FIRST((head)); \ (var) && ((tvar) = SLIST_NEXT((var), field), 1); \ @@ -259,6 +266,10 @@ (var); \ (var) = STAILQ_NEXT((var), field)) +#define STAILQ_FOREACH_FROM(var, head, field) \ + for ((var) = ((var) ? (var) : STAILQ_FIRST((head))); \ + (var); \ + (var) = STAILQ_NEXT((var), field)) #define STAILQ_FOREACH_SAFE(var, head, field, tvar) \ for ((var) = STAILQ_FIRST((head)); \ @@ -389,6 +400,11 @@ (var); \ (var) = LIST_NEXT((var), field)) +#define LIST_FOREACH_FROM(var, head, field) \ + for ((var) = ((var) ? (var) : LIST_FIRST((head))); \ + (var); \ + (var) = LIST_NEXT((var), field)) + #define LIST_FOREACH_SAFE(var, head, field, tvar) \ for ((var) = LIST_FIRST((head)); \ (var) && ((tvar) = LIST_NEXT((var), field), 1); \ @@ -526,6 +542,11 @@ (var); \ (var) = TAILQ_NEXT((var), field)) +#define TAILQ_FOREACH_FROM(var, head, field) \ + for ((var) = ((var) ? (var) : TAILQ_FIRST((head))); \ + (var); \ + (var) = TAILQ_NEXT((var), field)) + #define TAILQ_FOREACH_SAFE(var, head, field, tvar) \ for ((var) = TAILQ_FIRST((head)); \ (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \ @@ -536,6 +557,11 @@ (var); \ (var) = TAILQ_PREV((var), headname, field)) +#define TAILQ_FOREACH_REVERSE_FROM(var, head, headname, field) \ + for ((var) = ((var) ? (var) : TAILQ_LAST((head), headname)); \ + (var); \ + (var) = TAILQ_PREV((var), headname, field)) + #define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \ for ((var) = TAILQ_LAST((head), headname); \ (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \ Index: share/man/man3/queue.3 =================================================================== --- share/man/man3/queue.3 (revision 250136) +++ share/man/man3/queue.3 (working copy) @@ -32,7 +32,7 @@ .\" @(#)queue.3 8.2 (Berkeley) 1/24/94 .\" $FreeBSD$ .\" -.Dd Sep 12, 2012 +.Dd May 1, 2013 .Dt QUEUE 3 .Os .Sh NAME @@ -40,6 +40,7 @@ .Nm SLIST_ENTRY , .Nm SLIST_FIRST , .Nm SLIST_FOREACH , +.Nm SLIST_FOREACH_FROM , .Nm SLIST_FOREACH_SAFE , .Nm SLIST_HEAD , .Nm SLIST_HEAD_INITIALIZER , @@ -56,6 +57,7 @@ .Nm STAILQ_ENTRY , .Nm STAILQ_FIRST , .Nm STAILQ_FOREACH , +.Nm STAILQ_FOREACH_FROM , .Nm STAILQ_FOREACH_SAFE , .Nm STAILQ_HEAD , .Nm STAILQ_HEAD_INITIALIZER , @@ -73,6 +75,7 @@ .Nm LIST_ENTRY , .Nm LIST_FIRST , .Nm LIST_FOREACH , +.Nm LIST_FOREACH_FROM , .Nm LIST_FOREACH_SAFE , .Nm LIST_HEAD , .Nm LIST_HEAD_INITIALIZER , @@ -89,8 +92,10 @@ .Nm TAILQ_ENTRY , .Nm TAILQ_FIRST , .Nm TAILQ_FOREACH , +.Nm TAILQ_FOREACH_FROM , .Nm TAILQ_FOREACH_SAFE , .Nm TAILQ_FOREACH_REVERSE , +.Nm TAILQ_FOREACH_REVERSE_FROM , .Nm TAILQ_FOREACH_REVERSE_SAFE , .Nm TAILQ_HEAD , .Nm TAILQ_HEAD_INITIALIZER , @@ -113,6 +118,7 @@ .Fn SLIST_ENTRY "TYPE" .Fn SLIST_FIRST "SLIST_HEAD *head" .Fn SLIST_FOREACH "TYPE *var" "SLIST_HEAD *head" "SLIST_ENTRY NAME" +.Fn SLIST_FOREACH_FROM "TYPE *var" "SLIST_HEAD *head" "SLIST_ENTRY NAME" .Fn SLIST_FOREACH_SAFE "TYPE *var" "SLIST_HEAD *head" "SLIST_ENTRY NAME" "TYPE *temp_var" .Fn SLIST_HEAD "HEADNAME" "TYPE" .Fn SLIST_HEAD_INITIALIZER "SLIST_HEAD head" @@ -130,6 +136,7 @@ .Fn STAILQ_ENTRY "TYPE" .Fn STAILQ_FIRST "STAILQ_HEAD *head" .Fn STAILQ_FOREACH "TYPE *var" "STAILQ_HEAD *head" "STAILQ_ENTRY NAME" +.Fn STAILQ_FOREACH_FROM "TYPE *var" "STAILQ_HEAD *head" "STAILQ_ENTRY NAME" .Fn STAILQ_FOREACH_SAFE "TYPE *var" "STAILQ_HEAD *head" "STAILQ_ENTRY NAME" "TYPE *temp_var" .Fn STAILQ_HEAD "HEADNAME" "TYPE" .Fn STAILQ_HEAD_INITIALIZER "STAILQ_HEAD head" @@ -148,6 +155,7 @@ .Fn LIST_ENTRY "TYPE" .Fn LIST_FIRST "LIST_HEAD *head" .Fn LIST_FOREACH "TYPE *var" "LIST_HEAD *head" "LIST_ENTRY NAME" +.Fn LIST_FOREACH_FROM "TYPE *var" "LIST_HEAD *head" "LIST_ENTRY NAME" .Fn LIST_FOREACH_SAFE "TYPE *var" "LIST_HEAD *head" "LIST_ENTRY NAME" "TYPE *temp_var" .Fn LIST_HEAD "HEADNAME" "TYPE" .Fn LIST_HEAD_INITIALIZER "LIST_HEAD head" @@ -165,8 +173,10 @@ .Fn TAILQ_ENTRY "TYPE" .Fn TAILQ_FIRST "TAILQ_HEAD *head" .Fn TAILQ_FOREACH "TYPE *var" "TAILQ_HEAD *head" "TAILQ_ENTRY NAME" +.Fn TAILQ_FOREACH_FROM "TYPE *var" "TAILQ_HEAD *head" "TAILQ_ENTRY NAME" .Fn TAILQ_FOREACH_SAFE "TYPE *var" "TAILQ_HEAD *head" "TAILQ_ENTRY NAME" "TYPE *temp_var" .Fn TAILQ_FOREACH_REVERSE "TYPE *var" "TAILQ_HEAD *head" "HEADNAME" "TAILQ_ENTRY NAME" +.Fn TAILQ_FOREACH_REVERSE_FROM "TYPE *var" "TAILQ_HEAD *head" "HEADNAME" "TAILQ_ENTRY NAME" .Fn TAILQ_FOREACH_REVERSE_SAFE "TYPE *var" "TAILQ_HEAD *head" "HEADNAME" "TAILQ_ENTRY NAME" "TYPE *temp_var" .Fn TAILQ_HEAD "HEADNAME" "TYPE" .Fn TAILQ_HEAD_INITIALIZER "TAILQ_HEAD head" @@ -365,6 +375,19 @@ .Fa var . .Pp The macro +.Nm SLIST_FOREACH_FROM +behaves identically to +.Nm SLIST_FOREACH +when +.Fa var +is NULL, else it treats +.Fa var +as a previously found slist element and begins the loop at +.Fa var +instead of the first element in the slist referenced by +.Fa head . +.Pp +The macro .Nm SLIST_FOREACH_SAFE traverses the list referenced by .Fa head @@ -544,6 +567,19 @@ .Fa var . .Pp The macro +.Nm STAILQ_FOREACH_FROM +behaves identically to +.Nm STAILQ_FOREACH +when +.Fa var +is NULL, else it treats +.Fa var +as a previously found stailq element and begins the loop at +.Fa var +instead of the first element in the stailq referenced by +.Fa head . +.Pp +The macro .Nm STAILQ_FOREACH_SAFE traverses the tail queue referenced by .Fa head @@ -733,6 +769,19 @@ .Fa var . .Pp The macro +.Nm LIST_FOREACH_FROM +behaves identically to +.Nm LIST_FOREACH +when +.Fa var +is NULL, else it treats +.Fa var +as a previously found list element and begins the loop at +.Fa var +instead of the first element in the list referenced by +.Fa head . +.Pp +The macro .Nm LIST_FOREACH_SAFE traverses the list referenced by .Fa head @@ -918,12 +967,38 @@ if the loop completes normally, or if there were no elements. .Pp The macro +.Nm TAILQ_FOREACH_FROM +behaves identically to +.Nm TAILQ_FOREACH +when +.Fa var +is NULL, else it treats +.Fa var +as a previously found tailq element and begins the loop at +.Fa var +instead of the first element in the tailq referenced by +.Fa head . +.Pp +The macro .Nm TAILQ_FOREACH_REVERSE traverses the tail queue referenced by .Fa head in the reverse direction, assigning each element in turn to .Fa var . .Pp +The macro +.Nm TAILQ_FOREACH_REVERSE_FROM +behaves identically to +.Nm TAILQ_FOREACH_REVERSE +when +.Fa var +is NULL, else it treats +.Fa var +as a previously found tailq element and begins the reverse loop at +.Fa var +instead of the last element in the tailq referenced by +.Fa head . +.Pp The macros .Nm TAILQ_FOREACH_SAFE and