base/hash/m_hashtable.c
/*! This function is used to either rehash a h or destroy a h.
 *  Though it seems odd that they'd be the same function, they both iterate
 *  over the h the same exact way.  So in order to reduce this error-prone
 *  logic, they were combined into a single function.
 *  \param h  Pointer to the h
 *  \param is_destroy Whether or not this is a destroy call or a rehash call.
 *                    M_TRUE for destroy, M_FALSE for rehash. */
This function is used to either rehash a h or destroy a h.
Though it seems odd that they'd be the same function, they both iterate
over the h the same exact way.  So in order to reduce this error-prone
logic, they were combined into a single function.
\param h  Pointer to the h
\param is_destroy Whether or not this is a destroy call or a rehash call.
This function is used to either rehash a h or destroy a h . Though it seems odd that they ' d be the same function they both iterate over the h the same exact way . So in order to reduce this error - prone logic they were combined into a single function . \ param h Pointer to the h \ param is_destroy Whether or not this is a destroy call or a rehash call .
static void M_hashtable_rehash_or_destroy(M_hashtable_t *h, M_bool is_destroy, M_bool destroy_vals)
{
	M_uint32                   i;
	M_uint32                   old_size;
	struct M_hashtable_bucket *old;
	struct M_hashtable_bucket *ptr;
	struct M_hashtable_bucket *next;
	if (h == NULL)
		return;
	old      = h->buckets;
	old_size = h->size;
	if (!is_destroy) {
		if (h->size << 1 > M_HASHTABLE_MAX_BUCKETS)
			return;
		h->size      <<= 1;
		h->num_expansions++;
		h->buckets     = M_malloc(sizeof(*h->buckets) * h->size);
		M_mem_set(h->buckets, 0, sizeof(*h->buckets) * h->size);
	}
	for (i=0; i<old_size; i++) {
		if (old[i].key != NULL) {
			if (is_destroy) {
				M_hashtable_destroy_entry(h, &old[i], destroy_vals);
			} else {
				if (h->flags & M_HASHTABLE_MULTI_VALUE) {
					M_hashtable_insert_direct(h, M_HASHTABLE_INSERT_NODUP|M_HASHTABLE_INSERT_REHASH, old[i].key, old[i].value.multi_value);
				} else {
					M_hashtable_insert_direct(h, M_HASHTABLE_INSERT_NODUP|M_HASHTABLE_INSERT_REHASH, old[i].key, old[i].value.value);
				}
			}
			next = NULL;
			ptr  = old[i].next;
			while (ptr != NULL) {
				next = ptr->next;
				if (is_destroy) {
					M_hashtable_destroy_entry(h, ptr, destroy_vals);
				} else {
					if (h->flags & M_HASHTABLE_MULTI_VALUE) {
						M_hashtable_insert_direct(h, M_HASHTABLE_INSERT_NODUP|M_HASHTABLE_INSERT_REHASH, ptr->key, ptr->value.multi_value);
					} else {
						M_hashtable_insert_direct(h, M_HASHTABLE_INSERT_NODUP|M_HASHTABLE_INSERT_REHASH, ptr->key, ptr->value.value);
					}
				}
				M_free(ptr);
				ptr = next;
			}
		}
	}
	M_free(old);
	if (is_destroy) {
		if (h->flags & M_HASHTABLE_KEYS_ORDERED) {
			M_llist_destroy(h->keys, M_FALSE);
		}
		M_free(h);
	}
}
static void M_hashtable_rehash_or_destroy ( M_hashtable_t * h , M_bool is_destroy , M_bool destroy_vals ) { M_uint32 i ; M_uint32 old_size ; struct M_hashtable_bucket * old ; struct M_hashtable_bucket * ptr ; struct M_hashtable_bucket * next ; if ( h == NULL ) return ; old = h -> buckets ; old_size = h -> size ; if ( ! is_destroy ) { if ( h -> size << 1 > M_HASHTABLE_MAX_BUCKETS ) return ; h -> size <<= 1 ; h -> num_expansions ++ ; h -> buckets = M_malloc ( sizeof ( * h -> buckets ) * h -> size ) ; M_mem_set ( h -> buckets , 0 , sizeof ( * h -> buckets ) * h -> size ) ; } for ( i = 0 ; i < old_size ; i ++ ) { if ( old [ i ] . key != NULL ) { if ( is_destroy ) { M_hashtable_destroy_entry ( h , & old [ i ] , destroy_vals ) ; } else { if ( h -> flags & M_HASHTABLE_MULTI_VALUE ) { M_hashtable_insert_direct ( h , M_HASHTABLE_INSERT_NODUP | M_HASHTABLE_INSERT_REHASH , old [ i ] . key , old [ i ] . value . multi_value ) ; } else { M_hashtable_insert_direct ( h , M_HASHTABLE_INSERT_NODUP | M_HASHTABLE_INSERT_REHASH , old [ i ] . key , old [ i ] . value . value ) ; } } next = NULL ; ptr = old [ i ] . next ; while ( ptr != NULL ) { next = ptr -> next ; if ( is_destroy ) { M_hashtable_destroy_entry ( h , ptr , destroy_vals ) ; } else { if ( h -> flags & M_HASHTABLE_MULTI_VALUE ) { M_hashtable_insert_direct ( h , M_HASHTABLE_INSERT_NODUP | M_HASHTABLE_INSERT_REHASH , ptr -> key , ptr -> value . multi_value ) ; } else { M_hashtable_insert_direct ( h , M_HASHTABLE_INSERT_NODUP | M_HASHTABLE_INSERT_REHASH , ptr -> key , ptr -> value . value ) ; } } M_free ( ptr ) ; ptr = next ; } } } M_free ( old ) ; if ( is_destroy ) { if ( h -> flags & M_HASHTABLE_KEYS_ORDERED ) { M_llist_destroy ( h -> keys , M_FALSE ) ; } M_free ( h ) ; } }
This function is used to either rehash a h or destroy a h.
  Though it seems odd that they'd be the same function, they both iterate
  over the h the same exact way.
This function is used to either rehash a h or destroy a h . Though it seems odd that they ' d be the same function they both iterate over the h the same exact way .
/* If we are rehashing, we are going to create a new bucket list and
	 * re-insert (and thus re-hash) each item in the h one by one.
	 * We will NOT call the key_duplicate() or value_duplicate() callbacks
	 * though, we will use the existing memory pointers for those */ /* No-op if we grow too large.  Do not need to rehash, just return */ /* Free base entry */ /* Copy over base entry */ /* Copy then free any chained entries */ /* Destroy */ /* Copy */ /* Kill the bucket list */