コード例 #1
0
ファイル: cstl_hashtable.c プロジェクト: astrotycoon/libcstl
/*
 * Erase a range of element in an hashtable.
 */
void _hashtable_erase_range(
    _hashtable_t* pt_hashtable, _hashtable_iterator_t it_begin, _hashtable_iterator_t it_end)
{
    _hashtable_iterator_t it_iter;
    _hashtable_iterator_t it_next;

    assert(pt_hashtable != NULL);
    assert(_hashtable_is_inited(pt_hashtable));
    assert(_hashtable_iterator_belong_to_hashtable(pt_hashtable, it_begin));
    assert(_hashtable_iterator_belong_to_hashtable(pt_hashtable, it_end));
    assert(_hashtable_iterator_equal(it_begin, it_end) || _hashtable_iterator_before(it_begin, it_end));

    it_iter = it_next = it_begin;
    if(!_hashtable_iterator_equal(it_next, _hashtable_end(pt_hashtable)))
    {
        it_next = _hashtable_iterator_next(it_next);
    }
    while(!_hashtable_iterator_equal(it_iter, it_end))
    {
        _hashtable_erase_pos(pt_hashtable, it_iter);

        it_iter = it_next;
        if(!_hashtable_iterator_equal(it_next, _hashtable_end(pt_hashtable)))
        {
            it_next = _hashtable_iterator_next(it_next);
        }
    }
}
コード例 #2
0
/**
 * Calculate distance between two iterators.
 */
int _hashtable_iterator_distance(_hashtable_iterator_t it_first, _hashtable_iterator_t it_second)
{
    _hashtable_iterator_t it_iter;
    int                   n_distance = 0;

    if(_hashtable_iterator_before(it_first, it_second))
    {
        for(it_iter = it_first;
            !_hashtable_iterator_equal(it_iter, it_second);
            it_iter = _hashtable_iterator_next(it_iter))
        {
            n_distance++;
        }
        return n_distance;
    }
    else if(_hashtable_iterator_before(it_second, it_first))
    {
        for(it_iter = it_second;
            !_hashtable_iterator_equal(it_iter, it_first);
            it_iter = _hashtable_iterator_next(it_iter))
        {
            n_distance++;
        }
        return -n_distance;
    }
    else
    {
        return 0;
    }
}
コード例 #3
0
/**
 * Test the first iterator is before the second.
 */
bool_t _hashtable_iterator_before(_hashtable_iterator_t it_first, _hashtable_iterator_t it_second)
{
    _hashtable_iterator_t it_iter;
    _hashtable_t*         pt_hashtable = NULL;

    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_COREPOS(it_first) == _HASHTABLE_ITERATOR_COREPOS(it_second))
    {
        return false;
    }

    pt_hashtable = _HASHTABLE_ITERATOR_HASHTABLE(it_first);
    for(it_iter = it_first;
        !_hashtable_iterator_equal(it_iter, _hashtable_end(pt_hashtable));
        it_iter = _hashtable_iterator_next(it_iter))
    {
        if(_hashtable_iterator_equal(it_iter, it_second))
        {
            return true;
        }
    }

    if(_hashtable_iterator_equal(it_second, _hashtable_end(pt_hashtable)))
    {
        return true;
    }
    else
    {
        return false;
    }
}
コード例 #4
0
/**
 * 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;
}
コード例 #5
0
ファイル: cstl_hashtable.c プロジェクト: astrotycoon/libcstl
/**
 * Tests if the two rb tree are equal.
 */
bool_t _hashtable_equal(const _hashtable_t* cpt_first, const _hashtable_t* cpt_second)
{
    _hashtable_iterator_t it_first;
    _hashtable_iterator_t it_second;
    bool_t                b_less = false;
    bool_t                b_greater = false;

    assert(cpt_first != NULL);
    assert(cpt_second != NULL);
    assert(_hashtable_is_inited(cpt_first));
    assert(_hashtable_is_inited(cpt_second));

    if(cpt_first == cpt_second)
    {
        return true;
    }

    /* check type */
    if(!_hashtable_same_type_ex(cpt_first, cpt_second))
    {
        return false;
    }
    /* check size or bucket count*/
    if(_hashtable_size(cpt_first) != _hashtable_size(cpt_second) ||
       _hashtable_bucket_count(cpt_first) != _hashtable_bucket_count(cpt_second))
    {
        return false;
    }
    /* check each element */
    for(it_first = _hashtable_begin(cpt_first),
        it_second = _hashtable_begin(cpt_second);
        !_hashtable_iterator_equal(it_first, _hashtable_end(cpt_first)) && 
        !_hashtable_iterator_equal(it_second, _hashtable_end(cpt_second));
        it_first = _hashtable_iterator_next(it_first),
        it_second = _hashtable_iterator_next(it_second))
    {
        b_less = b_greater = _GET_HASHTABLE_TYPE_SIZE(cpt_first);
        _GET_HASHTABLE_TYPE_LESS_FUNCTION(cpt_first)(
                ((_hashnode_t*)_GET_HASHTABLE_COREPOS(it_first))->_pby_data,
                ((_hashnode_t*)_GET_HASHTABLE_COREPOS(it_second))->_pby_data, &b_less);
        _GET_HASHTABLE_TYPE_LESS_FUNCTION(cpt_first)(
                ((_hashnode_t*)_GET_HASHTABLE_COREPOS(it_second))->_pby_data,
                ((_hashnode_t*)_GET_HASHTABLE_COREPOS(it_first))->_pby_data, &b_greater);
        if(b_less || b_greater)
        {
            return false;
        }
    }

    assert(_hashtable_iterator_equal(it_first, _hashtable_end(cpt_first)) &&
           _hashtable_iterator_equal(it_second, _hashtable_end(cpt_second)));

    return true;
}
コード例 #6
0
ファイル: cstl_hashtable.c プロジェクト: astrotycoon/libcstl
/**
 * Inserts an range of unique element into a hashtable.
 */
void _hashtable_insert_unique_range(
    _hashtable_t* pt_hashtable, _hashtable_iterator_t it_begin, _hashtable_iterator_t it_end)
{
    _hashtable_iterator_t it_iter;

    assert(pt_hashtable != NULL);
    assert(_hashtable_is_inited(pt_hashtable));
    assert(_hashtable_same_hashtable_iterator_type(pt_hashtable, it_begin));
    assert(_hashtable_same_hashtable_iterator_type(pt_hashtable, it_end));
    assert(_hashtable_iterator_equal(it_begin, it_end) || _hashtable_iterator_before(it_begin, it_end));

    for(it_iter = it_begin; !_hashtable_iterator_equal(it_iter, it_end); it_iter = _hashtable_iterator_next(it_iter))
    {
        _hashtable_insert_unique(pt_hashtable, ((_hashnode_t*)_GET_HASHTABLE_COREPOS(it_iter))->_pby_data);
    }
}
コード例 #7
0
ファイル: cstl_hashtable.c プロジェクト: astrotycoon/libcstl
/**
 * Inserts an unique element into a hashtable.
 */
_hashtable_iterator_t _hashtable_insert_unique(_hashtable_t* pt_hashtable, const void* cpv_value)
{
    _hashtable_iterator_t it_iter;

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

    if(_hashtable_empty(pt_hashtable))
    {
        return _hashtable_insert_equal(pt_hashtable, cpv_value);
    }
    else
    {
        it_iter = _hashtable_find(pt_hashtable, cpv_value);
        if(!_hashtable_iterator_equal(it_iter, _hashtable_end(pt_hashtable)))
        {
            return _hashtable_end(pt_hashtable);
        }
        else
        {
            return _hashtable_insert_equal(pt_hashtable, cpv_value);
        }
    }
}
コード例 #8
0
ファイル: cstl_hashtable.c プロジェクト: astrotycoon/libcstl
/**
 * Tests if the first rb tree is less than the second rb tree.
 */
bool_t _hashtable_less(const _hashtable_t* cpt_first, const _hashtable_t* cpt_second)
{
    _hashtable_iterator_t it_first;
    _hashtable_iterator_t it_second;
    bool_t                b_less = false;
    bool_t                b_greater = false;

    assert(cpt_first != NULL);
    assert(cpt_second != NULL);
    assert(_hashtable_is_inited(cpt_first));
    assert(_hashtable_is_inited(cpt_second));
    assert(_hashtable_same_type_ex(cpt_first, cpt_second));

    /* check vector bucket count */
    if(vector_size(&cpt_first->_vec_bucket) == vector_size(&cpt_second->_vec_bucket))
    {
        /* check each element */
        for(it_first = _hashtable_begin(cpt_first),
            it_second = _hashtable_begin(cpt_second);
            !_hashtable_iterator_equal(it_first, _hashtable_end(cpt_first)) && 
            !_hashtable_iterator_equal(it_second, _hashtable_end(cpt_second));
            it_first = _hashtable_iterator_next(it_first),
            it_second = _hashtable_iterator_next(it_second))
        {
            b_less = _GET_HASHTABLE_TYPE_SIZE(cpt_first);
            _GET_HASHTABLE_TYPE_LESS_FUNCTION(cpt_first)(
                    ((_hashnode_t*)_GET_HASHTABLE_COREPOS(it_first))->_pby_data,
                    ((_hashnode_t*)_GET_HASHTABLE_COREPOS(it_second))->_pby_data, &b_less);
            if(b_less)
            {
                return true;
            }
            b_greater = _GET_HASHTABLE_TYPE_SIZE(cpt_first);
            _GET_HASHTABLE_TYPE_LESS_FUNCTION(cpt_first)(
                    ((_hashnode_t*)_GET_HASHTABLE_COREPOS(it_second))->_pby_data,
                    ((_hashnode_t*)_GET_HASHTABLE_COREPOS(it_first))->_pby_data, &b_greater);
            if(b_greater)
            {
                return false;
            }
        }
    }

    return _hashtable_size(cpt_first) < _hashtable_size(cpt_second) ? true : false;
}
コード例 #9
0
/**
 * Test the two hash_set iterator are equal.
 */
bool_t _hash_set_iterator_equal(hash_set_iterator_t it_first, hash_set_iterator_t it_second)
{
    assert(_GET_HASH_SET_CONTAINER_TYPE(it_first) == _HASH_SET_CONTAINER);
    assert(_GET_HASH_SET_ITERATOR_TYPE(it_first) == _BIDIRECTIONAL_ITERATOR);
    assert(_GET_HASH_SET_CONTAINER_TYPE(it_second) == _HASH_SET_CONTAINER);
    assert(_GET_HASH_SET_ITERATOR_TYPE(it_second) == _BIDIRECTIONAL_ITERATOR);

    return _hashtable_iterator_equal(it_first, it_second);
}
コード例 #10
0
ファイル: cstl_hashtable.c プロジェクト: Aluonna/libcstl
/**
 * Erase an element from a hashtable that match a specified element.
 */
size_t _hashtable_erase(_hashtable_t* pt_hashtable, const void* cpv_value)
{
    size_t t_countsize = _hashtable_count(pt_hashtable, cpv_value);
    range_t t_range = _hashtable_equal_range(pt_hashtable, cpv_value);

    if (!_hashtable_iterator_equal(t_range.it_begin, _hashtable_end(pt_hashtable))) {
        _hashtable_erase_range(pt_hashtable, t_range.it_begin, t_range.it_end);
    }

    return t_countsize;
}
コード例 #11
0
/**
 * Get data value pointer referenced by iterator.
 */
const void* _hashtable_iterator_get_pointer(_hashtable_iterator_t it_iter)
{
    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))));

    /* char* */
    if(strncmp(_GET_HASHTABLE_TYPE_BASENAME(_HASHTABLE_ITERATOR_HASHTABLE(it_iter)), _C_STRING_TYPE, _TYPE_NAME_SIZE) == 0)
    {
        return (char*)string_c_str((string_t*)((_hashnode_t*)_HASHTABLE_ITERATOR_COREPOS(it_iter))->_pby_data);
    }
    else
    {
        return ((_hashnode_t*)_HASHTABLE_ITERATOR_COREPOS(it_iter))->_pby_data;
    }
}
コード例 #12
0
ファイル: cstl_hashtable.c プロジェクト: astrotycoon/libcstl
/*
 * 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**)_GET_HASHTABLE_BUCKETPOS(it_pos);
    pt_node = *ppt_bucket;
    pt_deletion = (_hashnode_t*)_GET_HASHTABLE_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--;
}
コード例 #13
0
ファイル: cstl_hashtable.c プロジェクト: astrotycoon/libcstl
/**
 * Initialize hashtable container with specific range.
 */
void _hashtable_init_copy_range(
    _hashtable_t* pt_dest, _hashtable_iterator_t it_begin, _hashtable_iterator_t it_end,
    size_t t_bucketcount, unary_function_t ufun_hash, binary_function_t bfun_compare)
{
    assert(pt_dest != NULL);
    assert(_hashtable_is_created(pt_dest));
    assert(_hashtable_same_hashtable_iterator_type(pt_dest, it_begin));
    assert(_hashtable_same_hashtable_iterator_type(pt_dest, it_end));
    assert(_hashtable_iterator_equal(it_begin, it_end) || _hashtable_iterator_before(it_begin, it_end));

    /* initialize the dest hashtable with src hashtable attribute */
    _hashtable_init(pt_dest, t_bucketcount, ufun_hash, bfun_compare);
    /* insert node from src to dest */
    if(!_hashtable_empty(_GET_HASHTABLE(it_begin)))
    {
        _hashtable_insert_equal_range(pt_dest, it_begin, it_end);
    }
}
コード例 #14
0
/**
 * Get data value referenced by iterator.
 */
void _hashtable_iterator_get_value(_hashtable_iterator_t it_iter, void* pv_value)
{
    assert(pv_value != 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))));

    /* char* */
    if(strncmp(_GET_HASHTABLE_TYPE_BASENAME(_HASHTABLE_ITERATOR_HASHTABLE(it_iter)), _C_STRING_TYPE, _TYPE_NAME_SIZE) == 0)
    {
        *(char**)pv_value = (char*)string_c_str((string_t*)((_hashnode_t*)_HASHTABLE_ITERATOR_COREPOS(it_iter))->_pby_data);
    }
    else
    {
        bool_t b_result = _GET_HASHTABLE_TYPE_SIZE(_HASHTABLE_ITERATOR_HASHTABLE(it_iter));
        _GET_HASHTABLE_TYPE_COPY_FUNCTION(_HASHTABLE_ITERATOR_HASHTABLE(it_iter))(
            pv_value, ((_hashnode_t*)_HASHTABLE_ITERATOR_COREPOS(it_iter))->_pby_data, &b_result);
        assert(b_result);
    }
}
コード例 #15
0
ファイル: cstl_hashtable.c プロジェクト: Aluonna/libcstl
/**
 * Assign hashtable container.
 */
void _hashtable_assign(_hashtable_t* pt_dest, const _hashtable_t* cpt_src)
{
    _hashtable_iterator_t it_iter;

    assert(pt_dest != NULL);
    assert(cpt_src != NULL);
    assert(_hashtable_is_inited(pt_dest));
    assert(_hashtable_is_inited(cpt_src));
    assert(_hashtable_same_type_ex(pt_dest, cpt_src));

    /* clear all elements */
    _hashtable_clear(pt_dest);
    /* insert node from src to dest */
    for (it_iter = _hashtable_begin(cpt_src);
         !_hashtable_iterator_equal(it_iter, _hashtable_end(cpt_src));
         it_iter = _hashtable_iterator_next(it_iter)) {
        _hashtable_insert_equal(pt_dest, _hashtable_iterator_get_pointer_ignore_cstr(it_iter));
    }
}
コード例 #16
0
ファイル: cstl_hashtable.c プロジェクト: Aluonna/libcstl
/**
 * Initialize hashtable container with hashtable.
 */
void _hashtable_init_copy(_hashtable_t* pt_dest, const _hashtable_t* cpt_src)
{
    _hashtable_iterator_t it_iter;

    assert(pt_dest != NULL);
    assert(cpt_src != NULL);
    assert(_hashtable_is_created(pt_dest));
    assert(_hashtable_is_inited(cpt_src));
    assert(_hashtable_same_type(pt_dest, cpt_src));

    /* initialize the dest hashtable with src hashtable attribute */
    _hashtable_init(pt_dest, _hashtable_bucket_count(cpt_src), cpt_src->_ufun_hash, cpt_src->_bfun_compare);
    /* insert node from src to dest */
    for (it_iter = _hashtable_begin(cpt_src);
         !_hashtable_iterator_equal(it_iter, _hashtable_end(cpt_src));
         it_iter = _hashtable_iterator_next(it_iter)) {
        _hashtable_insert_equal(pt_dest, _hashtable_iterator_get_pointer_ignore_cstr(it_iter));
    }
}
コード例 #17
0
/**
 * 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;
}