⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cairo-hash.c

📁 按照官方的说法:Cairo is a vector graphics library with cross-device output support. 翻译过来
💻 C
📖 第 1 页 / 共 2 页
字号:
}/** * _cairo_hash_table_resize: * @hash_table: a hash table * * Resize the hash table if the number of entries has gotten much * bigger or smaller than the ideal number of entries for the current * size. * * Return value: CAIRO_STATUS_SUCCESS if successful or * CAIRO_STATUS_NO_MEMORY if out of memory. **/static cairo_status_t_cairo_hash_table_resize  (cairo_hash_table_t *hash_table){    cairo_hash_table_t tmp;    cairo_hash_entry_t **entry;    unsigned long new_size, i;    /* This keeps the hash table between 25% and 50% full. */    unsigned long high = hash_table->arrangement->high_water_mark;    unsigned long low = high >> 2;    if (hash_table->live_entries >= low && hash_table->live_entries <= high)	return CAIRO_STATUS_SUCCESS;    tmp = *hash_table;    if (hash_table->live_entries > high)    {	tmp.arrangement = hash_table->arrangement + 1;	/* This code is being abused if we can't make a table big enough. */	assert (tmp.arrangement - hash_table_arrangements <		NUM_HASH_TABLE_ARRANGEMENTS);    }    else /* hash_table->live_entries < low */    {	/* Can't shrink if we're at the smallest size */	if (hash_table->arrangement == &hash_table_arrangements[0])	    return CAIRO_STATUS_SUCCESS;	tmp.arrangement = hash_table->arrangement - 1;    }    new_size = tmp.arrangement->size;    tmp.entries = calloc (new_size, sizeof (cairo_hash_entry_t*));    if (tmp.entries == NULL)	return CAIRO_STATUS_NO_MEMORY;    for (i = 0; i < hash_table->arrangement->size; ++i) {	if (ENTRY_IS_LIVE (hash_table->entries[i])) {	    entry = _cairo_hash_table_lookup_internal (&tmp,						       hash_table->entries[i],						       TRUE);	    assert (ENTRY_IS_FREE(*entry));	    *entry = hash_table->entries[i];	}    }    free (hash_table->entries);    hash_table->entries = tmp.entries;    hash_table->arrangement = tmp.arrangement;    return CAIRO_STATUS_SUCCESS;}/** * _cairo_hash_table_lookup: * @hash_table: a hash table * @key: the key of interest * @entry_return: pointer for return value. * * Performs a lookup in @hash_table looking for an entry which has a * key that matches @key, (as determined by the keys_equal() function * passed to _cairo_hash_table_create). * * Return value: TRUE if there is an entry in the hash table that * matches the given key, (which will now be in *entry_return). FALSE * otherwise, (in which case *entry_return will be NULL). **/cairo_bool_t_cairo_hash_table_lookup (cairo_hash_table_t *hash_table,			  cairo_hash_entry_t *key,			  cairo_hash_entry_t **entry_return){    cairo_hash_entry_t **entry;    /* See if we have an entry in the table already. */    entry = _cairo_hash_table_lookup_internal (hash_table, key, FALSE);    if (ENTRY_IS_LIVE(*entry)) {	*entry_return = *entry;	return TRUE;    }    *entry_return = NULL;    return FALSE;}/** * _cairo_hash_table_random_entry: * @hash_table: a hash table * @predicate: a predicate function, or NULL for any entry. * * Find a random entry in the hash table satisfying the given * @predicate. A NULL @predicate is taken as equivalent to a function * which always returns TRUE, (eg. any entry in the table will do). * * We use the same algorithm as the lookup algorithm to walk over the * entries in the hash table in a pseudo-random order. Walking * linearly would favor entries following gaps in the hash table. We * could also call rand() repeatedly, which works well for almost-full * tables, but degrades when the table is almost empty, or predicate * returns TRUE for most entries. * * Return value: a random live entry or NULL if there are no entries * that match the given predicate. In particular, if predicate is * NULL, a NULL return value indicates that the table is empty. **/void *_cairo_hash_table_random_entry (cairo_hash_table_t	   *hash_table,				cairo_hash_predicate_func_t predicate){    cairo_hash_entry_t **entry;    unsigned long hash;    unsigned long table_size, i, idx, step;    table_size = hash_table->arrangement->size;    hash = rand ();    idx = hash % table_size;    step = 0;    for (i = 0; i < table_size; ++i)    {	entry = &hash_table->entries[idx];	if (ENTRY_IS_LIVE (*entry) &&	    (predicate == NULL || predicate (*entry)))	{	    return *entry;	}	if (step == 0) {	    step = hash % hash_table->arrangement->rehash;	    if (step == 0)		step = 1;	}	idx += step;	if (idx >= table_size)	    idx -= table_size;    }    return NULL;}/** * _cairo_hash_table_insert: * @hash_table: a hash table * @key_and_value: an entry to be inserted * * Insert the entry #key_and_value into the hash table. * * WARNING: It is a fatal error if an entry exists in the hash table * with a matching key, (this function will halt). * * WARNING: It is a fatal error to insert an element while * an iterator is running * * Instead of using insert to replace an entry, consider just editing * the entry obtained with _cairo_hash_table_lookup. Or if absolutely * necessary, use _cairo_hash_table_remove first. * * Return value: CAIRO_STATUS_SUCCESS if successful or * CAIRO_STATUS_NO_MEMORY if insufficient memory is available. **/cairo_status_t_cairo_hash_table_insert (cairo_hash_table_t *hash_table,			  cairo_hash_entry_t *key_and_value){    cairo_status_t status;    cairo_hash_entry_t **entry;    /* Insert is illegal while an iterator is running. */    assert (hash_table->iterating == 0);    entry = _cairo_hash_table_lookup_internal (hash_table,					       key_and_value, FALSE);    if (ENTRY_IS_LIVE(*entry))    {	/* User is being bad, let's crash. */	ASSERT_NOT_REACHED;    }    *entry = key_and_value;    hash_table->live_entries++;    status = _cairo_hash_table_resize (hash_table);    if (status)	return status;    return CAIRO_STATUS_SUCCESS;}/** * _cairo_hash_table_remove: * @hash_table: a hash table * @key: key of entry to be removed * * Remove an entry from the hash table which has a key that matches * @key, if any (as determined by the keys_equal() function passed to * _cairo_hash_table_create). * * Return value: CAIRO_STATUS_SUCCESS if successful or * CAIRO_STATUS_NO_MEMORY if out of memory. **/void_cairo_hash_table_remove (cairo_hash_table_t *hash_table,			  cairo_hash_entry_t *key){    cairo_hash_entry_t **entry;    entry = _cairo_hash_table_lookup_internal (hash_table, key, FALSE);    if (! ENTRY_IS_LIVE(*entry))	return;    *entry = DEAD_ENTRY;    hash_table->live_entries--;    /* Check for table resize. Don't do this when iterating as this will     * reorder elements of the table and cause the iteration to potentially     * skip some elements. */    if (hash_table->iterating == 0) {	/* This call _can_ fail, but only in failing to allocate new	 * memory to shrink the hash table. It does leave the table in a	 * consistent state, and we've already succeeded in removing the	 * entry, so we don't examine the failure status of this call. */	_cairo_hash_table_resize (hash_table);    }}/** * _cairo_hash_table_foreach: * @hash_table: a hash table * @hash_callback: function to be called for each live entry * @closure: additional argument to be passed to @hash_callback * * Call @hash_callback for each live entry in the hash table, in a * non-specified order. * * Entries in @hash_table may be removed by code executed from @hash_callback. * * Entries may not be inserted to @hash_table, nor may @hash_table * be destroyed by code executed from @hash_callback. The relevant * functions will halt in these cases. **/void_cairo_hash_table_foreach (cairo_hash_table_t	      *hash_table,			   cairo_hash_callback_func_t  hash_callback,			   void			      *closure){    unsigned long i;    cairo_hash_entry_t *entry;    if (hash_table == NULL)	return;    /* Mark the table for iteration */    ++hash_table->iterating;    for (i = 0; i < hash_table->arrangement->size; i++) {	entry = hash_table->entries[i];	if (ENTRY_IS_LIVE(entry))	    hash_callback (entry, closure);    }    /* If some elements were deleted during the iteration,     * the table may need resizing. Just do this every time     * as the check is inexpensive.     */    if (--hash_table->iterating == 0)	_cairo_hash_table_resize (hash_table);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -