Home | History | Annotate | Line # | Download | only in internal
      1      1.1  christos /*
      2      1.1  christos  * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
      3      1.1  christos  *
      4      1.1  christos  * Licensed under the Apache License 2.0 (the "License").  You may not use
      5      1.1  christos  * this file except in compliance with the License.  You can obtain a copy
      6      1.1  christos  * in the file LICENSE in the source distribution or at
      7      1.1  christos  * https://www.openssl.org/source/license.html
      8      1.1  christos  */
      9      1.1  christos 
     10      1.1  christos #ifndef OSSL_INTERNAL_LIST_H
     11  1.1.1.2  christos #define OSSL_INTERNAL_LIST_H
     12  1.1.1.2  christos #pragma once
     13      1.1  christos 
     14  1.1.1.2  christos #include <string.h>
     15  1.1.1.2  christos #include <assert.h>
     16      1.1  christos 
     17  1.1.1.2  christos #ifdef NDEBUG
     18  1.1.1.2  christos #define OSSL_LIST_DBG(x)
     19  1.1.1.2  christos #else
     20  1.1.1.2  christos #define OSSL_LIST_DBG(x) x;
     21  1.1.1.2  christos #endif
     22  1.1.1.2  christos 
     23  1.1.1.2  christos #define OSSL_LIST_FOREACH_FROM(p, name, init) \
     24  1.1.1.2  christos     for ((p) = (init);                        \
     25  1.1.1.2  christos         (p) != NULL;                          \
     26  1.1.1.2  christos         (p) = ossl_list_##name##_next(p))
     27  1.1.1.2  christos #define OSSL_LIST_FOREACH(p, name, l) \
     28      1.1  christos     OSSL_LIST_FOREACH_FROM(p, name, ossl_list_##name##_head(l))
     29      1.1  christos 
     30  1.1.1.2  christos #define OSSL_LIST_FOREACH_REV_FROM(p, name, init) \
     31  1.1.1.2  christos     for ((p) = (init);                            \
     32  1.1.1.2  christos         (p) != NULL;                              \
     33  1.1.1.2  christos         (p) = ossl_list_##name##_prev(p))
     34  1.1.1.2  christos #define OSSL_LIST_FOREACH_REV(p, name, l) \
     35      1.1  christos     OSSL_LIST_FOREACH_FROM(p, name, ossl_list_##name##_tail(l))
     36      1.1  christos 
     37  1.1.1.2  christos #define OSSL_LIST_FOREACH_DELSAFE_FROM(p, pn, name, init)        \
     38  1.1.1.2  christos     for ((p) = (init);                                           \
     39  1.1.1.2  christos         (p) != NULL && (((pn) = ossl_list_##name##_next(p)), 1); \
     40  1.1.1.2  christos         (p) = (pn))
     41  1.1.1.2  christos #define OSSL_LIST_FOREACH_DELSAFE(p, pn, name, l) \
     42      1.1  christos     OSSL_LIST_FOREACH_DELSAFE_FROM(p, pn, name, ossl_list_##name##_head(l))
     43      1.1  christos 
     44  1.1.1.2  christos #define OSSL_LIST_FOREACH_REV_DELSAFE_FROM(p, pn, name, init)    \
     45  1.1.1.2  christos     for ((p) = (init);                                           \
     46  1.1.1.2  christos         (p) != NULL && (((pn) = ossl_list_##name##_prev(p)), 1); \
     47  1.1.1.2  christos         (p) = (pn))
     48  1.1.1.2  christos #define OSSL_LIST_FOREACH_REV_DELSAFE(p, pn, name, l) \
     49      1.1  christos     OSSL_LIST_FOREACH_REV_DELSAFE_FROM(p, pn, name, ossl_list_##name##_tail(l))
     50      1.1  christos 
     51      1.1  christos /* Define a list structure */
     52  1.1.1.2  christos #define OSSL_LIST(name) OSSL_LIST_##name
     53      1.1  christos 
     54      1.1  christos /* Define fields to include an element of a list */
     55  1.1.1.2  christos #define OSSL_LIST_MEMBER(name, type)                    \
     56  1.1.1.2  christos     struct {                                            \
     57  1.1.1.2  christos         type *next, *prev;                              \
     58  1.1.1.2  christos         OSSL_LIST_DBG(struct ossl_list_st_##name *list) \
     59  1.1.1.2  christos     } ossl_list_##name
     60  1.1.1.2  christos 
     61  1.1.1.2  christos #define DECLARE_LIST_OF(name, type)                     \
     62  1.1.1.2  christos     typedef struct ossl_list_st_##name OSSL_LIST(name); \
     63  1.1.1.2  christos     struct ossl_list_st_##name {                        \
     64  1.1.1.2  christos         type *alpha, *omega;                            \
     65  1.1.1.2  christos         size_t num_elems;                               \
     66  1.1.1.2  christos     }
     67  1.1.1.2  christos 
     68  1.1.1.2  christos #define DEFINE_LIST_OF_IMPL(name, type)                                                       \
     69  1.1.1.2  christos     static ossl_unused ossl_inline void                                                       \
     70  1.1.1.2  christos     ossl_list_##name##_init(OSSL_LIST(name) * list)                                           \
     71  1.1.1.2  christos     {                                                                                         \
     72  1.1.1.2  christos         memset(list, 0, sizeof(*list));                                                       \
     73  1.1.1.2  christos     }                                                                                         \
     74  1.1.1.2  christos     static ossl_unused ossl_inline void                                                       \
     75  1.1.1.2  christos     ossl_list_##name##_init_elem(type *elem)                                                  \
     76  1.1.1.2  christos     {                                                                                         \
     77  1.1.1.2  christos         memset(&elem->ossl_list_##name, 0,                                                    \
     78  1.1.1.2  christos             sizeof(elem->ossl_list_##name));                                                  \
     79  1.1.1.2  christos     }                                                                                         \
     80  1.1.1.2  christos     static ossl_unused ossl_inline int                                                        \
     81  1.1.1.2  christos     ossl_list_##name##_is_empty(const OSSL_LIST(name) * list)                                 \
     82  1.1.1.2  christos     {                                                                                         \
     83  1.1.1.2  christos         return list->num_elems == 0;                                                          \
     84  1.1.1.2  christos     }                                                                                         \
     85  1.1.1.2  christos     static ossl_unused ossl_inline size_t                                                     \
     86  1.1.1.2  christos     ossl_list_##name##_num(const OSSL_LIST(name) * list)                                      \
     87  1.1.1.2  christos     {                                                                                         \
     88  1.1.1.2  christos         return list->num_elems;                                                               \
     89  1.1.1.2  christos     }                                                                                         \
     90  1.1.1.2  christos     static ossl_unused ossl_inline type *                                                     \
     91  1.1.1.2  christos     ossl_list_##name##_head(const OSSL_LIST(name) * list)                                     \
     92  1.1.1.2  christos     {                                                                                         \
     93  1.1.1.2  christos         assert(list->alpha == NULL                                                            \
     94  1.1.1.2  christos             || list->alpha->ossl_list_##name.list == list);                                   \
     95  1.1.1.2  christos         return list->alpha;                                                                   \
     96  1.1.1.2  christos     }                                                                                         \
     97  1.1.1.2  christos     static ossl_unused ossl_inline type *                                                     \
     98  1.1.1.2  christos     ossl_list_##name##_tail(const OSSL_LIST(name) * list)                                     \
     99  1.1.1.2  christos     {                                                                                         \
    100  1.1.1.2  christos         assert(list->omega == NULL                                                            \
    101  1.1.1.2  christos             || list->omega->ossl_list_##name.list == list);                                   \
    102  1.1.1.2  christos         return list->omega;                                                                   \
    103  1.1.1.2  christos     }                                                                                         \
    104  1.1.1.2  christos     static ossl_unused ossl_inline type *                                                     \
    105  1.1.1.2  christos     ossl_list_##name##_next(const type *elem)                                                 \
    106  1.1.1.2  christos     {                                                                                         \
    107  1.1.1.2  christos         assert(elem->ossl_list_##name.next == NULL                                            \
    108  1.1.1.2  christos             || elem->ossl_list_##name.next                                                    \
    109  1.1.1.2  christos                     ->ossl_list_##name.prev                                                   \
    110  1.1.1.2  christos                 == elem);                                                                     \
    111  1.1.1.2  christos         return elem->ossl_list_##name.next;                                                   \
    112  1.1.1.2  christos     }                                                                                         \
    113  1.1.1.2  christos     static ossl_unused ossl_inline type *                                                     \
    114  1.1.1.2  christos     ossl_list_##name##_prev(const type *elem)                                                 \
    115  1.1.1.2  christos     {                                                                                         \
    116  1.1.1.2  christos         assert(elem->ossl_list_##name.prev == NULL                                            \
    117  1.1.1.2  christos             || elem->ossl_list_##name.prev                                                    \
    118  1.1.1.2  christos                     ->ossl_list_##name.next                                                   \
    119  1.1.1.2  christos                 == elem);                                                                     \
    120  1.1.1.2  christos         return elem->ossl_list_##name.prev;                                                   \
    121  1.1.1.2  christos     }                                                                                         \
    122  1.1.1.2  christos     static ossl_unused ossl_inline void                                                       \
    123  1.1.1.2  christos     ossl_list_##name##_remove(OSSL_LIST(name) * list, type * elem)                            \
    124  1.1.1.2  christos     {                                                                                         \
    125  1.1.1.2  christos         assert(elem->ossl_list_##name.list == list);                                          \
    126  1.1.1.2  christos         OSSL_LIST_DBG(elem->ossl_list_##name.list = NULL)                                     \
    127  1.1.1.2  christos         if (list->alpha == elem)                                                              \
    128  1.1.1.2  christos             list->alpha = elem->ossl_list_##name.next;                                        \
    129  1.1.1.2  christos         if (list->omega == elem)                                                              \
    130  1.1.1.2  christos             list->omega = elem->ossl_list_##name.prev;                                        \
    131  1.1.1.2  christos         if (elem->ossl_list_##name.prev != NULL)                                              \
    132  1.1.1.2  christos             elem->ossl_list_##name.prev->ossl_list_##name.next = elem->ossl_list_##name.next; \
    133  1.1.1.2  christos         if (elem->ossl_list_##name.next != NULL)                                              \
    134  1.1.1.2  christos             elem->ossl_list_##name.next->ossl_list_##name.prev = elem->ossl_list_##name.prev; \
    135  1.1.1.2  christos         list->num_elems--;                                                                    \
    136  1.1.1.2  christos         memset(&elem->ossl_list_##name, 0,                                                    \
    137  1.1.1.2  christos             sizeof(elem->ossl_list_##name));                                                  \
    138  1.1.1.2  christos     }                                                                                         \
    139  1.1.1.2  christos     static ossl_unused ossl_inline void                                                       \
    140  1.1.1.2  christos     ossl_list_##name##_insert_head(OSSL_LIST(name) * list, type * elem)                       \
    141  1.1.1.2  christos     {                                                                                         \
    142  1.1.1.2  christos         assert(elem->ossl_list_##name.list == NULL);                                          \
    143  1.1.1.2  christos         OSSL_LIST_DBG(elem->ossl_list_##name.list = list)                                     \
    144  1.1.1.2  christos         if (list->alpha != NULL)                                                              \
    145  1.1.1.2  christos             list->alpha->ossl_list_##name.prev = elem;                                        \
    146  1.1.1.2  christos         elem->ossl_list_##name.next = list->alpha;                                            \
    147  1.1.1.2  christos         elem->ossl_list_##name.prev = NULL;                                                   \
    148  1.1.1.2  christos         list->alpha = elem;                                                                   \
    149  1.1.1.2  christos         if (list->omega == NULL)                                                              \
    150  1.1.1.2  christos             list->omega = elem;                                                               \
    151  1.1.1.2  christos         list->num_elems++;                                                                    \
    152  1.1.1.2  christos     }                                                                                         \
    153  1.1.1.2  christos     static ossl_unused ossl_inline void                                                       \
    154  1.1.1.2  christos     ossl_list_##name##_insert_tail(OSSL_LIST(name) * list, type * elem)                       \
    155  1.1.1.2  christos     {                                                                                         \
    156  1.1.1.2  christos         assert(elem->ossl_list_##name.list == NULL);                                          \
    157  1.1.1.2  christos         OSSL_LIST_DBG(elem->ossl_list_##name.list = list)                                     \
    158  1.1.1.2  christos         if (list->omega != NULL)                                                              \
    159  1.1.1.2  christos             list->omega->ossl_list_##name.next = elem;                                        \
    160  1.1.1.2  christos         elem->ossl_list_##name.prev = list->omega;                                            \
    161  1.1.1.2  christos         elem->ossl_list_##name.next = NULL;                                                   \
    162  1.1.1.2  christos         list->omega = elem;                                                                   \
    163  1.1.1.2  christos         if (list->alpha == NULL)                                                              \
    164  1.1.1.2  christos             list->alpha = elem;                                                               \
    165  1.1.1.2  christos         list->num_elems++;                                                                    \
    166  1.1.1.2  christos     }                                                                                         \
    167  1.1.1.2  christos     static ossl_unused ossl_inline void                                                       \
    168  1.1.1.2  christos     ossl_list_##name##_insert_before(OSSL_LIST(name) * list, type * e,                        \
    169  1.1.1.2  christos         type * elem)                                                                          \
    170  1.1.1.2  christos     {                                                                                         \
    171  1.1.1.2  christos         assert(elem->ossl_list_##name.list == NULL);                                          \
    172  1.1.1.2  christos         OSSL_LIST_DBG(elem->ossl_list_##name.list = list)                                     \
    173  1.1.1.2  christos         elem->ossl_list_##name.next = e;                                                      \
    174  1.1.1.2  christos         elem->ossl_list_##name.prev = e->ossl_list_##name.prev;                               \
    175  1.1.1.2  christos         if (e->ossl_list_##name.prev != NULL)                                                 \
    176  1.1.1.2  christos             e->ossl_list_##name.prev->ossl_list_##name.next = elem;                           \
    177  1.1.1.2  christos         e->ossl_list_##name.prev = elem;                                                      \
    178  1.1.1.2  christos         if (list->alpha == e)                                                                 \
    179  1.1.1.2  christos             list->alpha = elem;                                                               \
    180  1.1.1.2  christos         list->num_elems++;                                                                    \
    181  1.1.1.2  christos     }                                                                                         \
    182  1.1.1.2  christos     static ossl_unused ossl_inline void                                                       \
    183  1.1.1.2  christos     ossl_list_##name##_insert_after(OSSL_LIST(name) * list, type * e,                         \
    184  1.1.1.2  christos         type * elem)                                                                          \
    185  1.1.1.2  christos     {                                                                                         \
    186  1.1.1.2  christos         assert(elem->ossl_list_##name.list == NULL);                                          \
    187  1.1.1.2  christos         OSSL_LIST_DBG(elem->ossl_list_##name.list = list)                                     \
    188  1.1.1.2  christos         elem->ossl_list_##name.prev = e;                                                      \
    189  1.1.1.2  christos         elem->ossl_list_##name.next = e->ossl_list_##name.next;                               \
    190  1.1.1.2  christos         if (e->ossl_list_##name.next != NULL)                                                 \
    191  1.1.1.2  christos             e->ossl_list_##name.next->ossl_list_##name.prev = elem;                           \
    192  1.1.1.2  christos         e->ossl_list_##name.next = elem;                                                      \
    193  1.1.1.2  christos         if (list->omega == e)                                                                 \
    194  1.1.1.2  christos             list->omega = elem;                                                               \
    195  1.1.1.2  christos         list->num_elems++;                                                                    \
    196  1.1.1.2  christos     }                                                                                         \
    197  1.1.1.2  christos     struct ossl_list_st_##name
    198      1.1  christos 
    199  1.1.1.2  christos #define DEFINE_LIST_OF(name, type) \
    200  1.1.1.2  christos     DECLARE_LIST_OF(name, type);   \
    201      1.1  christos     DEFINE_LIST_OF_IMPL(name, type)
    202      1.1  christos 
    203      1.1  christos #endif
    204