_WPRTLINK void WCHashBase::base_construct( const WCHashBase * orig ) { WCExcept::base_construct( orig ); num_buckets = orig->num_buckets; if( num_buckets <= 0 ) return; num_entries = 0; if( !hash_array ) { // hash_array must be allocated or NULL before // base_construct is called num_buckets = 0; base_throw_out_of_memory(); } else { WCIsvSListIter<BaseHashLink> iter; BaseHashLink * link; BaseHashLink * new_link; // copy elements, making sure num_entries is always correct for( int i = 0; i < num_buckets; i++ ) { iter.reset( orig->hash_array[ i ] ); for( ;; ) { link = ++iter; if( link == 0 ) break; new_link = base_copy_link( link ); if( new_link == 0 ) { base_throw_out_of_memory(); return; } hash_array[ i ].append( new_link ); num_entries++; } } } };
_WPRTLINK WCbool WCHashBase::insert( TTypePtr elem ) { if( num_buckets == 0 ) { base_throw_out_of_memory(); return( false ); } BaseHashLink * link = WCHashNew( elem ); if( link == 0 ) { base_throw_out_of_memory(); return( false ); } hash_array[ base_get_bucket( elem ) ].append( link ); num_entries++; return( true ); }
_WPRTLINK void WCHashBase::resize( unsigned buckets ) { if( buckets <= 0 ) { base_throw_zero_buckets(); return; } WCIsvSList<BaseHashLink> * new_hash_array; new_hash_array = new WCIsvSList<BaseHashLink>[ buckets ]; if( new_hash_array == 0 ) { base_throw_out_of_memory(); return; } unsigned old_buckets = num_buckets; num_buckets = buckets; BaseHashLink * link; // we need to rehash all the values on a resize for( int i = 0; i < old_buckets; i++ ) { for( ;; ) { link = hash_array[ i ].get(); if( link == 0 ) break; new_hash_array[ base_get_bucket_for_link( link ) ].append( link ); } } delete [] hash_array; hash_array = new_hash_array; }
_WPRTLINK WCSLink * WCHashBase::base_set_insert( TTypePtr elem ) { unsigned bucket = 0; unsigned index = 0; if( base_find( elem, &bucket, &index, FIND_FIRST ) == 0 ) { if( num_buckets == 0 ) { base_throw_out_of_memory(); return( 0 ); } BaseHashLink * link = WCHashNew( elem ); if( link == 0 ) { base_throw_out_of_memory(); return( 0 ); } hash_array[ bucket ].append( link ); num_entries++; return( link ); } // find succeeded: an equivalent element was previously in the hash set base_throw_not_unique(); return( 0 ); };
_WPRTLINK WCSkipListPtrs * WCSkipNonTempBase::base_insert( TTypePtr elem ) { int k; node_ptr curr; node_ptr found; node_ptr new_node; node_ptr update[ WCSKIPLIST_MAX_PTRS ]; // find where to insert elem found = base_find_with_update( elem, update ); if( !allowDuplicates && found != 0 ) { // duplicates are not allowed for sets and dictionaries base_throw_not_unique(); return( 0 ); } // insert elem after all elements less than elem k = base_random_level(); if( k > level ) { // Make sure the new node has a maximum level more than one than the // current maximum level in the skip list. k = ++level; update[ k ] = header; } // allocate a new node, initailized with elem new_node = base_new_node( elem, k ); if( new_node == 0 ) { base_throw_out_of_memory(); return( 0 ); } // link new_node into the skip list do { curr = update[ k ]; new_node->forward[ k ] = curr->forward[ k ]; curr->forward[ k ] = new_node; } while( --k >= 0 ); num_entries++; return( new_node ); }