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