1 /*
2 ** Modular Logfile Analyzer
3 ** Copyright 2000 Jan Kneschke <jan@kneschke.de>
4 **
5 ** Homepage: http://www.modlogan.org
6 **
7 
8     This program is free software; you can redistribute it and/or modify
9     it under the terms of the GNU General Public License as published by
10     the Free Software Foundation; either version 2 of the License, or
11     (at your option) any later version, and provided that the above
12     copyright and permission notice is included with all distributed
13     copies of this or derived software.
14 
15     This program is distributed in the hope that it will be useful,
16     but WITHOUT ANY WARRANTY; without even the implied warranty of
17     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18     GNU General Public License for more details.
19 
20     You should have received a copy of the GNU General Public License
21     along with this program; if not, write to the Free Software
22     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
23 
24 **
25 ** $Id: mlist.c,v 1.27 2004/08/27 20:07:37 ostborn Exp $
26 */
27 
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <time.h>
31 #include <string.h>
32 #include <assert.h>
33 
34 #include "config.h"
35 #include "mlist.h"
36 #include "mdatatypes.h"
37 #include "mconfig.h"
38 
39 extern size_t mem_mlist_size;
40 extern size_t mem_mlist_count;
41 
mlist_sort_full_by_string(mlist * l)42 mlist* mlist_sort_full_by_string (mlist *l) {
43 	return mlist_sort_limited_by_string(l, -1);
44 }
45 
mlist_sort_limited_by_string(mlist * l,int count)46 mlist* mlist_sort_limited_by_string (mlist *l, int count) {
47 	mlist *act, *first;
48 	int i = 0;
49 
50 	if (l == NULL || count == 0) return l;
51 
52 	first = l;
53 	act = l;
54 
55 	if (count < 0) count = 0;
56 
57 	for ( i = 0; (!count || (i < count)) && act; i++) {
58 		mlist *w;
59 		mlist *s = act;
60 
61 		for (w = act->next; w; w = w->next) {
62 			if (strcmp(w->data->key, s->data->key) < 0 ) {
63 				s = w;
64 			}
65 		}
66 
67 		if ( s != act ) {
68 		/* insert in the sorted part of the list */
69 
70 		/* take 'act' from the list */
71 			s->prev->next = s->next;
72 
73 			if (s->next)
74 				s->next->prev = s->prev;
75 
76 			/* insert it at the right place */
77 
78 			if (act == first) {
79 				s->prev = NULL;
80 				s->next = first;
81 
82 				first->prev = s;
83 
84 				first = s;
85 			} else {
86 				s->prev = act->prev;
87 				s->next = act;
88 
89 				act->prev->next = s;
90 				act->prev = s;
91 			}
92 		} else {
93 			act = act->next;
94 		}
95 	}
96 
97 	return first;
98 }
99 
mlist_init()100 mlist *mlist_init () {
101 	mlist *l = malloc(sizeof(mlist));
102 	assert(l);
103 
104 	l->prev = NULL;
105 	l->next = NULL;
106 	l->data = NULL;
107 
108 	mem_mlist_count++;
109 	mem_mlist_size += sizeof(mlist);
110 
111 	return l;
112 }
113 
mlist_free_entry(mlist * l)114 int mlist_free_entry(mlist *l) {
115 	if (!l)	return -1;
116 	if (l->data)	mdata_free(l->data);
117 
118 	free(l);
119 
120 	return 0;
121 }
122 
mlist_free(mlist * l)123 int mlist_free(mlist *l) {
124 	mlist *act;
125 	if (!l) return 0;
126 
127 	/* rewind to the beginnig */
128 	for (;l->prev; l = l->prev);
129 
130 	/* erase the list */
131 	while (l) {
132 		act = l;
133 		l = l->next;
134 
135 		mlist_free_entry(act);
136 	}
137 
138 	return 0;
139 }
140 
mlist_is_empty(mlist * l)141 int mlist_is_empty(mlist *l) {
142 	if (!l) return 1;
143 
144 	return (l->data == NULL);
145 }
146 
147 /*
148 	einf�gen (eher ein append)
149 	bei gleichheit versuch des anh�ngens
150 */
151 
mlist_insert(mlist * l,mdata * ins_data)152 int mlist_insert (mlist *l, mdata *ins_data) {
153 	int inserted = 0;
154 
155 	if (!l) return -1;
156 	if (!ins_data) return -1;
157 
158 	if (NULL == ins_data->key) {
159 		M_DEBUG1(M_DEBUG_LEVEL_ERRORS, M_DEBUG_SECTION_INTERNALS, M_DEBUG_LEVEL_ERRORS,
160 			 "ins_data = %p, but its key is NULL\n", ins_data);
161 		return -1;
162 	}
163 
164 	for (; l && l->data; l = l->next) {
165 		mdata *data = l->data;
166 		int r = 0;
167 
168 		if (NULL == data->key) {
169 			fprintf(stderr, "%s.%d: no key -> %d\n", __FILE__, __LINE__, data->type);
170 		}
171 
172 		r = strcmp(ins_data->key, data->key);
173 
174 		if (0 == r) {
175 			if (mdata_append(data, ins_data) == M_DATA_APPENDED) {
176 				inserted = 1;
177 
178 				/* the memory isn't used anymore */
179 				mdata_free(ins_data);
180 				ins_data = NULL;
181 				break;
182 			}
183 		}
184 
185 		if (!l->next) break;
186 	}
187 
188 	if (!inserted) {
189 		if (mlist_is_empty(l)) {
190 			l->data = ins_data;
191 		} else {
192 			mlist *n = mlist_init();
193 
194 			n->data = ins_data;
195 			n->prev = l;
196 			l->next = n;
197 		}
198 	}
199 
200 	return 0;
201 }
202 
203 /*
204 	einf�gen (d.h. append)
205 	bei gleichheit ersetzen
206 */
207 
mlist_insert_replace(mlist * l,mdata * ins_data)208 int mlist_insert_replace (mlist *l, mdata *ins_data) {
209 	int inserted = 0;
210 
211 	if (!l) return -1;
212 	if (!ins_data) return -1;
213 
214 	for (; l && l->data;  l = l->next) {
215 		mdata *data = l->data;
216 
217 		if (data->key == NULL) {
218 			fprintf(stderr, "%s.%d: no key -> %d\n", __FILE__, __LINE__, data->type);
219 		}
220 
221 		if (0 == strcmp(ins_data->key, data->key)) {
222 			/* Free old Data */
223 			mdata_free(data);
224 			l->data = ins_data;
225 			ins_data = NULL;
226 			inserted = 1;
227 			break;
228 		}
229 
230 		if (!l->next) break;
231 	}
232 
233 	if (!inserted) {
234 		if (mlist_is_empty(l)) {
235 			l->data = ins_data;
236 		} else {
237 			mlist *n = mlist_init();
238 
239 			n->data = ins_data;
240 			n->prev = l;
241 			l->next = n;
242 		}
243 	}
244 
245 	return 0;
246 }
247 
248 /**
249  * sortiert einf�gen, aufsteigened
250  * bei gleichheit versuchen anzuh�ngen
251  *
252  * @return -1 one error, 0 if appended, 1 if inserted
253  */
254 
mlist_insert_sorted(mlist * l,mdata * ins_data)255 int mlist_insert_sorted (mlist *l, mdata *ins_data) {
256 	int ins_me = 0;
257 
258 	if (!l) return -1;
259 	if (!ins_data) return -1;
260 
261 	for (; l && l->data; l = l->next) {
262 		mdata *data = l->data;
263 		int res = 0;
264 
265 		if (data->type != ins_data->type) {
266 			fprintf(stderr, "%s.%d: die()\n", __FILE__, __LINE__);
267 			return -1;
268 		}
269 
270 		res = strcmp(ins_data->key, data->key);
271 
272 		if (res == 0) {
273 			if (mdata_append(data, ins_data) == M_DATA_APPENDED) {
274 				ins_me = -1;
275 			/* the memory isn't used anymore */
276 				mdata_free(ins_data);
277 				ins_data = NULL;
278 				break;
279 			}
280 		} else if (res < 0) {
281 			ins_me = 1;
282 			break;
283 		}
284 
285 		if (!l->next) break;
286 	}
287 
288 	/* every thing is done, just leave the building */
289 	if (ins_me == -1) {
290 
291 	} else if (!l->data) {
292 		l->data = ins_data;
293 	} else if (ins_me) {
294 		mlist *n = mlist_init();
295 
296 		n->data = l->data;
297 		l->data = ins_data;
298 		n->next = l->next;
299 		n->prev = l;
300 		if (n->next)
301 			n->next->prev = n;
302 		l->next = n;
303 	} else {
304 		mlist *n = mlist_init();
305 
306 		n->data = ins_data;
307 		n->prev = l;
308 		n->next = l->next;
309 		if (n->next)
310 			n->next->prev = n;
311 		l->next = n;
312 	}
313 
314 	return (ins_me == -1 ? 0 : 1);
315 }
316 
mlist_append(mlist * l,mdata * ins_data)317 int mlist_append (mlist *l, mdata *ins_data) {
318 	int inserted = 0;
319 
320 	if (!l) return -1;
321 	if (!ins_data) return -1;
322 
323 	while(l && l->data && l->next) {
324 		l = l->next;
325 	}
326 	if (!inserted) {
327 		if (mlist_is_empty(l)) {
328 			l->data = ins_data;
329 		} else {
330 			mlist *n = mlist_init();
331 
332 			n->data = ins_data;
333 			n->prev = l;
334 			l->next = n;
335 		}
336 	}
337 
338 	return 0;
339 }
340 
mlist_write(gzFile * fd,mlist * l)341 int mlist_write(gzFile *fd, mlist *l) {
342 	while (l) {
343 		if (l->data) {
344 			mdata_write(fd, l->data);
345 		}
346 		l = l->next;
347 	}
348 	return 0;
349 }
350 
mlist_count(mlist * l)351 int mlist_count(mlist *l) {
352 	int c = 0;
353 	if (!l) return 0;
354 
355 	while (l) {
356 		if (l->data) c++;
357 		l = l->next;
358 	}
359 
360 	return c;
361 }
362 
mlist_get_data(mlist * l,const char * str)363 mdata *mlist_get_data(mlist *l, const char *str) {
364 	mdata *data = NULL;
365 
366 	for (; l && l->data; l = l->next) {
367 		data = l->data;
368 
369 		if (!strcmp(str, data->key)) {
370 			break;
371 		}
372 
373 		data = NULL;
374 
375 		if (!l->next) break;
376 	}
377 
378 	return data;
379 }
380 
mlist_in_list(mlist * l,const char * str)381 int mlist_in_list(mlist *l, const char *str) {
382 	mdata *data = NULL;
383 
384 	for (; l && l->data; l = l->next) {
385 		data = l->data;
386 
387 		if (!strcmp(str, data->key)) {
388 			return 1;
389 		}
390 
391 		data = NULL;
392 
393 		if (!l->next) break;
394 	}
395 
396 	return 0;
397 }
398 
mlist_sumup(mlist * l)399 int mlist_sumup(mlist *l) {
400 	int c = 0;
401 	if (!l) return 0;
402 
403 	for (; l && l->data; l = l->next) {
404 		c += mdata_get_count(l->data);
405 	}
406 
407 	return c;
408 }
409 
mlist_sumup_vcount(mlist * l)410 double mlist_sumup_vcount(mlist *l) {
411 	double c = 0;
412 	if (!l) return 0;
413 
414 	while (l) {
415 		if (l->data) {
416 			c += mdata_get_vcount(l->data);
417 		}
418 		l = l->next;
419 	}
420 
421 	return c;
422 }
423