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