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