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-16 16:27 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 : #include "sclist.h" 20 : 21 : #include <stdlib.h> 22 : #include <stdio.h> 23 : #include <assert.h> 24 : 25 : /** Private list record structure 26 : */ 27 : typedef struct sclistrecord_s { 28 : void* value; /**< Pointer to value */ 29 : struct sclistrecord_s* next; /**< Next record in the list */ 30 : } sclistrecord_t; 31 : 32 : /** Opaque sclist structure 33 : */ 34 : typedef struct sclist_s { 35 : sclistrecord_t* first; /**< Pointer to the first record */ 36 : sclistrecord_t* last; /**< Pointer to the last record */ 37 : } sclist_t; 38 : 39 61 : sclist_t* sclist_new() { 40 : sclist_t* sclist; 41 61 : if (NULL==(sclist=malloc(sizeof(struct sclist_s)))) { 42 0 : perror("sclist_new OOM"); 43 0 : abort(); 44 : } 45 61 : sclist->first=NULL; 46 61 : sclist->last=NULL; 47 : 48 61 : return sclist; 49 : } 50 : 51 6 : void sclist_del(sclist_t* sclist) { 52 6 : assert(sclist); 53 : 54 12 : while (sclist->first!=NULL) { 55 6 : sclistrecord_t* first = sclist->first; 56 6 : sclist->first = sclist->first->next; 57 6 : free(first); 58 : } 59 6 : free(sclist); 60 6 : } 61 : 62 146 : sclistrecord_t* sclist_addrecord(sclist_t* sclist, void* value) { 63 : sclistrecord_t* record; 64 : 65 146 : assert(sclist); 66 : 67 : /* Create the record record */ 68 146 : if (NULL==(record=malloc(sizeof(struct sclistrecord_s)))) { 69 0 : perror("sclist_addrecord OOM"); 70 0 : abort(); 71 : } 72 146 : record->value = value; 73 146 : record->next = NULL; 74 : 75 : /* Add to the list */ 76 146 : if (NULL==sclist->first) { 77 : /* First record to be added in an empty list */ 78 : /* A sentinel record would avoid this test and optimize performances 79 : * at the cost of sentinel size RAM consumption */ 80 44 : sclist->first = record; 81 44 : sclist->last = record; 82 : } else { 83 : /* Add to the end of a non-empty list */ 84 102 : sclist->last->next = record; 85 102 : sclist->last = record; 86 : } 87 146 : return record; 88 : } 89 : 90 26 : void sclist_remrecord(sclist_t* sclist, sclistrecord_t* record) { 91 : sclistrecord_t* cur; 92 : sclistrecord_t* prev; 93 : 94 26 : assert(sclist); 95 26 : assert(record); 96 : 97 39 : for (cur=sclist->first, prev=NULL; (cur)&&(cur!=record); prev=cur,cur=cur->next); 98 : 99 : /* If found */ 100 26 : if (NULL!=cur) { 101 : /* Remove from the chain */ 102 22 : if (sclist->first==cur) 103 14 : sclist->first = cur->next; 104 : else 105 8 : prev->next = cur->next; 106 : /* Update the last pointer if needed */ 107 22 : if (sclist->last==cur) 108 16 : sclist->last = prev; 109 : } else { 110 4 : fprintf(stderr,"sclist_remrecord record not found.\n"); 111 4 : abort(); 112 : } 113 22 : } 114 : 115 116 : sclistrecord_t* sclist_firstrecord(const sclist_t* sclist) { 116 116 : assert(sclist); 117 : 118 116 : return sclist->first; 119 : } 120 : 121 162 : sclistrecord_t* sclist_nextrecord(const sclistrecord_t* record) { 122 162 : assert(record); 123 : 124 162 : return record->next; 125 : } 126 : 127 191 : void* sclist_getvalue(sclistrecord_t* record) { 128 191 : assert(record); 129 : 130 191 : return record->value; 131 : } 132 : /* vim: set tw=80: */