• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #ifndef _DEPOOLHASHSET_H
2 #define _DEPOOLHASHSET_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 hash-set class.
24  *//*--------------------------------------------------------------------*/
25 
26 #include "deDefs.h"
27 #include "dePoolHash.h"
28 #include "dePoolSet.h"
29 
30 DE_BEGIN_EXTERN_C
31 
32 void	dePoolHashSet_selfTest		(void);
33 
34 DE_END_EXTERN_C
35 
36 /*--------------------------------------------------------------------*//*!
37  * \brief Declare a template pool hash-set (hash of sets) class interface.
38  * \param TYPENAME	Type name of the declared hash-set.
39  * \param KEYTYPE	Type of the key.
40  * \param VALUETYPE	Type of the value.
41  *
42  * \todo [petri] Description.
43  *
44  * The functions for operating the hash are:
45  * \todo [petri] Figure out how to comment these in Doxygen-style.
46  *
47  * \code
48  * HashSet*    HashSet_create            (deMemPool* pool);
49  * int         HashSet_getNumElements    (const HashSet* hashSet);
50  * Set<Value>* HashSet_find              (const HashSet* hashSet, Key key); TODO: better API
51  * Hash<Set*>* HashSet_getHash           (const HashSet* hashSet); TODO: better API
52  * deBool      HashSet_insert            (HashSet* hashSet, Key key, Value value);
53  * void        HashSet_delete            (HashSet* hashSet, Key key, Value value);
54  * deBool      HashSet_exists            (const HashSet* hashSet, Key key, Value value);
55  * \endcode
56 *//*--------------------------------------------------------------------*/
57 #define DE_DECLARE_POOL_HASH_SET(TYPENAME, KEYTYPE, VALUETYPE)										\
58 																									\
59 DE_DECLARE_POOL_SET(TYPENAME##Set, VALUETYPE);														\
60 DE_DECLARE_POOL_HASH(TYPENAME##Hash, KEYTYPE, TYPENAME##Set*);										\
61 typedef struct TYPENAME##_s																			\
62 {																									\
63 	TYPENAME##Hash*	hash;																			\
64 } TYPENAME;	 /* NOLINT(TYPENAME) */																	\
65 																									\
66 DE_INLINE TYPENAME*			TYPENAME##_create			(deMemPool* pool);							\
67 DE_INLINE int				TYPENAME##_getNumElements	(const TYPENAME* hashSet)										DE_UNUSED_FUNCTION;	\
68 DE_INLINE TYPENAME##Hash*	TYPENAME##_getHash			(const TYPENAME* hashSet)										DE_UNUSED_FUNCTION;	\
69 DE_INLINE deBool			TYPENAME##_insert			(DE_PTR_TYPE(TYPENAME) hashSet, KEYTYPE key, VALUETYPE value)	DE_UNUSED_FUNCTION;	\
70 DE_INLINE deBool			TYPENAME##_safeInsert		(DE_PTR_TYPE(TYPENAME) hashSet, KEYTYPE key, VALUETYPE value)	DE_UNUSED_FUNCTION;	\
71 DE_INLINE TYPENAME##Set*	TYPENAME##_find				(const TYPENAME* hashSet, KEYTYPE key)							DE_UNUSED_FUNCTION;	\
72 DE_INLINE void				TYPENAME##_delete			(DE_PTR_TYPE(TYPENAME) hashSet, KEYTYPE key, VALUETYPE value)	DE_UNUSED_FUNCTION;	\
73 DE_INLINE deBool			TYPENAME##_exists			(const TYPENAME* hashSet, KEYTYPE key, VALUETYPE value)			DE_UNUSED_FUNCTION;	\
74 																									\
75 DE_INLINE TYPENAME* TYPENAME##_create (deMemPool* pool)												\
76 {																									\
77 	DE_PTR_TYPE(TYPENAME) hashSet = DE_POOL_NEW(pool, TYPENAME);									\
78 	if (!hashSet) return DE_NULL;																	\
79 	if ((hashSet->hash = TYPENAME##Hash_create(pool)) == DE_NULL)									\
80 		return DE_NULL;																				\
81 	return hashSet;																					\
82 }																									\
83 																									\
84 DE_INLINE int TYPENAME##_getNumElements (const TYPENAME* hashSet)									\
85 {																									\
86 	return TYPENAME##Hash_getNumElements(hashSet->hash);											\
87 }																									\
88 																									\
89 DE_INLINE TYPENAME##Hash* TYPENAME##_getHash (const TYPENAME* hashSet)								\
90 {																									\
91 	return hashSet->hash;																			\
92 }																									\
93 																									\
94 DE_INLINE deBool TYPENAME##_insert (DE_PTR_TYPE(TYPENAME) hashSet, KEYTYPE key, VALUETYPE value)	\
95 {																									\
96 	TYPENAME##Set**	setPtr	= TYPENAME##Hash_find(hashSet->hash, key);								\
97 	TYPENAME##Set*	set		= setPtr ? *setPtr : DE_NULL;											\
98 	if (!set)																						\
99 	{																								\
100 		set = TYPENAME##Set_create(hashSet->hash->pool);											\
101 		if (!set) return DE_FALSE;																	\
102 		if (!TYPENAME##Set_insert(set, value)) return DE_FALSE;										\
103 		return TYPENAME##Hash_insert(hashSet->hash, key, set);										\
104 	}																								\
105 	else																							\
106 	{																								\
107 		return TYPENAME##Set_insert(set, value);													\
108 	}																								\
109 }																									\
110 																									\
111 DE_INLINE deBool TYPENAME##_safeInsert (DE_PTR_TYPE(TYPENAME) hashSet, KEYTYPE key, VALUETYPE value)\
112 {																									\
113 	TYPENAME##Set**	setPtr	= TYPENAME##Hash_find(hashSet->hash, key);								\
114 	TYPENAME##Set*	set		= setPtr ? *setPtr : DE_NULL;											\
115 	if (!set)																						\
116 	{																								\
117 		return TYPENAME##_insert(hashSet, key, value);												\
118 	}																								\
119 	else																							\
120 	{																								\
121 		return TYPENAME##Set_safeInsert(set, value);												\
122 	}																								\
123 }																									\
124 																									\
125 DE_INLINE TYPENAME##Set* TYPENAME##_find (const TYPENAME* hashSet, KEYTYPE key)						\
126 {																									\
127 	TYPENAME##Set** setPtr = TYPENAME##Hash_find(hashSet->hash, key);								\
128 	return setPtr ? *setPtr : DE_NULL;																\
129 }																									\
130 																									\
131 DE_INLINE void TYPENAME##_delete (DE_PTR_TYPE(TYPENAME) hashSet, KEYTYPE key, VALUETYPE value)		\
132 {																									\
133 	TYPENAME##Set**	setPtr = TYPENAME##Hash_find(hashSet->hash, key);								\
134 	TYPENAME##Set*	set;																			\
135 	DE_ASSERT(setPtr);																				\
136 	set = *setPtr;																					\
137 	TYPENAME##Set_delete(set, value);																\
138 }																									\
139 																									\
140 DE_INLINE deBool TYPENAME##_exists (const TYPENAME* hashSet, KEYTYPE key, VALUETYPE value)			\
141 {																									\
142 	TYPENAME##Set** setPtr = TYPENAME##Hash_find(hashSet->hash, key);								\
143 	if (setPtr)																						\
144 		return TYPENAME##Set_exists(*setPtr, value);												\
145 	else																							\
146 		return DE_FALSE;																			\
147 }																									\
148 																									\
149 struct TYPENAME##Unused_s { int unused; }
150 
151 /*--------------------------------------------------------------------*//*!
152  * \brief Implement a template pool hash-set class.
153  * \param TYPENAME	Type name of the declared hash.
154  * \param KEYTYPE	Type of the key.
155  * \param VALUETYPE	Type of the value.
156  * \param HASHFUNC	Function used for hashing the key.
157  * \param CMPFUNC	Function used for exact matching of the keys.
158  *
159  * This macro has implements the hash declared with DE_DECLARE_POOL_HASH.
160  * Usually this macro should be used from a .c file, since the macro expands
161  * into multiple functions. The TYPENAME, KEYTYPE, and VALUETYPE parameters
162  * must match those of the declare macro.
163 *//*--------------------------------------------------------------------*/
164 #define DE_IMPLEMENT_POOL_HASH_SET(TYPENAME, KEYTYPE, VALUETYPE, KEYHASHFUNC, KEYCMPFUNC, VALUEHASHFUNC, VALUECMPFUNC)	\
165 DE_IMPLEMENT_POOL_SET(TYPENAME##Set, VALUETYPE, VALUEHASHFUNC, VALUECMPFUNC);											\
166 DE_IMPLEMENT_POOL_HASH(TYPENAME##Hash, KEYTYPE, TYPENAME##Set*, KEYHASHFUNC, KEYCMPFUNC);								\
167 struct TYPENAME##Unused2_s { int unused; }
168 
169 /* Copy-to-array templates. */
170 
171 #if 0
172 
173 #define DE_DECLARE_POOL_HASH_TO_ARRAY(HASHTYPENAME, KEYARRAYTYPENAME, VALUEARRAYTYPENAME)		\
174 	deBool HASHTYPENAME##_copyToArray(const HASHTYPENAME* set, KEYARRAYTYPENAME* keyArray, VALUEARRAYTYPENAME* valueArray);	\
175 	struct HASHTYPENAME##_##KEYARRAYTYPENAME##_##VALUEARRAYTYPENAME##_declare_unused { int unused; }
176 
177 #define DE_IMPLEMENT_POOL_HASH_TO_ARRAY(HASHTYPENAME, KEYARRAYTYPENAME, VALUEARRAYTYPENAME)		\
178 deBool HASHTYPENAME##_copyToArray(const HASHTYPENAME* hash, KEYARRAYTYPENAME* keyArray, VALUEARRAYTYPENAME* valueArray)	\
179 {	\
180 	int numElements	= hash->numElements;	\
181 	int arrayNdx	= 0;	\
182 	int slotNdx;	\
183 	\
184 	if ((keyArray && !KEYARRAYTYPENAME##_setSize(keyArray, numElements)) ||			\
185 		(valueArray && !VALUEARRAYTYPENAME##_setSize(valueArray, numElements)))		\
186 		return DE_FALSE;	\
187 	\
188 	for (slotNdx = 0; slotNdx < hash->slotTableSize; slotNdx++) \
189 	{ \
190 		const HASHTYPENAME##Slot* slot = hash->slotTable[slotNdx]; \
191 		while (slot) \
192 		{ \
193 			int elemNdx; \
194 			for (elemNdx = 0; elemNdx < slot->numUsed; elemNdx++) \
195 			{	\
196 				if (keyArray)	\
197 					KEYARRAYTYPENAME##_set(keyArray, arrayNdx, slot->keys[elemNdx]); \
198 				if (valueArray)	\
199 					VALUEARRAYTYPENAME##_set(valueArray, arrayNdx, slot->values[elemNdx]);	\
200 				arrayNdx++;	\
201 			} \
202 			slot = slot->nextSlot; \
203 		} \
204 	}	\
205 	DE_ASSERT(arrayNdx == numElements);	\
206 	return DE_TRUE;	\
207 }	\
208 struct HASHTYPENAME##_##KEYARRAYTYPENAME##_##VALUEARRAYTYPENAME##_implement_unused { int unused; }
209 
210 #endif
211 
212 #endif /* _DEPOOLHASHSET_H */
213