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