Actual source code: hashmap.h
1: #ifndef PETSC_HASHMAP_H
2: #define PETSC_HASHMAP_H
4: #include <petsc/private/hashtable.h>
6: /* SUBMANSEC = PetscH */
8: /*MC
9: PETSC_HASH_MAP - Instantiate a PETSc hash table map type
11: Synopsis:
12: #include <petsc/private/hashmap.h>
13: PETSC_HASH_MAP(HMapT, KeyType, ValType, HashFunc, EqualFunc, DefaultValue)
15: Input Parameters:
16: + HMapT - The hash table map type name suffix
17: . KeyType - The type of keys
18: . ValType - The type of values
19: . HashFunc - Routine or function-like macro computing hash values from keys
20: . EqualFunc - Routine or function-like macro computing whether two values are equal
21: - DefaultValue - Default value to use for queries in case of missing keys
23: Level: developer
25: Developer Note:
26: Each time this macro is used to create a new hash map type, the make rule for allmanpages in $PETSC_DIR/makefile should
27: be updated to cause the automatic generation of appropriate manual pages for that type. The manual pages
28: are generated from the templated version of the documentation in include/petsc/private/hashmap.txt.
30: References:
31: This code uses the standalone and portable C language khash software https://github.com/attractivechaos/klib
33: .seealso: `PetscHMapI`, `PetscHMapICreate()`, `PetscHMapIJ`, `PetscHMapIJCreate()`, `PETSC_HASH_SET()`
34: M*/
36: #define PETSC_HASH_MAP(HashT, KeyType, ValType, HashFunc, EqualFunc, DefaultValue) \
37: \
38: KHASH_INIT(HashT, KeyType, ValType, 1, HashFunc, EqualFunc) \
39: \
40: typedef khash_t(HashT) *Petsc##HashT; \
41: \
42: static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##Create(Petsc##HashT *ht) \
43: { \
45: *ht = kh_init(HashT); \
46: PetscHashAssert(*ht != NULL); \
47: return 0; \
48: } \
49: \
50: static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##Destroy(Petsc##HashT *ht) \
51: { \
53: if (!*ht) return 0; \
54: kh_destroy(HashT, *ht); \
55: *ht = NULL; \
56: return 0; \
57: } \
58: \
59: static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##Reset(Petsc##HashT ht) \
60: { \
62: kh_reset(HashT, ht); \
63: return 0; \
64: } \
65: \
66: static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##Duplicate(Petsc##HashT ht, Petsc##HashT *hd) \
67: { \
68: int ret; \
69: KeyType key; \
70: ValType val; \
73: *hd = kh_init(HashT); \
74: PetscHashAssert(*hd != NULL); \
75: ret = kh_resize(HashT, *hd, kh_size(ht)); \
76: PetscHashAssert(ret == 0); \
77: kh_foreach(ht, key, val, { \
78: khiter_t i; \
79: i = kh_put(HashT, *hd, key, &ret); \
80: PetscHashAssert(ret >= 0); \
81: kh_val(*hd, i) = val; \
82: }) return 0; \
83: } \
84: \
85: static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##Clear(Petsc##HashT ht) \
86: { \
88: kh_clear(HashT, ht); \
89: return 0; \
90: } \
91: \
92: static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##Resize(Petsc##HashT ht, PetscInt nb) \
93: { \
94: int ret; \
96: ret = kh_resize(HashT, ht, (khint_t)nb); \
97: PetscHashAssert(ret >= 0); \
98: return 0; \
99: } \
100: \
101: static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##GetSize(Petsc##HashT ht, PetscInt *n) \
102: { \
105: *n = (PetscInt)kh_size(ht); \
106: return 0; \
107: } \
108: \
109: static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##GetCapacity(Petsc##HashT ht, PetscInt *n) \
110: { \
113: *n = (PetscInt)kh_n_buckets(ht); \
114: return 0; \
115: } \
116: \
117: static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##Has(Petsc##HashT ht, KeyType key, PetscBool *has) \
118: { \
119: khiter_t iter; \
123: iter = kh_get(HashT, ht, key); \
124: *has = (iter != kh_end(ht)) ? PETSC_TRUE : PETSC_FALSE; \
125: return 0; \
126: } \
127: \
128: static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##Get(Petsc##HashT ht, KeyType key, ValType *val) \
129: { \
130: khiter_t iter; \
134: iter = kh_get(HashT, ht, key); \
135: *val = (iter != kh_end(ht)) ? kh_val(ht, iter) : (DefaultValue); \
136: return 0; \
137: } \
138: \
139: static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##Set(Petsc##HashT ht, KeyType key, ValType val) \
140: { \
141: int ret; \
142: khiter_t iter; \
145: iter = kh_put(HashT, ht, key, &ret); \
146: PetscHashAssert(ret >= 0); \
147: kh_val(ht, iter) = val; \
148: return 0; \
149: } \
150: \
151: static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##Del(Petsc##HashT ht, KeyType key) \
152: { \
153: khiter_t iter; \
156: iter = kh_get(HashT, ht, key); \
157: kh_del(HashT, ht, iter); \
158: return 0; \
159: } \
160: \
161: static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##QuerySet(Petsc##HashT ht, KeyType key, ValType val, PetscBool *missing) \
162: { \
163: int ret; \
164: khiter_t iter; \
168: iter = kh_put(HashT, ht, key, &ret); \
169: PetscHashAssert(ret >= 0); \
170: kh_val(ht, iter) = val; \
171: *missing = ret ? PETSC_TRUE : PETSC_FALSE; \
172: return 0; \
173: } \
174: \
175: static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##QueryDel(Petsc##HashT ht, KeyType key, PetscBool *present) \
176: { \
177: khiter_t iter; \
181: iter = kh_get(HashT, ht, key); \
182: if (iter != kh_end(ht)) { \
183: kh_del(HashT, ht, iter); \
184: *present = PETSC_TRUE; \
185: } else { \
186: *present = PETSC_FALSE; \
187: } \
188: return 0; \
189: } \
190: \
191: static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##Find(Petsc##HashT ht, KeyType key, PetscHashIter *iter, PetscBool *found) \
192: \
193: { \
198: *iter = kh_get(HashT, ht, key); \
199: *found = (*iter != kh_end(ht)) ? PETSC_TRUE : PETSC_FALSE; \
200: return 0; \
201: } \
202: \
203: static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##Put(Petsc##HashT ht, KeyType key, PetscHashIter *iter, PetscBool *missing) \
204: { \
205: int ret; \
210: *iter = kh_put(HashT, ht, key, &ret); \
211: PetscHashAssert(ret >= 0); \
212: *missing = ret ? PETSC_TRUE : PETSC_FALSE; \
213: return 0; \
214: } \
215: \
216: static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##IterGet(Petsc##HashT ht, PetscHashIter iter, ValType *val) \
217: { \
221: *val = PetscLikely(iter < kh_end(ht) && kh_exist(ht, iter)) ? kh_val(ht, iter) : (DefaultValue); \
222: return 0; \
223: } \
224: \
225: static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##IterSet(Petsc##HashT ht, PetscHashIter iter, ValType val) \
226: { \
229: if (PetscLikely(iter < kh_end(ht) && kh_exist(ht, iter))) kh_val(ht, iter) = val; \
230: return 0; \
231: } \
232: \
233: static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##IterDel(Petsc##HashT ht, PetscHashIter iter) \
234: { \
237: if (PetscLikely(iter < kh_end(ht))) kh_del(HashT, ht, iter); \
238: return 0; \
239: } \
240: \
241: static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##GetKeys(Petsc##HashT ht, PetscInt *off, KeyType array[]) \
242: { \
243: KeyType key; \
244: PetscInt pos; \
247: pos = *off; \
248: kh_foreach_key(ht, key, array[pos++] = key); \
249: *off = pos; \
250: return 0; \
251: } \
252: \
253: static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##GetVals(Petsc##HashT ht, PetscInt *off, ValType array[]) \
254: { \
255: ValType val; \
256: PetscInt pos; \
259: pos = *off; \
260: kh_foreach_value(ht, val, array[pos++] = val); \
261: *off = pos; \
262: return 0; \
263: } \
264: \
265: static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##GetPairs(Petsc##HashT ht, PetscInt *off, KeyType karray[], ValType varray[]) \
266: { \
267: ValType val; \
268: KeyType key; \
269: PetscInt pos; \
272: pos = *off; \
273: kh_foreach(ht, key, val, { \
274: karray[pos] = key; \
275: varray[pos++] = val; \
276: }) *off = pos; \
277: return 0; \
278: }
280: #endif /* PETSC_HASHMAP_H */