405 lines
5.4 KiB
C++
Raw Normal View History

/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//
// Bin.cpp
//
#include "stdAfx.h"
#include "bin.h"
#include "assert.h"
#include "list.h"
Bin::Bin ( int size )
{
assert ( size > 0 );
num_buckets = size;
sh_item = NULL;
bucket = new List[size];
}
Bin::~Bin ( )
{
Clear ();
delete [] bucket;
}
void Bin::Clear ( void )
{
int count = num_buckets;
sh_item = NULL;
while ( count-- )
{
List *head = &bucket[count];
BinItem *item;
while ( ( item = (BinItem *) head->Next ()))
{
Remove ( item );
}
}
}
void* Bin::Get ( OLECHAR *text1, OLECHAR *text2 )
{
BinItem *item;
if ( ( item = GetBinItem ( text1, text2 )) )
{
return item->Item();
}
return NULL;
}
void* Bin::GetNext ( void )
{
BinItem *item;
if ( ( item = GetNextBinItem ( )) )
{
return item->Item();
}
return NULL;
}
void Bin::Add ( void *data, OLECHAR *text1, OLECHAR *text2 )
{
BinItem *item;
List *list;
int hash;
sh_item = NULL;
hash = calc_hash ( text1 );
item = new BinItem ( data, hash, text1, text2 );
list = &bucket[hash%num_buckets];
list->AddToTail ( (ListNode *) item );
}
BinItem* Bin::GetBinItem ( OLECHAR *text1, OLECHAR *text2)
{
sh_size1 = sh_size2 = 0;
sh_text1 = text1;
sh_text2 = text2;
sh_hash = calc_hash ( text1 );
if ( sh_text1 )
{
sh_size1 = wcslen ( sh_text1 );
}
if ( sh_text2 )
{
sh_size2 = wcslen ( sh_text2 );
}
sh_item = (BinItem *) &bucket[sh_hash%num_buckets];
return GetNextBinItem ();
}
BinItem* Bin::GetNextBinItem ( void )
{
if ( sh_item )
{
sh_item = (BinItem *) sh_item->Next ();
}
while ( sh_item )
{
if ( sh_item->Same ( sh_hash, sh_text1, sh_size1, sh_text2, sh_size2 ))
{
break;
}
sh_item = (BinItem *) sh_item->Next ();
}
return sh_item;
}
BinItem* Bin::GetBinItem ( void *item )
{
BinItem *bitem = NULL;
int i;
for ( i=0; i< num_buckets; i++)
{
if ( ( bitem = (BinItem *) bucket[i].Find ( item )))
{
break;
}
}
return bitem;
}
void Bin::Remove ( void *item )
{
BinItem *bitem;
if ( ( bitem = GetBinItem ( item ) ))
{
Remove ( bitem );
}
}
void Bin::Remove ( OLECHAR *text1, OLECHAR *text2 )
{
BinItem *bitem;
if ( ( bitem = GetBinItem ( text1, text2 ) ))
{
Remove ( bitem );
}
}
void Bin::Remove ( BinItem *item )
{
sh_item = NULL;
item->Remove ();
delete item ;
}
BinItem::BinItem ( void *data, int new_hash, OLECHAR *new_text1, OLECHAR *new_text2 )
{
SetItem ( data );
hash = new_hash;
if ( (text1 = new_text1) )
{
text1size = wcslen ( text1 );
}
else
{
text1size = 0;
}
if ( (text2 = new_text2) )
{
text2size = wcslen ( text2 );
}
else
{
text2size = 0;
}
}
int BinItem::Same ( int chash, OLECHAR *ctext1, int size1, OLECHAR *ctext2, int size2 )
{
if ( hash != chash || text1size != size1 || text2size != size2 )
{
return FALSE;
}
if ( wcsicmp ( text1, ctext1 ))
{
return FALSE;
}
if ( text2 && ctext2 && wcsicmp ( text2, ctext2 ))
{
return FALSE;
}
return TRUE;
}
int Bin::calc_hash ( OLECHAR *text )
{
int hash = 0;
while ( *text )
{
hash += *text++;
}
return hash;
}
// Bin ID code
BinID::BinID ( int size )
{
assert ( size > 0 );
num_buckets = size;
bucket = new List[size];
}
BinID::~BinID ( )
{
Clear ();
delete [] bucket;
}
void BinID::Clear ( void )
{
int count = num_buckets;
while ( count-- )
{
List *head = &bucket[count];
BinIDItem *item;
while ( ( item = (BinIDItem *) head->Next ()))
{
Remove ( item );
}
}
}
void* BinID::Get ( int id)
{
BinIDItem *item;
if ( ( item = GetBinIDItem ( id )) )
{
return item->Item();
}
return NULL;
}
void BinID::Add ( void *data, int id )
{
BinIDItem *item;
List *list;
item = new BinIDItem ( data, id );
list = &bucket[id%num_buckets];
list->AddToTail ( (ListNode *) item );
}
BinIDItem* BinID::GetBinIDItem ( int id )
{
BinIDItem *item;
item = (BinIDItem *) bucket[id%num_buckets].Next();
while ( item )
{
if ( item->Same ( id ))
{
break;
}
item = (BinIDItem *) item->Next ();
}
return item ;
}
BinIDItem* BinID::GetBinIDItem ( void *item )
{
BinIDItem *bitem = NULL;
int i;
for ( i=0; i< num_buckets; i++)
{
if ( ( bitem = (BinIDItem *) bucket[i].Find ( item )))
{
break;
}
}
return bitem;
}
void BinID::Remove ( void *item )
{
BinIDItem *bitem;
if ( ( bitem = GetBinIDItem ( item ) ))
{
Remove ( bitem );
}
}
void BinID::Remove ( int id )
{
BinIDItem *bitem;
if ( ( bitem = GetBinIDItem ( id ) ))
{
Remove ( bitem );
}
}
void BinID::Remove ( BinIDItem *item )
{
item->Remove ();
delete item ;
}
BinIDItem::BinIDItem ( void *data, int new_id )
{
SetItem ( data );
id = new_id;
}
int BinIDItem::Same ( int compare_id )
{
return id == compare_id;
}