1 #ifndef _DEPOOLHASHSET_H
2 #define _DEPOOLHASHSET_H
3 /*-------------------------------------------------------------------------
4 * drawElements Memory Pool Library
5 * --------------------------------
7 * Copyright 2014 The Android Open Source Project
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
13 * http://www.apache.org/licenses/LICENSE-2.0
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.
23 * \brief Memory pool hash-set class.
24 *//*--------------------------------------------------------------------*/
27 #include "dePoolHash.h"
28 #include "dePoolSet.h"
32 void dePoolHashSet_selfTest (void);
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.
42 * \todo [petri] Description.
44 * The functions for operating the hash are:
45 * \todo [petri] Figure out how to comment these in Doxygen-style.
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);
56 *//*--------------------------------------------------------------------*/
57 #define DE_DECLARE_POOL_HASH_SET(TYPENAME, KEYTYPE, VALUETYPE) \
59 DE_DECLARE_POOL_SET(TYPENAME##Set, VALUETYPE); \
60 DE_DECLARE_POOL_HASH(TYPENAME##Hash, KEYTYPE, TYPENAME##Set*); \
61 typedef struct TYPENAME##_s \
63 TYPENAME##Hash* hash; \
64 } TYPENAME; /* NOLINT(TYPENAME) */ \
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; \
75 DE_INLINE TYPENAME* TYPENAME##_create (deMemPool* pool) \
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) \
84 DE_INLINE int TYPENAME##_getNumElements (const TYPENAME* hashSet) \
86 return TYPENAME##Hash_getNumElements(hashSet->hash); \
89 DE_INLINE TYPENAME##Hash* TYPENAME##_getHash (const TYPENAME* hashSet) \
91 return hashSet->hash; \
94 DE_INLINE deBool TYPENAME##_insert (DE_PTR_TYPE(TYPENAME) hashSet, KEYTYPE key, VALUETYPE value) \
96 TYPENAME##Set** setPtr = TYPENAME##Hash_find(hashSet->hash, key); \
97 TYPENAME##Set* set = setPtr ? *setPtr : DE_NULL; \
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); \
107 return TYPENAME##Set_insert(set, value); \
111 DE_INLINE deBool TYPENAME##_safeInsert (DE_PTR_TYPE(TYPENAME) hashSet, KEYTYPE key, VALUETYPE value)\
113 TYPENAME##Set** setPtr = TYPENAME##Hash_find(hashSet->hash, key); \
114 TYPENAME##Set* set = setPtr ? *setPtr : DE_NULL; \
117 return TYPENAME##_insert(hashSet, key, value); \
121 return TYPENAME##Set_safeInsert(set, value); \
125 DE_INLINE TYPENAME##Set* TYPENAME##_find (const TYPENAME* hashSet, KEYTYPE key) \
127 TYPENAME##Set** setPtr = TYPENAME##Hash_find(hashSet->hash, key); \
128 return setPtr ? *setPtr : DE_NULL; \
131 DE_INLINE void TYPENAME##_delete (DE_PTR_TYPE(TYPENAME) hashSet, KEYTYPE key, VALUETYPE value) \
133 TYPENAME##Set** setPtr = TYPENAME##Hash_find(hashSet->hash, key); \
134 TYPENAME##Set* set; \
137 TYPENAME##Set_delete(set, value); \
140 DE_INLINE deBool TYPENAME##_exists (const TYPENAME* hashSet, KEYTYPE key, VALUETYPE value) \
142 TYPENAME##Set** setPtr = TYPENAME##Hash_find(hashSet->hash, key); \
144 return TYPENAME##Set_exists(*setPtr, value); \
149 struct TYPENAME##Dummy_s { int dummy; }
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.
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##Dummy2_s { int dummy; }
169 /* Copy-to-array templates. */
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_dummy { int dummy; }
177 #define DE_IMPLEMENT_POOL_HASH_TO_ARRAY(HASHTYPENAME, KEYARRAYTYPENAME, VALUEARRAYTYPENAME) \
178 deBool HASHTYPENAME##_copyToArray(const HASHTYPENAME* hash, KEYARRAYTYPENAME* keyArray, VALUEARRAYTYPENAME* valueArray) \
180 int numElements = hash->numElements; \
184 if ((keyArray && !KEYARRAYTYPENAME##_setSize(keyArray, numElements)) || \
185 (valueArray && !VALUEARRAYTYPENAME##_setSize(valueArray, numElements))) \
188 for (slotNdx = 0; slotNdx < hash->slotTableSize; slotNdx++) \
190 const HASHTYPENAME##Slot* slot = hash->slotTable[slotNdx]; \
194 for (elemNdx = 0; elemNdx < slot->numUsed; elemNdx++) \
197 KEYARRAYTYPENAME##_set(keyArray, arrayNdx, slot->keys[elemNdx]); \
199 VALUEARRAYTYPENAME##_set(valueArray, arrayNdx, slot->values[elemNdx]); \
202 slot = slot->nextSlot; \
205 DE_ASSERT(arrayNdx == numElements); \
208 struct HASHTYPENAME##_##KEYARRAYTYPENAME##_##VALUEARRAYTYPENAME##_implement_dummy { int dummy; }
212 #endif /* _DEPOOLHASHSET_H */