• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #ifndef _DEPOOLMULTISET_H
2 #define _DEPOOLMULTISET_H
3 /*-------------------------------------------------------------------------
4  * drawElements Memory Pool Library
5  * --------------------------------
6  *
7  * Copyright 2014 The Android Open Source Project
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  *//*!
22  * \file
23  * \brief Memory pool multiset class.
24  *//*--------------------------------------------------------------------*/
25 
26 #include "deDefs.h"
27 #include "deMemPool.h"
28 #include "dePoolHash.h"
29 #include "deInt32.h"
30 
31 DE_BEGIN_EXTERN_C
32 
33 void	dePoolMultiSet_selfTest		(void);
34 
35 DE_END_EXTERN_C
36 
37 /*--------------------------------------------------------------------*//*!
38  * \brief Declare a template pool multiset class interface.
39  * \param TYPENAME	Type name of the declared multiset.
40  * \param KEYTYPE	Type of the key.
41  *
42  * This macro declares the interface for a multiset. For the implementation
43  * of the multiset, see DE_IMPLEMENT_POOL_MULTISET. Usually this macro is put
44  * into the header file and the implementation macro is put in some .c file.
45  *
46  * \todo [petri] Detailed description.
47  *
48  * The functions for operating the multiset are:
49  * \todo [petri] Figure out how to comment these in Doxygen-style.
50  *
51  * \code
52  * MultiSet* MultiSet_create            (deMemPool* pool);
53  * int       MultiSet_getNumElements    (const MultiSet* set);
54  * deBool    MultiSet_exists            (const MultiSet* set, Key key);
55  * deBool    MultiSet_insert            (MultiSet* set, Key key);
56  * void      MultiSet_delete            (MultiSet* set, Key key);
57  * int       MultiSet_getKeyCount       (const MultiSet* set, Key key);
58  * deBool    MultiSet_setKeyCount       (MultiSet* set, Key key, int count);
59  * \endcode
60 *//*--------------------------------------------------------------------*/
61 #define DE_DECLARE_POOL_MULTISET(TYPENAME, KEYTYPE)		\
62 \
63 DE_DECLARE_POOL_HASH(TYPENAME##Hash, KEYTYPE, int);	\
64 \
65 typedef struct TYPENAME##_s    \
66 {    \
67 	deMemPool*			pool;    \
68 	int					numElements;    \
69 	TYPENAME##Hash*		hash;	\
70 } TYPENAME;    \
71 \
72 TYPENAME*	TYPENAME##_create		(deMemPool* pool);    \
73 void		TYPENAME##_reset		(TYPENAME* set);    \
74 deBool		TYPENAME##_setKeyCount	(TYPENAME* set, KEYTYPE key, int newCount);	\
75 \
76 DE_INLINE int TYPENAME##_getNumElements (const TYPENAME* set)    \
77 {    \
78 	return set->numElements;    \
79 }    \
80 \
81 DE_INLINE int TYPENAME##_getKeyCount (const TYPENAME* set, KEYTYPE key)	\
82 {	\
83 	int* countPtr	= TYPENAME##Hash_find(set->hash, key);	\
84 	int  count		= countPtr ? *countPtr : 0;	\
85 	DE_ASSERT(count > 0 || !countPtr);	\
86 	return count;	\
87 }	\
88 \
89 DE_INLINE deBool TYPENAME##_exists (const TYPENAME* set, KEYTYPE key)    \
90 {    \
91 	return (TYPENAME##_getKeyCount(set, key) > 0);	\
92 }    \
93 \
94 DE_INLINE deBool TYPENAME##_insert (TYPENAME* set, KEYTYPE key)    \
95 {	\
96 	int oldCount = TYPENAME##_getKeyCount(set, key);	\
97 	return TYPENAME##_setKeyCount(set, key, oldCount + 1);	\
98 }	\
99 \
100 DE_INLINE void TYPENAME##_delete (TYPENAME* set, KEYTYPE key)    \
101 {    \
102 	int oldCount = TYPENAME##_getKeyCount(set, key);	\
103 	DE_ASSERT(oldCount > 0);	\
104 	TYPENAME##_setKeyCount(set, key, oldCount - 1);	\
105 }    \
106 \
107 struct TYPENAME##DeclareDummy_s { int dummy; }
108 
109 /*--------------------------------------------------------------------*//*!
110  * \brief Implement a template pool multiset class.
111  * \param TYPENAME	Type name of the declared multiset.
112  * \param KEYTYPE	Type of the key.
113  * \param HASHFUNC	Function used for hashing the key.
114  * \param CMPFUNC	Function used for exact matching of the keys.
115  *
116  * This macro has implements the set declared with DE_DECLARE_POOL_MULTISET.
117  * Usually this macro should be used from a .c file, since the macro expands
118  * into multiple functions. The TYPENAME and KEYTYPE parameters
119  * must match those of the declare macro.
120 *//*--------------------------------------------------------------------*/
121 #define DE_IMPLEMENT_POOL_MULTISET(TYPENAME, KEYTYPE, HASHFUNC, CMPFUNC)		\
122 \
123 DE_IMPLEMENT_POOL_HASH(TYPENAME##Hash, KEYTYPE, int, HASHFUNC, CMPFUNC);	\
124 \
125 TYPENAME* TYPENAME##_create (deMemPool* pool)    \
126 {   \
127 	/* Alloc struct. */ \
128 	TYPENAME* set = DE_POOL_NEW(pool, TYPENAME); \
129 	if (!set) \
130 		return DE_NULL; \
131 \
132 	/* Init. */ \
133 	memset(set, 0, sizeof(TYPENAME)); \
134 	set->pool = pool; \
135 \
136 	set->hash = TYPENAME##Hash_create(pool);	\
137 \
138 	return set; \
139 } \
140 \
141 void TYPENAME##_reset (TYPENAME* set)    \
142 {   \
143 	TYPENAME##Hash_reset(set->hash);	\
144 	set->numElements = 0;	\
145 }	\
146 \
147 deBool TYPENAME##_setKeyCount (TYPENAME* set, KEYTYPE key, int newCount)	\
148 {	\
149 	int* countPtr	= TYPENAME##Hash_find(set->hash, key);	\
150 	int  oldCount	= countPtr ? *countPtr : 0;	\
151 \
152 	DE_ASSERT(oldCount > 0 || !countPtr);	\
153 	DE_ASSERT(newCount >= 0);	\
154 	set->numElements += (newCount - oldCount);	\
155 \
156 	if (newCount == 0 && countPtr)	\
157 		TYPENAME##Hash_delete(set->hash, key);	\
158 	else if (newCount > 0 && countPtr)	\
159 		*countPtr = newCount;	\
160 	else if (newCount > 0)	\
161 		return TYPENAME##Hash_insert(set->hash, key, newCount);	\
162 	return DE_TRUE;	\
163 }	\
164 \
165 struct TYPENAME##ImplementDummy_s { int dummy; }
166 
167 /*--------------------------------------------------------------------*//*!
168  * \brief Declare set-wise operations for a multiset template.
169  * \param TYPENAME	Type name of the declared set.
170  * \param KEYTYPE	Type of the key.
171  *
172  * This macro declares union and intersection operations for a multiset.
173  * For implementation see DE_IMPLEMENT_POOL_MULTISET_UNION_INTERSECT.
174  *
175  * \todo [petri] Detailed description.
176  *
177  * The functions for operating the set are:
178  * \todo [petri] Figure out how to comment these in Doxygen-style.
179  *
180  * \code
181  * deBool	MultiSet_union				(Set* to, const Set* a, const Set* b);
182  * deBool	MultiSet_unionInplace		(Set* a, const Set* b);
183  * deBool	MultiSet_intersect			(Set* to, const Set* a, const Set* b);
184  * void		MultiSet_intersectInplace	(Set* a, const Set* b);
185  * deBool   MultiSet_sum				(Set* to, const Set* a, const Set* b);
186  * deBool   MultiSet_sumInplace			(Set* a, const Set* b);
187  * deBool   MultiSet_difference			(Set* to, const Set* a, const Set* b);
188  * void		MultiSet_differenceInplace	(Set* a, const Set* b);
189  * \endcode
190 *//*--------------------------------------------------------------------*/
191 #define DE_DECLARE_POOL_MULTISET_SETWISE_OPERATIONS(TYPENAME)	\
192 	deBool TYPENAME##_union (TYPENAME* to, const TYPENAME* a, const TYPENAME* b);	\
193 	deBool TYPENAME##_unionInplace (TYPENAME* a, const TYPENAME* b);	\
194 	deBool TYPENAME##_intersect (TYPENAME* to, const TYPENAME* a, const TYPENAME* b);	\
195 	void TYPENAME##_intersectInplace (TYPENAME* a, const TYPENAME* b);	\
196 	deBool TYPENAME##_sum (TYPENAME* to, const TYPENAME* a, const TYPENAME* b);	\
197 	deBool TYPENAME##_sumInplace (TYPENAME* a, const TYPENAME* b);	\
198 	deBool TYPENAME##_difference (TYPENAME* to, const TYPENAME* a, const TYPENAME* b);	\
199 	void TYPENAME##_differenceInplace (TYPENAME* a, const TYPENAME* b);	\
200 	struct TYPENAME##SetwiseDeclareDummy_s { int dummy; }
201 
202 #define DE_IMPLEMENT_POOL_MULTISET_SETWISE_OPERATIONS(TYPENAME, KEYTYPE)	\
203 deBool TYPENAME##_union (TYPENAME* to, const TYPENAME* a, const TYPENAME* b)	\
204 {	\
205 	TYPENAME##_reset(to);	\
206 	return TYPENAME##_unionInplace(to, a) && TYPENAME##_unionInplace(to, b);	\
207 }	\
208 \
209 deBool TYPENAME##_unionInplace (TYPENAME* a, const TYPENAME* b)	\
210 {	\
211 	TYPENAME##HashIter iter;	\
212 	for (TYPENAME##HashIter_init(b, &iter);	\
213 		 TYPENAME##HashIter_hasItem(&iter);	\
214 		 TYPENAME##HashIter_next(&iter))	\
215 	{	\
216 		KEYTYPE	key		= TYPENAME##HashIter_getKey(&iter);	\
217 		int		bCount	= TYPENAME##HashIter_getValue(&iter);	\
218 		int		aCount	= TYPENAME##_getKeyCount(a, key);	\
219 		int		count	= deMax32(aCount, bCount);	\
220 		if (bCount && !TYPENAME##_setKeyCount(a, key, aCount + bCount))	\
221 			return DE_FALSE;	\
222 	}	\
223 	return DE_TRUE;	\
224 }	\
225 \
226 deBool TYPENAME##_intersect (TYPENAME* to, const TYPENAME* a, const TYPENAME* b)	\
227 {	\
228 	TYPENAME##HashIter iter;	\
229 	TYPENAME##_reset(to);	\
230 	for (TYPENAME##HashIter_init(a, &iter);	\
231 		 TYPENAME##HashIter_hasItem(&iter);	\
232 		 TYPENAME##HashIter_next(&iter))	\
233 	{	\
234 		KEYTYPE key		= TYPENAME##HashIter_getKey(&iter);	\
235 		int		aCount	= TYPENAME##HashIter_getValue(&iter);	\
236 		int		bCount	= TYPENAME##_getKeyValue(b, key);	\
237 		int		count	= deMin32(aCount, bCount);	\
238 		if (count && !TYPENAME##_setKeyCount(to, key, count))	\
239 			return DE_FALSE;	\
240 	}	\
241 	return DE_TRUE;	\
242 }	\
243 \
244 void TYPENAME##_intersectInplace (TYPENAME* a, const TYPENAME* b)	\
245 {	\
246 	DE_ASSERT(!"Not implemented.");	\
247 }	\
248 \
249 deBool TYPENAME##_sum (TYPENAME* to, const TYPENAME* a, const TYPENAME* b)	\
250 {	\
251 	TYPENAME##_reset(to);	\
252 	return TYPENAME##_sumInplace(to, a) && TYPENAME##_sumInplace(to, b);	\
253 }	\
254 \
255 deBool TYPENAME##_sumInplace (TYPENAME* a, const TYPENAME* b)	\
256 {	\
257 	TYPENAME##HashIter iter;	\
258 	for (TYPENAME##HashIter_init(b, &iter);	\
259 		 TYPENAME##HashIter_hasItem(&iter);	\
260 		 TYPENAME##HashIter_next(&iter))	\
261 	{	\
262 		KEYTYPE	key		= TYPENAME##HashIter_getKey(&iter);	\
263 		int		aCount	= TYPENAME##_getKeyValue(a, key);	\
264 		int		bCount	= TYPENAME##HashIter_getValue(&iter);	\
265 		int		count	= aCount + bCount;	\
266 		if (!TYPENAME##_setKeyCount(a, key, count))	\
267 			return DE_FALSE;	\
268 	}	\
269 }	\
270 \
271 deBool TYPENAME##_difference (TYPENAME* to, const TYPENAME* a, const TYPENAME* b)	\
272 {	\
273 	TYPENAME##HashIter iter;	\
274 	TYPENAME##_reset(to);	\
275 	for (TYPENAME##HashIter_init(a, &iter);	\
276 		 TYPENAME##HashIter_hasItem(&iter);	\
277 		 TYPENAME##HashIter_next(&iter))	\
278 	{	\
279 		KEYTYPE key		= TYPENAME##HashIter_getKey(&iter);	\
280 		int		aCount	= TYPENAME##HashIter_getValue(&iter);	\
281 		int		bCount	= TYPENAME##_getKeyValue(b, key);	\
282 		int		count	= deMax32(0, aCount - bCount);	\
283 		if (count && !TYPENAME##_setKeyCount(to, key, count))	\
284 			return DE_FALSE;	\
285 	}	\
286 	return DE_TRUE;	\
287 }	\
288 \
289 void TYPENAME##_differenceInplace (TYPENAME* a, const TYPENAME* b)	\
290 {	\
291 	DE_ASSERT(!"Not implemented.");	\
292 }	\
293 \
294 struct TYPENAME##SetwiseImplementDummy_s { int dummy; }
295 
296 #endif /* _DEPOOLMULTISET_H */
297