1 /*
2  * Wrapper for list.h that keeps track of number of items.
3  *
4  * Copyright (c) 2007-2009  Marko Kreen, Skype Technologies OÜ
5  *
6  * Permission to use, copy, modify, and/or distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 /**
20  * @file
21  *
22  * Circular list that keep track of stats about the list.
23  *
24  * Currenly only count of abjects currently in list
25  * is kept track of.  The plan was to track more,
26  * like max, but it was not useful enough.
27  */
28 #ifndef _USUAL_STATLIST_H_
29 #define _USUAL_STATLIST_H_
30 
31 #include <usual/list.h>
32 
33 /**
34  * Header structure for StatList.
35  */
36 struct StatList {
37 	/** Actual list head */
38 	struct List head;
39 	/** Count of objects currently in list */
40 	int cur_count;
41 #ifdef LIST_DEBUG
42 	/** List name */
43 	const char *name;
44 #endif
45 };
46 
47 /** Define and initialize StatList head */
48 #ifdef LIST_DEBUG
49 #define STATLIST(var) struct StatList var = { {&var.head, &var.head}, 0, #var }
50 #else
51 #define STATLIST(var) struct StatList var = { {&var.head, &var.head}, 0 }
52 #endif
53 
54 /** Add to the start of the list */
statlist_prepend(struct StatList * list,struct List * item)55 static inline void statlist_prepend(struct StatList *list, struct List *item)
56 {
57 	list_prepend(&list->head, item);
58 	list->cur_count++;
59 }
60 
61 /** Add to the end of the list */
statlist_append(struct StatList * list,struct List * item)62 static inline void statlist_append(struct StatList *list, struct List *item)
63 {
64 	list_append(&list->head, item);
65 	list->cur_count++;
66 }
67 
68 /** Remove element from the list */
statlist_remove(struct StatList * list,struct List * item)69 static inline void statlist_remove(struct StatList *list, struct List *item)
70 {
71 	list_del(item);
72 	list->cur_count--;
73 
74 	/* Assert(list->cur_count >= 0); */
75 }
76 
77 /** Initialize StatList head */
statlist_init(struct StatList * list,const char * name)78 static inline void statlist_init(struct StatList *list, const char *name)
79 {
80 	list_init(&list->head);
81 	list->cur_count = 0;
82 #ifdef LIST_DEBUG
83 	list->name = name;
84 #endif
85 }
86 
87 /** return number of elements currently in list */
statlist_count(const struct StatList * list)88 static inline int statlist_count(const struct StatList *list)
89 {
90 	/* Assert(list->cur_count > 0 || list_empty(&list->head)); */
91 	return list->cur_count;
92 }
93 
94 /** remove and return first element */
statlist_pop(struct StatList * list)95 static inline struct List *statlist_pop(struct StatList *list)
96 {
97 	struct List *item = list_pop(&list->head);
98 
99 	if (item)
100 		list->cur_count--;
101 
102 	/* Assert(list->cur_count >= 0); */
103 
104 	return item;
105 }
106 
107 /** Return first element */
statlist_first(const struct StatList * list)108 static inline struct List *statlist_first(const struct StatList *list)
109 {
110 	return list_first(&list->head);
111 }
112 
113 /** Return last element */
statlist_last(const struct StatList * list)114 static inline struct List *statlist_last(const struct StatList *list)
115 {
116 	return list_last(&list->head);
117 }
118 
119 /** Is list empty */
statlist_empty(const struct StatList * list)120 static inline bool statlist_empty(const struct StatList *list)
121 {
122 	return list_empty(&list->head);
123 }
124 
125 /** Loop over list */
126 #define statlist_for_each(item, list) list_for_each(item, &((list)->head))
127 
128 /** Loop over list backwards */
129 #define statlist_for_each_reverse(item, list) list_for_each_reverse(item, &((list)->head))
130 
131 /** Loop over list safely, so that elements can be removed during */
132 #define statlist_for_each_safe(item, list, tmp) list_for_each_safe(item, &((list)->head), tmp)
133 
134 /** Loop over list backwards safely, so that elements can be removed during */
135 #define statlist_for_each_reverse_safe(item, list, tmp) list_for_each_reverse_safe(item, &((list)->head), tmp)
136 
137 /** Put intem before another */
statlist_put_before(struct StatList * list,struct List * item,struct List * pos)138 static inline void statlist_put_before(struct StatList *list, struct List *item, struct List *pos)
139 {
140 	list_append(pos, item);
141 	list->cur_count++;
142 }
143 
144 /** Put item after another */
statlist_put_after(struct StatList * list,struct List * item,struct List * pos)145 static inline void statlist_put_after(struct StatList *list, struct List *item, struct List *pos)
146 {
147 	list_prepend(pos, item);
148 	list->cur_count++;
149 }
150 
151 #endif /* __LIST_H_ */
152