1
0
mirror of https://github.com/OpenTTD/OpenTTD.git synced 2025-08-14 18:19:11 +00:00
Files
ai
data
docs
lang
makefiledir
media
music
openttd.xcode
os
scenario
scripts
sound
strgen
table
video
yapf
unittest
array.hpp
autocopyptr.hpp
binaryheap.hpp
blob.hpp
countedptr.hpp
crc32.hpp
fixedsizearray.hpp
follow_track.cpp
follow_track.hpp
hashtable.hpp
nodelist.hpp
track_dir.hpp
yapf.h
yapf.hpp
yapf_base.hpp
yapf_common.cpp
yapf_common.hpp
yapf_costbase.hpp
yapf_costcache.hpp
yapf_costrail.hpp
yapf_destrail.hpp
yapf_node.hpp
yapf_node_rail.hpp
yapf_node_road.hpp
yapf_rail.cpp
yapf_road.cpp
yapf_settings.h
yapf_ship.cpp
BUGS
COPYING
Doxyfile
Makefile
aircraft.h
aircraft_cmd.c
aircraft_gui.c
airport.c
airport.h
airport_gui.c
airport_movement.h
aystar.c
aystar.h
bmp.c
bmp.h
bridge.h
bridge_gui.c
bridge_map.c
bridge_map.h
callback_table.c
callback_table.h
changelog.txt
clear_cmd.c
clear_map.h
command.c
command.h
configure
console.c
console.h
console_cmds.c
currency.c
currency.h
date.c
date.h
debug.c
debug.h
dedicated.c
depot.c
depot.h
direction.h
disaster_cmd.c
dock_gui.c
driver.c
driver.h
dummy_land.c
economy.c
economy.h
elrail.c
endian_check.c
engine.c
engine.h
engine_gui.c
fileio.c
fileio.h
fios.c
fios.h
functions.h
genworld.c
genworld.h
genworld_gui.c
gfx.c
gfx.h
gfxinit.c
gfxinit.h
graph_gui.c
gui.h
hal.h
heightmap.c
heightmap.h
industry.h
industry_cmd.c
industry_gui.c
industry_map.h
intro_gui.c
known-bugs.txt
landscape.c
langs.vcproj
langs_vs80.vcproj
lzoconf.h
macros.h
main_gui.c
mainicon.ico
map.c
map.h
masm64.rules
md5.c
md5.h
mersenne.c
minilzo.c
minilzo.h
misc.c
misc_cmd.c
misc_gui.c
mixer.c
mixer.h
music.c
music.h
music_gui.c
namegen.c
namegen.h
network.c
network.h
network_client.c
network_client.h
network_core.h
network_data.c
network_data.h
network_gamelist.c
network_gamelist.h
network_gui.c
network_server.c
network_server.h
network_udp.c
network_udp.h
newgrf.c
newgrf.h
newgrf_callbacks.h
newgrf_cargo.c
newgrf_cargo.h
newgrf_engine.c
newgrf_engine.h
newgrf_spritegroup.c
newgrf_spritegroup.h
newgrf_station.c
newgrf_station.h
newgrf_text.c
newgrf_text.h
news.h
news_gui.c
npf.c
npf.h
oldloader.c
openttd.c
openttd.h
openttd.ico
openttd.sln
openttd.tgt
openttd.vcproj
openttd_vs80.sln
openttd_vs80.vcproj
order.h
order_cmd.c
order_gui.c
os2.c
os_timer.c
ottdres.rc
pathfind.c
pathfind.h
player.h
player_gui.c
players.c
pool.c
pool.h
queue.c
queue.h
rail.c
rail.h
rail_cmd.c
rail_gui.c
rail_map.h
railtypes.h
readme.txt
resource.h
road.h
road_cmd.c
road_cmd.h
road_gui.c
road_map.c
road_map.h
roadveh.h
roadveh_cmd.c
roadveh_gui.c
saveload.c
saveload.h
screenshot.c
screenshot.h
sdl.c
sdl.h
settings.c
settings.h
settings_gui.c
ship.h
ship_cmd.c
ship_gui.c
signs.c
signs.h
slope.h
smallmap_gui.c
sound.c
sound.h
sprite.h
spritecache.c
spritecache.h
station.h
station_cmd.c
station_gui.c
station_map.c
station_map.h
stdafx.h
string.c
string.h
strings.c
strings.h
subsidy_gui.c
svnup.sh
terraform_gui.c
texteff.c
tgp.c
tgp.h
thread.c
thread.h
tile.c
tile.h
town.h
town_cmd.c
town_gui.c
town_map.h
train.h
train_cmd.c
train_gui.c
tree_cmd.c
tree_map.h
tunnel_map.c
tunnel_map.h
tunnelbridge_cmd.c
unix.c
unmovable.h
unmovable_cmd.c
unmovable_map.h
variables.h
vehicle.c
vehicle.h
vehicle_gui.c
vehicle_gui.h
viewport.c
viewport.h
void_map.h
water_cmd.c
water_map.h
waypoint.c
waypoint.h
widget.c
win32.c
win32.h
win64.asm
window.c
window.h
yapf.txt
OpenTTD/yapf/hashtable.hpp

235 lines
6.4 KiB
C++

/* $Id$ */
#ifndef HASHTABLE_HPP
#define HASHTABLE_HPP
template <class Titem_>
struct CHashTableSlotT
{
typedef typename Titem_::Key Key; // make Titem_::Key a property of HashTable
Titem_* m_pFirst;
CHashTableSlotT() : m_pFirst(NULL) {}
/** hash table slot helper - linear search for item with given key through the given blob - const version */
FORCEINLINE const Titem_& Find(const Key& key) const
{
for (const Titem_* pItem = m_pFirst; pItem != NULL; pItem = pItem->GetHashNext()) {
if (pItem->GetKey() == key) {
// we have found the item, return it
return *pItem;
}
}
return *(Titem_*)NULL;
}
/** hash table slot helper - linear search for item with given key through the given blob - non-const version */
FORCEINLINE Titem_& Find(const Key& key)
{
for (Titem_* pItem = m_pFirst; pItem != NULL; pItem = pItem->GetHashNext()) {
if (pItem->GetKey() == key) {
// we have found the item, return it
return *pItem;
}
}
return *(Titem_*)NULL;
}
/** hash table slot helper - add new item to the slot */
FORCEINLINE void Attach(Titem_& new_item)
{
assert(new_item.GetHashNext() == NULL);
new_item.SetHashNext(m_pFirst);
m_pFirst = &new_item;
}
/** hash table slot helper - remove item from a slot */
FORCEINLINE bool Detach(Titem_& item_to_remove)
{
if (m_pFirst == &item_to_remove) {
m_pFirst = item_to_remove.GetHashNext();
item_to_remove.SetHashNext(NULL);
return true;
}
Titem_* pItem = m_pFirst;
while (true) {
if (pItem == NULL) {
return false;
}
Titem_* pNextItem = pItem->GetHashNext();
if (pNextItem == &item_to_remove) break;
pItem = pNextItem;
}
pItem->SetHashNext(item_to_remove.GetHashNext());
item_to_remove.SetHashNext(NULL);
return true;
}
/** hash table slot helper - remove and return item from a slot */
FORCEINLINE Titem_& Detach(const Key& key)
{
// do we have any items?
if (m_pFirst == NULL) {
return *(Titem_*)NULL;
}
// is it our first item?
if (m_pFirst->GetKey() == key) {
Titem_& ret_item = *m_pFirst;
m_pFirst = m_pFirst->GetHashNext();
ret_item.SetHashNext(NULL);
return ret_item;
}
// find it in the following items
Titem_* pPrev = m_pFirst;
for (Titem_* pItem = m_pFirst->GetHashNext(); pItem != NULL; pPrev = pItem, pItem = pItem->GetHashNext()) {
if (pItem->GetKey() == key) {
// we have found the item, unlink and return it
pPrev->SetHashNext(pItem->GetHashNext());
pItem->SetHashNext(NULL);
return *pItem;
}
}
return *(Titem_*)NULL;
}
};
/** @class CHashTableT<Titem, Thash_bits> - simple hash table
of pointers allocated elsewhere.
Supports: Add/Find/Remove of Titems.
Your Titem must meet some extra requirements to be CHashTableT
compliant:
- its constructor/destructor (if any) must be public
- if the copying of item requires an extra resource management,
you must define also copy constructor
- must support nested type (struct, class or typedef) Titem::Key
that defines the type of key class for that item
- must support public method:
const Key& GetKey() const; // return the item's key object
In addition, the Titem::Key class must support:
- public method that calculates key's hash:
int CalcHash() const;
- public 'equality' operator to compare the key with another one
bool operator == (const Key& other) const;
*/
template <class Titem_, int Thash_bits_>
class CHashTableT {
public:
typedef Titem_ Titem; // make Titem_ visible from outside of class
typedef typename Titem_::Key Tkey; // make Titem_::Key a property of HashTable
ST_CONST(int, Thash_bits = Thash_bits_); // publish num of hash bits
ST_CONST(int, Tcapacity = 1 << Thash_bits); // and num of slots 2^bits
protected:
/** each slot contains pointer to the first item in the list,
Titem contains pointer to the next item - GetHashNext(), SetHashNext() */
typedef CHashTableSlotT<Titem_> Slot;
Slot* m_slots; // here we store our data (array of blobs)
int m_num_items; // item counter
public:
// default constructor
FORCEINLINE CHashTableT()
{
// construct all slots
m_slots = new Slot[Tcapacity];
m_num_items = 0;
}
~CHashTableT() {delete [] m_slots; m_num_items = 0; m_slots = NULL;}
protected:
/** static helper - return hash for the given key modulo number of slots */
FORCEINLINE static int CalcHash(const Tkey& key)
{
int32 hash = key.CalcHash();
if ((8 * Thash_bits) < 32) hash ^= hash >> (min(8 * Thash_bits, 31));
if ((4 * Thash_bits) < 32) hash ^= hash >> (min(4 * Thash_bits, 31));
if ((2 * Thash_bits) < 32) hash ^= hash >> (min(2 * Thash_bits, 31));
if ((1 * Thash_bits) < 32) hash ^= hash >> (min(1 * Thash_bits, 31));
hash &= (1 << Thash_bits) - 1;
return hash;
}
/** static helper - return hash for the given item modulo number of slots */
FORCEINLINE static int CalcHash(const Titem_& item) {return CalcHash(item.GetKey());}
public:
/** item count */
FORCEINLINE int Count() const {return m_num_items;}
/** const item search */
const Titem_& Find(const Tkey& key) const
{
int hash = CalcHash(key);
const Slot& slot = m_slots[hash];
const Titem_& item = slot.Find(key);
return item;
}
/** non-const item search */
Titem_& Find(const Tkey& key)
{
int hash = CalcHash(key);
Slot& slot = m_slots[hash];
Titem_& item = slot.Find(key);
return item;
}
/** non-const item search & optional removal (if found) */
Titem_& TryPop(const Tkey& key)
{
int hash = CalcHash(key);
Slot& slot = m_slots[hash];
Titem_& item = slot.Detach(key);
if (&item != NULL) {
m_num_items--;
}
return item;
}
/** non-const item search & removal */
Titem_& Pop(const Tkey& key)
{
Titem_& item = TryPop(key);
assert(&item != NULL);
return item;
}
/** non-const item search & optional removal (if found) */
bool TryPop(Titem_& item)
{
const Tkey& key = item.GetKey();
int hash = CalcHash(key);
Slot& slot = m_slots[hash];
bool ret = slot.Detach(item);
if (ret) {
m_num_items--;
}
return ret;
}
/** non-const item search & removal */
void Pop(Titem_& item)
{
bool ret = TryPop(item);
assert(ret);
}
/** add one item - copy it from the given item */
void Push(Titem_& new_item)
{
int hash = CalcHash(new_item);
Slot& slot = m_slots[hash];
assert(&slot.Find(new_item.GetKey()) == NULL);
slot.Attach(new_item);
m_num_items++;
}
};
#endif /* HASHTABLE_HPP */