1 /*
2 *
3 * Copyright (c) 2014, Red Hat, Inc.
4 * Copyright (c) 2014, Masatake YAMATO
5 *
6 * This source code is released for free distribution under the terms of the
7 * GNU General Public License.
8 *
9 */
10
11 #include "general.h"
12
13 #include "debug.h"
14 #include "routines.h"
15 #include "trashbox.h"
16
17 typedef TrashBoxDestroyItemProc TrashDestroyItemProc;
18 typedef struct sTrash {
19 void* item;
20 struct sTrash* next;
21 TrashDestroyItemProc destrctor;
22 } Trash;
23
24 struct sTrashBox {
25 Trash *trash;
26 };
27
28 static TrashBox* defaultTrashBox;
29 static TrashBox* parserTrashBox;
30
31 static Trash* trashPut (Trash* trash, void* item,
32 TrashDestroyItemProc destrctor);
33 static Trash* trashTakeBack (Trash* trash, void* item, TrashDestroyItemProc* destrctor);
34 static Trash* trashMakeEmpty (Trash* trash);
35
trashBoxNew(void)36 extern TrashBox* trashBoxNew (void)
37 {
38 TrashBox *t = xMalloc (1, TrashBox);
39 t->trash = NULL;
40 return t;
41 }
42
trashBoxStack(TrashBox * trash_box)43 extern TrashBox* trashBoxStack (TrashBox* trash_box)
44 {
45 TrashBox *t = trashBoxNew();
46
47 if (!trash_box)
48 trash_box = defaultTrashBox;
49
50 trashBoxPut (trash_box, t, (TrashBoxDestroyItemProc) trashBoxDelete);
51
52 return t;
53 }
54
trashBoxDelete(TrashBox * trash_box)55 extern void trashBoxDelete (TrashBox* trash_box)
56 {
57 if (!trash_box)
58 trash_box = defaultTrashBox;
59
60 trashBoxMakeEmpty(trash_box);
61
62 eFree (trash_box);
63 }
64
trashBoxPut(TrashBox * trash_box,void * item,TrashBoxDestroyItemProc destroy)65 extern void* trashBoxPut (TrashBox* trash_box, void* item, TrashBoxDestroyItemProc destroy)
66 {
67 if (!trash_box)
68 trash_box = defaultTrashBox;
69
70 trash_box->trash = trashPut(trash_box->trash, item, destroy);
71 return item;
72 }
73
trashBoxTakeBack(TrashBox * trash_box,void * item)74 extern TrashBoxDestroyItemProc trashBoxTakeBack (TrashBox* trash_box, void* item)
75 {
76 TrashBoxDestroyItemProc d;
77
78 if (!trash_box)
79 trash_box = defaultTrashBox;
80
81 trash_box->trash = trashTakeBack(trash_box->trash, item, &d);
82 return d;
83 }
84
trashBoxMakeEmpty(TrashBox * trash_box)85 extern void trashBoxMakeEmpty (TrashBox* trash_box)
86 {
87 if (!trash_box)
88 trash_box = defaultTrashBox;
89
90 trash_box->trash = trashMakeEmpty (trash_box->trash);
91 }
92
93
trashBoxFree(TrashBox * trash_box,void * item)94 extern void trashBoxFree (TrashBox* trash_box, void* item)
95 {
96 TrashBoxDestroyItemProc d;
97
98 if (!trash_box)
99 trash_box = defaultTrashBox;
100
101 d = trashBoxTakeBack (trash_box, item);
102 d (item);
103 }
104
trashPut(Trash * trash,void * item,TrashDestroyItemProc destrctor)105 static Trash* trashPut (Trash* trash, void* item,
106 TrashDestroyItemProc destrctor)
107 {
108 Trash* t = xMalloc (1, Trash);
109 t->next = trash;
110 t->item = item;
111 t->destrctor = destrctor? destrctor: eFree;
112 return t;
113 }
114
trashTakeBack0(Trash ** trash,void * item)115 static TrashBoxDestroyItemProc trashTakeBack0 (Trash** trash, void* item)
116 {
117 TrashBoxDestroyItemProc removed;
118 Trash* tmp;
119
120 removed = NULL;
121 while (*trash)
122 {
123 if ( (*trash)->item == item )
124 {
125 tmp = *trash;
126 *trash = (*trash)->next;
127 tmp->next = NULL;
128 tmp->item = NULL;
129 removed = tmp->destrctor;
130
131 eFree (tmp);
132 tmp = NULL;
133 break;
134 }
135 else
136 trash = &(*trash)->next;
137 }
138
139 Assert (removed);
140 return removed;
141 }
142
trashTakeBack(Trash * trash,void * item,TrashDestroyItemProc * destrctor)143 static Trash* trashTakeBack (Trash* trash, void* item, TrashDestroyItemProc *destrctor)
144 {
145 TrashDestroyItemProc d;
146 d = trashTakeBack0 (&trash, item);
147 if (destrctor)
148 *destrctor = d;
149
150 return trash;
151 }
152
trashMakeEmpty(Trash * trash)153 static Trash* trashMakeEmpty (Trash* trash)
154 {
155 Trash* tmp;
156
157 while (trash)
158 {
159 tmp = trash;
160 trash = trash->next;
161 tmp->destrctor (tmp->item);
162 tmp->item = NULL;
163 tmp->destrctor = NULL;
164 eFree (tmp);
165 }
166 return NULL;
167 }
168
initDefaultTrashBox(void)169 extern void initDefaultTrashBox (void)
170 {
171 defaultTrashBox = trashBoxNew ();
172 }
173
finiDefaultTrashBox(void)174 extern void finiDefaultTrashBox (void)
175 {
176 trashBoxDelete (defaultTrashBox);
177 defaultTrashBox = NULL;
178 }
179
initParserTrashBox(void)180 extern void initParserTrashBox (void)
181 {
182 parserTrashBox = trashBoxNew ();
183 }
184
finiParserTrashBox(void)185 extern void finiParserTrashBox (void)
186 {
187 trashBoxDelete (parserTrashBox);
188 parserTrashBox = NULL;
189 }
190
parserTrashBoxPut(void * item,TrashBoxDestroyItemProc destroy)191 extern void* parserTrashBoxPut (void* item, TrashBoxDestroyItemProc destroy)
192 {
193 return trashBoxPut(parserTrashBox, item, destroy);
194 }
195
parserTrashBoxTakeBack(void * item)196 extern TrashBoxDestroyItemProc parserTrashBoxTakeBack (void* item)
197 {
198 return trashBoxTakeBack(parserTrashBox, item);
199 }
200
201 #ifdef TRASH_TEST
202 #include <stdio.h>
203
main(void)204 int main (void)
205 {
206 Trash* trash = NULL;
207 Trash* tmp;
208 char* d = eStrdup ("d");
209 char* b = eStrdup ("b");
210
211 trash = trashPut (trash, eStrdup ("a"));
212 trash = trashPut (trash, b);
213 trash = trashPut (trash, eStrdup ("c"));
214 trash = trashPut (trash, d);
215
216 trash = trashTakeBack (trash, b, NULL);
217 eFree (b);
218
219 fputs("expects: dca\nactual: ", stderr);
220 for (tmp = trash; tmp; tmp = tmp->next)
221 fputs(tmp->item, stderr);
222 fputc('\n', stderr);
223
224
225 trash = trashTakeBack (trash, d, NULL);
226 eFree (d);
227
228 fputs("expects: ca\nactual: ", stderr);
229 for (tmp = trash; tmp; tmp = tmp->next)
230 fputs(tmp->item, stderr);
231 fputc('\n', stderr);
232
233 trash = trashMakeEmpty (trash);
234
235 fputs("expects: \nactual: ", stderr);
236 for (tmp = trash; tmp; tmp = tmp->next)
237 fputs(tmp->item, stderr);
238 fputc('\n', stderr);
239 return 0;
240 }
241
242 #include <stdlib.h>
eFree(void * ptr)243 void eFree (void *ptr) { free(ptr); }
eMalloc(const size_t size)244 void *eMalloc (const size_t size) { return malloc(size); }
eStrdup(const char * str)245 char *eStrdup (const char* str) { return strdup(str); }
246 #endif
247