Path: blob/main/system/lib/llvm-libc/include/llvm-libc-macros/sys-queue-macros.h
6174 views
//===-- Macros defined in sys/queue.h header file -------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#ifndef LLVM_LIBC_MACROS_SYS_QUEUE_MACROS_H9#define LLVM_LIBC_MACROS_SYS_QUEUE_MACROS_H1011#include "containerof-macro.h"12#include "null-macro.h"1314#ifdef __cplusplus15#define QUEUE_TYPEOF(type) type16#else17#define QUEUE_TYPEOF(type) struct type18#endif1920// Singly-linked list definitions.2122#define SLIST_HEAD(name, type) \23struct name { \24struct type *slh_first; \25}2627#define SLIST_CLASS_HEAD(name, type) \28struct name { \29class type *slh_first; \30}3132#define SLIST_HEAD_INITIALIZER(head) \33{ NULL }3435#define SLIST_ENTRY(type) \36struct { \37struct type *next; \38}3940#define SLIST_CLASS_ENTRY(type) \41struct { \42class type *next; \43}4445// Singly-linked list access methods.4647#define SLIST_EMPTY(head) ((head)->slh_first == NULL)48#define SLIST_FIRST(head) ((head)->slh_first)49#define SLIST_NEXT(elem, field) ((elem)->field.next)5051#define SLIST_FOREACH(var, head, field) \52for ((var) = SLIST_FIRST(head); (var); (var) = SLIST_NEXT(var, field))5354#define SLIST_FOREACH_FROM(var, head, field) \55if (!(var)) \56(var) = SLIST_FIRST(head); \57for (; (var); (var) = SLIST_NEXT(var, field))5859#define SLIST_FOREACH_SAFE(var, head, field, tvar) \60for ((var) = SLIST_FIRST(head); \61(var) && ((tvar) = SLIST_NEXT(var, field), 1); (var) = (tvar))6263#define SLIST_FOREACH_FROM_SAFE(var, head, field, tvar) \64if (!(var)) \65(var) = SLIST_FIRST(head); \66for (; (var) && ((tvar) = SLIST_NEXT(var, field), 1); (var) = (tvar))6768// Singly-linked list functions.6970#define SLIST_CONCAT(head1, head2, type, field) \71do { \72if (SLIST_EMPTY(head1)) { \73if ((SLIST_FIRST(head1) = SLIST_FIRST(head2)) != NULL) \74SLIST_INIT(head2); \75} else if (!SLIST_EMPTY(head2)) { \76QUEUE_TYPEOF(type) *cur = SLIST_FIRST(head1); \77while (SLIST_NEXT(cur, field) != NULL) \78cur = SLIST_NEXT(cur, field); \79SLIST_NEXT(cur, field) = SLIST_FIRST(head2); \80SLIST_INIT(head2); \81} \82} while (0)8384#define SLIST_INIT(head) \85do { \86SLIST_FIRST(head) = NULL; \87} while (0)8889#define SLIST_INSERT_AFTER(slistelem, elem, field) \90do { \91SLIST_NEXT(elem, field) = SLIST_NEXT(slistelem, field); \92SLIST_NEXT(slistelem, field) = (elem); \93} while (0)9495#define SLIST_INSERT_HEAD(head, elem, field) \96do { \97SLIST_NEXT(elem, field) = SLIST_FIRST(head); \98SLIST_FIRST(head) = (elem); \99} while (0)100101#define SLIST_REMOVE(head, elem, type, field) \102do { \103if (SLIST_FIRST(head) == (elem)) { \104SLIST_REMOVE_HEAD(head, field); \105} else { \106QUEUE_TYPEOF(type) *cur = SLIST_FIRST(head); \107while (SLIST_NEXT(cur, field) != (elem)) \108cur = SLIST_NEXT(cur, field); \109SLIST_REMOVE_AFTER(cur, field); \110} \111} while (0)112113#define SLIST_REMOVE_AFTER(elem, field) \114do { \115SLIST_NEXT(elem, field) = SLIST_NEXT(SLIST_NEXT(elem, field), field); \116} while (0)117118#define SLIST_REMOVE_HEAD(head, field) \119do { \120SLIST_FIRST(head) = SLIST_NEXT(SLIST_FIRST(head), field); \121} while (0)122123#define SLIST_SWAP(head1, head2, type) \124do { \125QUEUE_TYPEOF(type) *first = SLIST_FIRST(head1); \126SLIST_FIRST(head1) = SLIST_FIRST(head2); \127SLIST_FIRST(head2) = first; \128} while (0)129130// Singly-linked tail queue definitions.131132#define STAILQ_HEAD(name, type) \133struct name { \134struct type *stqh_first; \135struct type **stqh_last; \136}137138#define STAILQ_CLASS_HEAD(name, type) \139struct name { \140class type *stqh_first; \141class type **stqh_last; \142}143144#define STAILQ_HEAD_INITIALIZER(head) \145{ NULL, &(head).stqh_first }146147#define STAILQ_ENTRY(type) \148struct { \149struct type *next; \150}151152#define STAILQ_CLASS_ENTRY(type) \153struct { \154class type *next; \155}156157// Singly-linked tail queue access methods.158159#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL)160#define STAILQ_FIRST(head) ((head)->stqh_first)161#define STAILQ_LAST(head, type, field) \162(STAILQ_EMPTY(head) \163? NULL \164: __containerof((head)->stqh_last, QUEUE_TYPEOF(type), field.next))165#define STAILQ_NEXT(elem, field) ((elem)->field.next)166167#define STAILQ_FOREACH(var, head, field) \168for ((var) = STAILQ_FIRST(head); (var); (var) = STAILQ_NEXT(var, field))169170#define STAILQ_FOREACH_FROM(var, head, field) \171if (!(var)) \172(var) = STAILQ_FIRST(head); \173for (; (var); (var) = STAILQ_NEXT(var, field))174175#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \176for ((var) = STAILQ_FIRST(head); \177(var) && ((tvar) = STAILQ_NEXT(var, field), 1); (var) = (tvar))178179#define STAILQ_FOREACH_FROM_SAFE(var, head, field, tvar) \180if (!(var)) \181(var) = STAILQ_FIRST(head); \182for (; (var) && ((tvar) = STAILQ_NEXT(var, field), 1); (var) = (tvar))183184// Singly-linked tail queue functions.185186#define STAILQ_CONCAT(head1, head2, type, field) \187do { \188if (!STAILQ_EMPTY(head2)) { \189*(head1)->stqh_last = (head2)->stqh_first; \190(head1)->stqh_last = (head2)->stqh_last; \191STAILQ_INIT(head2); \192} \193} while (0)194195#define STAILQ_INIT(head) \196do { \197STAILQ_FIRST(head) = NULL; \198(head)->stqh_last = &STAILQ_FIRST(head); \199} while (0)200201#define STAILQ_INSERT_AFTER(head, listelem, elem, field) \202do { \203if ((STAILQ_NEXT(elem, field) = STAILQ_NEXT(listelem, field)) == NULL) \204(head)->stqh_last = &STAILQ_NEXT(elem, field); \205STAILQ_NEXT(listelem, field) = (elem); \206} while (0)207208#define STAILQ_INSERT_HEAD(head, elem, field) \209do { \210if ((STAILQ_NEXT(elem, field) = STAILQ_FIRST(head)) == NULL) \211(head)->stqh_last = &STAILQ_NEXT(elem, field); \212STAILQ_FIRST(head) = (elem); \213} while (0)214215#define STAILQ_INSERT_TAIL(head, elem, field) \216do { \217STAILQ_NEXT(elem, field) = NULL; \218*(head)->stqh_last = (elem); \219(head)->stqh_last = &STAILQ_NEXT(elem, field); \220} while (0)221222#define STAILQ_REMOVE(head, elem, type, field) \223do { \224if (STAILQ_FIRST(head) == (elem)) { \225STAILQ_REMOVE_HEAD(head, field); \226} else { \227QUEUE_TYPEOF(type) *cur = STAILQ_FIRST(head); \228while (STAILQ_NEXT(cur, field) != (elem)) \229cur = STAILQ_NEXT(cur, field); \230STAILQ_REMOVE_AFTER(head, cur, field); \231} \232} while (0)233234#define STAILQ_REMOVE_AFTER(head, elem, field) \235do { \236if ((STAILQ_NEXT(elem, field) = \237STAILQ_NEXT(STAILQ_NEXT(elem, field), field)) == NULL) \238(head)->stqh_last = &STAILQ_NEXT(elem, field); \239} while (0)240241#define STAILQ_REMOVE_HEAD(head, field) \242do { \243if ((STAILQ_FIRST(head) = STAILQ_NEXT(STAILQ_FIRST(head), field)) == NULL) \244(head)->stqh_last = &STAILQ_FIRST(head); \245} while (0)246247#define STAILQ_SWAP(head1, head2, type) \248do { \249QUEUE_TYPEOF(type) *first = STAILQ_FIRST(head1); \250QUEUE_TYPEOF(type) **last = (head1)->stqh_last; \251STAILQ_FIRST(head1) = STAILQ_FIRST(head2); \252(head1)->stqh_last = (head2)->stqh_last; \253STAILQ_FIRST(head2) = first; \254(head2)->stqh_last = last; \255if (STAILQ_EMPTY(head1)) \256(head1)->stqh_last = &STAILQ_FIRST(head1); \257if (STAILQ_EMPTY(head2)) \258(head2)->stqh_last = &STAILQ_FIRST(head2); \259} while (0)260261#endif // LLVM_LIBC_MACROS_SYS_QUEUE_MACROS_H262263264