/* * 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); } } }
/** * 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; } }
/** * 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; } }
/** * 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; }
/** * 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; }
/** * 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); } }
/** * 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); } } }
/** * 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; }
/** * 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); }
/** * 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; }
/** * 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; } }
/* * 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--; }
/** * 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); } }
/** * 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); } }
/** * 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)); } }
/** * 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)); } }
/** * 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; }