Merge vk-gl-cts/opengl-es-cts-3.2.3 into vk-gl-cts/opengl-es-cts-3.2.4
[platform/upstream/VK-GL-CTS.git] / framework / delibs / depool / dePoolHashSet.h
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##Dummy_s { int dummy; }
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##Dummy2_s { int dummy; }
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_dummy { int dummy; }
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_dummy { int dummy; }
209
210 #endif
211
212 #endif /* _DEPOOLHASHSET_H */