Welcome to mirror list, hosted at ThFree Co, Russian Federation.

llist.h « mac « include « stack « zigbee « STM32_WPAN « ST « Middlewares - github.com/Flipper-Zero/STM32CubeWB.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 8c986267bded515272e9f0c426ac7bcbffdb9297 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
/* Copyright [2009 - 2018] Exegin Technologies Limited. All rights reserved. */
/* Description: Double Linked List Helpers */

#ifndef LLIST_H
#define LLIST_H

/* Static initializers */
#define LINK_LIST_STATIC(_p_) {(_p_), (_p_)}

/* Initialize a list to an empty state, or an item to an unlinked state. */
#define LINK_LIST_INIT(_p_) \
    do {  \
        (_p_)->next = (_p_); \
        (_p_)->prev = (_p_); \
    } while (false)

/* Cast a list item to its parent type. */
/*lint --emacro((413),LINK_LIST_ITEM) */
/*lint --emacro((511),LINK_LIST_ITEM) */
/*lint --emacro((613),LINK_LIST_ITEM) */
/*lint --emacro((923),LINK_LIST_ITEM) */
/*lint --emacro((9033),LINK_LIST_ITEM) */
/* Warning 413: Likely use of null pointer 'unknown-name' in left argument to operator '->' [MISRA 2012 Rule 1.3, required] */
/* Warning 511: Size incompatibility in cast from 'unsigned long' (8 bytes) to 'struct ZbMsgT *' (4 bytes) */
/* Warning 613: Possible use of null pointer 'zb' in left argument to operator '->' */
/* Note 923: cast from pointer to unsigned long [MISRA 2012 Rule 11.6, required] */
/* Note 9033: Impermissible cast of composite expression (different essential type categories) [MISRA 2012 Rule 10.8, required] */
#define LINK_LIST_ITEM(_p_, _type_, _member_)   ((_type_ *)((unsigned long)(_p_) - (unsigned long)(&((_type_ *)0)->_member_)))

/* Returns the next/previous list item or NULL if at the end of the list. */
#define LINK_LIST_NEXT(_p_, _list_)     (((_p_)->next != (_list_)) ? (_p_)->next : NULL)
#define LINK_LIST_PREV(_p_, _list_)     (((_p_)->prev != (_list_)) ? (_p_)->prev : NULL)

/* Checks if an item is linked into the list. */
#define LINK_LIST_ISLINKED(_p_)         (((_p_)->next != (_p_)) && ((_p_)->prev != (_p_)))

/* Unlinks an item from a list, has no effect if already unlinked. */
#define LINK_LIST_UNLINK(_p_) \
    do { \
        (_p_)->next->prev = (_p_)->prev; \
        (_p_)->prev->next = (_p_)->next; \
        (_p_)->next = (_p_); \
        (_p_)->prev = (_p_); \
    } while (false)

/* Returns the head/tail of a list, or NULL if empty. */
#define LINK_LIST_HEAD(_list_)          LINK_LIST_NEXT(_list_, _list_)
#define LINK_LIST_TAIL(_list_)          LINK_LIST_PREV(_list_, _list_)

#define LINK_LIST_INSERT_BEFORE(_p_, _add_) \
    do { \
        (_add_)->next = (_p_); \
        (_add_)->prev = (_p_)->prev; \
        (_add_)->next->prev = (_add_); \
        (_add_)->prev->next = (_add_); \
    } while (false)

#define LINK_LIST_INSERT_AFTER(_p_, _add_) \
    do { \
        (_add_)->prev = (_p_); \
        (_add_)->next = (_p_)->next; \
        (_add_)->prev->next = (_add_); \
        (_add_)->next->prev = (_add_); \
    } while (false)

#define LINK_LIST_INSERT_HEAD(_list_, _add_) LINK_LIST_INSERT_AFTER(_list_, _add_)
#define LINK_LIST_INSERT_TAIL(_list_, _add_) LINK_LIST_INSERT_BEFORE(_list_, _add_)

/* FIXME 1 - replace these with their INSERT relatives, but careful with parameters */
#define LINK_LIST_ADD_BEFORE(_p_, _at_) LINK_LIST_INSERT_BEFORE(_at_, _p_)
#define LINK_LIST_ADD_AFTER(_p_, _at_) LINK_LIST_INSERT_AFTER(_at_, _p_)
#define LINK_LIST_ADD_HEAD(_p_, _list_) LINK_LIST_INSERT_AFTER(_list_, _p_)
#define LINK_LIST_ADD_TAIL(_p_, _list_) LINK_LIST_INSERT_BEFORE(_list_, _p_)

/* Adds an item to a list while keeping the list sorted. */
#define LINK_LIST_ADD_SORT(_add_, _list_, _cmp_) \
    do { \
        struct LinkListT *_i_ = (_list_)->next; \
        while (true) { \
            if (_i_ == (_list_)) { \
                break; \
            } \
            if (_cmp_(_add_, _i_) < 0) { \
                break; \
            } \
            _i_ = _i_->next; \
        } \
        LINK_LIST_INSERT_BEFORE(_i_, _add_); \
    } while (false)

/* Checks if a list is empty. */
#define LINK_LIST_ISEMPTY(_list_)       (!LINK_LIST_ISLINKED(_list_))

/* List iteration macro. */
#define LINK_LIST_FOREACH(_p_, _list_) \
    for ((_p_) = LINK_LIST_HEAD(_list_); (_p_) != NULL; (_p_) = LINK_LIST_NEXT(_p_, _list_))

/* Linked list type */
struct LinkListT {
    struct LinkListT *next;
    struct LinkListT *prev;
};

#endif /* LLIST_H */