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