示例#1
0
/**
 * Return an iterator that addresses the first element in the hashtable.
 */
_hashtable_iterator_t _hashtable_begin(const _hashtable_t* cpt_hashtable)
{
    vector_iterator_t     it_bucket;
    _hashtable_iterator_t it_iter = _create_hashtable_iterator();

    assert(cpt_hashtable != NULL);
    assert(_hashtable_is_inited(cpt_hashtable));

    for (it_bucket = vector_begin(&cpt_hashtable->_vec_bucket);
         !iterator_equal(it_bucket, vector_end(&cpt_hashtable->_vec_bucket));
         it_bucket = iterator_next(it_bucket)) {
        _HASHTABLE_ITERATOR_BUCKETPOS(it_iter) = _VECTOR_ITERATOR_COREPOS(it_bucket);
        if (*(_hashnode_t**)_HASHTABLE_ITERATOR_BUCKETPOS(it_iter) != NULL) {
            _HASHTABLE_ITERATOR_COREPOS(it_iter) = (_byte_t*)*(_hashnode_t**)_HASHTABLE_ITERATOR_BUCKETPOS(it_iter);
            break;
        }
    }
    if (iterator_equal(it_bucket, vector_end(&cpt_hashtable->_vec_bucket))) {
        assert(_HASHTABLE_ITERATOR_COREPOS(it_iter) == NULL);
        _HASHTABLE_ITERATOR_BUCKETPOS(it_iter) = _VECTOR_ITERATOR_COREPOS(it_bucket);
    }
    _HASHTABLE_ITERATOR_HASHTABLE_POINTER(it_iter) = (_hashtable_t*)cpt_hashtable;

    return it_iter;
}
/**
 * Return iterator reference previous element.
 */
_hashtable_iterator_t _hashtable_iterator_prev(_hashtable_iterator_t it_iter)
{
    vector_iterator_t it_bucket;
    _hashnode_t*      pt_node = NULL;
    _hashnode_t*      pt_prevnode = NULL;

    assert(_hashtable_iterator_belong_to_hashtable(_HASHTABLE_ITERATOR_HASHTABLE(it_iter), it_iter));
    assert(!_hashtable_iterator_equal(it_iter, _hashtable_begin(_HASHTABLE_ITERATOR_HASHTABLE(it_iter))));

	/* hashtable end is specifical condition. corepos == NULL and bucketpos is invalid pos */
	if(_hashtable_iterator_equal(it_iter, _hashtable_end(_HASHTABLE_ITERATOR_HASHTABLE(it_iter))))
	{
		it_bucket = iterator_prev(vector_end(&_HASHTABLE_ITERATOR_HASHTABLE(it_iter)->_vec_bucket));
		_HASHTABLE_ITERATOR_BUCKETPOS(it_iter) = _VECTOR_ITERATOR_COREPOS(it_bucket);
	}

    pt_node = (_hashnode_t*)_HASHTABLE_ITERATOR_COREPOS(it_iter);
	pt_prevnode = *(_hashnode_t**)_HASHTABLE_ITERATOR_BUCKETPOS(it_iter);

	/* current node is first node in current bucket */
	if(pt_prevnode == pt_node)
	{
		it_bucket = vector_begin(&(_HASHTABLE_ITERATOR_HASHTABLE(it_iter)->_vec_bucket));
		_VECTOR_ITERATOR_COREPOS(it_bucket) = _HASHTABLE_ITERATOR_BUCKETPOS(it_iter);
		for(it_bucket = iterator_prev(it_bucket);
			iterator_greater_equal(it_bucket, vector_begin(&(_HASHTABLE_ITERATOR_HASHTABLE(it_iter)->_vec_bucket)));
			it_bucket = iterator_prev(it_bucket))
		{
			pt_node = *(_hashnode_t**)_VECTOR_ITERATOR_COREPOS(it_bucket);
			if(pt_node != NULL)
			{
				/* get the last hashnode */
				while(pt_node->_pt_next != NULL)
				{
					pt_node = pt_node->_pt_next;
				}
				/* set bucket pos and core pos */
				_HASHTABLE_ITERATOR_BUCKETPOS(it_iter) = _VECTOR_ITERATOR_COREPOS(it_bucket);
				_HASHTABLE_ITERATOR_COREPOS(it_iter) = (_byte_t*)pt_node;
				break;
			}
		}
	}
	else
	{
		while(pt_prevnode->_pt_next != pt_node)
		{
			pt_prevnode = pt_prevnode->_pt_next;
		}
		/* set core pos */
		_HASHTABLE_ITERATOR_COREPOS(it_iter) = (_byte_t*)pt_prevnode;
	}

    return it_iter;
}
/**
 * Test the two hashtable iterator are equal.
 */
bool_t _hashtable_iterator_equal(_hashtable_iterator_t it_first, _hashtable_iterator_t it_second)
{
    assert(_hashtable_iterator_belong_to_hashtable(_HASHTABLE_ITERATOR_HASHTABLE(it_first), it_first));
    assert(_hashtable_iterator_belong_to_hashtable(_HASHTABLE_ITERATOR_HASHTABLE(it_second), it_second));
    assert(_HASHTABLE_ITERATOR_HASHTABLE(it_first) == _HASHTABLE_ITERATOR_HASHTABLE(it_second));

    if(_HASHTABLE_ITERATOR_BUCKETPOS(it_first) == _HASHTABLE_ITERATOR_BUCKETPOS(it_second) &&
       _HASHTABLE_ITERATOR_COREPOS(it_first) == _HASHTABLE_ITERATOR_COREPOS(it_second))
    {
        return true;
    }
    else
    {
        return false;
    }
}
/**
 * Return iterator reference next element.
 */
_hashtable_iterator_t _hashtable_iterator_next(_hashtable_iterator_t it_iter)
{
    vector_iterator_t it_bucket;
    _hashnode_t*      pt_node = NULL;

    assert(_hashtable_iterator_belong_to_hashtable(_HASHTABLE_ITERATOR_HASHTABLE(it_iter), it_iter));
    assert(!_hashtable_iterator_equal(it_iter, _hashtable_end(_HASHTABLE_ITERATOR_HASHTABLE(it_iter))));

    pt_node = (_hashnode_t*)_HASHTABLE_ITERATOR_COREPOS(it_iter);
    assert(pt_node != NULL);

    if(pt_node->_pt_next == NULL)
    {
        /* iterator from current bucket pos to end */
        it_bucket = vector_begin(&(_HASHTABLE_ITERATOR_HASHTABLE(it_iter)->_vec_bucket));
        _VECTOR_ITERATOR_COREPOS(it_bucket) = _HASHTABLE_ITERATOR_BUCKETPOS(it_iter);
        for(it_bucket = iterator_next(it_bucket);
            !iterator_equal(it_bucket, vector_end(&(_HASHTABLE_ITERATOR_HASHTABLE(it_iter)->_vec_bucket)));
            it_bucket = iterator_next(it_bucket))
        {
            _HASHTABLE_ITERATOR_BUCKETPOS(it_iter) = _VECTOR_ITERATOR_COREPOS(it_bucket);
            if(*(_hashnode_t**)_HASHTABLE_ITERATOR_BUCKETPOS(it_iter) != NULL)
            {
                _HASHTABLE_ITERATOR_COREPOS(it_iter) = (_byte_t*)(*(_hashnode_t**)_HASHTABLE_ITERATOR_BUCKETPOS(it_iter));
                break;
            }
        }
        if(iterator_equal(it_bucket, vector_end(&(_HASHTABLE_ITERATOR_HASHTABLE(it_iter)->_vec_bucket))))
        {
            assert((_hashnode_t*)_HASHTABLE_ITERATOR_COREPOS(it_iter) == pt_node);
            _HASHTABLE_ITERATOR_COREPOS(it_iter) = NULL;
            _HASHTABLE_ITERATOR_BUCKETPOS(it_iter) = _VECTOR_ITERATOR_COREPOS(it_bucket);
        }
    }
    else
    {
        _HASHTABLE_ITERATOR_COREPOS(it_iter) = (_byte_t*)pt_node->_pt_next;
    }

    return it_iter;
}
/**
 * Create hashtable iterator.
 */
_hashtable_iterator_t _create_hashtable_iterator(void)
{
    _hashtable_iterator_t it_iter;

    _HASHTABLE_ITERATOR_BUCKETPOS(it_iter) = NULL;
    _HASHTABLE_ITERATOR_COREPOS(it_iter) = NULL;
    _HASHTABLE_ITERATOR_HASHTABLE_POINTER(it_iter) = NULL;

    _ITERATOR_CONTAINER(it_iter) = NULL;

    return it_iter;
}
示例#6
0
/**
 * Test iterator referenced data is within the hashtable.
 */
bool_t _hashtable_iterator_belong_to_hashtable(const _hashtable_t* cpt_hashtable, _hashtable_iterator_t it_iter)
{
    vector_iterator_t it_bucket;
    vector_iterator_t it_begin;
    vector_iterator_t it_end;

    assert(cpt_hashtable != NULL);
    assert(_hashtable_is_inited(cpt_hashtable));
    assert(_HASHTABLE_ITERATOR_BUCKETPOS(it_iter) != NULL);
    assert(_HASHTABLE_ITERATOR_HASHTABLE(it_iter) == cpt_hashtable);

    /* check for the end node */
    it_bucket = vector_end(&cpt_hashtable->_vec_bucket);
    if (_VECTOR_ITERATOR_COREPOS(it_bucket) == _HASHTABLE_ITERATOR_BUCKETPOS(it_iter) &&
        _HASHTABLE_ITERATOR_COREPOS(it_iter) == NULL) {
        return true;
    } else {
        _hashnode_t* pt_node = NULL;
        it_begin = vector_begin(&cpt_hashtable->_vec_bucket);
        it_end = vector_end(&cpt_hashtable->_vec_bucket);
        for (it_bucket = it_begin; !iterator_equal(it_bucket, it_end); it_bucket = iterator_next(it_bucket)) {
            if (_HASHTABLE_ITERATOR_BUCKETPOS(it_iter) == _VECTOR_ITERATOR_COREPOS(it_bucket)) {
                pt_node = *(_hashnode_t**)_VECTOR_ITERATOR_COREPOS(it_bucket);
                while (pt_node != NULL) {
                    if (pt_node == (_hashnode_t*)_HASHTABLE_ITERATOR_COREPOS(it_iter)) {
                        return true;
                    }

                    pt_node = pt_node->_pt_next;
                }
            }
        }

        return false;
    }
}
示例#7
0
/**
 * Return an iterator that addresses the location succeeding the last element in the hashtable.
 */
_hashtable_iterator_t _hashtable_end(const _hashtable_t* cpt_hashtable)
{
    vector_iterator_t     it_bucket;
    _hashtable_iterator_t it_iter = _create_hashtable_iterator();

    assert(cpt_hashtable != NULL);
    assert(_hashtable_is_inited(cpt_hashtable));

    it_bucket = vector_end(&cpt_hashtable->_vec_bucket);
    _HASHTABLE_ITERATOR_BUCKETPOS(it_iter) = _VECTOR_ITERATOR_COREPOS(it_bucket);
    _HASHTABLE_ITERATOR_COREPOS(it_iter) = NULL;
    _HASHTABLE_ITERATOR_HASHTABLE_POINTER(it_iter) = (_hashtable_t*)cpt_hashtable;

    return it_iter;
}
示例#8
0
/**
 * Find specific element.
 */
_hashtable_iterator_t _hashtable_find(const _hashtable_t* cpt_hashtable, const void* cpv_value)
{
    _hashtable_iterator_t it_iter = _create_hashtable_iterator();
    size_t                t_bucketcount = 0;
    _hashnode_t*          pt_node = NULL;
    _hashnode_t**         ppt_bucket = NULL;
    size_t                t_tmp = 0;
    size_t                t_pos = 0;
    bool_t                b_less = false;
    bool_t                b_greater = false;

    assert(cpt_hashtable != NULL);
    assert(cpv_value != NULL);
    assert(_hashtable_is_inited(cpt_hashtable));

    t_bucketcount = _hashtable_bucket_count(cpt_hashtable);
    t_tmp = _GET_HASHTABLE_TYPE_SIZE(cpt_hashtable);
    _hashtable_hash_auxiliary(cpt_hashtable, cpv_value, &t_tmp);
    t_pos = t_tmp % t_bucketcount;
    ppt_bucket = (_hashnode_t**)vector_at(&cpt_hashtable->_vec_bucket, t_pos);
    pt_node = *ppt_bucket;

    while (pt_node != NULL) {
        b_less = b_greater = _GET_HASHTABLE_TYPE_SIZE(cpt_hashtable);
        _hashtable_elem_compare_auxiliary(cpt_hashtable, pt_node->_pby_data, cpv_value, &b_less);
        _hashtable_elem_compare_auxiliary(cpt_hashtable, cpv_value, pt_node->_pby_data, &b_greater);
        if (b_less || b_greater) {
            pt_node = pt_node->_pt_next;
        } else {
            break;
        }
    }

    if (pt_node == NULL) {
        return _hashtable_end(cpt_hashtable);
    } else {
        _HASHTABLE_ITERATOR_BUCKETPOS(it_iter) = (_byte_t*)ppt_bucket;
        _HASHTABLE_ITERATOR_COREPOS(it_iter) = (_byte_t*)pt_node;
        _HASHTABLE_ITERATOR_HASHTABLE_POINTER(it_iter) = (_hashtable_t*)cpt_hashtable;

        return it_iter;
    }
}
示例#9
0
/*
 * Erase an element in an hashtable from specificed position.
 */
void _hashtable_erase_pos(_hashtable_t* pt_hashtable, _hashtable_iterator_t it_pos)
{
    _hashnode_t** ppt_bucket = NULL;
    _hashnode_t*  pt_node = NULL;
    _hashnode_t*  pt_deletion = NULL;
    bool_t        b_result = false;

    assert(pt_hashtable != NULL);
    assert(_hashtable_is_inited(pt_hashtable));
    assert(_hashtable_iterator_belong_to_hashtable(pt_hashtable, it_pos));
    assert(!_hashtable_iterator_equal(it_pos, _hashtable_end(pt_hashtable)));

    /* get the previous node */
    ppt_bucket = (_hashnode_t**)_HASHTABLE_ITERATOR_BUCKETPOS(it_pos);
    pt_node = *ppt_bucket;
    pt_deletion = (_hashnode_t*)_HASHTABLE_ITERATOR_COREPOS(it_pos);
    if (pt_node == pt_deletion) {
        /* the deletion node is the first node of node list */
        *ppt_bucket = pt_node->_pt_next;
    } else {
        while (pt_node->_pt_next != NULL) {
            if (pt_node->_pt_next == pt_deletion) {
                pt_node->_pt_next = pt_deletion->_pt_next;
                break;
            } else {
                pt_node = pt_node->_pt_next;
            }
        }
    }
    /* delete the node */
    b_result = _GET_HASHTABLE_TYPE_SIZE(pt_hashtable);
    _GET_HASHTABLE_TYPE_DESTROY_FUNCTION(pt_hashtable)(pt_deletion->_pby_data, &b_result);
    assert(b_result);
    _alloc_deallocate(
        &pt_hashtable->_t_allocator, pt_deletion, _HASHTABLE_NODE_SIZE(_GET_HASHTABLE_TYPE_SIZE(pt_hashtable)), 1);
    /* update the hashtable size */
    pt_hashtable->_t_nodecount--;
}
示例#10
0
/**
 * Return an iterator range that is equal to a specific element.
 */
range_t _hashtable_equal_range(const _hashtable_t* cpt_hashtable, const void* cpv_value)
{
    range_t       r_result;
    size_t        t_bucketcount = 0;
    _hashnode_t*  pt_begin = NULL;
    _hashnode_t*  pt_end = NULL;
    _hashnode_t** ppt_bucket = NULL;
    size_t        t_tmp = 0;
    size_t        t_pos = 0;
    bool_t        b_less = false;
    bool_t        b_greater = false;
    size_t        i = 0;

    assert(cpt_hashtable != NULL);
    assert(cpv_value != NULL);
    assert(_hashtable_is_inited(cpt_hashtable));

    r_result.it_begin = _create_hashtable_iterator();
    r_result.it_end = _create_hashtable_iterator();

    t_bucketcount = _hashtable_bucket_count(cpt_hashtable);
    t_tmp = _GET_HASHTABLE_TYPE_SIZE(cpt_hashtable);
    _hashtable_hash_auxiliary(cpt_hashtable, cpv_value, &t_tmp);
    t_pos = t_tmp % t_bucketcount;
    ppt_bucket = (_hashnode_t**)vector_at(&cpt_hashtable->_vec_bucket, t_pos);

    for (pt_begin = *ppt_bucket; pt_begin != NULL; pt_begin = pt_begin->_pt_next) {
        b_less = b_greater = _GET_HASHTABLE_TYPE_SIZE(cpt_hashtable);
        _hashtable_elem_compare_auxiliary(cpt_hashtable, pt_begin->_pby_data, cpv_value, &b_less);
        _hashtable_elem_compare_auxiliary(cpt_hashtable, cpv_value, pt_begin->_pby_data, &b_greater);
        if (!b_less && !b_greater) {
            for (pt_end = pt_begin->_pt_next; pt_end != NULL; pt_end = pt_end->_pt_next) {
                b_less = b_greater = _GET_HASHTABLE_TYPE_SIZE(cpt_hashtable);
                _hashtable_elem_compare_auxiliary(cpt_hashtable, pt_end->_pby_data, cpv_value, &b_less);
                _hashtable_elem_compare_auxiliary(cpt_hashtable, cpv_value, pt_end->_pby_data, &b_greater);
                if (b_less || b_greater) {
                    _HASHTABLE_ITERATOR_BUCKETPOS(r_result.it_begin) = (_byte_t*)ppt_bucket;
                    _HASHTABLE_ITERATOR_COREPOS(r_result.it_begin) = (_byte_t*)pt_begin;
                    _HASHTABLE_ITERATOR_HASHTABLE_POINTER(r_result.it_begin) = (_hashtable_t*)cpt_hashtable;

                    _HASHTABLE_ITERATOR_BUCKETPOS(r_result.it_end) = (_byte_t*)ppt_bucket;
                    _HASHTABLE_ITERATOR_COREPOS(r_result.it_end) = (_byte_t*)pt_end;
                    _HASHTABLE_ITERATOR_HASHTABLE_POINTER(r_result.it_end) = (_hashtable_t*)cpt_hashtable;

                    return r_result;
                }
            }
            
            _HASHTABLE_ITERATOR_BUCKETPOS(r_result.it_begin) = (_byte_t*)ppt_bucket;
            _HASHTABLE_ITERATOR_COREPOS(r_result.it_begin) = (_byte_t*)pt_begin;
            _HASHTABLE_ITERATOR_HASHTABLE_POINTER(r_result.it_begin) = (_hashtable_t*)cpt_hashtable;

            for (i = t_pos + 1; i < t_bucketcount; ++i) {
                ppt_bucket = (_hashnode_t**)vector_at(&cpt_hashtable->_vec_bucket, i);
                pt_end = *ppt_bucket;
                if (pt_end != NULL) {
                    _HASHTABLE_ITERATOR_BUCKETPOS(r_result.it_end) = (_byte_t*)ppt_bucket;
                    _HASHTABLE_ITERATOR_COREPOS(r_result.it_end) = (_byte_t*)pt_end;
                    _HASHTABLE_ITERATOR_HASHTABLE_POINTER(r_result.it_end) = (_hashtable_t*)cpt_hashtable;

                    return r_result;
                }
            }

            r_result.it_end = _hashtable_end(cpt_hashtable);

            return r_result;
        }
    }

    r_result.it_begin = _hashtable_end(cpt_hashtable);
    r_result.it_end = _hashtable_end(cpt_hashtable);

    return r_result;
}
示例#11
0
/**
 * Inserts an element into a hashtable.
 */
_hashtable_iterator_t _hashtable_insert_equal(_hashtable_t* pt_hashtable, const void* cpv_value)
{
    size_t                t_bucketcount = 0;
    _hashnode_t*          pt_node = NULL;
    _hashnode_t*          pt_cur = NULL;
    _hashnode_t**         ppt_nodelist = NULL;
    _hashtable_iterator_t it_iter = _create_hashtable_iterator();
    bool_t                b_result = false;
    size_t                t_tmp = 0;
    size_t                t_pos = 0;
    bool_t                b_less = false;
    bool_t                b_greater = false;

    assert(pt_hashtable != NULL);
    assert(cpv_value != NULL);
    assert(_hashtable_is_inited(pt_hashtable));

    /* resize */
    _hashtable_resize(pt_hashtable, _hashtable_size(pt_hashtable) + 1);

    /* allocate node */
    pt_node = _alloc_allocate(
        &pt_hashtable->_t_allocator, _HASHTABLE_NODE_SIZE(_GET_HASHTABLE_TYPE_SIZE(pt_hashtable)), 1);
    assert(pt_node != NULL);
    _hashtable_init_elem_auxiliary(pt_hashtable, pt_node);
    b_result = _GET_HASHTABLE_TYPE_SIZE(pt_hashtable);
    _GET_HASHTABLE_TYPE_COPY_FUNCTION(pt_hashtable)(pt_node->_pby_data, cpv_value, &b_result);
    assert(b_result);

    /* hash */
    t_bucketcount = _hashtable_bucket_count(pt_hashtable);
    t_tmp = _GET_HASHTABLE_TYPE_SIZE(pt_hashtable);
    _hashtable_hash_auxiliary(pt_hashtable, pt_node->_pby_data, &t_tmp);
    t_pos = t_tmp % t_bucketcount;

    /* insert node into hashtable, note the node has same value together */
    ppt_nodelist = (_hashnode_t**)vector_at(&pt_hashtable->_vec_bucket, t_pos);
    assert(ppt_nodelist != NULL);
    pt_cur = *ppt_nodelist;
    if (pt_cur == NULL) {
        pt_node->_pt_next = pt_cur;
        *ppt_nodelist = pt_node;
    } else {
        b_less = b_greater = _GET_HASHTABLE_TYPE_SIZE(pt_hashtable);
        _hashtable_elem_compare_auxiliary(pt_hashtable, pt_cur->_pby_data, pt_node->_pby_data, &b_less);
        _hashtable_elem_compare_auxiliary(pt_hashtable, pt_node->_pby_data, pt_cur->_pby_data, &b_greater);
        if (!b_less && !b_greater) {
            pt_node->_pt_next = pt_cur;
            *ppt_nodelist = pt_node;
        } else {
            while (pt_cur->_pt_next != NULL) {
                b_less = b_greater = _GET_HASHTABLE_TYPE_SIZE(pt_hashtable);
                _hashtable_elem_compare_auxiliary(
                    pt_hashtable, pt_cur->_pt_next->_pby_data, pt_node->_pby_data, &b_less);
                _hashtable_elem_compare_auxiliary(
                    pt_hashtable, pt_node->_pby_data, pt_cur->_pt_next->_pby_data, &b_greater);

                if (b_less || b_greater) {
                    pt_cur = pt_cur->_pt_next;
                } else {
                    break;
                }
            } 
            pt_node->_pt_next = pt_cur->_pt_next;
            pt_cur->_pt_next = pt_node;
        }
    }
    pt_hashtable->_t_nodecount++;

    _HASHTABLE_ITERATOR_BUCKETPOS(it_iter) = (_byte_t*)ppt_nodelist;
    _HASHTABLE_ITERATOR_COREPOS(it_iter) = (_byte_t*)pt_node;
    _HASHTABLE_ITERATOR_HASHTABLE_POINTER(it_iter) = pt_hashtable;

    return it_iter;
}