github.com/256dpi/max-go@v0.7.0/lib/max/ext_hashtab.h (about) 1 #ifndef _EXT_HASHTAB_H_ 2 #define _EXT_HASHTAB_H_ 3 4 #include "ext_linklist.h" 5 6 #if C74_PRAGMA_STRUCT_PACKPUSH 7 #pragma pack(push, 2) 8 #elif C74_PRAGMA_STRUCT_PACK 9 #pragma pack(2) 10 #endif 11 12 /** 13 Default number of slots in the hash table. 14 Creating a hashtab using hashtab_new() with an argument of 0 will use the default number of slots. 15 Primes typically work well for the number of slots. 16 17 @ingroup hashtab 18 */ 19 enum { 20 HASH_DEFSLOTS = 59 21 }; 22 23 24 /** A hashtab entry. This struct is provided for debugging convenience, 25 but should be considered opaque and is subject to change without notice. 26 27 @ingroup hashtab 28 @see t_hashtab 29 */ 30 typedef struct _hashtab_entry 31 { 32 t_object ob; 33 t_symbol *key; 34 t_object *value; 35 long flags; 36 struct _hashtab *parent; 37 } t_hashtab_entry; 38 39 40 /** The hashtab object. This struct is provided for debugging convenience, 41 but should be considered opaque and is subject to change without notice. 42 43 @ingroup hashtab 44 @see t_hashtab 45 */ 46 typedef struct _hashtab 47 { 48 t_object ob; 49 long slotcount; 50 t_linklist **slots; 51 long readonly; 52 long flags; 53 void *reserved; 54 } t_hashtab; 55 56 57 #if C74_PRAGMA_STRUCT_PACKPUSH 58 #pragma pack(pop) 59 #elif C74_PRAGMA_STRUCT_PACK 60 #pragma pack() 61 #endif 62 63 64 BEGIN_USING_C_LINKAGE 65 66 /** 67 Create a new hashtab object. 68 You can free the hashtab by calling object_free() on the hashtab's pointer, 69 or by using hashtab_chuck(). 70 71 @ingroup hashtab 72 @param slotcount The number of slots in the hash table. Prime numbers typically work well. 73 Pass 0 to get the default size. 74 @return Pointer to the new hashtab object. 75 76 @see HASH_DEFSLOTS 77 @see object_free() 78 @see hashtab_chuck() 79 */ 80 t_hashtab *hashtab_new(long slotcount); 81 82 83 /** 84 Store an item in a hashtab with an associated key. 85 86 @ingroup hashtab 87 88 @param x The hashtab instance. 89 @param key The key in the hashtab with which to associate the value. 90 @param val The value to store. 91 92 @return A Max error code. 93 @see hashtab_lookup(), hashtab_storesafe(), hashtab_storelong(), hashtab_storesym() 94 */ 95 t_max_err hashtab_store(t_hashtab *x, t_symbol *key, t_object *val); 96 97 /** 98 Store a t_atom_long value in a hashtab with an associated key. 99 100 @ingroup hashtab 101 102 @param x The hashtab instance. 103 @param key The key in the hashtab with which to associate the value. 104 @param val The t_atom_long value to store. 105 106 @return A Max error code. 107 @see hashtab_lookuplong(), hashtab_store(), hashtab_storesafe(), hashtab_storesym() 108 */ 109 t_max_err hashtab_storelong(t_hashtab *x, t_symbol *key, t_atom_long val); 110 111 /** 112 Store a t_symbol value in a hashtab with an associated key. 113 114 @ingroup hashtab 115 116 @param x The hashtab instance. 117 @param key The key in the hashtab with which to associate the value. 118 @param val The t_symbol pointer to store. 119 120 @return A Max error code. 121 @see hashtab_lookupsym(), hashtab_store(), hashtab_storesafe(), hashtab_storelong() 122 */ 123 t_max_err hashtab_storesym(t_hashtab *x, t_symbol *key, t_symbol *val); 124 125 126 /** Store an item in a hashtab with an associated key. 127 The difference between hashtab_store_safe() and hashtab_store() is what happens in the event of a collision in the hash table. 128 The normal hashtab_store() function will free the existing value at the collision location with sysmem_freeptr() and then replaces it. 129 This version doesn't try to free the existing value at the collision location, but instead just over-writes it. 130 131 @ingroup hashtab 132 @param x The hashtab instance. 133 @param key The key in the hashtab with which to associate the value. 134 @param val The value to store. 135 @return A Max error code. 136 @see hashtab_store() 137 */ 138 t_max_err hashtab_store_safe(t_hashtab *x, t_symbol *key, t_object *val); 139 140 141 /** Store an item in a hashtab with an associated key and also flags that define the behavior of the item. 142 The hashtab_store() method is the same as calling this method with the default (0) flags. 143 144 @ingroup hashtab 145 @param x The hashtab instance. 146 @param key The key in the hashtab with which to associate the value. 147 @param val The value to store. 148 @param flags One of the values listed in #e_max_datastore_flags. 149 @return A Max error code. 150 @see hashtab_store() 151 */ 152 t_max_err hashtab_storeflags(t_hashtab *x, t_symbol *key, t_object *val, long flags); 153 154 155 /** 156 Return an item stored in a hashtab with the specified key. 157 158 @ingroup hashtab 159 160 @param x The hashtab instance. 161 @param key The key in the hashtab to fetch. 162 @param val The address of a pointer to which the fetched value will be assigned. 163 164 @return A Max error code. 165 @see hashtab_store(), hashtab_lookuplong(), hashtab_lookupsym() 166 */ 167 t_max_err hashtab_lookup(t_hashtab *x, t_symbol *key, t_object **val); 168 169 /** 170 Return a t_atom_long value stored in a hashtab with the specified key. 171 172 @ingroup hashtab 173 174 @param x The hashtab instance. 175 @param key The key in the hashtab to fetch. 176 @param val A pointer to a t_atom_long to which the fetched value will be assigned. 177 178 @return A Max error code. 179 @see hashtab_storelong(), hashtab_lookup(), hashtab_lookupsym() 180 */ 181 t_max_err hashtab_lookuplong(t_hashtab *x, t_symbol *key, t_atom_long *val); 182 183 /** 184 Return a t_symbol value stored in a hashtab with the specified key. 185 186 @ingroup hashtab 187 188 @param x The hashtab instance. 189 @param key The key in the hashtab to fetch. 190 @param val A pointer to the address of a t_symbol to which the fetched value will be assigned. 191 192 @return A Max error code. 193 @see hashtab_storesym(), hashtab_lookup(), hashtab_lookuplong() 194 */ 195 t_max_err hashtab_lookupsym(t_hashtab *x, t_symbol *key, t_symbol **val); 196 197 // private 198 t_max_err hashtab_lookupentry(t_hashtab *x, t_symbol *key, t_hashtab_entry **entry); 199 200 201 /** Return an item stored in a hashtab with the specified key, also returning the items flags. 202 @ingroup hashtab 203 @param x The hashtab instance. 204 @param key The key in the hashtab to fetch. 205 @param val The address of a pointer to which the fetched value will be assigned. 206 @param flags The address of a value to which the fetched flags will be assigned. 207 @return A Max error code. 208 @see hashtab_lookup() 209 @see hashtab_store_flags() 210 */ 211 t_max_err hashtab_lookupflags(t_hashtab *x, t_symbol *key, t_object **val, long *flags); 212 213 214 /** 215 Remove an item from a hashtab associated with the specified key and free it. 216 217 The hashtab can contain a variety of different types of data. 218 By default, the hashtab assumes that all items are max objects with a valid 219 #t_object header. Thus by default, it frees items by calling object_free() on them. 220 221 You can alter the hashtab's notion of what it contains by using the 222 hashtab_flags() method. 223 224 If you wish to remove an item from the hashtab and free it yourself, then you 225 should use hashtab_chuckkey(). 226 227 @ingroup hashtab 228 229 @param x The hashtab instance. 230 @param key The key of the item to delete. 231 @return A Max error code. 232 233 @see hashtab_chuckkey() 234 @see hashtab_clear() 235 @see hashtab_flags() 236 */ 237 t_max_err hashtab_delete(t_hashtab *x, t_symbol *key); 238 239 240 /** 241 Delete all items stored in a hashtab. 242 This is the equivalent of calling hashtab_delete() on every item in a hashtab. 243 244 @ingroup hashtab 245 @return A max error code. 246 @see hashtab_flags() 247 @see hashtab_delete() 248 */ 249 t_max_err hashtab_clear(t_hashtab *x); 250 251 252 /** 253 Remove an item from a hashtab associated with a given key. 254 255 You are responsible for freeing any memory associated with the item that is 256 removed from the hashtab. 257 258 @ingroup hashtab 259 260 @param x The hashtab instance. 261 @param key The key of the item to delete. 262 @return A Max error code. 263 264 @see hashtab_delete 265 */ 266 t_max_err hashtab_chuckkey(t_hashtab *x, t_symbol *key); 267 268 269 /** 270 Free a hashtab, but don't free the items it contains. 271 272 The hashtab can contain a variety of different types of data. 273 By default, the hashtab assumes that all items are max objects with a valid 274 #t_object header. 275 276 You can alter the hashtab's notion of what it contains by using the 277 hashtab_flags() method. 278 279 When you free the hashtab by calling object_free() it then tries to free all of the items it contains. 280 If the hashtab is storing a custom type of data, or should otherwise not free the data it contains, 281 then call hashtab_chuck() to free the object instead of object_free(). 282 283 @ingroup hashtab 284 @param x The hashtab object to be freed. 285 @return A max error code. 286 @see object_free 287 */ 288 t_max_err hashtab_chuck(t_hashtab *x); 289 290 291 /** 292 Search the hash table for the first item meeting defined criteria. 293 The items in the hashtab are iteratively processed, calling a specified comparison function on each 294 until the comparison function returns true. 295 296 @ingroup hashtab 297 @param x The hashtab instance. 298 @param o The address to pointer that will be set with the matching item. 299 @param cmpfn The function used to determine a match in the list. 300 @param cmpdata An argument to be passed to the #t_cmpfn. 301 This will be passed as the second of the two args to the #t_cmpfn. 302 The first arg will be the hashtab item at each iteration in the list. 303 @return A max error code. 304 305 @see linklist_findfirst() 306 @see t_cmpfn 307 */ 308 t_max_err hashtab_findfirst(t_hashtab *x, void **o, long cmpfn(void *, void *), void *cmpdata); 309 310 311 /** 312 Call the named message on every object in the hashtab. 313 The hashtab_methodall() function requires that all items in the hashtab are 314 object instances with a valid #t_object header. 315 316 @ingroup hashtab 317 @param x The hashtab instance. 318 @param s The name of the message to send to the objects. 319 @param ... Any arguments to be sent with the message. 320 @return A max error code. 321 322 @remark Internally, this function uses object_method(), meaning that no errors will be 323 posted if the message name does not exist for the object. It also means that 324 messages sent methods with #A_GIMME definitions will need to be given a symbol 325 argument prior to the argc and argv array information. 326 */ 327 t_max_err hashtab_methodall(t_hashtab *x, t_symbol *s, ...); 328 329 #ifdef C74_X64 330 #define hashtab_methodall(...) C74_VARFUN(hashtab_methodall_imp, __VA_ARGS__) 331 #endif 332 333 t_max_err hashtab_methodall_imp(void *x, void *sym, void *p1, void *p2, void *p3, void *p4, void *p5, void *p6, void *p7, void *p8); 334 335 336 /** 337 Call the specified function for every item in the hashtab. 338 339 @ingroup hashtab 340 @param x The hashtab instance. 341 @param fun The function to call, specified as function pointer cast to a Max #method. 342 @param arg An argument that you would like to pass to the function being called. 343 @return A max error code. 344 345 @remark The hashtab_funall() method will call your function for every item in the list. 346 It will pass both a pointer to the item in the list, and any argument that you 347 provide. The following example shows a function that could be called by hashtab_funall(). 348 @code 349 void myFun(t_hashtab_entry *e, void *myArg) 350 { 351 if (e->key && e->value) { 352 // do something with e->key, e->value, and myArg here as appropriate 353 } 354 } 355 @endcode 356 */ 357 t_max_err hashtab_funall(t_hashtab *x, method fun, void *arg); 358 359 360 // private 361 t_max_err hashtab_objfunall(t_hashtab *x, method fun, void *arg); 362 363 364 /** 365 Return the number of items stored in a hashtab. 366 367 @ingroup hashtab 368 @param x The hashtab instance. 369 @return The number of items in the hash table. 370 */ 371 t_atom_long hashtab_getsize(t_hashtab *x); 372 373 374 /** 375 Post a hashtab's statistics to the Max window. 376 377 @ingroup hashtab 378 @param x The hashtab instance. 379 */ 380 void hashtab_print(t_hashtab *x); 381 382 383 /** 384 Set the hashtab's readonly bit. 385 386 By default the readonly bit is 0, indicating that it is threadsafe for both reading and writing. 387 Setting the readonly bit to 1 will disable the hashtab's theadsafety mechanism, increasing 388 performance but at the expense of threadsafe operation. 389 Unless you can guarantee the threading context for a hashtab's use, you should leave this set to 0. 390 391 @ingroup hashtab 392 @param x The hashtab instance. 393 @param readonly A 1 or 0 for setting the readonly bit. 394 */ 395 void hashtab_readonly(t_hashtab *x, long readonly); 396 397 398 /** 399 Set the hashtab's datastore flags. The available flags are enumerated in #e_max_datastore_flags. 400 These flags control the behavior of the hashtab, particularly when removing items from the list 401 using functions such as hashtab_clear(), hashtab_delete(), or when freeing the hashtab itself. 402 403 @ingroup hashtab 404 @param x The hashtab instance. 405 @param flags A valid value from the #e_max_datastore_flags. The default is #OBJ_FLAG_OBJ. 406 */ 407 void hashtab_flags(t_hashtab *x, long flags); 408 409 410 /** 411 Get the hashtab's datastore flags. 412 413 @ingroup hashtab 414 @param x The hashtab instance. 415 @return The current state of the hashtab flags as enumerated in #e_max_datastore_flags. 416 */ 417 t_atom_long hashtab_getflags(t_hashtab *x); 418 419 420 /** Change the flags for an item stored in the hashtab with a given key. 421 @ingroup hashtab 422 @param x The hashtab instance. 423 @param key The key in the hashtab whose flags will be changed. 424 @param flags One of the values listed in #e_max_datastore_flags. 425 @return A Max error code. 426 @see hashtab_store_flags() 427 */ 428 t_max_err hashtab_keyflags(t_hashtab *x, t_symbol *key, long flags); 429 430 431 /** Retrieve the flags for an item stored in the hashtab with a given key. 432 @ingroup hashtab 433 @param x The hashtab instance. 434 @param key The key in the hashtab whose flags will be returned. 435 @return The flags for the given key. 436 @see hashtab_store_flags() 437 */ 438 t_atom_long hashtab_getkeyflags(t_hashtab *x, t_symbol *key); 439 440 441 /** 442 Retrieve all of the keys stored in a hashtab. 443 444 If the kc and kv parameters are properly initialized to zero, then hashtab_getkeys() will allocate memory 445 for the keys it returns. You are then responsible for freeing this memory using sysmem_freeptr(). 446 447 @ingroup hashtab 448 @param x The hashtab instance. 449 @param kc The address of a long where the number of keys retrieved will be set. 450 @param kv The address of the first of an array #t_symbol pointers where the retrieved keys will be set. 451 @return A max error code. 452 453 @remark The following example demonstrates fetching all of the keys from a hashtab in order to iterate through 454 each item stored in the hashtab. 455 @code 456 t_symbol **keys = NULL; 457 long numKeys = 0; 458 long i; 459 t_object *anItem; 460 461 hashtab_getkeys(aHashtab, &numKeys, &keys); 462 for(i=0; i<numKeys; i++){ 463 hashtab_lookup(aHashtab, keys[i], &anItem); 464 // Do something with anItem here... 465 } 466 if(keys) 467 sysmem_freeptr(keys); 468 @endcode 469 */ 470 t_max_err hashtab_getkeys(t_hashtab *x, long *kc, t_symbol ***kv); 471 472 473 // private 474 t_hashtab_entry *hashtab_entry_new(t_symbol *key, t_object *val); 475 476 477 // private 478 void hashtab_entry_free(t_hashtab_entry *x); 479 480 481 END_USING_C_LINKAGE 482 483 #endif // _EXT_HASHTAB_H_ 484