Add macros for iterating the containing entry
This commit is contained in:
+66
-8
@@ -155,16 +155,44 @@ static UC_INLINE void uc_tailq_move_tail(struct TailQ *entry, struct TailQ *head
|
|||||||
* @param head the struct TailQ* head of the tailq
|
* @param head the struct TailQ* head of the tailq
|
||||||
*/
|
*/
|
||||||
#define UC_TAILQ_FOREACH(entry, head)\
|
#define UC_TAILQ_FOREACH(entry, head)\
|
||||||
for ((entry) = (head)->next; (entry) != (head); (entry) = (entry)->next)
|
for ((entry) = UC_TAILQ_FIRST(head); \
|
||||||
|
(entry) != (head); \
|
||||||
|
(entry) = UC_TAILQ_NEXT(entry))
|
||||||
|
|
||||||
/** Iterate over a tailq in reverse order. The tailq cannot be altered while
|
/** Iterate over the containing element in a tailq.
|
||||||
* iterating.
|
* The tailq cannot be altered while iterating.
|
||||||
|
*
|
||||||
|
* @param ptr a pointer to the struct which the tailq nodes are member of
|
||||||
|
* @param member the member of ptr that is the tailq node
|
||||||
|
* @param head the struct TailQ* head of the tailq
|
||||||
|
*/
|
||||||
|
#define UC_TAILQ_FOREACH_CONTAINER(ptr, member, head)\
|
||||||
|
for ((ptr) = UC_TAILQ_CONTAINER(UC_TAILQ_FIRST(head), typeof(*ptr), member);\
|
||||||
|
&(ptr)->member != (head);\
|
||||||
|
(ptr) = UC_TAILQ_CONTAINER(UC_TAILQ_NEXT(&(ptr)->member), typeof(*ptr), member))
|
||||||
|
|
||||||
|
/** Iterate over a tailq in reverse order.
|
||||||
|
* The tailq cannot be altered while iterating.
|
||||||
*
|
*
|
||||||
* @param entry a struct TailQ* to which each element is assigned.
|
* @param entry a struct TailQ* to which each element is assigned.
|
||||||
* @param head the struct TailQ* head of the tailq
|
* @param head the struct TailQ* head of the tailq
|
||||||
*/
|
*/
|
||||||
#define UC_TAILQ_FOREACH_REVERSE(entry, head)\
|
#define UC_TAILQ_FOREACH_REVERSE(entry, head)\
|
||||||
for ((entry) = (head)->prev; (entry) != (head); (entry) = (entry)->prev)
|
for ((entry) = UC_TAILQ_LAST(entry); \
|
||||||
|
(entry) != (head); \
|
||||||
|
(entry) = UC_TAILQ_PREV(entry)
|
||||||
|
|
||||||
|
/** Iterate over the containing element in a tailq in reverse.
|
||||||
|
* The tailq cannot be altered while iterating.
|
||||||
|
*
|
||||||
|
* @param ptr a pointer to the struct which the tailq nodes are member of
|
||||||
|
* @param member the member of ptr that is the tailq node
|
||||||
|
* @param head the struct TailQ* head of the tailq
|
||||||
|
*/
|
||||||
|
#define UC_TAILQ_FOREACH_REVERSE_CONTAINER(ptr, member, head)\
|
||||||
|
for ((ptr) = UC_TAILQ_CONTAINER(UC_TAILQ_LAST(head), typeof(*ptr), member);\
|
||||||
|
&(ptr)->member != (head);\
|
||||||
|
(ptr) = UC_TAILQ_CONTAINER(UC_TAILQ_PREV(&(ptr)->member), typeof(*ptr), member))
|
||||||
|
|
||||||
/** Iterate over a tailq. safe to remove the entry when iterating.
|
/** Iterate over a tailq. safe to remove the entry when iterating.
|
||||||
*
|
*
|
||||||
@@ -173,9 +201,24 @@ static UC_INLINE void uc_tailq_move_tail(struct TailQ *entry, struct TailQ *head
|
|||||||
* @param head the struct TailQ* head of the tailq
|
* @param head the struct TailQ* head of the tailq
|
||||||
*/
|
*/
|
||||||
#define UC_TAILQ_FOREACH_SAFE(entry, nxt, head)\
|
#define UC_TAILQ_FOREACH_SAFE(entry, nxt, head)\
|
||||||
for ((entry) = (head)->next, nxt = (entry)->next; \
|
for ((entry) = UC_TAILQ_FIRST(head), (nxt) = UC_TAILQ_NEXT(entry); \
|
||||||
(entry) != (head); \
|
(entry) != (head); \
|
||||||
(entry) = (nxt), (nxt) = (entry)->next)
|
(entry) = (nxt), (nxt) = UC_TAILQ_NEXT(entry))\
|
||||||
|
|
||||||
|
/** Iterate over the containing element in a tailq, safe to remove
|
||||||
|
* the entry when iterating
|
||||||
|
*
|
||||||
|
* @param ptr a pointer to the struct which the tailq nodes are member of
|
||||||
|
* @param nxt same type as ptr needed for temporary storage.
|
||||||
|
* @param member the member of ptr that is the tailq node
|
||||||
|
* @param head the struct TailQ* head of the tailq
|
||||||
|
*/
|
||||||
|
#define UC_TAILQ_FOREACH_CONTAINER_SAFE(ptr, nxt, member, head)\
|
||||||
|
for ((ptr) = UC_TAILQ_CONTAINER(UC_TAILQ_FIRST(head), typeof(*ptr), member),\
|
||||||
|
(nxt) = UC_TAILQ_CONTAINER(UC_TAILQ_NEXT(&(ptr)->member), typeof(*ptr), member);\
|
||||||
|
&(ptr)->member != (head);\
|
||||||
|
(ptr) = (nxt),\
|
||||||
|
(nxt) = UC_TAILQ_CONTAINER(UC_TAILQ_NEXT(&(ptr)->member), typeof(*ptr), member))
|
||||||
|
|
||||||
/** Iterate over a tailq in reverse order. safe to remove the entry when
|
/** Iterate over a tailq in reverse order. safe to remove the entry when
|
||||||
* iterating.
|
* iterating.
|
||||||
@@ -185,9 +228,24 @@ static UC_INLINE void uc_tailq_move_tail(struct TailQ *entry, struct TailQ *head
|
|||||||
* @param head the struct TailQ* head of the tailq
|
* @param head the struct TailQ* head of the tailq
|
||||||
*/
|
*/
|
||||||
#define UC_TAILQ_FOREACH_REVERSE_SAFE(entry, prv, head)\
|
#define UC_TAILQ_FOREACH_REVERSE_SAFE(entry, prv, head)\
|
||||||
for ((entry) = (head)->prev, prev = (entry)->prev; \
|
for ((entry) = UC_TAILQ_LAST(head), (prv) = UC_TAILQ_PREV(entry); \
|
||||||
(entry) != (head); \
|
(entry) != (head); \
|
||||||
(entry) = (prv), (prv) = (entry)->prev)
|
(entry) = (prv), (prv) = UC_TAILQ_PREV(entry))\
|
||||||
|
|
||||||
|
/** Iterate over the containing element in a tailq in reverse order, safe
|
||||||
|
* to remove the entry when iterating
|
||||||
|
*
|
||||||
|
* @param ptr a pointer to the struct which the tailq nodes are member of
|
||||||
|
* @param prv same type as ptr needed for temporary storage.
|
||||||
|
* @param member the member of ptr that is the tailq node
|
||||||
|
* @param head the struct TailQ* head of the tailq
|
||||||
|
*/
|
||||||
|
#define UC_TAILQ_FOREACH_REVERSE_CONTAINER_SAFE(ptr, prv, member, head)\
|
||||||
|
for ((ptr) = UC_TAILQ_CONTAINER(UC_TAILQ_LAST(head), typeof(*ptr), member),\
|
||||||
|
(prv) = UC_TAILQ_CONTAINER(UC_TAILQ_PREV(&(ptr)->member), typeof(*ptr), member);\
|
||||||
|
&(ptr)->member != (head);\
|
||||||
|
(ptr) = (prv),\
|
||||||
|
(prv) = UC_TAILQ_CONTAINER(UC_TAILQ_NEXT(&(ptr)->member), typeof(*ptr), member))
|
||||||
|
|
||||||
#undef UC_INLINE
|
#undef UC_INLINE
|
||||||
|
|
||||||
|
|||||||
+22
-14
@@ -23,32 +23,38 @@ void add_block(struct File *f, const char *txt)
|
|||||||
|
|
||||||
void print_file(struct File *f)
|
void print_file(struct File *f)
|
||||||
{
|
{
|
||||||
struct TailQ *entry;
|
struct Block *entry;
|
||||||
printf("File: %s\n", f->name);
|
printf("File: %s\n", f->name);
|
||||||
UC_TAILQ_FOREACH(entry, &f->head) {
|
UC_TAILQ_FOREACH_CONTAINER(entry, blocks, &f->head) {
|
||||||
struct Block *b = UC_CONTAINER_OF(entry, struct Block, blocks);
|
printf("Block: %s\n", entry->text);
|
||||||
printf("Block: %s\n", b->text);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_file_reverse(struct File *f)
|
||||||
|
{
|
||||||
|
struct Block *entry;
|
||||||
|
printf("File: %s\n", f->name);
|
||||||
|
UC_TAILQ_FOREACH_REVERSE_CONTAINER(entry, blocks, &f->head) {
|
||||||
|
printf("Block: %s\n", entry->text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void delete_block(struct File *f, const char *txt)
|
void delete_block(struct File *f, const char *txt)
|
||||||
{
|
{
|
||||||
struct TailQ *entry, *next;
|
struct Block *entry, *next;
|
||||||
UC_TAILQ_FOREACH_SAFE(entry, next, &f->head) {
|
UC_TAILQ_FOREACH_CONTAINER_SAFE(entry, next, blocks, &f->head) {
|
||||||
struct Block *b = UC_CONTAINER_OF(entry, struct Block, blocks);
|
if (strcmp(txt, entry->text) == 0) {
|
||||||
if (strcmp(txt, b->text) == 0) {
|
uc_tailq_remove(&entry->blocks);
|
||||||
uc_tailq_remove(entry);
|
free(entry);
|
||||||
free(b);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void delete_all_blocks(struct File *f)
|
void delete_all_blocks(struct File *f)
|
||||||
{
|
{
|
||||||
struct TailQ *entry, *next;
|
struct Block *entry, *next;
|
||||||
UC_TAILQ_FOREACH_SAFE(entry, next, &f->head) {
|
UC_TAILQ_FOREACH_CONTAINER_SAFE(entry, next, blocks, &f->head) {
|
||||||
struct Block *b = UC_CONTAINER_OF(entry, struct Block, blocks);
|
free(entry);
|
||||||
free(b);
|
|
||||||
}
|
}
|
||||||
uc_tailq_init(&f->head);
|
uc_tailq_init(&f->head);
|
||||||
}
|
}
|
||||||
@@ -74,6 +80,8 @@ int main(void)
|
|||||||
add_block(&f,"three");
|
add_block(&f,"three");
|
||||||
add_block(&f,"three");
|
add_block(&f,"three");
|
||||||
print_file(&f);
|
print_file(&f);
|
||||||
|
puts("\nReverse order:");
|
||||||
|
print_file_reverse(&f);
|
||||||
|
|
||||||
puts("\nDeleting three");
|
puts("\nDeleting three");
|
||||||
delete_block(&f, "three");
|
delete_block(&f, "three");
|
||||||
|
|||||||
Reference in New Issue
Block a user