Path: blob/main/crypto/openssl/include/internal/list.h
104660 views
/*1* Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.2*3* Licensed under the Apache License 2.0 (the "License"). You may not use4* this file except in compliance with the License. You can obtain a copy5* in the file LICENSE in the source distribution or at6* https://www.openssl.org/source/license.html7*/89#ifndef OSSL_INTERNAL_LIST_H10#define OSSL_INTERNAL_LIST_H11#pragma once1213#include <string.h>14#include <assert.h>1516#ifdef NDEBUG17#define OSSL_LIST_DBG(x)18#else19#define OSSL_LIST_DBG(x) x;20#endif2122#define OSSL_LIST_FOREACH_FROM(p, name, init) \23for ((p) = (init); \24(p) != NULL; \25(p) = ossl_list_##name##_next(p))26#define OSSL_LIST_FOREACH(p, name, l) \27OSSL_LIST_FOREACH_FROM(p, name, ossl_list_##name##_head(l))2829#define OSSL_LIST_FOREACH_REV_FROM(p, name, init) \30for ((p) = (init); \31(p) != NULL; \32(p) = ossl_list_##name##_prev(p))33#define OSSL_LIST_FOREACH_REV(p, name, l) \34OSSL_LIST_FOREACH_FROM(p, name, ossl_list_##name##_tail(l))3536#define OSSL_LIST_FOREACH_DELSAFE_FROM(p, pn, name, init) \37for ((p) = (init); \38(p) != NULL && (((pn) = ossl_list_##name##_next(p)), 1); \39(p) = (pn))40#define OSSL_LIST_FOREACH_DELSAFE(p, pn, name, l) \41OSSL_LIST_FOREACH_DELSAFE_FROM(p, pn, name, ossl_list_##name##_head(l))4243#define OSSL_LIST_FOREACH_REV_DELSAFE_FROM(p, pn, name, init) \44for ((p) = (init); \45(p) != NULL && (((pn) = ossl_list_##name##_prev(p)), 1); \46(p) = (pn))47#define OSSL_LIST_FOREACH_REV_DELSAFE(p, pn, name, l) \48OSSL_LIST_FOREACH_REV_DELSAFE_FROM(p, pn, name, ossl_list_##name##_tail(l))4950/* Define a list structure */51#define OSSL_LIST(name) OSSL_LIST_##name5253/* Define fields to include an element of a list */54#define OSSL_LIST_MEMBER(name, type) \55struct { \56type *next, *prev; \57OSSL_LIST_DBG(struct ossl_list_st_##name *list) \58} ossl_list_##name5960#define DECLARE_LIST_OF(name, type) \61typedef struct ossl_list_st_##name OSSL_LIST(name); \62struct ossl_list_st_##name { \63type *alpha, *omega; \64size_t num_elems; \65}6667#define DEFINE_LIST_OF_IMPL(name, type) \68static ossl_unused ossl_inline void \69ossl_list_##name##_init(OSSL_LIST(name) * list) \70{ \71memset(list, 0, sizeof(*list)); \72} \73static ossl_unused ossl_inline void \74ossl_list_##name##_init_elem(type *elem) \75{ \76memset(&elem->ossl_list_##name, 0, \77sizeof(elem->ossl_list_##name)); \78} \79static ossl_unused ossl_inline int \80ossl_list_##name##_is_empty(const OSSL_LIST(name) * list) \81{ \82return list->num_elems == 0; \83} \84static ossl_unused ossl_inline size_t \85ossl_list_##name##_num(const OSSL_LIST(name) * list) \86{ \87return list->num_elems; \88} \89static ossl_unused ossl_inline type * \90ossl_list_##name##_head(const OSSL_LIST(name) * list) \91{ \92assert(list->alpha == NULL \93|| list->alpha->ossl_list_##name.list == list); \94return list->alpha; \95} \96static ossl_unused ossl_inline type * \97ossl_list_##name##_tail(const OSSL_LIST(name) * list) \98{ \99assert(list->omega == NULL \100|| list->omega->ossl_list_##name.list == list); \101return list->omega; \102} \103static ossl_unused ossl_inline type * \104ossl_list_##name##_next(const type *elem) \105{ \106assert(elem->ossl_list_##name.next == NULL \107|| elem->ossl_list_##name.next \108->ossl_list_##name.prev \109== elem); \110return elem->ossl_list_##name.next; \111} \112static ossl_unused ossl_inline type * \113ossl_list_##name##_prev(const type *elem) \114{ \115assert(elem->ossl_list_##name.prev == NULL \116|| elem->ossl_list_##name.prev \117->ossl_list_##name.next \118== elem); \119return elem->ossl_list_##name.prev; \120} \121static ossl_unused ossl_inline void \122ossl_list_##name##_remove(OSSL_LIST(name) * list, type * elem) \123{ \124assert(elem->ossl_list_##name.list == list); \125OSSL_LIST_DBG(elem->ossl_list_##name.list = NULL) \126if (list->alpha == elem) \127list->alpha = elem->ossl_list_##name.next; \128if (list->omega == elem) \129list->omega = elem->ossl_list_##name.prev; \130if (elem->ossl_list_##name.prev != NULL) \131elem->ossl_list_##name.prev->ossl_list_##name.next = elem->ossl_list_##name.next; \132if (elem->ossl_list_##name.next != NULL) \133elem->ossl_list_##name.next->ossl_list_##name.prev = elem->ossl_list_##name.prev; \134list->num_elems--; \135memset(&elem->ossl_list_##name, 0, \136sizeof(elem->ossl_list_##name)); \137} \138static ossl_unused ossl_inline void \139ossl_list_##name##_insert_head(OSSL_LIST(name) * list, type * elem) \140{ \141assert(elem->ossl_list_##name.list == NULL); \142OSSL_LIST_DBG(elem->ossl_list_##name.list = list) \143if (list->alpha != NULL) \144list->alpha->ossl_list_##name.prev = elem; \145elem->ossl_list_##name.next = list->alpha; \146elem->ossl_list_##name.prev = NULL; \147list->alpha = elem; \148if (list->omega == NULL) \149list->omega = elem; \150list->num_elems++; \151} \152static ossl_unused ossl_inline void \153ossl_list_##name##_insert_tail(OSSL_LIST(name) * list, type * elem) \154{ \155assert(elem->ossl_list_##name.list == NULL); \156OSSL_LIST_DBG(elem->ossl_list_##name.list = list) \157if (list->omega != NULL) \158list->omega->ossl_list_##name.next = elem; \159elem->ossl_list_##name.prev = list->omega; \160elem->ossl_list_##name.next = NULL; \161list->omega = elem; \162if (list->alpha == NULL) \163list->alpha = elem; \164list->num_elems++; \165} \166static ossl_unused ossl_inline void \167ossl_list_##name##_insert_before(OSSL_LIST(name) * list, type * e, \168type * elem) \169{ \170assert(elem->ossl_list_##name.list == NULL); \171OSSL_LIST_DBG(elem->ossl_list_##name.list = list) \172elem->ossl_list_##name.next = e; \173elem->ossl_list_##name.prev = e->ossl_list_##name.prev; \174if (e->ossl_list_##name.prev != NULL) \175e->ossl_list_##name.prev->ossl_list_##name.next = elem; \176e->ossl_list_##name.prev = elem; \177if (list->alpha == e) \178list->alpha = elem; \179list->num_elems++; \180} \181static ossl_unused ossl_inline void \182ossl_list_##name##_insert_after(OSSL_LIST(name) * list, type * e, \183type * elem) \184{ \185assert(elem->ossl_list_##name.list == NULL); \186OSSL_LIST_DBG(elem->ossl_list_##name.list = list) \187elem->ossl_list_##name.prev = e; \188elem->ossl_list_##name.next = e->ossl_list_##name.next; \189if (e->ossl_list_##name.next != NULL) \190e->ossl_list_##name.next->ossl_list_##name.prev = elem; \191e->ossl_list_##name.next = elem; \192if (list->omega == e) \193list->omega = elem; \194list->num_elems++; \195} \196struct ossl_list_st_##name197198#define DEFINE_LIST_OF(name, type) \199DECLARE_LIST_OF(name, type); \200DEFINE_LIST_OF_IMPL(name, type)201202#endif203204205