1 /*
2 * Author: William Chia-Wei Cheng (bill.cheng@acm.org)
3 *
4 * Copyright (C) 2001-2009, William Chia-Wei Cheng.
5 *
6 * This file may be distributed under the terms of the Q Public License
7 * as defined by Trolltech AS of Norway and appearing in the file
8 * LICENSE.QPL included in the packaging of this file.
9 *
10 * THIS FILE IS PROVIDED AS IS WITH NO WARRANTY OF ANY KIND, INCLUDING
11 * THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
12 * PURPOSE. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
13 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
14 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
15 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
16 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 *
18 * @(#)$Header: /mm2/home/cvs/bc-src/tgif/list.c,v 1.6 2011/05/16 16:21:58 william Exp $
19 */
20
21 #define _INCLUDE_FROM_LIST_C_
22
23 #include "tgifdefs.h"
24
25 #include "list.e"
26 #include "msg.e"
27
28 /* -------------------- Utility Functions -------------------- */
29
CompareForStringList(void * pv1,void * pv2)30 int CompareForStringList(void *pv1, void *pv2)
31 {
32 return strcmp(((char*)pv1), ((char*)pv2));
33 }
34
35 /* -------------------- CVListElem -------------------- */
36
37 static
NewCVListElem(void * obj)38 CVListElem *NewCVListElem(void *obj)
39 {
40 CVListElem *new_elem=(CVListElem*)malloc(sizeof(CVListElem));
41
42 if (new_elem == NULL) {
43 FailAllocMessage();
44 return NULL;
45 }
46 memset(new_elem, 0, sizeof(CVListElem));
47 new_elem->obj = obj;
48
49 return new_elem;
50 }
51
52 /* -------------------- CVList -------------------- */
53
ListLength(CVList * list)54 int ListLength(CVList *list)
55 {
56 return list->num_members;
57 }
58
ListEmpty(CVList * list)59 int ListEmpty(CVList *list)
60 {
61 return (list->num_members <= 0);
62 }
63
ListAppend(CVList * list,void * obj)64 int ListAppend(CVList *list, void *obj)
65 {
66 CVListElem *new_elem=NewCVListElem(obj);
67
68 if (new_elem == NULL) return FALSE;
69
70 new_elem->next = &(list->anchor);
71 new_elem->prev = list->anchor.prev;
72 list->anchor.prev->next = new_elem;
73 list->anchor.prev = new_elem;
74 list->num_members++;
75
76 return TRUE;
77 }
78
ListPrepend(CVList * list,void * obj)79 int ListPrepend(CVList *list, void *obj)
80 {
81 CVListElem *new_elem=NewCVListElem(obj);
82
83 if (new_elem == NULL) return FALSE;
84
85 new_elem->prev = &(list->anchor);
86 new_elem->next = list->anchor.next;
87 list->anchor.next->prev = new_elem;
88 list->anchor.next = new_elem;
89 list->num_members++;
90
91 return TRUE;
92 }
93
ListUnlink(CVList * list,CVListElem * elem)94 void ListUnlink(CVList *list, CVListElem *elem)
95 /* this will not free elem */
96 {
97 elem->prev->next = elem->next;
98 elem->next->prev = elem->prev;
99 elem->next = elem->prev = NULL;
100 list->num_members--;
101 }
102
ListUnlinkAll(CVList * list)103 void ListUnlinkAll(CVList *list)
104 /* this frees all the elements */
105 {
106 CVListElem *elem=NULL, *next_elem=NULL;
107
108 for (elem=ListFirst(list); elem != NULL; elem=next_elem) {
109 next_elem = ListNext(list, elem);
110 elem->prev = elem->next = NULL;
111 free(elem);
112 }
113 list->num_members = 0;
114 list->anchor.next = list->anchor.prev = (&list->anchor);
115 }
116
ListInsertAfter(CVList * list,void * obj,CVListElem * elem)117 int ListInsertAfter(CVList *list, void *obj, CVListElem *elem)
118 {
119 if (list->Empty(list) || elem == NULL) {
120 return ListPrepend(list, obj);
121 } else {
122 CVListElem *new_elem=NewCVListElem(obj);
123
124 if (new_elem == NULL) return FALSE;
125
126 new_elem->next = elem->next;
127 new_elem->prev = elem;
128 new_elem->next->prev = new_elem;
129 new_elem->prev->next = new_elem;
130 list->num_members++;
131 }
132 return TRUE;
133 }
134
ListInsertBefore(CVList * list,void * obj,CVListElem * elem)135 int ListInsertBefore(CVList *list, void *obj, CVListElem *elem)
136 {
137 if (list->Empty(list) || elem == NULL) {
138 return ListAppend(list, obj);
139 } else {
140 CVListElem *new_elem=NewCVListElem(obj);
141
142 if (new_elem == NULL) return FALSE;
143
144 new_elem->prev = elem->prev;
145 new_elem->next = elem;
146 new_elem->next->prev = new_elem;
147 new_elem->prev->next = new_elem;
148 list->num_members++;
149 }
150 return TRUE;
151 }
152
ListFirst(CVList * list)153 CVListElem *ListFirst(CVList *list)
154 {
155 if (list->Empty(list)) return NULL;
156
157 return list->anchor.next;
158 }
159
ListLast(CVList * list)160 CVListElem *ListLast(CVList *list)
161 {
162 if (list->Empty(list)) return NULL;
163
164 return list->anchor.prev;
165 }
166
ListNext(CVList * list,CVListElem * cur)167 CVListElem *ListNext(CVList *list, CVListElem *cur)
168 {
169 return (cur->next == (&list->anchor) ? NULL : cur->next);
170 }
171
ListPrev(CVList * list,CVListElem * cur)172 CVListElem *ListPrev(CVList *list, CVListElem *cur)
173 {
174 return (cur->prev == (&list->anchor) ? NULL : cur->prev);
175 }
176
ListFind(CVList * list,void * obj,CMPFN * pcmpfunc)177 CVListElem *ListFind(CVList *list, void *obj, CMPFN *pcmpfunc)
178 {
179 CVListElem *ptr=NULL;
180
181 for (ptr=ListFirst(list); ptr != NULL; ptr=ListNext(list, ptr)) {
182 if (pcmpfunc == NULL) {
183 if (ptr->obj == obj) {
184 return ptr;
185 }
186 } else if ((pcmpfunc)(ptr->obj, obj) == 0) {
187 return ptr;
188 }
189 }
190 return NULL;
191 }
192
CVListCleanUp(CVList * list)193 void CVListCleanUp(CVList *list)
194 {
195 if (list == NULL) return;
196
197 if (list->num_members) {
198 CVListElem *elem=NULL, *next_elem=NULL;
199
200 for (elem=ListFirst(list); elem != NULL; elem=next_elem) {
201 next_elem = ListNext(list, elem);
202 free(elem);
203 }
204 }
205 memset(list, 0, sizeof(CVList));
206 }
207
CVListInit(CVList * list)208 int CVListInit(CVList *list)
209 {
210 if (list == NULL) return FALSE;
211
212 memset(list, 0, sizeof(CVList));
213
214 list->num_members = 0;
215 list->anchor.prev = list->anchor.next = (&list->anchor);
216
217 list->First = ListFirst;
218 list->Last = ListLast;
219 list->Next = ListNext;
220 list->Prev = ListPrev;
221
222 list->Length = ListLength;
223
224 list->Append = ListAppend;
225 list->Prepend = ListPrepend;
226 list->Unlink = ListUnlink;
227 list->UnlinkAll = ListUnlinkAll;
228 list->InsertBefore = ListInsertBefore;
229 list->InsertAfter = ListInsertAfter;
230
231 list->Find = ListFind;
232
233 list->Empty = ListEmpty;
234
235 return TRUE;
236 }
237
238