Path: blob/main/crypto/openssl/include/internal/list.h
34879 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 == elem); \109return elem->ossl_list_ ## name.next; \110} \111static ossl_unused ossl_inline type * \112ossl_list_##name##_prev(const type *elem) \113{ \114assert(elem->ossl_list_ ## name.prev == NULL \115|| elem->ossl_list_ ## name.prev \116->ossl_list_ ## name.next == elem); \117return elem->ossl_list_ ## name.prev; \118} \119static ossl_unused ossl_inline void \120ossl_list_##name##_remove(OSSL_LIST(name) *list, type *elem) \121{ \122assert(elem->ossl_list_ ## name.list == list); \123OSSL_LIST_DBG(elem->ossl_list_ ## name.list = NULL) \124if (list->alpha == elem) \125list->alpha = elem->ossl_list_ ## name.next; \126if (list->omega == elem) \127list->omega = elem->ossl_list_ ## name.prev; \128if (elem->ossl_list_ ## name.prev != NULL) \129elem->ossl_list_ ## name.prev->ossl_list_ ## name.next = \130elem->ossl_list_ ## name.next; \131if (elem->ossl_list_ ## name.next != NULL) \132elem->ossl_list_ ## name.next->ossl_list_ ## name.prev = \133elem->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