1 /** 2 * @file cstl_rawlist.h 3 * @copyright Copyright (c) Huawei Technologies Co., Ltd. 2021-2021. All rights reserved. 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 16 * @brief cstl_rawlist 对外头文件 17 * @details 18 * Notes: 1、链表遍历过程中删除节点,必须先调 next 函数获取到下一个节点,才能调 erase 删除当前节点。 19 * 2、链表节点在删除时如果用户注册了释放函数,则调用该函数释放资源。用户数据中的句柄、指针等私有资源,需要用户在释放函数中释放。 20 * 若用户不注册释放函数,则仅将该节点从链表中摘除,用户必须自行释放节点内存。 21 * +-----------------------------------------------------------+ 22 * | +------------------------------------------------------+ | 23 * | | head | | 24 * | | +----------+ +----------+ +--------------+ | | 25 * | +---| prev |<---| prev |<---| prev |<--+ | 26 * +---->| next |--->| next |--->| next |------+ 27 * +----------+ +----------+ +--------------+ 28 * | count | | userdata | | userdata1 | 29 * | freefunc | | ... | | pointer |-----------+ 用户私有资源 30 * +----------+ +----------+ | userdata... | \|/ 31 * +--------------+ +-------------+ 32 * | privatedata | 33 * +-------------+ 34 * @date 2021-04-15 35 * @version v0.1.0 36 * ******************************************************************************************* 37 * @par 修改日志: 38 * <table> 39 * <tr><th>Date <th>Version <th>Description 40 * <tr><td>2021-04-15 <td>0.1.0 <td>初始化版本 41 * </table> 42 * ******************************************************************************************* 43 * @par 修改日志: 44 * <table> 45 * <tr><th>Date <th>Version <th>Description 46 * <tr><td>2021-07-20 <td>1.0.0 <td>车规规范整改 47 * </table> 48 * ******************************************************************************************* 49 */ 50 51 /** 52 * @defgroup cstl_rawlist Raw双向链表 53 * @ingroup cstl 54 */ 55 #ifndef CSTL_RAWLIST_H 56 #define CSTL_RAWLIST_H 57 58 #include <stdint.h> 59 #include <stddef.h> 60 #include <stdbool.h> 61 62 #include "cstl_public.h" 63 64 #ifdef __cplusplus 65 extern "C" { 66 #endif 67 68 /** 69 * @ingroup cstl_rawlist 70 * 该结构被用来保存双向链表中节点的前向指针和后向指针。 71 * 这个链表不包含实质的数据区,一般用于组织(串接)数据节点 72 */ 73 struct TagCstlRawListNode { 74 struct TagCstlRawListNode *next; /**< 指向下一个节点 */ 75 struct TagCstlRawListNode *prev; /**< 指向前一个节点 */ 76 }; 77 78 /** 79 * @ingroup cstl_rawlist 80 * 链表头 81 */ 82 typedef struct TagCstlRawListNode CstlRawListNode; 83 84 /** 85 * @ingroup cstl_rawlist 86 * 链表头 87 */ 88 typedef struct { 89 CstlRawListNode head; /**< 链表头 */ 90 CstlFreeFunc freeFunc; /**< 节点内存释放函数,该函数需要释放节点及节点中的其他私有资源 */ 91 } CstlRawList; 92 93 /** 94 * @ingroup cstl_rawlist 95 * @brief 初始化链表 96 * @par 描述:初始化链表,按需注册用户数据中的私有资源释放函数。本函数不会申请资源。 97 * @attention \n 98 * 1:rawlist模块中的链表节点由用户进行封装并申请内存,rawlist仅做链表的维护,其资源释放应由用户在freeFunc中完成。\n 99 * 2:用户在添加数据时,传递给rawlist的参数为CstlRawListNode节点,因此rawlist传递给用户freeFunc的参数也是CstlRawListNode节点。 100 * @param list [IN] 链表。 101 * @param freeFunc [IN] 用户资源释放函数。 102 * @retval #CSTL_OK 0,链表初始化成功。 103 * @retval #ERRNO_CSTL_INPUT_INVALID,即0xa030002。表明链表为NULL,初始化失败。 104 * @li cstl_rawlist.h:该接口声明所在的头文件。 105 */ 106 int32_t CstlRawListInit(CstlRawList *list, CstlFreeFunc freeFunc); 107 108 /** 109 * @ingroup cstl_rawlist 110 * @brief 链表节点清空,删除所有节点 111 * @par 描述:链表节点清空,删除所有节点,调用户注册的free函数释放用户私有资源,回归链表初始化后的状态。 112 * @param list [IN] 链表 113 * @retval #CSTL_OK 0,链表清空成功。 114 * @retval #ERRNO_CSTL_INPUT_INVALID,即0xa030002。表明链表为NULL,操作失败。 115 * @li cstl_rawlist.h:该接口声明所在的头文件。 116 */ 117 int32_t CstlRawListClear(CstlRawList *list); 118 119 /** 120 * @ingroup cstl_rawlist 121 * @brief 链表去初始化 122 * @par 描述:链表去初始化:删除所有节点,调用户注册的free函数释放用户私有资源,去注册钩子函数。但链表头还在。 123 * @param list [IN] 链表 124 * @retval #CSTL_OK 0,链表去初始化成功。 125 * @retval #ERRNO_CSTL_INPUT_INVALID,即0xa030002。表明链表为NULL,操作失败。 126 * @li cstl_rawlist.h:该接口声明所在的头文件。 127 */ 128 int32_t CstlRawListDeinit(CstlRawList *list); 129 130 /** 131 * @ingroup cstl_rawlist 132 * @brief 检查链表是否为空 133 * @param list [IN] 待检查的链表 134 * @retval #true 1,链表为空或者无数据。 135 * @retval #false 0,链表不为空。 136 * @li cstl_rawlist.h:该接口声明所在的头文件。 137 */ 138 bool CstlRawListEmpty(const CstlRawList *list); 139 140 /** 141 * @ingroup cstl_rawlist 142 * @brief 获取链表中节点个数 143 * @param list [IN] 链表 144 * @retval 链表节点个数 145 * @li cstl_rawlist.h:该接口声明所在的头文件。 146 */ 147 size_t CstlRawListSize(const CstlRawList *list); 148 149 /** 150 * @ingroup cstl_rawlist 151 * @brief 在链表头部插入节点 152 * @param list [IN] 链表 153 * @param node [IN] 待插入的节点 154 * @retval #CSTL_OK 0,链表头部插入成功。 155 * @retval #ERRNO_CSTL_INPUT_INVALID,即0xa030002。链表为NULL,操作失败。 156 * @li cstl_rawlist.h:该接口声明所在的头文件。 157 */ 158 int32_t CstlRawListPushFront(CstlRawList *list, CstlRawListNode *node); 159 160 /** 161 * @ingroup cstl_rawlist 162 * @brief 在链表尾插入节点 163 * @param list [IN] 链表 164 * @param node [IN] 待插入的节点 165 * @retval #CSTL_OK 0,链表尾部插入成功。 166 * @retval #ERRNO_CSTL_INPUT_INVALID,即0xa030002。表明链表是NULL或者node为NULL,操作失败。 167 * @li cstl_rawlist.h:该接口声明所在的头文件。 168 */ 169 int32_t CstlRawListPushBack(CstlRawList *list, CstlRawListNode *node); 170 171 /** 172 * @ingroup cstl_rawlist 173 * @brief 在指定节点前插入节点 174 * @param curNode [IN] 指定的节点 175 * @param newNode [IN] 待插入的节点 176 * @retval #CSTL_OK 0,链表插入成功。 177 * @retval #ERRNO_CSTL_INPUT_INVALID,即0xa030002。表明参数不合法,操作失败。 178 * @li cstl_rawlist.h:该接口声明所在的头文件。 179 */ 180 int32_t CstlRawListInsert(const CstlRawListNode *curNode, CstlRawListNode *newNode); 181 182 /** 183 * @ingroup cstl_rawlist 184 * @brief 从链表头部POP一个节点 185 * @par 描述:从链表中移除头节点。如果在初始化时注册了free函数,还会调该钩子函数释放用户资源。\n 186 * 如果链表为空,则不做任何事情。 187 * @param list [IN] 链表 188 * @retval #CSTL_OK 0,链表头部弹出成功。 189 * @retval #ERRNO_CSTL_INPUT_INVALID,即0xa030002。表明参数不合法,操作失败 190 * @retval #ERRNO_CSTL_ELEMENT_EMPTY,即0xa030001。表明list不是空指针但是无数据,操作失败。 191 * @li cstl_rawlist.h:该接口声明所在的头文件。 192 */ 193 int32_t CstlRawListPopFront(CstlRawList *list); 194 195 /** 196 * @ingroup cstl_rawlist 197 * @brief 从链表中尾部POP一个节点 198 * @par 描述:从链表中移除尾节点。如果在初始化时注册了free函数,还会调该钩子函数释放用户资源。\n 199 * 如果链表为空,则不做任何事情。 200 * @param list [IN] 链表 201 * @retval #CSTL_OK 0,链表尾部弹出成功。 202 * @retval #ERRNO_CSTL_INPUT_INVALID,即0xa030002,表明参数不合法,操作失败 203 * @retval #ERRNO_CSTL_ELEMENT_EMPTY,即0xa030001,表明list不是空指针但是无数据,操作失败。 204 * @li cstl_rawlist.h:该接口声明所在的头文件。 205 */ 206 int32_t CstlRawListPopBack(CstlRawList *list); 207 208 /** 209 * @ingroup cstl_rawlist 210 * @brief 删除链表中指定节点。 211 * @par 描述:\n 212 * 1.list为NULL且node在链表中时,仅将node从链表中摘除。 213 * 2.list非NULL且node在链表中时,从链表中摘除该节点,如果在初始化时注册了free函数,还会调该钩子函数释放用户资源。 214 * @param list [IN] 链表 215 * @param node [IN] 待删除的节点 216 * @retval #CSTL_OK 0,链表删除成功。 217 * @retval #ERRNO_CSTL_INPUT_INVALID,即0xa030002。表明参数不合法,操作失败 218 * @li cstl_rawlist.h:该接口声明所在的头文件。 219 */ 220 int32_t CstlRawListErase(CstlRawList *list, CstlRawListNode *node); 221 222 /** 223 * @ingroup cstl_rawlist 224 * @brief 返回头节点指针 225 * @par 描述:仅用于访问头节点,不会删除该节点;如果链表为NULL,则返回NULL。 226 * @param list [IN] 链表 227 * @attention 如果用户传入的参数不合理则一定返回NULL,所以用户需要使用正确的参数。 228 * @retval 非NULL 头节点的指针 229 * @retval NULL 链表为NULL 230 * @li cstl_rawlist.h:该接口声明所在的头文件。 231 */ 232 CstlRawListNode *CstlRawListFront(const CstlRawList *list); 233 234 /** 235 * @ingroup cstl_rawlist 236 * @brief 返回尾节点指针。 237 * @par 描述:仅用于访问尾节点,不会删除该节点;如果链表为NULL,则返回NULL。 238 * @param list [IN] 链表 239 * @attention 如果用户传入的参数不合理则一定返回NULL,所以用户需要使用正确的参数。 240 * @retval 非NULL 尾节点的指针 241 * @retval NULL 链表为NULL 242 * @li cstl_rawlist.h:该接口声明所在的头文件。 243 */ 244 CstlRawListNode *CstlRawListBack(const CstlRawList *list); 245 246 /** 247 * @ingroup cstl_rawlist 248 * @brief 获取当前节点的前一个节点。 249 * @par 描述:获取当前节点的前一个节点指针。如果当前节点是头节点,则返回NULL。 250 * @param list [IN] 链表 251 * @param node [IN] 当前节点 252 * @attention 如果用户传入的参数不合理则一定返回NULL,所以用户需要使用正确的参数。 253 * @retval 非NULL 当前节点的前一个节点 254 * @retval NULL 头节点的前一个节点为空 255 * @li cstl_rawlist.h:该接口声明所在的头文件。 256 */ 257 CstlRawListNode *CstlRawListPrev(const CstlRawList *list, const CstlRawListNode *node); 258 259 /** 260 * @ingroup cstl_rawlist 261 * @brief 获取当前节点的后一个节点。 262 * @par 描述:获取当前节点的后一个节点指针。如果当前节点是尾节点,则返回NULL。 263 * @param list [IN] 链表 264 * @param node [IN] 当前节点 265 * @attention 如果用户传入的参数不合理则一定返回NULL,所以用户需要使用正确的参数。 266 * @retval 非NULL 当前节点的后一个节点 267 * @retval NULL 尾节点的下一个节点为空 268 * @li cstl_rawlist.h:该接口声明所在的头文件。 269 */ 270 CstlRawListNode *CstlRawListNext(const CstlRawList *list, const CstlRawListNode *node); 271 272 /** 273 * @ingroup cstl_rawlist 274 * @brief 根据用户定义的排序函数,对链表节点进行排序。 275 * @par 描述:根据用户定义的排序函数,对链表节点进行排序,排序顺序按排序函数定义实行。 276 * @attention \n 277 * 1、此处用户输入的排序函数钩子,其两个入参为两个待比较的节点值,入参类型是(CstlRawListNode *)。\n 278 * 2、用户在排序函数内部的实现,需根据节点地址偏移到用户结构体信息再进行排序比较。 279 * @param list [IN] 链表 280 * @param cmpFunc [IN] 排序函数钩子 281 * @retval CSTL_OK 排序成功 282 * @retval CSTL_ERROR 排序失败 283 * @retval #ERRNO_CSTL_INPUT_INVALID,即0xa030002。表明参数不合法,操作失败 284 * @li cstl_rawlist.h:该接口声明所在的头文件。 285 */ 286 int32_t CstlRawListSort(CstlRawList *list, CstlDataCmpFunc cmpFunc); 287 288 /** 289 * @ingroup cstl_rawlist 290 * @brief 根据用户定义的节点匹配函数,搜索用户想要的节点。 291 * @par 描述:根据用户定义的节点匹配函数,搜索用户想要的节点。 292 * @attention \n 293 * 1、将从链表头往后遍历,对每个节点依次调用匹配函数,直到找到第一个匹配的节点或者遍历到链表尾部结束。\n 294 * 2、此处用户输入的匹配函数钩子,其第一个入参地址是每个待搜索的节点值,入参类型是(CstlRawListNode *)。\n 295 * 3、用户在匹配钩子内部的实现,需根据节点地址偏移到用户结构体信息再进行匹配比较。 296 * 4、如果用户传入的参数不合理则一定返回NULL,所以用户需要使用正确的参数。 297 * @param list [IN] 链表 298 * @param nodeMatchFunc [IN] 匹配函数钩子 299 * @param data [IN] 关键信息 300 * @retval 非NULL 查询成功,返回节点指针 301 * @retval NULL 查询失败,未找到匹配的节点 302 * @li cstl_rawlist.h:该接口声明所在的头文件。 303 */ 304 CstlRawListNode *CstlRawListNodeFind(const CstlRawList *list, CstlMatchFunc nodeMatchFunc, uintptr_t data); 305 306 #ifdef __cplusplus 307 } 308 #endif 309 310 #endif /* CSTL_RAWLIST_H */ 311