Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2015 Cisco and/or its affiliates. |
| 3 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | * you may not use this file except in compliance with the License. |
| 5 | * You may obtain a copy of the License at: |
| 6 | * |
| 7 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | * |
| 9 | * Unless required by applicable law or agreed to in writing, software |
| 10 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | * See the License for the specific language governing permissions and |
| 13 | * limitations under the License. |
| 14 | */ |
| 15 | /* |
| 16 | Copyright (c) 2001-2005 Eliot Dresselhaus |
| 17 | |
| 18 | Permission is hereby granted, free of charge, to any person obtaining |
| 19 | a copy of this software and associated documentation files (the |
| 20 | "Software"), to deal in the Software without restriction, including |
| 21 | without limitation the rights to use, copy, modify, merge, publish, |
| 22 | distribute, sublicense, and/or sell copies of the Software, and to |
| 23 | permit persons to whom the Software is furnished to do so, subject to |
| 24 | the following conditions: |
| 25 | |
| 26 | The above copyright notice and this permission notice shall be |
| 27 | included in all copies or substantial portions of the Software. |
| 28 | |
| 29 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
| 30 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| 31 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
| 32 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE |
| 33 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
| 34 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
| 35 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| 36 | */ |
| 37 | |
| 38 | #ifndef included_hash_h |
| 39 | #define included_hash_h |
| 40 | |
| 41 | #include <vppinfra/error.h> |
| 42 | #include <vppinfra/format.h> |
| 43 | #include <vppinfra/vec.h> |
| 44 | #include <vppinfra/vector.h> |
| 45 | |
| 46 | struct hash_header; |
| 47 | |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 48 | typedef uword (hash_key_sum_function_t) (struct hash_header *, uword key); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 49 | typedef uword (hash_key_equal_function_t) |
| 50 | (struct hash_header *, uword key1, uword key2); |
| 51 | |
| 52 | /* Vector header for hash tables. */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 53 | typedef struct hash_header |
| 54 | { |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 55 | /* Number of elements in hash table. */ |
| 56 | uword elts; |
| 57 | |
| 58 | /* Flags as follows. */ |
| 59 | u32 flags; |
| 60 | |
| 61 | /* Set if user does not want table to auto-resize when sufficiently full. */ |
| 62 | #define HASH_FLAG_NO_AUTO_GROW (1 << 0) |
| 63 | /* Set if user does not want table to auto-resize when sufficiently empty. */ |
| 64 | #define HASH_FLAG_NO_AUTO_SHRINK (1 << 1) |
| 65 | /* Set when hash_next is in the process of iterating through this hash table. */ |
| 66 | #define HASH_FLAG_HASH_NEXT_IN_PROGRESS (1 << 2) |
| 67 | |
| 68 | u32 log2_pair_size; |
| 69 | |
| 70 | /* Function to compute the "sum" of a hash key. |
| 71 | Hash function is this sum modulo the prime size of |
| 72 | the hash table (vec_len (v)). */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 73 | hash_key_sum_function_t *key_sum; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 74 | |
| 75 | /* Special values for key_sum "function". */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 76 | #define KEY_FUNC_NONE (0) /*< sum = key */ |
| 77 | #define KEY_FUNC_POINTER_UWORD (1) /*< sum = *(uword *) key */ |
| 78 | #define KEY_FUNC_POINTER_U32 (2) /*< sum = *(u32 *) key */ |
| 79 | #define KEY_FUNC_STRING (3) /*< sum = string_key_sum, etc. */ |
Ole Troan | 73710c7 | 2018-06-04 22:27:49 +0200 | [diff] [blame] | 80 | #define KEY_FUNC_MEM (4) /*< sum = mem_key_sum */ |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 81 | |
| 82 | /* key comparison function */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 83 | hash_key_equal_function_t *key_equal; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 84 | |
| 85 | /* Hook for user's data. Used to parameterize sum/equal functions. */ |
| 86 | any user; |
| 87 | |
| 88 | /* Format a (k,v) pair */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 89 | format_function_t *format_pair; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 90 | |
| 91 | /* Format function arg */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 92 | void *format_pair_arg; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 93 | |
| 94 | /* Bit i is set if pair i is a user object (as opposed to being |
| 95 | either zero or an indirect array of pairs). */ |
Damjan Marion | 2b702da | 2022-03-17 17:54:48 +0100 | [diff] [blame] | 96 | uword *is_user; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 97 | } hash_t; |
| 98 | |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 99 | /* Returns a pointer to the hash header given the vector pointer */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 100 | always_inline hash_t * |
| 101 | hash_header (void *v) |
| 102 | { |
Damjan Marion | a4a28f0 | 2022-03-17 15:46:25 +0100 | [diff] [blame] | 103 | return vec_header (v); |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 104 | } |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 105 | |
| 106 | /* Number of elements in the hash table */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 107 | always_inline uword |
| 108 | hash_elts (void *v) |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 109 | { |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 110 | hash_t *h = hash_header (v); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 111 | return v ? h->elts : 0; |
| 112 | } |
| 113 | |
| 114 | /* Number of elements the hash table can hold */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 115 | always_inline uword |
| 116 | hash_capacity (void *v) |
| 117 | { |
| 118 | return vec_len (v); |
| 119 | } |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 120 | |
| 121 | /* Returns 1 if the hash pair contains user data */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 122 | always_inline uword |
| 123 | hash_is_user (void *v, uword i) |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 124 | { |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 125 | hash_t *h = hash_header (v); |
Gabriel Oginski | 813c1bd | 2022-10-21 07:05:56 +0000 | [diff] [blame^] | 126 | uword bits = BITS (h->is_user[0]); |
| 127 | uword i0 = i / bits; |
| 128 | uword i1 = i % bits; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 129 | return (h->is_user[i0] & ((uword) 1 << i1)) != 0; |
| 130 | } |
| 131 | |
| 132 | /* Set the format function and format argument for a hash table */ |
| 133 | always_inline void |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 134 | hash_set_pair_format (void *v, |
| 135 | format_function_t * format_pair, void *format_pair_arg) |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 136 | { |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 137 | hash_t *h = hash_header (v); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 138 | h->format_pair = format_pair; |
| 139 | h->format_pair_arg = format_pair_arg; |
| 140 | } |
| 141 | |
| 142 | /* Set hash table flags */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 143 | always_inline void |
| 144 | hash_set_flags (void *v, uword flags) |
| 145 | { |
| 146 | hash_header (v)->flags |= flags; |
| 147 | } |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 148 | |
| 149 | /* Key value pairs. */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 150 | typedef struct |
| 151 | { |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 152 | /* The Key */ |
| 153 | uword key; |
| 154 | |
| 155 | /* The Value. Length is 2^log2_pair_size - 1. */ |
| 156 | uword value[0]; |
| 157 | } hash_pair_t; |
| 158 | |
| 159 | /* The indirect pair structure |
| 160 | |
| 161 | If log2_pair_size > 0 we overload hash pairs |
| 162 | with indirect pairs for buckets with more than one |
| 163 | pair. */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 164 | typedef struct |
| 165 | { |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 166 | /* pair vector */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 167 | hash_pair_t *pairs; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 168 | /* padding */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 169 | u8 pad[sizeof (uword) - sizeof (hash_pair_t *)]; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 170 | /* allocated length */ |
| 171 | uword alloc_len; |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 172 | } |
| 173 | hash_pair_indirect_t; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 174 | |
| 175 | /* Direct / Indirect pair union */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 176 | typedef union |
| 177 | { |
| 178 | hash_pair_t direct; |
| 179 | hash_pair_indirect_t indirect; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 180 | } hash_pair_union_t; |
| 181 | |
| 182 | #define LOG2_ALLOC_BITS (5) |
| 183 | #define PAIR_BITS (BITS (uword) - LOG2_ALLOC_BITS) |
| 184 | |
| 185 | /* Log2 number of bytes allocated in pairs array. */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 186 | always_inline uword |
| 187 | indirect_pair_get_log2_bytes (hash_pair_indirect_t * p) |
| 188 | { |
| 189 | return p->alloc_len >> PAIR_BITS; |
| 190 | } |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 191 | |
| 192 | /* Get the length of an indirect pair */ |
| 193 | always_inline uword |
| 194 | indirect_pair_get_len (hash_pair_indirect_t * p) |
| 195 | { |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 196 | if (!p->pairs) |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 197 | return 0; |
| 198 | else |
| 199 | return p->alloc_len & (((uword) 1 << PAIR_BITS) - 1); |
| 200 | } |
| 201 | |
| 202 | /* Set the length of an indirect pair */ |
| 203 | always_inline void |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 204 | indirect_pair_set (hash_pair_indirect_t * p, uword log2_alloc, uword len) |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 205 | { |
| 206 | ASSERT (len < ((uword) 1 << PAIR_BITS)); |
| 207 | ASSERT (log2_alloc < ((uword) 1 << LOG2_ALLOC_BITS)); |
| 208 | p->alloc_len = (log2_alloc << PAIR_BITS) | len; |
| 209 | } |
| 210 | |
| 211 | /* internal routine to fetch value for given key */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 212 | uword *_hash_get (void *v, uword key); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 213 | |
| 214 | /* internal routine to fetch value (key, value) pair for given key */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 215 | hash_pair_t *_hash_get_pair (void *v, uword key); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 216 | |
| 217 | /* internal routine to unset a (key, value) pair */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 218 | void *_hash_unset (void *v, uword key, void *old_value); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 219 | |
| 220 | /* internal routine to set a (key, value) pair, return the old value */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 221 | void *_hash_set3 (void *v, uword key, void *value, void *old_value); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 222 | |
| 223 | /* Resize a hash table */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 224 | void *hash_resize (void *old, uword new_size); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 225 | |
| 226 | /* duplicate a hash table */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 227 | void *hash_dup (void *old); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 228 | |
| 229 | /* Returns the number of bytes used by a hash table */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 230 | uword hash_bytes (void *v); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 231 | |
| 232 | /* Public macro to set a (key, value) pair, return the old value */ |
| 233 | #define hash_set3(h,key,value,old_value) \ |
| 234 | ({ \ |
| 235 | uword _v = (uword) (value); \ |
| 236 | (h) = _hash_set3 ((h), (uword) (key), (void *) &_v, (old_value)); \ |
| 237 | }) |
| 238 | |
| 239 | /* Public macro to fetch value for given key */ |
| 240 | #define hash_get(h,key) _hash_get ((h), (uword) (key)) |
| 241 | |
| 242 | /* Public macro to fetch value (key, value) pair for given key */ |
| 243 | #define hash_get_pair(h,key) _hash_get_pair ((h), (uword) (key)) |
| 244 | |
| 245 | /* Public macro to set a (key, value) pair */ |
| 246 | #define hash_set(h,key,value) hash_set3(h,key,value,0) |
| 247 | |
| 248 | /* Public macro to set (key, 0) pair */ |
| 249 | #define hash_set1(h,key) (h) = _hash_set3(h,(uword) (key),0,0) |
| 250 | |
| 251 | /* Public macro to unset a (key, value) pair */ |
| 252 | #define hash_unset(h,key) ((h) = _hash_unset ((h), (uword) (key),0)) |
| 253 | |
| 254 | /* Public macro to unset a (key, value) pair, return the old value */ |
| 255 | #define hash_unset3(h,key,old_value) ((h) = _hash_unset ((h), (uword) (key), (void *) (old_value))) |
| 256 | |
| 257 | /* get/set/unset for pointer keys. */ |
| 258 | |
| 259 | /* Public macro to fetch value for given pointer key */ |
| 260 | #define hash_get_mem(h,key) _hash_get ((h), pointer_to_uword (key)) |
| 261 | |
| 262 | /* Public macro to fetch (key, value) for given pointer key */ |
| 263 | #define hash_get_pair_mem(h,key) _hash_get_pair ((h), pointer_to_uword (key)) |
| 264 | |
| 265 | /* Public macro to set (key, value) for pointer key */ |
| 266 | #define hash_set_mem(h,key,value) hash_set3 (h, pointer_to_uword (key), (value), 0) |
| 267 | |
Paul Vinciguerra | ec11b13 | 2018-09-24 05:25:00 -0700 | [diff] [blame] | 268 | /* Public inline function allocate and copy key to use in hash for pointer key */ |
John Lo | e6bfeab | 2018-01-04 16:39:42 -0500 | [diff] [blame] | 269 | always_inline void |
Neale Ranns | c190cf0 | 2020-01-06 21:09:12 +0000 | [diff] [blame] | 270 | hash_set_mem_alloc (uword ** h, const void *key, uword v) |
John Lo | e6bfeab | 2018-01-04 16:39:42 -0500 | [diff] [blame] | 271 | { |
Damjan Marion | 56f54af | 2021-10-12 20:30:02 +0200 | [diff] [blame] | 272 | int objsize = __builtin_object_size (key, 0); |
John Lo | e6bfeab | 2018-01-04 16:39:42 -0500 | [diff] [blame] | 273 | size_t ksz = hash_header (*h)->user; |
Damjan Marion | 56f54af | 2021-10-12 20:30:02 +0200 | [diff] [blame] | 274 | void *copy; |
| 275 | if (objsize > 0) |
| 276 | { |
| 277 | ASSERT (objsize == ksz); |
| 278 | copy = clib_mem_alloc (objsize); |
| 279 | clib_memcpy_fast (copy, key, objsize); |
| 280 | } |
| 281 | else |
| 282 | { |
| 283 | copy = clib_mem_alloc (ksz); |
| 284 | clib_memcpy_fast (copy, key, ksz); |
| 285 | } |
John Lo | e6bfeab | 2018-01-04 16:39:42 -0500 | [diff] [blame] | 286 | hash_set_mem (*h, copy, v); |
| 287 | } |
| 288 | |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 289 | /* Public macro to set (key, 0) for pointer key */ |
| 290 | #define hash_set1_mem(h,key) hash_set3 ((h), pointer_to_uword (key), 0, 0) |
| 291 | |
| 292 | /* Public macro to unset (key, value) for pointer key */ |
| 293 | #define hash_unset_mem(h,key) ((h) = _hash_unset ((h), pointer_to_uword (key),0)) |
| 294 | |
Paul Vinciguerra | ec11b13 | 2018-09-24 05:25:00 -0700 | [diff] [blame] | 295 | /* Public inline function to unset pointer key and then free the key memory */ |
John Lo | e6bfeab | 2018-01-04 16:39:42 -0500 | [diff] [blame] | 296 | always_inline void |
Neale Ranns | c190cf0 | 2020-01-06 21:09:12 +0000 | [diff] [blame] | 297 | hash_unset_mem_free (uword ** h, const void *key) |
John Lo | e6bfeab | 2018-01-04 16:39:42 -0500 | [diff] [blame] | 298 | { |
| 299 | hash_pair_t *hp = hash_get_pair_mem (*h, key); |
John Lo | 5957a14 | 2018-01-18 12:44:50 -0500 | [diff] [blame] | 300 | if (PREDICT_TRUE (hp != NULL)) |
| 301 | { |
Neale Ranns | c190cf0 | 2020-01-06 21:09:12 +0000 | [diff] [blame] | 302 | void *_k = uword_to_pointer (hp->key, void *); |
| 303 | hash_unset_mem (*h, _k); |
| 304 | clib_mem_free (_k); |
John Lo | 5957a14 | 2018-01-18 12:44:50 -0500 | [diff] [blame] | 305 | } |
John Lo | e6bfeab | 2018-01-04 16:39:42 -0500 | [diff] [blame] | 306 | } |
| 307 | |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 308 | /* internal routine to free a hash table */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 309 | extern void *_hash_free (void *v); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 310 | |
| 311 | /* Public macro to free a hash table */ |
| 312 | #define hash_free(h) (h) = _hash_free ((h)) |
| 313 | |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 314 | clib_error_t *hash_validate (void *v); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 315 | |
Paul Vinciguerra | ec11b13 | 2018-09-24 05:25:00 -0700 | [diff] [blame] | 316 | /* Public inline function to get the number of value bytes for a hash table */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 317 | always_inline uword |
| 318 | hash_value_bytes (hash_t * h) |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 319 | { |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 320 | hash_pair_t *p; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 321 | return (sizeof (p->value[0]) << h->log2_pair_size) - sizeof (p->key); |
| 322 | } |
| 323 | |
Paul Vinciguerra | ec11b13 | 2018-09-24 05:25:00 -0700 | [diff] [blame] | 324 | /* Public inline function to get log2(size of a (key,value) pair) */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 325 | always_inline uword |
| 326 | hash_pair_log2_bytes (hash_t * h) |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 327 | { |
| 328 | uword log2_bytes = h->log2_pair_size; |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 329 | ASSERT (BITS (hash_pair_t) == 32 || BITS (hash_pair_t) == 64); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 330 | if (BITS (hash_pair_t) == 32) |
| 331 | log2_bytes += 2; |
| 332 | else if (BITS (hash_pair_t) == 64) |
| 333 | log2_bytes += 3; |
| 334 | return log2_bytes; |
| 335 | } |
| 336 | |
Paul Vinciguerra | ec11b13 | 2018-09-24 05:25:00 -0700 | [diff] [blame] | 337 | /* Public inline function to get size of a (key,value) pair */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 338 | always_inline uword |
| 339 | hash_pair_bytes (hash_t * h) |
| 340 | { |
| 341 | return (uword) 1 << hash_pair_log2_bytes (h); |
| 342 | } |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 343 | |
Paul Vinciguerra | ec11b13 | 2018-09-24 05:25:00 -0700 | [diff] [blame] | 344 | /* Public inline function to advance a pointer past one (key,value) pair */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 345 | always_inline void * |
| 346 | hash_forward1 (hash_t * h, void *v) |
| 347 | { |
| 348 | return (u8 *) v + hash_pair_bytes (h); |
| 349 | } |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 350 | |
Paul Vinciguerra | ec11b13 | 2018-09-24 05:25:00 -0700 | [diff] [blame] | 351 | /* Public inline function to advance a pointer past N (key,value) pairs */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 352 | always_inline void * |
| 353 | hash_forward (hash_t * h, void *v, uword n) |
| 354 | { |
| 355 | return (u8 *) v + ((n * sizeof (hash_pair_t)) << h->log2_pair_size); |
| 356 | } |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 357 | |
Chris Luke | 5cdaf63 | 2016-07-30 15:05:07 -0400 | [diff] [blame] | 358 | /** Iterate over hash pairs. |
| 359 | |
| 360 | @param p The current (key,value) pair. This should be of type |
| 361 | <code>(hash_pair_t *)</code>. |
| 362 | @param v The hash table to iterate. |
| 363 | @param body The operation to perform on each (key,value) pair. |
| 364 | |
| 365 | Executes the expression or code block @c body with each active hash pair. |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 366 | */ |
Chris Luke | 5cdaf63 | 2016-07-30 15:05:07 -0400 | [diff] [blame] | 367 | /* A previous version of this macro made use of the hash_pair_union_t |
| 368 | * structure; this version does not since that approach mightily upset |
| 369 | * the static analysis tool. In the rare chance someone is reading this |
| 370 | * code, pretend that _p below is of type hash_pair_union_t and that when |
| 371 | * used as an rvalue it's really using one of the union members as the |
| 372 | * rvalue. If you were confused before you might be marginally less |
| 373 | * confused after. |
| 374 | */ |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 375 | #define hash_foreach_pair(p,v,body) \ |
| 376 | do { \ |
| 377 | __label__ _hash_foreach_done; \ |
| 378 | hash_t * _h = hash_header (v); \ |
Chris Luke | 5cdaf63 | 2016-07-30 15:05:07 -0400 | [diff] [blame] | 379 | void * _p; \ |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 380 | hash_pair_t * _q, * _q_end; \ |
| 381 | uword _i, _i1, _id, _pair_increment; \ |
| 382 | \ |
Chris Luke | 5cdaf63 | 2016-07-30 15:05:07 -0400 | [diff] [blame] | 383 | _p = (v); \ |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 384 | _i = 0; \ |
| 385 | _pair_increment = 1; \ |
| 386 | if ((v)) \ |
| 387 | _pair_increment = 1 << _h->log2_pair_size; \ |
| 388 | while (_i < hash_capacity (v)) \ |
| 389 | { \ |
| 390 | _id = _h->is_user[_i / BITS (_h->is_user[0])]; \ |
| 391 | _i1 = _i + BITS (_h->is_user[0]); \ |
| 392 | \ |
| 393 | do { \ |
| 394 | if (_id & 1) \ |
| 395 | { \ |
Chris Luke | 5cdaf63 | 2016-07-30 15:05:07 -0400 | [diff] [blame] | 396 | _q = _p; \ |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 397 | _q_end = _q + _pair_increment; \ |
| 398 | } \ |
| 399 | else \ |
| 400 | { \ |
Chris Luke | 5cdaf63 | 2016-07-30 15:05:07 -0400 | [diff] [blame] | 401 | hash_pair_indirect_t * _pi = _p; \ |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 402 | _q = _pi->pairs; \ |
| 403 | if (_h->log2_pair_size > 0) \ |
| 404 | _q_end = hash_forward (_h, _q, indirect_pair_get_len (_pi)); \ |
| 405 | else \ |
| 406 | _q_end = vec_end (_q); \ |
| 407 | } \ |
| 408 | \ |
| 409 | /* Loop through all elements in bucket. \ |
| 410 | Bucket may have 0 1 or more (indirect case) pairs. */ \ |
| 411 | while (_q < _q_end) \ |
| 412 | { \ |
| 413 | uword _break_in_body = 1; \ |
| 414 | (p) = _q; \ |
| 415 | do { \ |
| 416 | body; \ |
| 417 | _break_in_body = 0; \ |
| 418 | } while (0); \ |
| 419 | if (_break_in_body) \ |
| 420 | goto _hash_foreach_done; \ |
| 421 | _q += _pair_increment; \ |
| 422 | } \ |
| 423 | \ |
Chris Luke | 5cdaf63 | 2016-07-30 15:05:07 -0400 | [diff] [blame] | 424 | _p = (hash_pair_t *)_p + _pair_increment; \ |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 425 | _id = _id / 2; \ |
| 426 | _i++; \ |
| 427 | } while (_i < _i1); \ |
| 428 | } \ |
| 429 | _hash_foreach_done: \ |
| 430 | /* Be silent Mr. Compiler-Warning. */ \ |
| 431 | ; \ |
| 432 | } while (0) |
| 433 | |
| 434 | /* Iterate over key/value pairs |
| 435 | |
| 436 | @param key_var the current key |
| 437 | @param value_var the current value |
| 438 | @param h the hash table to iterate across |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 439 | @param body the operation to perform on each (key_var,value_var) pair. |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 440 | |
| 441 | calls body with each active hash pair |
| 442 | */ |
Paul Vinciguerra | ec11b13 | 2018-09-24 05:25:00 -0700 | [diff] [blame] | 443 | /* Iterate over key/value pairs. */ |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 444 | #define hash_foreach(key_var,value_var,h,body) \ |
| 445 | do { \ |
| 446 | hash_pair_t * _r; \ |
| 447 | hash_foreach_pair (_r, (h), { \ |
| 448 | (key_var) = (__typeof__ (key_var)) _r->key; \ |
| 449 | (value_var) = (__typeof__ (value_var)) _r->value[0]; \ |
| 450 | do { body; } while (0); \ |
| 451 | }); \ |
| 452 | } while (0) |
| 453 | |
| 454 | /* Iterate over key/value pairs for pointer key hash tables |
| 455 | |
| 456 | @param key_var the current key |
| 457 | @param value_var the current value |
| 458 | @param h the hash table to iterate across |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 459 | @param body the operation to perform on each (key_var,value_var) pair. |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 460 | |
| 461 | calls body with each active hash pair |
| 462 | */ |
| 463 | #define hash_foreach_mem(key_var,value_var,h,body) \ |
| 464 | do { \ |
| 465 | hash_pair_t * _r; \ |
| 466 | hash_foreach_pair (_r, (h), { \ |
| 467 | (key_var) = (__typeof__ (key_var)) uword_to_pointer (_r->key, void *); \ |
| 468 | (value_var) = (__typeof__ (value_var)) _r->value[0]; \ |
| 469 | do { body; } while (0); \ |
| 470 | }); \ |
| 471 | } while (0) |
| 472 | |
| 473 | /* Support for iteration through hash table. */ |
| 474 | |
| 475 | /* This struct saves iteration state for hash_next. |
| 476 | None of these fields are meant to be visible to the user. |
| 477 | Hence, the cryptic short-hand names. */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 478 | typedef struct |
| 479 | { |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 480 | uword i, j, f; |
| 481 | } hash_next_t; |
| 482 | |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 483 | hash_pair_t *hash_next (void *v, hash_next_t * hn); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 484 | |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 485 | void *_hash_create (uword elts, hash_t * h); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 486 | |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 487 | always_inline void |
| 488 | hash_set_value_bytes (hash_t * h, uword value_bytes) |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 489 | { |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 490 | hash_pair_t *p; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 491 | h->log2_pair_size = |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 492 | max_log2 ((sizeof (p->key) + value_bytes + sizeof (p->key) - |
| 493 | 1) / sizeof (p->key)); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 494 | } |
| 495 | |
| 496 | #define hash_create2(_elts,_user,_value_bytes, \ |
| 497 | _key_sum,_key_equal, \ |
| 498 | _format_pair,_format_pair_arg) \ |
| 499 | ({ \ |
| 500 | hash_t _h; \ |
Dave Barach | b7b9299 | 2018-10-17 10:38:51 -0400 | [diff] [blame] | 501 | clib_memset (&_h, 0, sizeof (_h)); \ |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 502 | _h.user = (_user); \ |
| 503 | _h.key_sum = (hash_key_sum_function_t *) (_key_sum); \ |
| 504 | _h.key_equal = (_key_equal); \ |
| 505 | hash_set_value_bytes (&_h, (_value_bytes)); \ |
| 506 | _h.format_pair = (format_function_t *) (_format_pair); \ |
| 507 | _h.format_pair_arg = (_format_pair_arg); \ |
| 508 | _hash_create ((_elts), &_h); \ |
| 509 | }) |
| 510 | |
| 511 | /* Hash function based on that of Bob Jenkins (bob_jenkins@compuserve.com). |
| 512 | Public domain per: http://www.burtleburtle.net/bob/hash/doobs.html |
| 513 | Thanks, Bob. */ |
| 514 | |
| 515 | #define hash_mix_step(a,b,c,s0,s1,s2) \ |
| 516 | do { \ |
| 517 | (a) -= (b) + (c); (a) ^= (c) >> (s0); \ |
| 518 | (b) -= (c) + (a); (b) ^= (a) << (s1); \ |
| 519 | (c) -= (a) + (b); (c) ^= (b) >> (s2); \ |
| 520 | } while (0) |
| 521 | |
| 522 | #define hash_mix32_step_1(a,b,c) hash_mix_step(a,b,c,13,8,13) |
| 523 | #define hash_mix32_step_2(a,b,c) hash_mix_step(a,b,c,12,16,5) |
| 524 | #define hash_mix32_step_3(a,b,c) hash_mix_step(a,b,c,3,10,15) |
| 525 | |
| 526 | #define hash_mix64_step_1(a,b,c) hash_mix_step(a,b,c,43,9,8) |
| 527 | #define hash_mix64_step_2(a,b,c) hash_mix_step(a,b,c,38,23,5) |
| 528 | #define hash_mix64_step_3(a,b,c) hash_mix_step(a,b,c,35,49,11) |
| 529 | #define hash_mix64_step_4(a,b,c) hash_mix_step(a,b,c,12,18,22) |
| 530 | |
Damjan Marion | 8799768 | 2022-03-26 00:57:50 +0100 | [diff] [blame] | 531 | #if uword_bits == 64 |
| 532 | #define hash_mix(a, b, c) hash_mix64 (a, b, c) |
| 533 | #else |
| 534 | #define hash_mix(a, b, c) hash_mix32 (a, b, c) |
| 535 | #endif |
| 536 | |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 537 | /* Hash function based on that of Bob Jenkins (bob_jenkins@compuserve.com). |
| 538 | Thanks, Bob. */ |
| 539 | #define hash_mix64(a0,b0,c0) \ |
| 540 | do { \ |
| 541 | hash_mix64_step_1 (a0, b0, c0); \ |
| 542 | hash_mix64_step_2 (a0, b0, c0); \ |
| 543 | hash_mix64_step_3 (a0, b0, c0); \ |
| 544 | hash_mix64_step_4 (a0, b0, c0); \ |
| 545 | } while (0) \ |
| 546 | |
| 547 | #define hash_mix32(a0,b0,c0) \ |
| 548 | do { \ |
| 549 | hash_mix32_step_1 (a0, b0, c0); \ |
| 550 | hash_mix32_step_2 (a0, b0, c0); \ |
| 551 | hash_mix32_step_3 (a0, b0, c0); \ |
| 552 | } while (0) \ |
| 553 | |
| 554 | /* Finalize from Bob Jenkins lookup3.c */ |
| 555 | |
| 556 | always_inline uword |
| 557 | hash32_rotate_left (u32 x, u32 i) |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 558 | { |
| 559 | return (x << i) | (x >> (BITS (i) - i)); |
| 560 | } |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 561 | |
| 562 | #define hash_v3_mix32(a,b,c) \ |
| 563 | do { \ |
| 564 | (a) -= (c); (a) ^= hash32_rotate_left ((c), 4); (c) += (b); \ |
| 565 | (b) -= (a); (b) ^= hash32_rotate_left ((a), 6); (a) += (c); \ |
| 566 | (c) -= (b); (c) ^= hash32_rotate_left ((b), 8); (b) += (a); \ |
| 567 | (a) -= (c); (a) ^= hash32_rotate_left ((c),16); (c) += (b); \ |
| 568 | (b) -= (a); (b) ^= hash32_rotate_left ((a),19); (a) += (c); \ |
| 569 | (c) -= (b); (c) ^= hash32_rotate_left ((b), 4); (b) += (a); \ |
| 570 | } while (0) |
| 571 | |
| 572 | #define hash_v3_finalize32(a,b,c) \ |
| 573 | do { \ |
| 574 | (c) ^= (b); (c) -= hash32_rotate_left ((b), 14); \ |
| 575 | (a) ^= (c); (a) -= hash32_rotate_left ((c), 11); \ |
| 576 | (b) ^= (a); (b) -= hash32_rotate_left ((a), 25); \ |
| 577 | (c) ^= (b); (c) -= hash32_rotate_left ((b), 16); \ |
| 578 | (a) ^= (c); (a) -= hash32_rotate_left ((c), 4); \ |
| 579 | (b) ^= (a); (b) -= hash32_rotate_left ((a), 14); \ |
| 580 | (c) ^= (b); (c) -= hash32_rotate_left ((b), 24); \ |
| 581 | } while (0) |
| 582 | |
| 583 | /* 32 bit mixing/finalize in steps. */ |
| 584 | |
| 585 | #define hash_v3_mix32_step1(a,b,c) \ |
| 586 | do { \ |
| 587 | (a) -= (c); (a) ^= hash32_rotate_left ((c), 4); (c) += (b); \ |
| 588 | (b) -= (a); (b) ^= hash32_rotate_left ((a), 6); (a) += (c); \ |
| 589 | } while (0) |
| 590 | |
| 591 | #define hash_v3_mix32_step2(a,b,c) \ |
| 592 | do { \ |
| 593 | (c) -= (b); (c) ^= hash32_rotate_left ((b), 8); (b) += (a); \ |
| 594 | (a) -= (c); (a) ^= hash32_rotate_left ((c),16); (c) += (b); \ |
| 595 | } while (0) |
| 596 | |
| 597 | #define hash_v3_mix32_step3(a,b,c) \ |
| 598 | do { \ |
| 599 | (b) -= (a); (b) ^= hash32_rotate_left ((a),19); (a) += (c); \ |
| 600 | (c) -= (b); (c) ^= hash32_rotate_left ((b), 4); (b) += (a); \ |
| 601 | } while (0) |
| 602 | |
| 603 | #define hash_v3_finalize32_step1(a,b,c) \ |
| 604 | do { \ |
| 605 | (c) ^= (b); (c) -= hash32_rotate_left ((b), 14); \ |
| 606 | (a) ^= (c); (a) -= hash32_rotate_left ((c), 11); \ |
| 607 | } while (0) |
| 608 | |
| 609 | #define hash_v3_finalize32_step2(a,b,c) \ |
| 610 | do { \ |
| 611 | (b) ^= (a); (b) -= hash32_rotate_left ((a), 25); \ |
| 612 | (c) ^= (b); (c) -= hash32_rotate_left ((b), 16); \ |
| 613 | } while (0) |
| 614 | |
| 615 | #define hash_v3_finalize32_step3(a,b,c) \ |
| 616 | do { \ |
| 617 | (a) ^= (c); (a) -= hash32_rotate_left ((c), 4); \ |
| 618 | (b) ^= (a); (b) -= hash32_rotate_left ((a), 14); \ |
| 619 | (c) ^= (b); (c) -= hash32_rotate_left ((b), 24); \ |
| 620 | } while (0) |
| 621 | |
| 622 | /* Vector v3 mixing/finalize. */ |
| 623 | #define hash_v3_mix_step_1_u32x(a,b,c) \ |
| 624 | do { \ |
| 625 | (a) -= (c); (a) ^= u32x_irotate_left ((c), 4); (c) += (b); \ |
| 626 | (b) -= (a); (b) ^= u32x_irotate_left ((a), 6); (a) += (c); \ |
| 627 | (c) -= (b); (c) ^= u32x_irotate_left ((b), 8); (b) += (a); \ |
| 628 | } while (0) |
| 629 | |
| 630 | #define hash_v3_mix_step_2_u32x(a,b,c) \ |
| 631 | do { \ |
| 632 | (a) -= (c); (a) ^= u32x_irotate_left ((c),16); (c) += (b); \ |
| 633 | (b) -= (a); (b) ^= u32x_irotate_left ((a),19); (a) += (c); \ |
| 634 | (c) -= (b); (c) ^= u32x_irotate_left ((b), 4); (b) += (a); \ |
| 635 | } while (0) |
| 636 | |
| 637 | #define hash_v3_finalize_step_1_u32x(a,b,c) \ |
| 638 | do { \ |
| 639 | (c) ^= (b); (c) -= u32x_irotate_left ((b), 14); \ |
| 640 | (a) ^= (c); (a) -= u32x_irotate_left ((c), 11); \ |
| 641 | (b) ^= (a); (b) -= u32x_irotate_left ((a), 25); \ |
| 642 | } while (0) |
| 643 | |
| 644 | #define hash_v3_finalize_step_2_u32x(a,b,c) \ |
| 645 | do { \ |
| 646 | (c) ^= (b); (c) -= u32x_irotate_left ((b), 16); \ |
| 647 | (a) ^= (c); (a) -= u32x_irotate_left ((c), 4); \ |
| 648 | (b) ^= (a); (b) -= u32x_irotate_left ((a), 14); \ |
| 649 | (c) ^= (b); (c) -= u32x_irotate_left ((b), 24); \ |
| 650 | } while (0) |
| 651 | |
| 652 | #define hash_v3_mix_u32x(a,b,c) \ |
| 653 | do { \ |
| 654 | hash_v3_mix_step_1_u32x(a,b,c); \ |
| 655 | hash_v3_mix_step_2_u32x(a,b,c); \ |
| 656 | } while (0) |
| 657 | |
| 658 | #define hash_v3_finalize_u32x(a,b,c) \ |
| 659 | do { \ |
| 660 | hash_v3_finalize_step_1_u32x(a,b,c); \ |
| 661 | hash_v3_finalize_step_2_u32x(a,b,c); \ |
| 662 | } while (0) |
| 663 | |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 664 | extern uword hash_memory (void *p, word n_bytes, uword state); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 665 | |
| 666 | extern uword mem_key_sum (hash_t * h, uword key); |
| 667 | extern uword mem_key_equal (hash_t * h, uword key1, uword key2); |
| 668 | |
| 669 | #define hash_create_mem(elts,key_bytes,value_bytes) \ |
| 670 | hash_create2((elts),(key_bytes),(value_bytes),mem_key_sum,mem_key_equal,0,0) |
| 671 | |
| 672 | extern uword vec_key_sum (hash_t * h, uword key); |
| 673 | extern uword vec_key_equal (hash_t * h, uword key1, uword key2); |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 674 | extern u8 *vec_key_format_pair (u8 * s, va_list * args); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 675 | |
| 676 | #define hash_create_vec(elts,key_bytes,value_bytes) \ |
| 677 | hash_create2((elts),(key_bytes),(value_bytes),\ |
| 678 | vec_key_sum,vec_key_equal,vec_key_format_pair,0) |
| 679 | |
| 680 | extern uword string_key_sum (hash_t * h, uword key); |
| 681 | extern uword string_key_equal (hash_t * h, uword key1, uword key2); |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 682 | extern u8 *string_key_format_pair (u8 * s, va_list * args); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 683 | |
Ole Troan | 73710c7 | 2018-06-04 22:27:49 +0200 | [diff] [blame] | 684 | /* |
| 685 | * Note: if you plan to put a hash into shared memory, |
| 686 | * the key sum and key equal functions MUST be set to magic constants! |
| 687 | * PIC means that whichever process sets up the hash won't have |
| 688 | * the actual key sum functions at the same place, leading to |
| 689 | * very hard-to-find bugs... |
| 690 | */ |
| 691 | |
| 692 | #define hash_create_shmem(elts,key_bytes,value_bytes) \ |
| 693 | hash_create2((elts),(key_bytes),(value_bytes), \ |
| 694 | (hash_key_sum_function_t *) KEY_FUNC_MEM, \ |
| 695 | (hash_key_equal_function_t *)KEY_FUNC_MEM, \ |
| 696 | 0, 0) |
| 697 | |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 698 | #define hash_create_string(elts,value_bytes) \ |
| 699 | hash_create2((elts),0,(value_bytes), \ |
| 700 | (hash_key_sum_function_t *) KEY_FUNC_STRING, \ |
| 701 | (hash_key_equal_function_t *)KEY_FUNC_STRING, \ |
| 702 | 0, 0) |
| 703 | |
| 704 | #define hash_create(elts,value_bytes) \ |
| 705 | hash_create2((elts),0,(value_bytes), \ |
| 706 | (hash_key_sum_function_t *) KEY_FUNC_NONE, \ |
| 707 | (hash_key_equal_function_t *) KEY_FUNC_NONE, \ |
| 708 | 0,0) |
| 709 | |
| 710 | #define hash_create_uword(elts,value_bytes) \ |
| 711 | hash_create2((elts),0,(value_bytes), \ |
| 712 | (hash_key_sum_function_t *) KEY_FUNC_POINTER_UWORD, \ |
| 713 | (hash_key_equal_function_t *) KEY_FUNC_POINTER_UWORD, \ |
| 714 | 0,0) |
| 715 | |
| 716 | #define hash_create_u32(elts,value_bytes) \ |
| 717 | hash_create2((elts),0,(value_bytes), \ |
| 718 | (hash_key_sum_function_t *) KEY_FUNC_POINTER_U32, \ |
| 719 | (hash_key_equal_function_t *) KEY_FUNC_POINTER_U32, \ |
| 720 | 0,0) |
| 721 | |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 722 | u8 *format_hash (u8 * s, va_list * va); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 723 | |
| 724 | /* Looks up input in hash table indexed by either vec string or |
| 725 | c string (null terminated). */ |
| 726 | unformat_function_t unformat_hash_vec_string; |
| 727 | unformat_function_t unformat_hash_string; |
| 728 | |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 729 | /* Main test routine. */ |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 730 | int test_hash_main (unformat_input_t * input); |
| 731 | |
| 732 | #endif /* included_hash_h */ |
Dave Barach | c379999 | 2016-08-15 11:12:27 -0400 | [diff] [blame] | 733 | |
| 734 | /* |
| 735 | * fd.io coding-style-patch-verification: ON |
| 736 | * |
| 737 | * Local Variables: |
| 738 | * eval: (c-set-style "gnu") |
| 739 | * End: |
| 740 | */ |