1 /*************************************************************************** 2 begin : Sat Jun 28 2003 3 copyright : (C) 2018 by Martin Preuss 4 email : martin@libchipcard.de 5 6 *************************************************************************** 7 * * 8 * This library is free software; you can redistribute it and/or * 9 * modify it under the terms of the GNU Lesser General Public * 10 * License as published by the Free Software Foundation; either * 11 * version 2.1 of the License, or (at your option) any later version. * 12 * * 13 * This library is distributed in the hope that it will be useful, * 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 16 * Lesser General Public License for more details. * 17 * * 18 * You should have received a copy of the GNU Lesser General Public * 19 * License along with this library; if not, write to the Free Software * 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * 21 * MA 02111-1307 USA * 22 * * 23 ***************************************************************************/ 24 25 26 #include <gwenhywfar/gwenhywfarapi.h> 27 #include <gwenhywfar/types.h> 28 #include <assert.h> 29 30 31 #ifndef GWEN_DUMMY_EMPTY_ARG 32 /** Necessary for MSVC compiler because it does not accept a left-out 33 macro argument. */ 34 # define GWEN_DUMMY_EMPTY_ARG 35 #endif 36 37 38 #ifndef GWEN_LIST1_H 39 #define GWEN_LIST1_H 40 41 42 #ifdef __cplusplus 43 extern "C" { 44 #endif 45 46 47 /** @defgroup GWEN_MACRO_LIST Macros For Typesafe List Handling 48 * 49 * The macros of this group facilitates typesafe use of lists. 50 * 51 * <p> 52 * Let's assume you have a structure type called MYSTRUCT and you want 53 * to manage lists of them. Let's further assume that you want the 54 * functions dealing with that struct have prefixes like MyStruct (as in 55 * @b MyStruct_new) 56 * </p> 57 * The header file would look like this: 58 * 59 * @code 60 * 61 * / * mystruct.h * / 62 * 63 * #ifndef MYSTRUCT_H 64 * #define MYSTRUCT_H 65 * 66 * typedef struct MYSTRUCT MYSTRUCT; 67 * 68 * GWEN_LIST_FUNCTION_DEFS(MYSTRUCT, MyStruct); 69 * 70 * struct MYSTRUCT { 71 * GWEN_LIST_ELEMENT(MYSTRUCT); 72 * int myData; 73 * } 74 * 75 * 76 * MYSTRUCT *MyStruct_new(int myData); 77 * void MyStruct_free(MYSTRUCT *myStruct); 78 * 79 * #endif 80 * @endcode 81 * <p> 82 * This defines all necessary data and function prototypes needed for 83 * list management. 84 * </p> 85 * 86 * <p> 87 * The code file would look quite similar to the following: 88 * </p> 89 * 90 * @code 91 * 92 * / * mystruct.c * / 93 * 94 * GWEN_LIST_FUNCTIONS(MYSTRUCT, MyStruct) 95 * 96 * MYSTRUCT *MyStruct_new(int myData) { 97 * MYSTRUCT *pMyStruct; 98 * 99 * pMyStruct=(MYSTRUCT*)malloc(sizeof(MYSTRUCT)); 100 * memset(pMyStruct, 0, sizeof(MYSTRUCT)); 101 * 102 * GWEN_LIST_INIT(MYSTRUCT, pMyStruct) 103 * 104 * pMyStruct->myData=myData; 105 * return pMyStruct; 106 * } 107 * 108 * void MyStruct_free(MYSTRUCT *pMyStruct) { 109 * if (pMyStruct) { 110 * pMyStruct->myData=0; 111 * 112 * GWEN_LIST_FINI(MYSTRUCT, pMyStruct) 113 * 114 * free(pMyStruct); 115 * } 116 * } 117 * 118 * @endcode 119 * Please note the three macros used in the code file: 120 * <ul> 121 * <li>@ref GWEN_LIST_FUNCTIONS creates the functions for the list 122 * management</li> 123 * <li>@ref GWEN_LIST_INIT initializes the list data inside your 124 * struct to defined values </li> 125 * <li>@ref GWEN_LIST_FINI frees all ressources occupied by the list 126 * management code. Please note that this macro should be the last 127 * statement inside the destructor function before @b free()</li> 128 * </ul> 129 * 130 * <p>Note: When writing these macro code lines, the original ISO 131 * C89 standard for the C language does not allow terminating the 132 * macro statement with a semicolon ';'. Any recent compiler will 133 * probably silently ignore such an extra ';', but you should be 134 * aware that this can cause problems once one of your users tries 135 * to compile this with a different compiler. Therefore these code 136 * lines should end directly with the closing parentheses.</p> 137 * 138 * <p> 139 * The list management code assumes that there is a function called 140 * (in this example) @b MyStruct_free() (or generally: TYPEPREFIX_free). 141 * This is used when destroying a list of MYSTRUCT elements. In this case 142 * all elements still enlisted are destroyed upon destruction of the list. 143 * </p> 144 */ 145 /*@{*/ 146 147 148 /** @name Internal Functions 149 * 150 * All functions and structs within this group should be considered 151 * internal. They just implement the functionality behind the typesafe list 152 * macros (see @ref GWEN_LIST_FUNCTION_LIB_DEFS and following). 153 */ 154 /*@{*/ 155 typedef struct GWEN_LIST1 GWEN_LIST1; 156 typedef struct GWEN_LIST1_ELEMENT GWEN_LIST1_ELEMENT; 157 158 typedef int GWENHYWFAR_CB(*GWEN_LIST1_SORT_FN)(const void *a, const void *b, int ascending); 159 160 161 /** Allocate (create) a new empty list. */ 162 GWENHYWFAR_API 163 GWEN_LIST1 *GWEN_List1_new(void); 164 165 /** Free (delete) an existing list. The list elements are 166 * untouched by this function; they need to be freed 167 * beforehand. */ 168 GWENHYWFAR_API 169 void GWEN_List1_free(GWEN_LIST1 *l); 170 171 /** Returns the number of elements in this list. This value is 172 * cached in the list structure, so this function is a cheap 173 * function. */ 174 GWENHYWFAR_API 175 int GWEN_List1_GetCount(const GWEN_LIST1 *l); 176 177 /** Adds (appends) a list element at the end of the list. (This 178 * operation is also called "append" or "push_back" elsewhere.) */ 179 GWENHYWFAR_API 180 int GWEN_List1_Add(GWEN_LIST1 *l, GWEN_LIST1_ELEMENT *el); 181 182 /** Inserts (prepends) a list element at the beginning of the 183 * list. (This operation is also called "prepend" or "push_front" 184 * elsewhere.) */ 185 GWENHYWFAR_API 186 int GWEN_List1_Insert(GWEN_LIST1 *l, GWEN_LIST1_ELEMENT *el); 187 188 /** Deletes (removes) a list element from the list it used to 189 * belong to. The list element is not free'd or anything, it is 190 * only removed from the list it used to belong to. (This 191 * operation is also called "remove" or "unlink" elsewhere.) */ 192 GWENHYWFAR_API 193 int GWEN_List1_Del(GWEN_LIST1_ELEMENT *el); 194 195 /** Adds (appends) the second list to the end of the first 196 * list. (This operation is also called "append" or "concatenate" 197 * elsewhere.) */ 198 GWENHYWFAR_API 199 int GWEN_List1_AddList(GWEN_LIST1 *dest, GWEN_LIST1 *l); 200 201 /** Returns the data pointer of the first list element. */ 202 GWENHYWFAR_API 203 void *GWEN_List1_GetFirst(const GWEN_LIST1 *l); 204 205 /** Returns the data pointer of the last list element. */ 206 GWENHYWFAR_API 207 void *GWEN_List1_GetLast(const GWEN_LIST1 *l); 208 209 GWENHYWFAR_API 210 GWEN_LIST1_SORT_FN GWEN_List1_SetSortFn(GWEN_LIST1 *l, GWEN_LIST1_SORT_FN fn); 211 212 GWENHYWFAR_API 213 void GWEN_List1_Sort(GWEN_LIST1 *l, int ascending); 214 215 216 217 /** Allocate (create) a new list element structure. */ 218 GWENHYWFAR_API 219 GWEN_LIST1_ELEMENT *GWEN_List1Element_new(void *d); 220 221 /** Free (delete) a list element structure. */ 222 GWENHYWFAR_API 223 void GWEN_List1Element_free(GWEN_LIST1_ELEMENT *el); 224 225 /** Returns the data pointer of the given list element 226 * structure. */ 227 GWENHYWFAR_API 228 void *GWEN_List1Element_GetData(const GWEN_LIST1_ELEMENT *el); 229 230 /** Returns the data pointer of the list element that is the 231 * previous (predecessor) to the given one in its list. If there 232 * is no such prepending list element, returns NULL. */ 233 GWENHYWFAR_API 234 void *GWEN_List1Element_GetPrevious(const GWEN_LIST1_ELEMENT *el); 235 236 /** Returns the data pointer of the list element that is the next 237 * one (successor) to the given one in its list. If there is no 238 * such prepending list element, returns NULL. */ 239 GWENHYWFAR_API 240 void *GWEN_List1Element_GetNext(const GWEN_LIST1_ELEMENT *el); 241 242 243 /*@}*/ 244 245 246 /** @name Typesafe Macros 247 * 248 */ 249 /*@{*/ 250 251 /** 252 * Use this inside the declaration of a struct for which you want to create 253 * lists. 254 */ 255 #define GWEN_LIST_ELEMENT(t) \ 256 GWEN_LIST1_ELEMENT *_list1_element; 257 258 /** 259 * Use this macro in your public header files to export only list functions 260 * which do not modify a list. This allows your code to return lists which can 261 * not be modified by callers. It also prevents callers from creating their 262 * own lists (this is sometimes needed). 263 */ 264 #define GWEN_LIST_FUNCTION_LIB_DEFS_CONST(t, pr, decl) \ 265 typedef GWEN_LIST1 t##_LIST; \ 266 typedef int GWENHYWFAR_CB (*t##_LIST_SORT_FN)(const t *a, const t *b, int ascending); \ 267 typedef t* (t##_LIST_FOREACH)(t *element, void *user_data); \ 268 \ 269 \ 270 decl t* pr##_List_First(const t##_LIST *l); \ 271 decl t* pr##_List_Last(const t##_LIST *l); \ 272 decl t* pr##_List_Next(const t *element); \ 273 decl t* pr##_List_Previous(const t *element); \ 274 decl uint32_t pr##_List_GetCount(const t##_LIST *l); \ 275 decl int pr##_List_HasElement(const t##_LIST *l, const t *element); \ 276 decl t##_LIST_SORT_FN pr##_List_SetSortFn(t##_LIST *l, t##_LIST_SORT_FN fn); \ 277 decl void pr##_List_Sort(t##_LIST *l, int ascending); \ 278 decl t* pr##_List_ForEach(t##_LIST *l, t##_LIST_FOREACH fn, void *user_data); 279 280 281 #define GWEN_LIST_FUNCTION_LIB_DEFS_NOCONST(t, pr, decl) \ 282 typedef GWEN_LIST1_ELEMENT t##_LIST_ELEMENT; \ 283 \ 284 decl void pr##_List_Clear(t##_LIST *l); \ 285 decl t##_LIST* pr##_List_new(); \ 286 decl void pr##_List_free(t##_LIST *l); \ 287 decl int pr##_List_AddList(t##_LIST *dst, t##_LIST *l); \ 288 decl int pr##_List_Add(t *element, t##_LIST *list); \ 289 decl int pr##_List_Insert(t *element, t##_LIST *list); \ 290 decl int pr##_List_Del(t *element); 291 292 293 #define GWEN_LIST_FUNCTION_DEFS_CONST(t, pr) \ 294 GWEN_LIST_FUNCTION_LIB_DEFS_CONST(t, pr, GWEN_DUMMY_EMPTY_ARG) 295 296 #define GWEN_LIST_FUNCTION_DEFS_NOCONST(t, pr) \ 297 GWEN_LIST_FUNCTION_LIB_DEFS_NOCONST(t, pr, GWEN_DUMMY_EMPTY_ARG) 298 299 300 /** 301 * Use this in public header files to define some prototypes for list 302 * functions. 303 * Let's assume the type of your list elements is "MYTYPE" and you want to 304 * use the prefix "MyType_" for the list functions. 305 * The following function prototypes will then be created: 306 * <ul> 307 * <li> 308 * void MyType_List_Add(MYTYPE *element, MYTYPE_LIST *list);<br> 309 * Adds (appends) a MYTYPE struct at the end of the given 310 * list. (We apologize for the unusual argument order here.) 311 * </li> 312 * <li> 313 * void MyType_List_Del(MYTYPE *element);<br> 314 * Removes a MyType struct from the list it is enlisted to. 315 * </li> 316 * <li> 317 * MYTYPE *MyType_List_First(MYTYPE *element); <br> 318 * Returns the first element of the given list. 319 * </li> 320 * <li> 321 * MYTYPE* MyType_List_Next(const MYTYPE *element);<br> 322 * Returns the next list element to the given one (the 323 * successor) in its list. 324 * </li> 325 * <li> 326 * MYTYPE* MyType_List_Previous(const MYTYPE *element);<br> 327 * Returns the previous list element to the given one (the 328 * predecessor) in its list. 329 * </li> 330 * <li> 331 * void MyType_List_Clear(MYTYPE *element); <br> 332 * Frees all entries of the given list. 333 * This function assumes that there is a function Mytype_free(). 334 * </li> 335 * <li> 336 * MYTYPE_LIST *MyType_List_new(); <br> 337 * Creates a new list of elements of MYTYPE type. 338 * </li> 339 * <li> 340 * void MyType_List_free(MYTYPE_LIST *l); <br> 341 * Clears and frees a list of elements of MYTYPE type. 342 * All objects inside the list are freed. 343 * This function assumes that there is a function Mytype_free(). 344 * </li> 345 * </ul> 346 * 347 */ 348 #define GWEN_LIST_FUNCTION_LIB_DEFS(t, pr, decl) \ 349 GWEN_LIST_FUNCTION_LIB_DEFS_CONST(t, pr, decl) \ 350 GWEN_LIST_FUNCTION_LIB_DEFS_NOCONST(t, pr, decl) 351 352 353 /** 354 * This macro should be used in applications, not in libraries. In 355 * libraries please use the macro @ref GWEN_LIST_FUNCTION_LIB_DEFS. 356 */ 357 #define GWEN_LIST_FUNCTION_DEFS(t, pr) \ 358 GWEN_LIST_FUNCTION_LIB_DEFS(t, pr, GWEN_DUMMY_EMPTY_ARG) 359 360 361 /** 362 * Use this inside your code files (*.c). 363 * Actually implements the functions for which the prototypes have been 364 * defined via @ref GWEN_LIST_FUNCTION_DEFS. 365 */ 366 #define GWEN_LIST_FUNCTIONS(t, pr) \ 367 \ 368 int pr##_List_Add(t *element, t##_LIST *l) { \ 369 return GWEN_List1_Add(l, element->_list1_element); \ 370 } \ 371 \ 372 int pr##_List_AddList(t##_LIST *dst, t##_LIST *l) { \ 373 return GWEN_List1_AddList(dst, l); \ 374 } \ 375 \ 376 int pr##_List_Insert(t *element, t##_LIST *l) { \ 377 return GWEN_List1_Insert(l, element->_list1_element); \ 378 } \ 379 \ 380 int pr##_List_Del(t *element){ \ 381 return GWEN_List1_Del(element->_list1_element); \ 382 }\ 383 \ 384 t* pr##_List_First(const t##_LIST *l) { \ 385 if (l) return (t*)GWEN_List1_GetFirst(l);\ 386 else return 0; \ 387 } \ 388 \ 389 t* pr##_List_Last(const t##_LIST *l) { \ 390 if (l) return (t*) GWEN_List1_GetLast(l);\ 391 else return 0; \ 392 } \ 393 \ 394 void pr##_List_Clear(t##_LIST *l) { \ 395 t* el; \ 396 while( (el=(t*) GWEN_List1_GetFirst(l)) ) {\ 397 pr##_List_Del(el);\ 398 pr##_free(el);\ 399 } /* while */ \ 400 } \ 401 \ 402 int pr##_List_HasElement(const t##_LIST *l, const t *element) { \ 403 const t* el; \ 404 el=(t*)GWEN_List1_GetFirst(l); \ 405 while(el) {\ 406 if (el==element) \ 407 return 1; \ 408 el=(const t*)GWEN_List1Element_GetNext(el->_list1_element); \ 409 } /* while */ \ 410 return 0; \ 411 } \ 412 \ 413 t##_LIST* pr##_List_new(){\ 414 return (t##_LIST*)GWEN_List1_new(); \ 415 }\ 416 \ 417 void pr##_List_free(t##_LIST *l) {\ 418 if (l) { \ 419 pr##_List_Clear(l);\ 420 GWEN_List1_free(l); \ 421 }\ 422 } \ 423 \ 424 t* pr##_List_Next(const t *element) { \ 425 return (t*)GWEN_List1Element_GetNext(element->_list1_element);\ 426 } \ 427 \ 428 t* pr##_List_Previous(const t *element) { \ 429 return (t*)GWEN_List1Element_GetPrevious(element->_list1_element);\ 430 } \ 431 \ 432 uint32_t pr##_List_GetCount(const t##_LIST *l){\ 433 return GWEN_List1_GetCount(l);\ 434 } \ 435 \ 436 t##_LIST_SORT_FN pr##_List_SetSortFn(t##_LIST *l, t##_LIST_SORT_FN fn) { \ 437 return (t##_LIST_SORT_FN) GWEN_List1_SetSortFn(l, (GWEN_LIST1_SORT_FN) fn); \ 438 } \ 439 \ 440 void pr##_List_Sort(t##_LIST *l, int ascending){\ 441 GWEN_List1_Sort(l, ascending);\ 442 }\ 443 \ 444 t* pr##_List_ForEach(t##_LIST *l, t##_LIST_FOREACH fn, void *user_data){ \ 445 t *el; \ 446 if (!l) return 0; \ 447 \ 448 el=pr##_List_First(l); \ 449 while(el) { \ 450 t *elReturned; \ 451 elReturned=fn(el, user_data); \ 452 if (elReturned) { \ 453 return elReturned; \ 454 } \ 455 el=pr##_List_Next(el); \ 456 } \ 457 return 0; \ 458 } 459 460 /** 461 * Use this in your code file (*.c) inside the init code for the struct 462 * you want to use in lists (in GWEN these are the functions which end with 463 * "_new". 464 */ 465 #define GWEN_LIST_INIT(t, element) \ 466 element->_list1_element=GWEN_List1Element_new(element); 467 468 469 /** 470 * Use this in your code file (*.c) inside the fini code for the struct 471 * you want to use in lists (in GWEN these are the functions which end with 472 * "_free". 473 */ 474 #define GWEN_LIST_FINI(t, element) \ 475 if (element && element->_list1_element) { \ 476 GWEN_List1Element_free(element->_list1_element); \ 477 element->_list1_element=0; \ 478 } 479 480 /*@}*/ 481 482 /*@}*/ /* defgroup */ 483 484 485 #ifdef __cplusplus 486 } 487 #endif 488 489 490 #endif 491 492 493