1 /**************************************************************************** 2 * 3 * Copyright (c) 2023, Michael Becker (michael.f.becker@gmail.com) 4 * 5 * This file is part of the FreeRTOS Add-ons project. 6 * 7 * Source Code: 8 * https://github.com/michaelbecker/freertos-addons 9 * 10 * Project Page: 11 * http://michaelbecker.github.io/freertos-addons/ 12 * 13 * On-line Documentation: 14 * http://michaelbecker.github.io/freertos-addons/docs/html/index.html 15 * 16 * MIT License 17 * 18 * Permission is hereby granted, free of charge, to any person obtaining a 19 * copy of this software and associated documentation files 20 * (the "Software"), to deal in the Software without restriction, including 21 * without limitation the rights to use, copy, modify, merge, publish, 22 * distribute, sublicense, and/or sell copies of the Software, and to 23 * permit persons to whom the Software is furnished to do so,subject to the 24 * following conditions: 25 * 26 * + The above copyright notice and this permission notice shall be included 27 * in all copies or substantial portions of the Software. 28 * + Credit is appreciated, but not required, if you find this project 29 * useful enough to include in your application, product, device, etc. 30 * 31 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 32 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 33 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 34 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 35 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 36 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 37 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 38 * 39 ***************************************************************************/ 40 /* 41 * Copyright 2023-2024 NXP 42 * 43 * SPDX-License-Identifier: BSD-3-Clause 44 * 45 */ 46 47 #ifndef SLIST_H_ 48 #define SLIST_H_ 49 50 /** 51 * The singly linked list structure. 52 * 53 * This is designed to be embedded within your data 54 * structure(s). 55 * 56 * These lists offer the smallest storage overhead (one pointer per item), 57 * but many operations may take O(n) time. 58 */ 59 typedef struct SlNode_t_ 60 { 61 /** 62 * A pointer to ourselves. 63 */ 64 struct SlNode_t_ *Next; 65 66 } SlNode_t; 67 68 /** 69 * Macro to initialize a list head. 70 * 71 * @param _head A pointer to the list head. 72 */ 73 #define SlInitHead(_head) (_head)->Next = NULL; 74 75 /** 76 * Add a node to the list head. 77 * Runs in O(1) time. 78 * 79 * @param _head A pointer to the existing list head. 80 * @param _node A pointer to the node you are adding. 81 */ 82 #define SlAddNodeToHead(_head, _node) SlInsertNodeAfter(_head, _node) 83 84 /** 85 * Add a node to the list tail. 86 * Runs in O(n) time. 87 * 88 * @param Head A pointer to the existing list head. 89 * @param Node A pointer to the node you are adding. 90 */ 91 void SlAddNodeToTail(SlNode_t *Head, SlNode_t *Node); 92 93 /** 94 * Removes the node from the list head. 95 * Runs in O(1) time. 96 * 97 * @param Head A pointer to the existing list head. 98 * @return The node removed, or NULL for an empty list. 99 */ 100 SlNode_t *SlRemoveNodeFromHead(SlNode_t *Head); 101 102 /** 103 * Removes the node from the list tail. 104 * Runs in O(n) time. 105 * 106 * @param Head A pointer to the existing list head. 107 * @return The node removed, or NULL for an empty list. 108 */ 109 SlNode_t *SlRemoveNodeFromTail(SlNode_t *Head); 110 111 /** 112 * Check if the list is empty. 113 * 114 * @param _head A pointer to the existing list head. 115 * @return true if the list is empty, false otherwise. 116 */ 117 #define SlIsListEmpty(_head) ((_head)->Next == NULL) 118 119 /** 120 * Inserts a new node into the list right after the marker element. 121 * Runs in O(1) time. 122 * 123 * @param Marker The node you are inserting after. Cannot be NULL. 124 * @param Node The node you are inserting. Cannot be NULL. 125 */ 126 void SlInsertNodeAfter(SlNode_t *Marker, SlNode_t *Node); 127 128 /** 129 * Inserts a new node into the list right before the marker element. 130 * Runs in O(n) time. 131 * 132 * @param Head Pointer to the list head. 133 * @param Marker Node you are inserting before. Cannot be NULL. 134 * @param Node The node you are inserting. Cannot be NULL. 135 */ 136 void SlInsertNodeBefore(SlNode_t *Head, SlNode_t *Marker, SlNode_t *Node); 137 138 /** 139 * Removes a node from the list. 140 * Runs in O(n) time worst case. 141 * 142 * @param Head Pointer to the list head. 143 * @param Node The node you are removing. 144 */ 145 void SlRemoveNode(SlNode_t *Head, SlNode_t *Node); 146 147 /** 148 * Given here in case you do not have an equivalent macro. 149 * @param _type The structure type. 150 * @param _field The name of the field you want the offset to. 151 * @returns The offset into _type where _field starts, in bytes. 152 */ 153 #ifndef OFFSET_OF 154 #define OFFSET_OF(_type, _field) ((size_t) & ((_type *)0)->_field) 155 #endif 156 157 /** 158 * Given here in case you do not have an equivalent macro. 159 * @param _address The real address of the _field you have. 160 * @param _type The structure type. 161 * @param _field The name of the field you want the offset to. 162 * @returns A typed pointer to the structure containing the _field 163 * at _address. 164 */ 165 #ifndef CONTAINING_RECORD 166 #define CONTAINING_RECORD(_address, _type, _field) ((_type *)((unsigned char *)(_address)-OFFSET_OF(_type, _field))) 167 #endif 168 169 /** 170 * Macro to ease walking through all of the nodes in a list. 171 * Runs in O(n) time. 172 * 173 * This will work for an empty list. 174 * 175 * @param _head A pointer to the list head. Cannot be NULL. 176 * @param _node An SlNode_t pointer that you need to define before calling 177 * this macro. 178 */ 179 #define SlForEachNode(_head, _node) for ((_node) = (_head)->Next; (_node) != NULL; (_node) = (_node)->Next) 180 181 #endif 182