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