Line data Source code
1 : /** 2 : * @file sclist.c 3 : * @brief Basic single chained generic list 4 : * 5 : * @author François Cerbelle (Fanfan), francois@cerbelle.net 6 : * 7 : * @internal 8 : * Created: 15/11/2024 9 : * Revision: none 10 : * Last modified: 2024-11-29 17:58 11 : * Compiler: gcc 12 : * Organization: Cerbelle.net 13 : * Copyright: Copyright (c) 2024, François Cerbelle 14 : * 15 : * This source code is released for free distribution under the terms of the 16 : * GNU General Public License as published by the Free Software Foundation. 17 : */ 18 : 19 : #ifdef HAVE_CONFIG_H 20 : #include "config.h" 21 : #endif 22 : 23 : #include "sclist.h" 24 : 25 : #include <stdlib.h> 26 : #include <stdio.h> 27 : #include <assert.h> 28 : 29 : /** Private list record structure 30 : */ 31 : typedef struct sclistrecord_s { 32 : void* value; /**< Pointer to value */ 33 : struct sclistrecord_s* next; /**< Next record in the list */ 34 : } sclistrecord_t; 35 : 36 : /** Opaque sclist structure 37 : */ 38 : typedef struct sclist_s { 39 : sclistrecord_t* first; /**< Pointer to the first record */ 40 : sclistrecord_t* last; /**< Pointer to the last record */ 41 : } sclist_t; 42 : 43 233 : sclist_t* sclist_new() { 44 : sclist_t* sclist; 45 233 : if (NULL==(sclist=malloc(sizeof(struct sclist_s)))) { 46 0 : perror("sclist_new OOM"); 47 0 : abort(); 48 : } 49 233 : sclist->first=NULL; 50 233 : sclist->last=NULL; 51 : 52 233 : return sclist; 53 : } 54 : 55 164 : void sclist_del(sclist_t* sclist) { 56 164 : assert(sclist); 57 : 58 173 : while (sclist->first!=NULL) { 59 9 : sclistrecord_t* first = sclist->first; 60 9 : sclist->first = sclist->first->next; 61 9 : free(first); 62 : } 63 164 : free(sclist); 64 164 : } 65 : 66 352 : sclistrecord_t* sclist_addrecord(sclist_t* sclist, void* value) { 67 : sclistrecord_t* record; 68 : 69 352 : assert(sclist); 70 : 71 : /* Create the record record */ 72 352 : if (NULL==(record=malloc(sizeof(struct sclistrecord_s)))) { 73 0 : perror("sclist_addrecord OOM"); 74 0 : abort(); 75 : } 76 352 : record->value = value; 77 352 : record->next = NULL; 78 : 79 : /* Add to the list */ 80 352 : if (NULL==sclist->first) { 81 : /* First record to be added in an empty list */ 82 : /* A sentinel record would avoid this test and optimize performances 83 : * at the cost of sentinel size RAM consumption */ 84 158 : sclist->first = record; 85 158 : sclist->last = record; 86 : } else { 87 : /* Add to the end of a non-empty list */ 88 194 : sclist->last->next = record; 89 194 : sclist->last = record; 90 : } 91 352 : return record; 92 : } 93 : 94 223 : sclist_t* sclist_remrecord(sclist_t* sclist, sclistrecord_t* record) { 95 : sclistrecord_t* cur; 96 : sclistrecord_t* prev; 97 : 98 223 : assert(sclist); 99 223 : assert(record); 100 : 101 256 : for (cur=sclist->first, prev=NULL; (cur)&&(cur!=record); prev=cur,cur=cur->next); 102 : 103 : /* If found */ 104 223 : if (NULL!=cur) { 105 : /* Remove from the chain */ 106 215 : if (sclist->first==cur) 107 200 : sclist->first = cur->next; 108 : else 109 15 : prev->next = cur->next; 110 : /* Update the last pointer if needed */ 111 215 : if (sclist->last==cur) 112 125 : sclist->last = prev; 113 215 : free(cur); 114 215 : return sclist; 115 : } else { 116 8 : fprintf(stderr,"ERROR: sclist_remrecord record not found.\n"); 117 8 : return NULL; 118 : } 119 : } 120 : 121 372 : sclistrecord_t* sclist_firstrecord(const sclist_t* sclist) { 122 372 : assert(sclist); 123 : 124 372 : return sclist->first; 125 : } 126 : 127 456 : sclistrecord_t* sclist_nextrecord(const sclistrecord_t* record) { 128 456 : assert(record); 129 : 130 456 : return record->next; 131 : } 132 : 133 586 : void* sclist_getvalue(sclistrecord_t* record) { 134 586 : assert(record); 135 : 136 586 : return record->value; 137 : } 138 : /* vim: set tw=80: */