summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crawl-ref/source/decks.cc116
-rw-r--r--crawl-ref/source/externs.h2
-rw-r--r--crawl-ref/source/hash.cc1260
-rw-r--r--crawl-ref/source/hash.h308
-rw-r--r--crawl-ref/source/items.cc4
-rw-r--r--crawl-ref/source/makefile.obj4
-rw-r--r--crawl-ref/source/store.cc1615
-rw-r--r--crawl-ref/source/store.h402
8 files changed, 2081 insertions, 1630 deletions
diff --git a/crawl-ref/source/decks.cc b/crawl-ref/source/decks.cc
index 1df11df893..5364ef2d44 100644
--- a/crawl-ref/source/decks.cc
+++ b/crawl-ref/source/decks.cc
@@ -144,7 +144,7 @@ static unsigned long cards_in_deck(const item_def &deck)
const CrawlHashTable &props = deck.props;
ASSERT(props.exists("cards"));
- return (unsigned long) props["cards"].get_table().size();
+ return (unsigned long) props["cards"].get_vector().size();
}
static void shuffle_deck(item_def &deck)
@@ -154,16 +154,14 @@ static void shuffle_deck(item_def &deck)
CrawlHashTable &props = deck.props;
ASSERT(props.exists("cards"));
- CrawlHashTable &cards = props["cards"];
+ CrawlVector &cards = props["cards"];
ASSERT(cards.size() > 1);
- CrawlHashTable &flags = props["card_flags"];
+ CrawlVector &flags = props["card_flags"];
ASSERT(flags.size() == cards.size());
// Don't use std::shuffle(), since we want to apply exactly the
// same shuffling to both the cards vector and the flags vector.
- // Also, the CrawlHashTable iterator doesn't provide the interface
- // required for using it with std::shuffle().
std::vector<long> pos;
for (unsigned long i = 0, size = cards.size(); i < size; i++)
pos.push_back(random2(size));
@@ -179,8 +177,8 @@ static card_type get_card_and_flags(const item_def& deck, int idx,
unsigned char& _flags)
{
const CrawlHashTable &props = deck.props;
- const CrawlHashTable &cards = props["cards"].get_table();
- const CrawlHashTable &flags = props["card_flags"].get_table();
+ const CrawlVector &cards = props["cards"].get_vector();
+ const CrawlVector &flags = props["card_flags"].get_vector();
if (idx == -1)
idx = (int) cards.size() - 1;
@@ -194,8 +192,8 @@ static void set_card_and_flags(item_def& deck, int idx, card_type card,
unsigned char _flags)
{
CrawlHashTable &props = deck.props;
- CrawlHashTable &cards = props["cards"];
- CrawlHashTable &flags = props["card_flags"];
+ CrawlVector &cards = props["cards"];
+ CrawlVector &flags = props["card_flags"];
if (idx == -1)
idx = (int) cards.size() - 1;
@@ -365,8 +363,8 @@ static card_type draw_top_card(item_def& deck, bool message,
unsigned char &_flags)
{
CrawlHashTable &props = deck.props;
- CrawlHashTable &cards = props["cards"].get_table();
- CrawlHashTable &flags = props["card_flags"].get_table();
+ CrawlVector &cards = props["cards"].get_vector();
+ CrawlVector &flags = props["card_flags"].get_vector();
int num_cards = cards.size();
int idx = num_cards - 1;
@@ -374,9 +372,8 @@ static card_type draw_top_card(item_def& deck, bool message,
ASSERT(num_cards > 0);
card_type card = get_card_and_flags(deck, idx, _flags);
-
- cards.erase(idx);
- flags.erase(idx);
+ cards.pop_back();
+ flags.pop_back();
retry_blank_card(card, deck, _flags);
@@ -397,13 +394,11 @@ static void push_top_card(item_def& deck, card_type card,
unsigned char _flags)
{
CrawlHashTable &props = deck.props;
- CrawlHashTable &cards = props["cards"].get_table();
- CrawlHashTable &flags = props["card_flags"].get_table();
-
- int idx = cards.size();
+ CrawlVector &cards = props["cards"].get_vector();
+ CrawlVector &flags = props["card_flags"].get_vector();
- cards[idx] = (char) card;
- flags[idx] = (char) _flags;
+ cards.push_back((char) card);
+ flags.push_back((char) _flags);
}
static bool wielding_deck()
@@ -425,33 +420,43 @@ static bool check_buggy_deck(item_def& deck)
CrawlHashTable &props = deck.props;
- if (!props.exists("cards") || cards_in_deck(deck) == 0)
+ if (!props.exists("cards")
+ || props["cards"].get_type() != SV_VEC
+ || props["cards"].get_vector().get_type() != SV_BYTE
+ || cards_in_deck(deck) == 0)
{
crawl_state.zero_turns_taken();
- std::string msg = "";
-
if (!props.exists("cards"))
- msg += "Seems this deck never had any cards in the first place!";
+ msg::stream << "Seems this deck never had any cards in the "
+ "first place!";
+ else if (props["cards"].get_type() != SV_VEC)
+ msg::stream << "'cards' property isn't a vector.";
else
{
- msg += "Strange, this deck is already empty.";
-
- int cards_left = 0;
- if (deck.plus2 >= 0)
- cards_left = deck.plus - deck.plus2;
- else
- cards_left = -deck.plus;
+ if (props["cards"].get_vector().get_type() != SV_BYTE)
+ msg::stream << "'cards' vector doesn't contain bytes. ";
- if (cards_left != 0)
+ if (cards_in_deck(deck) == 0)
{
- msg += " But there should be been ";
- msg += cards_left;
- msg += " cards left.";
+ msg::stream << "Strange, this deck is already empty.";
+
+ int cards_left = 0;
+ if (deck.plus2 >= 0)
+ cards_left = deck.plus - deck.plus2;
+ else
+ cards_left = -deck.plus;
+
+ if (cards_left != 0)
+ {
+ msg::stream << " But there should be been ";
+ msg::stream << cards_left;
+ msg::stream << " cards left.";
+ }
}
}
+ msg::stream << std::endl;
- mpr(msg.c_str());
mpr("A swarm of software bugs snatches the deck from you and "
"whisk it away.");
@@ -466,32 +471,29 @@ static bool check_buggy_deck(item_def& deck)
bool problems = false;
- CrawlHashTable &cards = props["cards"].get_table();
- CrawlHashTable &flags = props["card_flags"].get_table();
-
- problems = cards.fixup_indexed_array("the card stack");
- problems = flags.fixup_indexed_array("the flag stack");
+ CrawlVector &cards = props["cards"].get_vector();
+ CrawlVector &flags = props["card_flags"].get_vector();
unsigned long num_cards = cards.size();
unsigned long num_flags = flags.size();
unsigned int num_buggy = 0;
unsigned int num_marked = 0;
- unsigned int counted_cards = 0;
for (unsigned long i = 0; i < num_cards; i++)
{
- unsigned char card = (unsigned char) cards[i].get_byte();
- unsigned char _flags = (unsigned char) flags[i].get_byte();
+ unsigned char card = cards[i].get_byte();
+ unsigned char _flags = flags[i].get_byte();
if (card >= NUM_CARDS)
{
cards.erase(i);
flags.erase(i);
+ i--;
+ num_cards--;
num_buggy++;
}
else
{
- counted_cards++;
if (_flags & CFLAG_MARKED)
num_marked++;
}
@@ -501,8 +503,6 @@ static bool check_buggy_deck(item_def& deck)
{
mprf("%d buggy cards found in the deck, discarding them.",
num_buggy);
- cards.compact_indicies(0, num_cards - 1);
- flags.compact_indicies(0, num_flags - 1);
deck.plus2 += num_buggy;
@@ -512,7 +512,7 @@ static bool check_buggy_deck(item_def& deck)
problems = true;
}
- if (num_cards == 0)
+ if (num_cards <= 0)
{
crawl_state.zero_turns_taken();
@@ -567,7 +567,7 @@ static bool check_buggy_deck(item_def& deck)
problems = true;
}
- if (props["num_marked"].get_byte() > (char) counted_cards)
+ if (props["num_marked"].get_byte() > (char) num_cards)
{
mpr("More cards marked than in the deck?");
props["num_marked"] = (char) num_marked;
@@ -686,8 +686,8 @@ bool deck_peek()
return false;
}
- CrawlHashTable &cards = deck.props["cards"];
- int num_cards = cards.size();
+ CrawlVector &cards = deck.props["cards"];
+ int num_cards = cards.size();
card_type card1, card2, card3;
unsigned char flags1, flags2, flags3;
@@ -2141,8 +2141,6 @@ bool top_card_is_known(const item_def &deck)
if (!is_deck(deck))
return false;
- ASSERT(cards_in_deck(deck) > 0);
-
unsigned char flags;
get_card_and_flags(deck, -1, flags);
@@ -2154,8 +2152,6 @@ card_type top_card(const item_def &deck)
if (!is_deck(deck))
return NUM_CARDS;
- ASSERT(cards_in_deck(deck) > 0);
-
unsigned char flags;
card_type card = get_card_and_flags(deck, -1, flags);
@@ -2177,7 +2173,9 @@ bool bad_deck(const item_def &item)
return false;
return (!item.props.exists("cards")
- || item.props["cards"].get_table().get_type() != HV_BYTE);
+ || item.props["cards"].get_type() != SV_VEC
+ || item.props["cards"].get_vector().get_type() != SV_BYTE
+ || cards_in_deck(item) == 0);
}
deck_rarity_type deck_rarity(const item_def &item)
@@ -2221,10 +2219,10 @@ void init_deck(item_def &item)
ASSERT(item.special >= DECK_RARITY_COMMON
&& item.special <= DECK_RARITY_LEGENDARY);
- props.set_default_flags(HFLAG_CONST_TYPE);
+ props.set_default_flags(SFLAG_CONST_TYPE);
- props["cards"].new_table(HV_BYTE);
- props["card_flags"].new_table(HV_BYTE);
+ props["cards"].new_vector(SV_BYTE).resize(item.plus);
+ props["card_flags"].new_vector(SV_BYTE).resize(item.plus);
for (int i = 0; i < item.plus; i++)
{
diff --git a/crawl-ref/source/externs.h b/crawl-ref/source/externs.h
index f94cdd07f6..6d505674f4 100644
--- a/crawl-ref/source/externs.h
+++ b/crawl-ref/source/externs.h
@@ -30,9 +30,9 @@
#include "defines.h"
#include "enum.h"
#include "FixAry.h"
-#include "hash.h"
#include "libutil.h"
#include "mpr.h"
+#include "store.h"
#define INFO_SIZE 200 // size of message buffers
#define ITEMNAME_SIZE 200 // size of item names/shop names/etc
diff --git a/crawl-ref/source/hash.cc b/crawl-ref/source/hash.cc
deleted file mode 100644
index 60a5816f9c..0000000000
--- a/crawl-ref/source/hash.cc
+++ /dev/null
@@ -1,1260 +0,0 @@
-/*
- * File: hash.cc
- * Summary: Saveable hash-table capable of storing multiple types
- * of data.
- * Written by: Matthew Cline
- *
- * Modified for Crawl Reference by $Author$ on $Date$
- *
- * Change History (most recent first):
-
- * <1> 10/5/07 MPC Created
- */
-
-#include "AppHdr.h"
-#include "hash.h"
-
-#include "externs.h"
-#include "tags.h"
-
-CrawlHashValue::CrawlHashValue()
- : type(HV_NONE), flags(HFLAG_UNSET)
-{
- val.ptr = NULL;
-}
-
-CrawlHashValue::CrawlHashValue(const CrawlHashValue &other)
-{
- ASSERT(other.type >= HV_NONE && other.type < NUM_HASH_VAL_TYPES);
-
- type = other.type;
- flags = other.flags;
-
- if (flags & HFLAG_UNSET)
- {
- val = other.val;
- return;
- }
-
- switch (type)
- {
- case HV_NONE:
- case HV_BOOL:
- case HV_BYTE:
- case HV_SHORT:
- case HV_LONG:
- case HV_FLOAT:
- val = other.val;
- break;
-
- case HV_STR:
- {
- std::string* str;
- str = new std::string(*static_cast<std::string*>(other.val.ptr));
- val.ptr = static_cast<void*>(str);
- break;
- }
-
- case HV_COORD:
- {
- coord_def* coord;
- coord = new coord_def(*static_cast<coord_def*>(other.val.ptr));
- val.ptr = static_cast<void*>(coord);
- break;
- }
-
- case HV_HASH:
- {
- CrawlHashTable* hash;
- CrawlHashTable* tmp = static_cast<CrawlHashTable*>(other.val.ptr);
- hash = new CrawlHashTable(*tmp);
- val.ptr = static_cast<void*>(hash);
- break;
- }
-
- case HV_ITEM:
- {
- item_def* item;
- item = new item_def(*static_cast<item_def*>(other.val.ptr));
- val.ptr = static_cast<void*>(item);
- break;
- }
-
- case NUM_HASH_VAL_TYPES:
- ASSERT(false);
- }
-}
-
-CrawlHashValue::CrawlHashValue(const unsigned char _flags,
- const hash_val_type _type)
- : type(_type), flags(_flags)
-{
- ASSERT(type >= HV_NONE && type < NUM_HASH_VAL_TYPES);
- ASSERT(!(flags & HFLAG_UNSET));
-
- flags |= HFLAG_UNSET;
- val.ptr = NULL;
-}
-
-CrawlHashValue::~CrawlHashValue()
-{
- unset(true);
-}
-
-void CrawlHashValue::unset(bool force)
-{
- if (flags & HFLAG_UNSET)
- return;
-
- if (force)
- flags &= ~HFLAG_NO_ERASE;
-
- ASSERT(!(flags & HFLAG_NO_ERASE));
-
- switch (type)
- {
- case HV_BOOL:
- val.boolean = false;
- break;
-
- case HV_BYTE:
- val.byte = 0;
- break;
-
- case HV_SHORT:
- val._short = 0;
- break;
-
- case HV_LONG:
- val._long = 0;
- break;
-
- case HV_FLOAT:
- val._float = 0.0;
- break;
-
- case HV_STR:
- {
- std::string* str = static_cast<std::string*>(val.ptr);
- delete str;
- val.ptr = NULL;
- break;
- }
-
- case HV_COORD:
- {
- coord_def* coord = static_cast<coord_def*>(val.ptr);
- delete coord;
- val.ptr = NULL;
- break;
- }
-
- case HV_HASH:
- {
- CrawlHashTable* hash = static_cast<CrawlHashTable*>(val.ptr);
- delete hash;
- val.ptr = NULL;
- break;
- }
-
- case HV_ITEM:
- {
- item_def* item = static_cast<item_def*>(val.ptr);
- delete item;
- val.ptr = NULL;
- break;
- }
-
- case HV_NONE:
- ASSERT(false);
-
- case NUM_HASH_VAL_TYPES:
- ASSERT(false);
- }
-
- flags |= HFLAG_UNSET;
-}
-
-// Only needed to do some assertion checking.
-CrawlHashValue &CrawlHashValue::operator = (const CrawlHashValue &other)
-{
- ASSERT(other.type >= HV_NONE && other.type < NUM_HASH_VAL_TYPES);
- ASSERT(other.type != HV_NONE || type == HV_NONE);
-
- // NOTE: We don't bother checking HFLAG_CONST_VAL, since the
- // asignment operator is used when swapping two elements.
-
- if (!(flags & HFLAG_UNSET))
- {
- if (flags & HFLAG_CONST_TYPE)
- ASSERT(type == HV_NONE || type == other.type);
- }
-
- type = other.type;
- flags = other.flags;
- val = other.val;
-
- return (*this);
-}
-
-///////////////////////////////////
-// Meta-data accessors and changers
-unsigned char CrawlHashValue::get_flags() const
-{
- return flags;
-}
-
-unsigned char CrawlHashValue::set_flags(unsigned char _flags)
-{
- flags |= _flags;
- return flags;
-}
-
-unsigned char CrawlHashValue::unset_flags(unsigned char _flags)
-{
- flags &= ~_flags;
- return flags;
-}
-
-hash_val_type CrawlHashValue::get_type() const
-{
- return type;
-}
-
-//////////////////////////////
-// Read/write from/to savefile
-void CrawlHashValue::write(tagHeader &th) const
-{
- ASSERT(!(flags & HFLAG_UNSET));
-
- marshallByte(th, (char) type);
- marshallByte(th, (char) flags);
-
- switch (type)
- {
- case HV_BOOL:
- marshallBoolean(th, val.boolean);
- break;
-
- case HV_BYTE:
- marshallByte(th, val.byte);
- break;
-
- case HV_SHORT:
- marshallShort(th, val._short);
- break;
-
- case HV_LONG:
- marshallLong(th, val._long);
- break;
-
- case HV_FLOAT:
- marshallFloat(th, val._float);
- break;
-
- case HV_STR:
- {
- std::string* str = static_cast<std::string*>(val.ptr);
- marshallString(th, *str);
- break;
- }
-
- case HV_COORD:
- {
- coord_def* coord = static_cast<coord_def*>(val.ptr);
- marshallCoord(th, *coord);
- break;
- }
-
- case HV_HASH:
- {
- CrawlHashTable* hash = static_cast<CrawlHashTable*>(val.ptr);
- hash->write(th);
- break;
- }
-
- case HV_ITEM:
- {
- item_def* item = static_cast<item_def*>(val.ptr);
- marshallItem(th, *item);
- break;
- }
-
- case HV_NONE:
- ASSERT(false);
-
- case NUM_HASH_VAL_TYPES:
- ASSERT(false);
- }
-}
-
-void CrawlHashValue::read(tagHeader &th)
-{
- type = static_cast<hash_val_type>(unmarshallByte(th));
- flags = (unsigned char) unmarshallByte(th);
-
- ASSERT(!(flags & HFLAG_UNSET));
-
- switch (type)
- {
- case HV_BOOL:
- val.boolean = unmarshallBoolean(th);
- break;
-
- case HV_BYTE:
- val.byte = unmarshallByte(th);
- break;
-
- case HV_SHORT:
- val._short = unmarshallShort(th);
- break;
-
- case HV_LONG:
- val._long = unmarshallLong(th);
- break;
-
- case HV_FLOAT:
- val._float = unmarshallFloat(th);
- break;
-
- case HV_STR:
- {
- std::string str = unmarshallString(th);
- val.ptr = (void*) new std::string(str);
- break;
- }
-
- case HV_COORD:
- {
- coord_def coord;
- unmarshallCoord(th, coord);
- val.ptr = (void*) new coord_def(coord);
-
- break;
- }
-
- case HV_HASH:
- {
- CrawlHashTable* hash = new CrawlHashTable();
- hash->read(th);
- val.ptr = (void*) hash;
-
- break;
- }
-
- case HV_ITEM:
- {
- item_def item;
- unmarshallItem(th, item);
- val.ptr = (void*) new item_def(item);
-
- break;
- }
-
- case HV_NONE:
- ASSERT(false);
-
- case NUM_HASH_VAL_TYPES:
- ASSERT(false);
- }
-}
-
-////////////////////////////////////////////////////////////////
-// Setup a new table with the given flags and/or type; assert if
-// a table already exists.
-CrawlHashTable &CrawlHashValue::new_table(unsigned char _flags)
-{
- return new_table(HV_NONE, flags);
-}
-
-CrawlHashTable &CrawlHashValue::new_table(hash_val_type _type,
- unsigned char _flags)
-{
- CrawlHashTable* old_table = static_cast<CrawlHashTable*>(val.ptr);
-
- ASSERT(flags & HFLAG_UNSET);
- ASSERT(type == HV_NONE
- || (type == HV_HASH
- && old_table->size() == 0
- && old_table->get_type() == HV_NONE
- && old_table->get_default_flags() == 0));
-
- CrawlHashTable &table = get_table();
-
- table.default_flags = _flags;
- table.type = _type;
-
- type = HV_HASH;
- flags &= ~HFLAG_UNSET;
-
- return table;
-}
-
-///////////////////////////////////////////
-// Dynamic type-checking accessor functions
-#define GET_VAL(x, _type, field, value) \
- ASSERT((flags & HFLAG_UNSET) || !(flags & HFLAG_CONST_VAL)); \
- if (type != (x)) \
- { \
- if (type == HV_NONE) \
- { \
- type = (x); \
- field = (value); \
- } \
- else \
- { \
- ASSERT(!(flags & HFLAG_CONST_TYPE)); \
- switch(type) \
- { \
- case HV_BOOL: \
- field = (_type) val.boolean; \
- break; \
- case HV_BYTE: \
- field = (_type) val.byte; \
- break; \
- case HV_SHORT: \
- field = (_type) val._short; \
- break; \
- case HV_LONG: \
- field = (_type) val._long; \
- break; \
- case HV_FLOAT: \
- field = (_type) val._float; \
- break; \
- default: \
- ASSERT(false); \
- } \
- type = (x); \
- } \
- } \
- flags &= ~HFLAG_UNSET; \
- return field;
-
-#define GET_VAL_PTR(x, _type, value) \
- ASSERT((flags & HFLAG_UNSET) || !(flags & HFLAG_CONST_VAL)); \
- if (type != (x)) \
- { \
- if (type == HV_NONE) \
- { \
- type = (x); \
- val.ptr = (value); \
- } \
- else \
- { \
- unset(); \
- val.ptr = (value); \
- type = (x); \
- } \
- } \
- flags &= ~HFLAG_UNSET; \
- return *((_type) val.ptr);
-
-bool &CrawlHashValue::get_bool()
-{
- GET_VAL(HV_BOOL, bool, val.boolean, false);
-}
-
-char &CrawlHashValue::get_byte()
-{
- GET_VAL(HV_BYTE, char, val.byte, 0);
-}
-
-short &CrawlHashValue::get_short()
-{
- GET_VAL(HV_SHORT, short, val._short, 0);
-}
-
-long &CrawlHashValue::get_long()
-{
- GET_VAL(HV_LONG, long, val._long, 0);
-}
-
-float &CrawlHashValue::get_float()
-{
- GET_VAL(HV_FLOAT, float, val._float, 0.0);
-}
-
-std::string &CrawlHashValue::get_string()
-{
- GET_VAL_PTR(HV_STR, std::string*, new std::string(""));
-}
-
-coord_def &CrawlHashValue::get_coord()
-{
- GET_VAL_PTR(HV_COORD, coord_def*, new coord_def());
-}
-
-CrawlHashTable &CrawlHashValue::get_table()
-{
- GET_VAL_PTR(HV_HASH, CrawlHashTable*, new CrawlHashTable());
-}
-
-item_def &CrawlHashValue::get_item()
-{
- GET_VAL_PTR(HV_ITEM, item_def*, new item_def());
-}
-
-///////////////////////////
-// Const accessor functions
-#define GET_CONST_SETUP(x) \
- ASSERT(!(flags & HFLAG_UNSET)); \
- ASSERT(type == (x));
-
-bool CrawlHashValue::get_bool() const
-{
- GET_CONST_SETUP(HV_BOOL);
- return val.boolean;
-}
-
-char CrawlHashValue::get_byte() const
-{
- GET_CONST_SETUP(HV_BYTE);
- return val.byte;
-}
-
-short CrawlHashValue::get_short() const
-{
- GET_CONST_SETUP(HV_SHORT);
- return val._short;
-}
-
-long CrawlHashValue::get_long() const
-{
- GET_CONST_SETUP(HV_LONG);
- return val._long;
-}
-
-float CrawlHashValue::get_float() const
-{
- GET_CONST_SETUP(HV_FLOAT);
- return val._float;
-}
-
-std::string CrawlHashValue::get_string() const
-{
- GET_CONST_SETUP(HV_STR);
- return *((std::string*)val.ptr);
-}
-
-coord_def CrawlHashValue::get_coord() const
-{
- GET_CONST_SETUP(HV_COORD);
- return *((coord_def*)val.ptr);
-}
-
-const CrawlHashTable& CrawlHashValue::get_table() const
-{
- GET_CONST_SETUP(HV_HASH);
- return *((CrawlHashTable*)val.ptr);
-}
-
-const item_def& CrawlHashValue::get_item() const
-{
- GET_CONST_SETUP(HV_ITEM);
- return *((item_def*)val.ptr);
-}
-
-/////////////////////
-// Typecast operators
-&CrawlHashValue::operator bool()
-{
- return get_bool();
-}
-
-&CrawlHashValue::operator char()
-{
- return get_byte();
-}
-
-&CrawlHashValue::operator short()
-{
- return get_short();
-}
-
-&CrawlHashValue::operator float()
-{
- return get_float();
-}
-
-&CrawlHashValue::operator long()
-{
- return get_long();
-}
-
-&CrawlHashValue::operator std::string()
-{
- return get_string();
-}
-
-&CrawlHashValue::operator coord_def()
-{
- return get_coord();
-}
-
-&CrawlHashValue::operator CrawlHashTable()
-{
- return get_table();
-}
-
-&CrawlHashValue::operator item_def()
-{
- return get_item();
-}
-
-///////////////////////////
-// Const typecast operators
-CrawlHashValue::operator bool() const
-{
- return get_bool();
-}
-
-#define CONST_INT_CAST() \
- switch(type) \
- { \
- case HV_BYTE: \
- return get_byte(); \
- case HV_SHORT: \
- return get_short(); \
- case HV_LONG: \
- return get_long(); \
- default: \
- ASSERT(false); \
- return 0; \
- }
-
-CrawlHashValue::operator char() const
-{
- CONST_INT_CAST();
-}
-
-CrawlHashValue::operator short() const
-{
- CONST_INT_CAST();
-}
-
-CrawlHashValue::operator long() const
-{
- CONST_INT_CAST();
-}
-
-CrawlHashValue::operator float() const
-{
- return get_float();
-}
-
-CrawlHashValue::operator std::string() const
-{
- return get_string();
-}
-
-CrawlHashValue::operator coord_def() const
-{
- return get_coord();
-}
-
-///////////////////////
-// Assignment operators
-bool &CrawlHashValue::operator = (const bool &_val)
-{
- return (get_bool() = _val);
-}
-
-char &CrawlHashValue::operator = (const char &_val)
-{
- return (get_byte() = _val);
-}
-
-short &CrawlHashValue::operator = (const short &_val)
-{
- return (get_short() = _val);
-}
-
-long &CrawlHashValue::operator = (const long &_val)
-{
- return (get_long() = _val);
-}
-
-float &CrawlHashValue::operator = (const float &_val)
-{
- return (get_float() = _val);
-}
-
-std::string &CrawlHashValue::operator = (const std::string &_val)
-{
- return (get_string() = _val);
-}
-
-const char* CrawlHashValue::operator = (const char* _val)
-{
- get_string() = _val;
- return get_string().c_str();
-}
-
-coord_def &CrawlHashValue::operator = (const coord_def &_val)
-{
- return (get_coord() = _val);
-}
-
-CrawlHashTable &CrawlHashValue::operator = (const CrawlHashTable &_val)
-{
- return (get_table() = _val);
-}
-
-item_def &CrawlHashValue::operator = (const item_def &_val)
-{
- return (get_item() = _val);
-}
-
-///////////////////////////////////////////////////
-// Non-assignment operators which affect the lvalue
-#define INT_OPERATOR_UNARY(op) \
- switch(type) \
- { \
- case HV_BYTE: \
- { \
- char &temp = get_byte(); \
- temp op; \
- return temp; \
- } \
- \
- case HV_SHORT: \
- { \
- short &temp = get_short(); \
- temp op; \
- return temp; \
- } \
- case HV_LONG: \
- { \
- long &temp = get_long(); \
- temp op; \
- return temp; \
- } \
- \
- default: \
- ASSERT(false); \
- return 0; \
- }
-
-// Prefix
-long CrawlHashValue::operator ++ ()
-{
- INT_OPERATOR_UNARY(++);
-}
-
-long CrawlHashValue::operator -- ()
-{
- INT_OPERATOR_UNARY(--);
-}
-
-// Postfix
-long CrawlHashValue::operator ++ (int)
-{
- INT_OPERATOR_UNARY(++);
-}
-
-long CrawlHashValue::operator -- (int)
-{
- INT_OPERATOR_UNARY(--);
-}
-
-std::string &CrawlHashValue::operator += (const std::string &_val)
-{
- return (get_string() += _val);
-}
-
-////////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////////
-
-CrawlHashTable::CrawlHashTable()
- : type(HV_NONE), default_flags(0)
-{
-}
-
-CrawlHashTable::CrawlHashTable(unsigned char flags)
- : type(HV_NONE), default_flags(flags)
-{
- ASSERT(!(default_flags & HFLAG_UNSET));
-}
-
-CrawlHashTable::CrawlHashTable(hash_val_type _type, unsigned char flags)
- : type(_type), default_flags(flags)
-{
- ASSERT(type >= HV_NONE && type < NUM_HASH_VAL_TYPES);
- ASSERT(!(default_flags & HFLAG_UNSET));
-}
-
-CrawlHashTable::~CrawlHashTable()
-{
- assert_validity();
-}
-
-//////////////////////////////
-// Read/write from/to savefile
-void CrawlHashTable::write(tagHeader &th) const
-{
- assert_validity();
- if (empty())
- {
- marshallByte(th, 0);
- return;
- }
-
- marshallByte(th, size());
- marshallByte(th, static_cast<char>(type));
- marshallByte(th, (char) default_flags);
-
- CrawlHashTable::hash_map_type::const_iterator i = hash_map.begin();
-
- for (; i != hash_map.end(); i++)
- {
- marshallString(th, i->first);
- i->second.write(th);
- }
-
- assert_validity();
-}
-
-void CrawlHashTable::read(tagHeader &th)
-{
- assert_validity();
-
- ASSERT(empty());
- ASSERT(type == HV_NONE);
- ASSERT(default_flags == 0);
-
- unsigned char _size = (unsigned char) unmarshallByte(th);
-
- if (_size == 0)
- return;
-
- type = static_cast<hash_val_type>(unmarshallByte(th));
- default_flags = (unsigned char) unmarshallByte(th);
-
- for (unsigned char i = 0; i < _size; i++)
- {
- std::string key = unmarshallString(th);
- CrawlHashValue &val = (*this)[key];
-
- val.read(th);
- }
-
- assert_validity();
-}
-
-
-//////////////////
-// Misc functions
-
-unsigned char CrawlHashTable::get_default_flags() const
-{
- assert_validity();
- return default_flags;
-}
-
-unsigned char CrawlHashTable::set_default_flags(unsigned char flags)
-{
- assert_validity();
- ASSERT(!(flags & HFLAG_UNSET));
- default_flags |= flags;
-
- return default_flags;
-}
-
-unsigned char CrawlHashTable::unset_default_flags(unsigned char flags)
-{
- assert_validity();
- ASSERT(!(flags & HFLAG_UNSET));
- default_flags &= ~flags;
-
- return default_flags;
-}
-
-hash_val_type CrawlHashTable::get_type() const
-{
- assert_validity();
- return type;
-}
-
-bool CrawlHashTable::exists(const std::string key) const
-{
- assert_validity();
- hash_map_type::const_iterator i = hash_map.find(key);
-
- return (i != hash_map.end());
-}
-
-bool CrawlHashTable::exists(const long index) const
-{
- char buf[12];
- sprintf(buf, "%ld", index);
- return exists(buf);
-}
-
-void CrawlHashTable::assert_validity() const
-{
-#if DEBUG
- ASSERT(!(default_flags & HFLAG_UNSET));
-
- hash_map_type::const_iterator i = hash_map.begin();
-
- unsigned long actual_size = 0;
-
- for (; i != hash_map.end(); i++)
- {
- actual_size++;
-
- const std::string &key = i->first;
- const CrawlHashValue &val = i->second;
-
- ASSERT(key != "");
- std::string trimmed = trimmed_string(key);
- ASSERT(key == trimmed);
-
- ASSERT(val.type != HV_NONE);
- ASSERT(!(val.flags & HFLAG_UNSET));
-
- switch(val.type)
- {
- case HV_STR:
- case HV_COORD:
- case HV_ITEM:
- ASSERT(val.val.ptr != NULL);
- break;
-
- case HV_HASH:
- {
- ASSERT(val.val.ptr != NULL);
-
- CrawlHashTable* nested;
- nested = static_cast<CrawlHashTable*>(val.val.ptr);
-
- nested->assert_validity();
- break;
- }
-
- default:
- break;
- }
- }
-
- ASSERT(size() == actual_size);
-
- ASSERT(size() <= 255);
-#endif
-}
-
-int CrawlHashTable::compact_indicies(long min_index, long max_index,
- bool compact_down)
-{
- ASSERT(min_index <= max_index);
-
- if (min_index == max_index)
- return 0;
-
- long min_exists, max_exists;
-
- for (min_exists = min_index; min_exists <= max_index; min_exists++)
- if (exists(min_exists))
- break;
-
- if (min_exists > max_index)
- return 0;
-
- for (max_exists = max_index; max_exists >= min_exists; max_exists--)
- if (exists(max_exists))
- break;
-
- if (max_exists <= min_exists)
- return 0;
-
- bool hole_found = false;
- for (long i = min_exists; i < max_exists; i++)
- if (!exists(i))
- {
- hole_found = true;
- break;
- }
-
- if (!hole_found)
- return 0;
-
- long start, stop, dir;
- if (compact_down)
- {
- start = min_exists;
- stop = max_exists;
- dir = +1;
- }
- else
- {
- start = max_exists;
- stop = min_exists;
- dir = -1;
- }
- stop += dir;
-
- long move = 0;
- for (long i = start; i != stop; i += dir)
- {
- if (!exists(i))
- {
- move++;
- continue;
- }
-
- if (move == 0)
- continue;
-
- char buf1[12], buf2[12];
- sprintf(buf1, "%ld", i - (move * dir));
- sprintf(buf2, "%ld", i);
-
- CrawlHashValue &val = hash_map[buf2];
- hash_map[buf1] = val;
-
- // Ensure a new()'d object isn't freed, since the other
- // CrawlHashValue now owns it.
- val.type = HV_BOOL;
- erase(buf2);
- }
-
- return move;
-}
-
-bool CrawlHashTable::fixup_indexed_array(std::string name)
-{
- bool problems = false;
- long max_index = 0;
- std::vector<std::string> bad_keys;
- for (hash_map_type::iterator i = begin(); i != end(); i++)
- {
- int index = strtol(i->first.c_str(), NULL, 10);
-
- if (index < 0)
- {
- if (name != "")
- mprf("Negative index %ld found in %s.",
- index, name.c_str());
- problems = true;
- bad_keys.push_back(i->first);
- }
- else if (index == 0 && i->first != "0")
- {
- if (name != "")
- mprf("Non-numerical index '%s' found in %s.",
- i->first.c_str(), name.c_str());
- problems = true;
- bad_keys.push_back(i->first);
- }
- else if (index > max_index)
- max_index = index;
- }
- for (unsigned long i = 0, _size = bad_keys.size(); i < _size; i++)
- erase(bad_keys[i]);
- int holes = compact_indicies(0, max_index);
- if (holes > 0 && name != "")
- mprf("%d holes found in %s.", holes, name.c_str());
-
- return problems;
-}
-
-////////////
-// Accessors
-
-CrawlHashValue& CrawlHashTable::get_value(const std::string &key)
-{
- assert_validity();
- hash_map_type::iterator i = hash_map.find(key);
-
- if (i == hash_map.end())
- {
- hash_map[key] = CrawlHashValue(default_flags);
- CrawlHashValue &val = hash_map[key];
-
- if (type != HV_NONE)
- {
- val.type = type;
- val.flags |= HFLAG_CONST_TYPE;
- }
-
- return (val);
- }
-
- return (i->second);
-}
-
-CrawlHashValue& CrawlHashTable::get_value(const long &index)
-{
- char buf[12];
- sprintf(buf, "%ld", index);
- return get_value(buf);
-}
-
-const CrawlHashValue& CrawlHashTable::get_value(const std::string &key) const
-{
- assert_validity();
- hash_map_type::const_iterator i = hash_map.find(key);
-
- ASSERT(i != hash_map.end());
- ASSERT(i->second.type != HV_NONE);
- ASSERT(!(i->second.flags & HFLAG_UNSET));
-
- return (i->second);
-}
-
-const CrawlHashValue& CrawlHashTable::get_value(const long &index) const
-{
- char buf[12];
- sprintf(buf, "%ld", index);
- return get_value(buf);
-}
-
-CrawlHashValue& CrawlHashTable::operator[] (const std::string &key)
-{
- return get_value(key);
-}
-
-CrawlHashValue& CrawlHashTable::operator[] (const long &index)
-{
- return get_value(index);
-}
-
-const CrawlHashValue& CrawlHashTable::operator[] (const std::string &key) const
-{
- return get_value(key);
-}
-
-const CrawlHashValue& CrawlHashTable::operator[] (const long &index) const
-{
- return get_value(index);
-}
-
-///////////////////////////
-// std::map style interface
-size_t CrawlHashTable::size() const
-{
- return hash_map.size();
-}
-
-bool CrawlHashTable::empty() const
-{
- return hash_map.empty();
-}
-
-void CrawlHashTable::erase(const std::string key)
-{
- assert_validity();
- hash_map_type::iterator i = hash_map.find(key);
-
- if (i != hash_map.end())
- {
- CrawlHashValue &val = i->second;
-
- ASSERT(!(val.flags & HFLAG_NO_ERASE));
-
- hash_map.erase(i);
- }
-}
-
-void CrawlHashTable::erase(const long index)
-{
- char buf[12];
- sprintf(buf, "%ld", index);
- erase(buf);
-}
-
-void CrawlHashTable::clear()
-{
- assert_validity();
- ASSERT(!(default_flags & HFLAG_NO_ERASE));
-
- hash_map_type::iterator i = hash_map.begin();
- for (; i != hash_map.end(); i++)
- ASSERT(!(i->second.flags & HFLAG_NO_ERASE));
-
- hash_map.clear();
-}
-
-CrawlHashTable::hash_map_type::iterator CrawlHashTable::begin()
-{
- assert_validity();
- return hash_map.begin();
-}
-
-CrawlHashTable::hash_map_type::iterator CrawlHashTable::end()
-{
- assert_validity();
- return hash_map.end();
-}
-
-CrawlHashTable::hash_map_type::const_iterator CrawlHashTable::begin() const
-{
- assert_validity();
- return hash_map.begin();
-}
-
-CrawlHashTable::hash_map_type::const_iterator CrawlHashTable::end() const
-{
- assert_validity();
- return hash_map.end();
-}
-
-/////////////////////////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////////////////////////
-
-template <typename T, hash_val_type TYPE>
-CrawlTableWrapper<T, TYPE>::CrawlTableWrapper()
-{
- table = NULL;
-}
-
-template <typename T, hash_val_type TYPE>
-CrawlTableWrapper<T, TYPE>::CrawlTableWrapper(CrawlHashTable& _table)
-{
- wrap(_table);
-}
-
-template <typename T, hash_val_type TYPE>
-CrawlTableWrapper<T, TYPE>::CrawlTableWrapper(CrawlHashTable* _table)
-{
- wrap(_table);
-}
-
-template <typename T, hash_val_type TYPE>
-void CrawlTableWrapper<T, TYPE>::wrap(CrawlHashTable& _table)
-{
- wrap(&_table);
-}
-
-template <typename T, hash_val_type TYPE>
-void CrawlTableWrapper<T, TYPE>::wrap(CrawlHashTable* _table)
-{
- ASSERT(_table != NULL);
- ASSERT(_table->get_type() == TYPE);
-
- table = _table;
-}
-
-template <typename T, hash_val_type TYPE>
-T& CrawlTableWrapper<T, TYPE>::operator[] (const std::string &key)
-{
- return (T&) (*table)[key];
-}
-
-template <typename T, hash_val_type TYPE>
-T& CrawlTableWrapper<T, TYPE>::operator[] (const long &index)
-{
- return (T&) (*table)[index];
-}
-
-template <typename T, hash_val_type TYPE>
-const T CrawlTableWrapper<T, TYPE>::operator[] (const std::string &key) const
-{
- return (T) (*table)[key];
-}
-
-template <typename T, hash_val_type TYPE>
-const T CrawlTableWrapper<T, TYPE>::operator[] (const long &index) const
-{
- return (T) (*table)[index];
-}
diff --git a/crawl-ref/source/hash.h b/crawl-ref/source/hash.h
deleted file mode 100644
index 7c658c1667..0000000000
--- a/crawl-ref/source/hash.h
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
- * File: hash.h
- * Summary: Saveable hash-table capable of storing multiple types
- * of data.
- * Written by: Matthew Cline
- *
- * Modified for Crawl Reference by $Author$ on $Date$
- *
- * Change History (most recent first):
- *
- * <1> 10/5/07 MPC Created
- */
-
-#ifndef HASH_H
-#define HASH_H
-
-#include <string>
-#include <map>
-
-struct tagHeader;
-class CrawlHashTable;
-class item_def;
-class coord_def;
-
-// NOTE: Changing the ordering of these enums will break savefile
-// compatibility.
-enum hash_val_type
-{
- HV_NONE = 0,
- HV_BOOL,
- HV_BYTE,
- HV_SHORT,
- HV_LONG,
- HV_FLOAT,
- HV_STR,
- HV_COORD,
- HV_HASH,
- HV_ITEM,
- NUM_HASH_VAL_TYPES
-};
-
-enum hash_flag_type
-{
- HFLAG_UNSET = (1 << 0),
- HFLAG_CONST_VAL = (1 << 1),
- HFLAG_CONST_TYPE = (1 << 2),
- HFLAG_NO_ERASE = (1 << 3)
-};
-
-
-// Can't just cast everything into a void pointer, since a float might
-// not fit into a pointer on all systems.
-typedef union HashUnion HashUnion;
-union HashUnion
-{
- bool boolean;
- char byte;
- short _short;
- long _long;
- float _float;
- void* ptr;
-};
-
-
-class CrawlHashValue
-{
-public:
- CrawlHashValue();
- CrawlHashValue(const CrawlHashValue &other);
-
- ~CrawlHashValue();
-
- // Only needed for doing some assertion checking.
- CrawlHashValue &operator = (const CrawlHashValue &other);
-
-protected:
- hash_val_type type;
- unsigned char flags;
- HashUnion val;
-
-public:
- unsigned char get_flags() const;
- unsigned char set_flags(unsigned char flags);
- unsigned char unset_flags(unsigned char flags);
- hash_val_type get_type() const;
-
- CrawlHashTable &new_table(unsigned char flags);
- CrawlHashTable &new_table(hash_val_type type, unsigned char flags = 0);
-
- bool &get_bool();
- char &get_byte();
- short &get_short();
- long &get_long();
- float &get_float();
- std::string &get_string();
- coord_def &get_coord();
- CrawlHashTable &get_table();
- item_def &get_item();
-
- bool get_bool() const;
- char get_byte() const;
- short get_short() const;
- long get_long() const;
- float get_float() const;
- std::string get_string() const;
- coord_def get_coord() const;
-
- const CrawlHashTable& get_table() const;
- const item_def& get_item() const;
-
- void set_bool(const bool val);
- void set_byte(const char val);
- void set_short(const short val);
- void set_long(const long val);
- void set_float(const float val);
- void set_string(const std::string &val);
- void set_coord(const coord_def &val);
- void set_table(const CrawlHashTable &val);
- void set_item(const item_def &val);
-
-public:
- // NOTE: All operators will assert if the hash value is of the
- // wrong type for the operation. If the value has no type yet,
- // the operation will set it to the appropriate type. If the
- // value has no type yet and the operation modifies the existing
- // value rather than replacing it (i.e., ++) the value will be set
- // to a default before the operation is done.
-
- // If the hash value is a hash table, the table's values can be
- // accessed with the [] operator.
- CrawlHashValue &operator [] (const std::string &key);
- CrawlHashValue &operator [] (const long &key);
-
- const CrawlHashValue &operator [] (const std::string &key) const;
- const CrawlHashValue &operator [] (const long &key) const;
-
- // Typecast operators
- &operator bool();
- &operator char();
- &operator short();
- &operator long();
- &operator float();
- &operator std::string();
- &operator coord_def();
- &operator CrawlHashTable();
- &operator item_def();
-
- operator bool() const;
- operator char() const;
- operator short() const;
- operator long() const;
- operator float() const;
- operator std::string() const;
- operator coord_def() const;
-
- // Assignment operators
- bool &operator = (const bool &val);
- char &operator = (const char &val);
- short &operator = (const short &val);
- long &operator = (const long &val);
- float &operator = (const float &val);
- std::string &operator = (const std::string &val);
- const char* operator = (const char* val);
- coord_def &operator = (const coord_def &val);
- CrawlHashTable &operator = (const CrawlHashTable &val);
- item_def &operator = (const item_def &val);
-
- // Misc operators
- std::string &operator += (const std::string &val);
-
- // Prefix
- long operator ++ ();
- long operator -- ();
-
- // Postfix
- long operator ++ (int);
- long operator -- (int);
-
-protected:
- CrawlHashValue(const unsigned char flags,
- const hash_val_type type = HV_NONE);
-
- void write(tagHeader &th) const;
- void read(tagHeader &th);
-
- void unset(bool force = false);
-
- friend class CrawlHashTable;
-};
-
-
-// A hash table can have a maximum of 255 key/value pairs. If you
-// want more than that you can use nested hash tables.
-//
-// By default a hash table's value data types are heterogeneous. To
-// make it homogeneous (which causes dynamic type checking) you have
-// to give a type to the hash table constructor; once it's been
-// created it's type (or lack of type) is immutable.
-//
-// An empty hash table will take up only 1 byte in the savefile. A
-// non-empty hash table will have an overhead of 3 bytes for the hash
-// table overall and 2 bytes per key/value pair, over and above the
-// number of bytes needed to store the keys and values themselves.
-class CrawlHashTable
-{
-public:
- CrawlHashTable();
- CrawlHashTable(unsigned char flags);
- CrawlHashTable(hash_val_type type, unsigned char flags = 0);
-
- ~CrawlHashTable();
-
- typedef std::map<std::string, CrawlHashValue> hash_map_type;
-
-protected:
- hash_val_type type;
- unsigned char default_flags;
- hash_map_type hash_map;
-
- friend class CrawlHashValue;
-
-public:
- void write(tagHeader &th) const;
- void read(tagHeader &th);
-
- unsigned char get_default_flags() const;
- unsigned char set_default_flags(unsigned char flags);
- unsigned char unset_default_flags(unsigned char flags);
- hash_val_type get_type() const;
- bool exists(const std::string key) const;
- bool exists(const long key) const;
- void assert_validity() const;
- int compact_indicies(long min_index, long max_index,
- bool compact_down = true);
- bool fixup_indexed_array(std::string name = "");
-
- // NOTE: If get_value() or [] is given a key which doesn't exist
- // in the table, an unset/empty CrawlHashValue will be created
- // with that key and returned. If it is not then given a value
- // then the next call to assert_validity() will fail. If the
- // hash table has a type (rather than being heterogeneous)
- // then trying to assign a different type to the CrawlHashValue
- // will assert.
- CrawlHashValue& get_value(const std::string &key);
- CrawlHashValue& get_value(const long &index);
- CrawlHashValue& operator[] (const std::string &key);
- CrawlHashValue& operator[] (const long &index);
-
- // NOTE: If the const versions of get_value() or [] are given a
- // key which doesn't exist, they will assert.
- const CrawlHashValue& get_value(const std::string &key) const;
- const CrawlHashValue& get_value(const long &index) const;
- const CrawlHashValue& operator[] (const std::string &key) const;
- const CrawlHashValue& operator[] (const long &index) const;
-
- // std::map style interface
- size_t size() const;
- bool empty() const;
-
- void erase(const std::string key);
- void erase(const long index);
- void clear();
-
- hash_map_type::iterator begin();
- hash_map_type::iterator end();
-
- hash_map_type::const_iterator begin() const;
- hash_map_type::const_iterator end() const;
-};
-
-
-// A wrapper for non-heterogeneous hash tables, so that the values can
-// be accessed without using get_foo(). T needs to have both normal
-// and const type-cast operators defined by CrawlHashValue for this
-// template to work.
-template <typename T, hash_val_type TYPE>
-class CrawlTableWrapper
-{
-public:
- CrawlTableWrapper();
- CrawlTableWrapper(CrawlHashTable& table);
- CrawlTableWrapper(CrawlHashTable* table);
-
-protected:
- CrawlHashTable* table;
-
-public:
- void wrap(CrawlHashTable& table);
- void wrap(CrawlHashTable* table);
-
- CrawlHashTable* get_table();
- T& operator[] (const std::string &key);
- T& operator[] (const long &index);
-
- const CrawlHashTable* get_table() const;
- const T operator[] (const std::string &key) const;
- const T operator[] (const long &index) const;
-};
-
-typedef CrawlTableWrapper<bool, HV_BOOL> CrawlBoolTable;
-typedef CrawlTableWrapper<char, HV_BYTE> CrawlByteTable;
-typedef CrawlTableWrapper<short, HV_SHORT> CrawlShortTable;
-typedef CrawlTableWrapper<long, HV_LONG> CrawlLongTable;
-typedef CrawlTableWrapper<float, HV_FLOAT> CrawlFloatTable;
-typedef CrawlTableWrapper<std::string, HV_STR> CrawlStringTable;
-typedef CrawlTableWrapper<coord_def, HV_COORD> CrawlCoordTable;
-
-#endif
diff --git a/crawl-ref/source/items.cc b/crawl-ref/source/items.cc
index 35e84a18d9..c50d7e5efc 100644
--- a/crawl-ref/source/items.cc
+++ b/crawl-ref/source/items.cc
@@ -264,6 +264,7 @@ bool dec_inv_item_quantity( int obj, int amount )
you.inv[obj].base_type = OBJ_UNASSIGNED;
you.inv[obj].quantity = 0;
+ you.inv[obj].props.clear();
ret = true;
@@ -462,6 +463,7 @@ void unlink_item( int dest )
mitm[dest].x = 0;
mitm[dest].y = 0;
mitm[dest].link = NON_ITEM;
+ mitm[dest].props.clear();
// Look through all items for links to this item.
for (c = 0; c < MAX_ITEMS; c++)
@@ -579,6 +581,7 @@ void lose_item_stack( int x, int y )
mitm[o].base_type = OBJ_UNASSIGNED;
mitm[o].quantity = 0;
+ mitm[o].props.clear();
}
o = next;
@@ -601,6 +604,7 @@ void destroy_item_stack( int x, int y, int cause )
mitm[o].base_type = OBJ_UNASSIGNED;
mitm[o].quantity = 0;
+ mitm[o].props.clear();
}
o = next;
diff --git a/crawl-ref/source/makefile.obj b/crawl-ref/source/makefile.obj
index f871fa43f6..170eb8b367 100644
--- a/crawl-ref/source/makefile.obj
+++ b/crawl-ref/source/makefile.obj
@@ -12,8 +12,8 @@ cloud.o \
command.o \
database.o \
debug.o \
-delay.o \
decks.o \
+delay.o \
describe.o \
dgnevent.o \
direct.o \
@@ -24,7 +24,6 @@ files.o \
food.o \
format.o \
ghost.o \
-hash.o \
hiscores.o \
initfile.o \
insult.o \
@@ -76,6 +75,7 @@ spl-util.o \
sqldbm.o \
state.o \
stash.o \
+store.o \
stuff.o \
tags.o \
terrain.o \
diff --git a/crawl-ref/source/store.cc b/crawl-ref/source/store.cc
new file mode 100644
index 0000000000..912369b27a
--- /dev/null
+++ b/crawl-ref/source/store.cc
@@ -0,0 +1,1615 @@
+/*
+ * File: store.cc
+ * Summary: Saveable hash-table and vector capable of storing
+ * multiple types of data.
+ * Written by: Matthew Cline
+ *
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
+ * Change History (most recent first):
+
+ * <1> 10/5/07 MPC Created
+ */
+
+#include "AppHdr.h"
+#include "store.h"
+
+#include "externs.h"
+#include "tags.h"
+
+CrawlStoreValue::CrawlStoreValue()
+ : type(SV_NONE), flags(SFLAG_UNSET)
+{
+ val.ptr = NULL;
+}
+
+CrawlStoreValue::CrawlStoreValue(const CrawlStoreValue &other)
+{
+ ASSERT(other.type >= SV_NONE && other.type < NUM_STORE_VAL_TYPES);
+
+ type = other.type;
+ flags = other.flags;
+
+ if (flags & SFLAG_UNSET)
+ {
+ val = other.val;
+ return;
+ }
+
+ switch (type)
+ {
+ case SV_NONE:
+ case SV_BOOL:
+ case SV_BYTE:
+ case SV_SHORT:
+ case SV_LONG:
+ case SV_FLOAT:
+ val = other.val;
+ break;
+
+ case SV_STR:
+ {
+ std::string* str;
+ str = new std::string(*static_cast<std::string*>(other.val.ptr));
+ val.ptr = static_cast<void*>(str);
+ break;
+ }
+
+ case SV_COORD:
+ {
+ coord_def* coord;
+ coord = new coord_def(*static_cast<coord_def*>(other.val.ptr));
+ val.ptr = static_cast<void*>(coord);
+ break;
+ }
+
+ case SV_ITEM:
+ {
+ item_def* item;
+ item = new item_def(*static_cast<item_def*>(other.val.ptr));
+ val.ptr = static_cast<void*>(item);
+ break;
+ }
+
+ case SV_HASH:
+ {
+ CrawlHashTable* hash;
+ CrawlHashTable* tmp = static_cast<CrawlHashTable*>(other.val.ptr);
+ hash = new CrawlHashTable(*tmp);
+ val.ptr = static_cast<void*>(hash);
+ break;
+ }
+
+ case SV_VEC:
+ {
+ CrawlVector* vec;
+ CrawlVector* tmp = static_cast<CrawlVector*>(other.val.ptr);
+ vec = new CrawlVector(*tmp);
+ val.ptr = static_cast<void*>(vec);
+ break;
+ }
+
+ case NUM_STORE_VAL_TYPES:
+ ASSERT(false);
+ }
+}
+
+CrawlStoreValue::CrawlStoreValue(const store_flags _flags,
+ const store_val_type _type)
+ : type(_type), flags(_flags)
+{
+ ASSERT(type >= SV_NONE && type < NUM_STORE_VAL_TYPES);
+ ASSERT(!(flags & SFLAG_UNSET));
+
+ flags |= SFLAG_UNSET;
+ val.ptr = NULL;
+}
+
+// Conversion constructors
+CrawlStoreValue::CrawlStoreValue(const bool _val)
+ : type(SV_BOOL), flags(0)
+{
+ get_bool() = _val;
+}
+
+CrawlStoreValue::CrawlStoreValue(const char &_val)
+ : type(SV_BYTE), flags(0)
+{
+ get_byte() = _val;
+}
+
+CrawlStoreValue::CrawlStoreValue(const short &_val)
+ : type(SV_SHORT), flags(0)
+{
+ get_short() = _val;
+}
+
+CrawlStoreValue::CrawlStoreValue(const long &_val)
+ : type(SV_LONG), flags(0)
+{
+ get_long() = _val;
+}
+
+CrawlStoreValue::CrawlStoreValue(const float &_val)
+ : type(SV_FLOAT), flags(0)
+{
+ get_float() = _val;
+}
+
+CrawlStoreValue::CrawlStoreValue(const std::string &_val)
+ : type(SV_STR), flags(0)
+{
+ get_string() = _val;
+}
+
+CrawlStoreValue::CrawlStoreValue(const char* _val)
+ : type(SV_STR), flags(0)
+{
+ get_string() = _val;
+}
+
+CrawlStoreValue::CrawlStoreValue(const coord_def &_val)
+ : type(SV_COORD), flags(0)
+{
+ get_coord() = _val;
+}
+
+CrawlStoreValue::CrawlStoreValue(const item_def &_val)
+ : type(SV_ITEM), flags(0)
+{
+ get_item() = _val;
+}
+
+CrawlStoreValue::CrawlStoreValue(const CrawlHashTable &_val)
+ : type(SV_HASH), flags(0)
+{
+ get_table() = _val;
+}
+
+CrawlStoreValue::CrawlStoreValue(const CrawlVector &_val)
+ : type(SV_VEC), flags(0)
+{
+ get_vector() = _val;
+}
+
+CrawlStoreValue::~CrawlStoreValue()
+{
+ unset(true);
+}
+
+void CrawlStoreValue::unset(bool force)
+{
+ if (flags & SFLAG_UNSET)
+ return;
+
+ if (force)
+ flags &= ~SFLAG_NO_ERASE;
+
+ ASSERT(!(flags & SFLAG_NO_ERASE));
+
+ switch (type)
+ {
+ case SV_BOOL:
+ val.boolean = false;
+ break;
+
+ case SV_BYTE:
+ val.byte = 0;
+ break;
+
+ case SV_SHORT:
+ val._short = 0;
+ break;
+
+ case SV_LONG:
+ val._long = 0;
+ break;
+
+ case SV_FLOAT:
+ val._float = 0.0;
+ break;
+
+ case SV_STR:
+ {
+ std::string* str = static_cast<std::string*>(val.ptr);
+ delete str;
+ val.ptr = NULL;
+ break;
+ }
+
+ case SV_COORD:
+ {
+ coord_def* coord = static_cast<coord_def*>(val.ptr);
+ delete coord;
+ val.ptr = NULL;
+ break;
+ }
+
+ case SV_ITEM:
+ {
+ item_def* item = static_cast<item_def*>(val.ptr);
+ delete item;
+ val.ptr = NULL;
+ break;
+ }
+
+ case SV_HASH:
+ {
+ CrawlHashTable* hash = static_cast<CrawlHashTable*>(val.ptr);
+ delete hash;
+ val.ptr = NULL;
+ break;
+ }
+
+ case SV_VEC:
+ {
+ CrawlVector* vec = static_cast<CrawlVector*>(val.ptr);
+ delete vec;
+ val.ptr = NULL;
+ break;
+ }
+
+ case SV_NONE:
+ ASSERT(false);
+
+ case NUM_STORE_VAL_TYPES:
+ ASSERT(false);
+ }
+
+ flags |= SFLAG_UNSET;
+}
+
+// Only needed to do some assertion checking.
+CrawlStoreValue &CrawlStoreValue::operator = (const CrawlStoreValue &other)
+{
+ ASSERT(other.type >= SV_NONE && other.type < NUM_STORE_VAL_TYPES);
+ ASSERT(other.type != SV_NONE || type == SV_NONE);
+
+ // NOTE: We don't bother checking SFLAG_CONST_VAL, since the
+ // asignment operator is used when swapping two elements.
+
+ if (!(flags & SFLAG_UNSET))
+ {
+ if (flags & SFLAG_CONST_TYPE)
+ ASSERT(type == SV_NONE || type == other.type);
+ }
+
+ type = other.type;
+ flags = other.flags;
+ val = other.val;
+
+ return (*this);
+}
+
+///////////////////////////////////
+// Meta-data accessors and changers
+store_flags CrawlStoreValue::get_flags() const
+{
+ return flags;
+}
+
+store_flags CrawlStoreValue::set_flags(store_flags _flags)
+{
+ flags |= _flags;
+ return flags;
+}
+
+store_flags CrawlStoreValue::unset_flags(store_flags _flags)
+{
+ flags &= ~_flags;
+ return flags;
+}
+
+store_val_type CrawlStoreValue::get_type() const
+{
+ return type;
+}
+
+//////////////////////////////
+// Read/write from/to savefile
+void CrawlStoreValue::write(tagHeader &th) const
+{
+ ASSERT(!(flags & SFLAG_UNSET));
+
+ marshallByte(th, (char) type);
+ marshallByte(th, (char) flags);
+
+ switch (type)
+ {
+ case SV_BOOL:
+ marshallBoolean(th, val.boolean);
+ break;
+
+ case SV_BYTE:
+ marshallByte(th, val.byte);
+ break;
+
+ case SV_SHORT:
+ marshallShort(th, val._short);
+ break;
+
+ case SV_LONG:
+ marshallLong(th, val._long);
+ break;
+
+ case SV_FLOAT:
+ marshallFloat(th, val._float);
+ break;
+
+ case SV_STR:
+ {
+ std::string* str = static_cast<std::string*>(val.ptr);
+ marshallString(th, *str);
+ break;
+ }
+
+ case SV_COORD:
+ {
+ coord_def* coord = static_cast<coord_def*>(val.ptr);
+ marshallCoord(th, *coord);
+ break;
+ }
+
+ case SV_ITEM:
+ {
+ item_def* item = static_cast<item_def*>(val.ptr);
+ marshallItem(th, *item);
+ break;
+ }
+
+ case SV_HASH:
+ {
+ CrawlHashTable* hash = static_cast<CrawlHashTable*>(val.ptr);
+ hash->write(th);
+ break;
+ }
+
+ case SV_VEC:
+ {
+ CrawlVector* vec = static_cast<CrawlVector*>(val.ptr);
+ vec->write(th);
+ break;
+ }
+
+ case SV_NONE:
+ ASSERT(false);
+
+ case NUM_STORE_VAL_TYPES:
+ ASSERT(false);
+ }
+}
+
+void CrawlStoreValue::read(tagHeader &th)
+{
+ type = static_cast<store_val_type>(unmarshallByte(th));
+ flags = (store_flags) unmarshallByte(th);
+
+ ASSERT(!(flags & SFLAG_UNSET));
+
+ switch (type)
+ {
+ case SV_BOOL:
+ val.boolean = unmarshallBoolean(th);
+ break;
+
+ case SV_BYTE:
+ val.byte = unmarshallByte(th);
+ break;
+
+ case SV_SHORT:
+ val._short = unmarshallShort(th);
+ break;
+
+ case SV_LONG:
+ val._long = unmarshallLong(th);
+ break;
+
+ case SV_FLOAT:
+ val._float = unmarshallFloat(th);
+ break;
+
+ case SV_STR:
+ {
+ std::string str = unmarshallString(th);
+ val.ptr = (void*) new std::string(str);
+ break;
+ }
+
+ case SV_COORD:
+ {
+ coord_def coord;
+ unmarshallCoord(th, coord);
+ val.ptr = (void*) new coord_def(coord);
+
+ break;
+ }
+
+ case SV_ITEM:
+ {
+ item_def item;
+ unmarshallItem(th, item);
+ val.ptr = (void*) new item_def(item);
+
+ break;
+ }
+
+ case SV_HASH:
+ {
+ CrawlHashTable* hash = new CrawlHashTable();
+ hash->read(th);
+ val.ptr = (void*) hash;
+
+ break;
+ }
+
+ case SV_VEC:
+ {
+ CrawlVector* vec = new CrawlVector();
+ vec->read(th);
+ val.ptr = (void*) vec;
+
+ break;
+ }
+
+ case SV_NONE:
+ ASSERT(false);
+
+ case NUM_STORE_VAL_TYPES:
+ ASSERT(false);
+ }
+}
+
+////////////////////////////////////////////////////////////////
+// Setup a new table with the given flags and/or type; assert if
+// a table already exists.
+CrawlHashTable &CrawlStoreValue::new_table(store_flags _flags)
+{
+ return new_table(SV_NONE, flags);
+}
+
+CrawlHashTable &CrawlStoreValue::new_table(store_val_type _type,
+ store_flags _flags)
+{
+ CrawlHashTable* old_table = static_cast<CrawlHashTable*>(val.ptr);
+
+ ASSERT(flags & SFLAG_UNSET);
+ ASSERT(type == SV_NONE
+ || (type == SV_HASH
+ && old_table->size() == 0
+ && old_table->get_type() == SV_NONE
+ && old_table->get_default_flags() == 0));
+
+ CrawlHashTable &table = get_table();
+
+ table.default_flags = _flags;
+ table.type = _type;
+
+ type = SV_HASH;
+ flags &= ~SFLAG_UNSET;
+
+ return table;
+}
+
+////////////////////////////////////////////////////////////////
+// Setup a new vector with the given flags and/or type; assert if
+// a vector already exists.
+CrawlVector &CrawlStoreValue::new_vector(store_flags _flags,
+ vec_size max_size)
+{
+ return new_vector(SV_NONE, flags, max_size);
+}
+
+CrawlVector &CrawlStoreValue::new_vector(store_val_type _type,
+ store_flags _flags,
+ vec_size _max_size)
+{
+ CrawlVector* old_vector = static_cast<CrawlVector*>(val.ptr);
+
+ ASSERT(flags & SFLAG_UNSET);
+ ASSERT(type == SV_NONE
+ || (type == SV_VEC
+ && old_vector->size() == 0
+ && old_vector->get_type() == SV_NONE
+ && old_vector->get_default_flags() == 0
+ && old_vector->get_max_size() == VEC_MAX_SIZE));
+
+ CrawlVector &vector = get_vector();
+
+ vector.default_flags = _flags;
+ vector.type = _type;
+
+ type = SV_VEC;
+ flags &= ~SFLAG_UNSET;
+
+ return vector;
+}
+
+///////////////////////////////////////////
+// Dynamic type-checking accessor functions
+#define GET_VAL(x, _type, field, value) \
+ ASSERT((flags & SFLAG_UNSET) || !(flags & SFLAG_CONST_VAL)); \
+ if (type != (x)) \
+ { \
+ if (type == SV_NONE) \
+ { \
+ type = (x); \
+ field = (value); \
+ } \
+ else \
+ { \
+ ASSERT(!(flags & SFLAG_CONST_TYPE)); \
+ switch(type) \
+ { \
+ case SV_BOOL: \
+ field = (_type) val.boolean; \
+ break; \
+ case SV_BYTE: \
+ field = (_type) val.byte; \
+ break; \
+ case SV_SHORT: \
+ field = (_type) val._short; \
+ break; \
+ case SV_LONG: \
+ field = (_type) val._long; \
+ break; \
+ case SV_FLOAT: \
+ field = (_type) val._float; \
+ break; \
+ default: \
+ ASSERT(false); \
+ } \
+ type = (x); \
+ } \
+ } \
+ flags &= ~SFLAG_UNSET; \
+ return field;
+
+#define GET_VAL_PTR(x, _type, value) \
+ ASSERT((flags & SFLAG_UNSET) || !(flags & SFLAG_CONST_VAL)); \
+ if (type != (x)) \
+ { \
+ if (type == SV_NONE) \
+ { \
+ type = (x); \
+ val.ptr = (value); \
+ } \
+ else \
+ { \
+ unset(); \
+ val.ptr = (value); \
+ type = (x); \
+ } \
+ } \
+ flags &= ~SFLAG_UNSET; \
+ return *((_type) val.ptr);
+
+bool &CrawlStoreValue::get_bool()
+{
+ GET_VAL(SV_BOOL, bool, val.boolean, false);
+}
+
+char &CrawlStoreValue::get_byte()
+{
+ GET_VAL(SV_BYTE, char, val.byte, 0);
+}
+
+short &CrawlStoreValue::get_short()
+{
+ GET_VAL(SV_SHORT, short, val._short, 0);
+}
+
+long &CrawlStoreValue::get_long()
+{
+ GET_VAL(SV_LONG, long, val._long, 0);
+}
+
+float &CrawlStoreValue::get_float()
+{
+ GET_VAL(SV_FLOAT, float, val._float, 0.0);
+}
+
+std::string &CrawlStoreValue::get_string()
+{
+ GET_VAL_PTR(SV_STR, std::string*, new std::string(""));
+}
+
+coord_def &CrawlStoreValue::get_coord()
+{
+ GET_VAL_PTR(SV_COORD, coord_def*, new coord_def());
+}
+
+item_def &CrawlStoreValue::get_item()
+{
+ GET_VAL_PTR(SV_ITEM, item_def*, new item_def());
+}
+
+CrawlHashTable &CrawlStoreValue::get_table()
+{
+ GET_VAL_PTR(SV_HASH, CrawlHashTable*, new CrawlHashTable());
+}
+
+CrawlVector &CrawlStoreValue::get_vector()
+{
+ GET_VAL_PTR(SV_VEC, CrawlVector*, new CrawlVector());
+}
+
+CrawlStoreValue &CrawlStoreValue::operator [] (const std::string &key)
+{
+ return get_table()[key];
+}
+
+CrawlStoreValue &CrawlStoreValue::operator [] (const vec_size &index)
+{
+ return get_vector()[index];
+}
+
+///////////////////////////
+// Const accessor functions
+#define GET_CONST_SETUP(x) \
+ ASSERT(!(flags & SFLAG_UNSET)); \
+ ASSERT(type == (x));
+
+bool CrawlStoreValue::get_bool() const
+{
+ GET_CONST_SETUP(SV_BOOL);
+ return val.boolean;
+}
+
+char CrawlStoreValue::get_byte() const
+{
+ GET_CONST_SETUP(SV_BYTE);
+ return val.byte;
+}
+
+short CrawlStoreValue::get_short() const
+{
+ GET_CONST_SETUP(SV_SHORT);
+ return val._short;
+}
+
+long CrawlStoreValue::get_long() const
+{
+ GET_CONST_SETUP(SV_LONG);
+ return val._long;
+}
+
+float CrawlStoreValue::get_float() const
+{
+ GET_CONST_SETUP(SV_FLOAT);
+ return val._float;
+}
+
+std::string CrawlStoreValue::get_string() const
+{
+ GET_CONST_SETUP(SV_STR);
+ return *((std::string*)val.ptr);
+}
+
+coord_def CrawlStoreValue::get_coord() const
+{
+ GET_CONST_SETUP(SV_COORD);
+ return *((coord_def*)val.ptr);
+}
+
+const item_def& CrawlStoreValue::get_item() const
+{
+ GET_CONST_SETUP(SV_ITEM);
+ return *((item_def*)val.ptr);
+}
+
+const CrawlHashTable& CrawlStoreValue::get_table() const
+{
+ GET_CONST_SETUP(SV_HASH);
+ return *((CrawlHashTable*)val.ptr);
+}
+
+const CrawlVector& CrawlStoreValue::get_vector() const
+{
+ GET_CONST_SETUP(SV_VEC);
+ return *((CrawlVector*)val.ptr);
+}
+
+const CrawlStoreValue &CrawlStoreValue::operator
+ [] (const std::string &key) const
+{
+ return get_table()[key];
+}
+
+const CrawlStoreValue &CrawlStoreValue::operator
+ [](const vec_size &index) const
+{
+ return get_vector()[index];
+}
+
+/////////////////////
+// Typecast operators
+&CrawlStoreValue::operator bool()
+{
+ return get_bool();
+}
+
+&CrawlStoreValue::operator char()
+{
+ return get_byte();
+}
+
+&CrawlStoreValue::operator short()
+{
+ return get_short();
+}
+
+&CrawlStoreValue::operator float()
+{
+ return get_float();
+}
+
+&CrawlStoreValue::operator long()
+{
+ return get_long();
+}
+
+&CrawlStoreValue::operator std::string()
+{
+ return get_string();
+}
+
+&CrawlStoreValue::operator coord_def()
+{
+ return get_coord();
+}
+
+&CrawlStoreValue::operator CrawlHashTable()
+{
+ return get_table();
+}
+
+&CrawlStoreValue::operator CrawlVector()
+{
+ return get_vector();
+}
+
+&CrawlStoreValue::operator item_def()
+{
+ return get_item();
+}
+
+///////////////////////////
+// Const typecast operators
+CrawlStoreValue::operator bool() const
+{
+ return get_bool();
+}
+
+#define CONST_INT_CAST() \
+ switch(type) \
+ { \
+ case SV_BYTE: \
+ return get_byte(); \
+ case SV_SHORT: \
+ return get_short(); \
+ case SV_LONG: \
+ return get_long(); \
+ default: \
+ ASSERT(false); \
+ return 0; \
+ }
+
+CrawlStoreValue::operator char() const
+{
+ CONST_INT_CAST();
+}
+
+CrawlStoreValue::operator short() const
+{
+ CONST_INT_CAST();
+}
+
+CrawlStoreValue::operator long() const
+{
+ CONST_INT_CAST();
+}
+
+CrawlStoreValue::operator float() const
+{
+ return get_float();
+}
+
+CrawlStoreValue::operator std::string() const
+{
+ return get_string();
+}
+
+CrawlStoreValue::operator coord_def() const
+{
+ return get_coord();
+}
+
+///////////////////////
+// Assignment operators
+CrawlStoreValue &CrawlStoreValue::operator = (const bool &_val)
+{
+ get_bool() = _val;
+ return (*this);
+}
+
+CrawlStoreValue &CrawlStoreValue::operator = (const char &_val)
+{
+ get_byte() = _val;
+ return (*this);
+}
+
+CrawlStoreValue &CrawlStoreValue::operator = (const short &_val)
+{
+ get_short() = _val;
+ return (*this);
+}
+
+CrawlStoreValue &CrawlStoreValue::operator = (const long &_val)
+{
+ get_long() = _val;
+ return (*this);
+}
+
+CrawlStoreValue &CrawlStoreValue::operator = (const float &_val)
+{
+ get_float() = _val;
+ return (*this);
+}
+
+CrawlStoreValue &CrawlStoreValue::operator = (const std::string &_val)
+{
+ get_string() = _val;
+ return (*this);
+}
+
+CrawlStoreValue &CrawlStoreValue::operator = (const char* _val)
+{
+ get_string() = _val;
+ return (*this);
+}
+
+CrawlStoreValue &CrawlStoreValue::operator = (const coord_def &_val)
+{
+ get_coord() = _val;
+ return (*this);
+}
+
+CrawlStoreValue &CrawlStoreValue::operator = (const CrawlHashTable &_val)
+{
+ get_table() = _val;
+ return (*this);
+}
+
+CrawlStoreValue &CrawlStoreValue::operator = (const CrawlVector &_val)
+{
+ get_vector() = _val;
+ return (*this);
+}
+
+CrawlStoreValue &CrawlStoreValue::operator = (const item_def &_val)
+{
+ get_item() = _val;
+ return (*this);
+}
+
+///////////////////////////////////////////////////
+// Non-assignment operators which affect the lvalue
+#define INT_OPERATOR_UNARY(op) \
+ switch(type) \
+ { \
+ case SV_BYTE: \
+ { \
+ char &temp = get_byte(); \
+ temp op; \
+ return temp; \
+ } \
+ \
+ case SV_SHORT: \
+ { \
+ short &temp = get_short(); \
+ temp op; \
+ return temp; \
+ } \
+ case SV_LONG: \
+ { \
+ long &temp = get_long(); \
+ temp op; \
+ return temp; \
+ } \
+ \
+ default: \
+ ASSERT(false); \
+ return 0; \
+ }
+
+// Prefix
+long CrawlStoreValue::operator ++ ()
+{
+ INT_OPERATOR_UNARY(++);
+}
+
+long CrawlStoreValue::operator -- ()
+{
+ INT_OPERATOR_UNARY(--);
+}
+
+// Postfix
+long CrawlStoreValue::operator ++ (int)
+{
+ INT_OPERATOR_UNARY(++);
+}
+
+long CrawlStoreValue::operator -- (int)
+{
+ INT_OPERATOR_UNARY(--);
+}
+
+std::string &CrawlStoreValue::operator += (const std::string &_val)
+{
+ return (get_string() += _val);
+}
+
+////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+
+CrawlHashTable::CrawlHashTable()
+ : type(SV_NONE), default_flags(0)
+{
+}
+
+CrawlHashTable::CrawlHashTable(store_flags flags)
+ : type(SV_NONE), default_flags(flags)
+{
+ ASSERT(!(default_flags & SFLAG_UNSET));
+}
+
+CrawlHashTable::CrawlHashTable(store_val_type _type, store_flags flags)
+ : type(_type), default_flags(flags)
+{
+ ASSERT(type >= SV_NONE && type < NUM_STORE_VAL_TYPES);
+ ASSERT(!(default_flags & SFLAG_UNSET));
+}
+
+CrawlHashTable::~CrawlHashTable()
+{
+ assert_validity();
+}
+
+//////////////////////////////
+// Read/write from/to savefile
+void CrawlHashTable::write(tagHeader &th) const
+{
+ assert_validity();
+ if (empty())
+ {
+ marshallByte(th, 0);
+ return;
+ }
+
+ marshallByte(th, size());
+ marshallByte(th, static_cast<char>(type));
+ marshallByte(th, (char) default_flags);
+
+ CrawlHashTable::hash_map_type::const_iterator i = hash_map.begin();
+
+ for (; i != hash_map.end(); i++)
+ {
+ marshallString(th, i->first);
+ i->second.write(th);
+ }
+
+ assert_validity();
+}
+
+void CrawlHashTable::read(tagHeader &th)
+{
+ assert_validity();
+
+ ASSERT(empty());
+ ASSERT(type == SV_NONE);
+ ASSERT(default_flags == 0);
+
+ hash_size _size = (hash_size) unmarshallByte(th);
+
+ if (_size == 0)
+ return;
+
+ type = static_cast<store_val_type>(unmarshallByte(th));
+ default_flags = (store_flags) unmarshallByte(th);
+
+ for (hash_size i = 0; i < _size; i++)
+ {
+ std::string key = unmarshallString(th);
+ CrawlStoreValue &val = (*this)[key];
+
+ val.read(th);
+ }
+
+ assert_validity();
+}
+
+
+//////////////////
+// Misc functions
+
+store_flags CrawlHashTable::get_default_flags() const
+{
+ assert_validity();
+ return default_flags;
+}
+
+store_flags CrawlHashTable::set_default_flags(store_flags flags)
+{
+ assert_validity();
+ ASSERT(!(flags & SFLAG_UNSET));
+ default_flags |= flags;
+
+ return default_flags;
+}
+
+store_flags CrawlHashTable::unset_default_flags(store_flags flags)
+{
+ assert_validity();
+ ASSERT(!(flags & SFLAG_UNSET));
+ default_flags &= ~flags;
+
+ return default_flags;
+}
+
+store_val_type CrawlHashTable::get_type() const
+{
+ assert_validity();
+ return type;
+}
+
+bool CrawlHashTable::exists(const std::string key) const
+{
+ assert_validity();
+ hash_map_type::const_iterator i = hash_map.find(key);
+
+ return (i != hash_map.end());
+}
+
+void CrawlHashTable::assert_validity() const
+{
+#if DEBUG
+ ASSERT(!(default_flags & SFLAG_UNSET));
+
+ hash_map_type::const_iterator i = hash_map.begin();
+
+ unsigned long actual_size = 0;
+
+ for (; i != hash_map.end(); i++)
+ {
+ actual_size++;
+
+ const std::string &key = i->first;
+ const CrawlStoreValue &val = i->second;
+
+ ASSERT(key != "");
+ std::string trimmed = trimmed_string(key);
+ ASSERT(key == trimmed);
+
+ ASSERT(val.type != SV_NONE);
+ ASSERT(!(val.flags & SFLAG_UNSET));
+
+ switch(val.type)
+ {
+ case SV_STR:
+ case SV_COORD:
+ case SV_ITEM:
+ ASSERT(val.val.ptr != NULL);
+ break;
+
+ case SV_HASH:
+ {
+ ASSERT(val.val.ptr != NULL);
+
+ CrawlHashTable* nested;
+ nested = static_cast<CrawlHashTable*>(val.val.ptr);
+
+ nested->assert_validity();
+ break;
+ }
+
+ default:
+ break;
+ }
+ }
+
+ ASSERT(size() == actual_size);
+#endif
+}
+
+////////////////////////////////
+// Accessors to contained values
+
+CrawlStoreValue& CrawlHashTable::get_value(const std::string &key)
+{
+ assert_validity();
+ iterator i = hash_map.find(key);
+
+ if (i == hash_map.end())
+ {
+ hash_map[key] = CrawlStoreValue(default_flags);
+ CrawlStoreValue &val = hash_map[key];
+
+ if (type != SV_NONE)
+ {
+ val.type = type;
+ val.flags |= SFLAG_CONST_TYPE;
+ }
+
+ return (val);
+ }
+
+ return (i->second);
+}
+
+const CrawlStoreValue& CrawlHashTable::get_value(const std::string &key) const
+{
+ assert_validity();
+ hash_map_type::const_iterator i = hash_map.find(key);
+
+ ASSERT(i != hash_map.end());
+ ASSERT(i->second.type != SV_NONE);
+ ASSERT(!(i->second.flags & SFLAG_UNSET));
+
+ return (i->second);
+}
+
+CrawlStoreValue& CrawlHashTable::operator[] (const std::string &key)
+{
+ return get_value(key);
+}
+
+const CrawlStoreValue& CrawlHashTable::operator[] (const std::string &key)
+ const
+{
+ return get_value(key);
+}
+
+///////////////////////////
+// std::map style interface
+hash_size CrawlHashTable::size() const
+{
+ return hash_map.size();
+}
+
+bool CrawlHashTable::empty() const
+{
+ return hash_map.empty();
+}
+
+void CrawlHashTable::erase(const std::string key)
+{
+ assert_validity();
+ iterator i = hash_map.find(key);
+
+ if (i != hash_map.end())
+ {
+ CrawlStoreValue &val = i->second;
+
+ ASSERT(!(val.flags & SFLAG_NO_ERASE));
+
+ hash_map.erase(i);
+ }
+}
+
+void CrawlHashTable::clear()
+{
+ assert_validity();
+ ASSERT(!(default_flags & SFLAG_NO_ERASE));
+
+ iterator i = hash_map.begin();
+ for (; i != hash_map.end(); i++)
+ ASSERT(!(i->second.flags & SFLAG_NO_ERASE));
+
+ hash_map.clear();
+}
+
+CrawlHashTable::iterator CrawlHashTable::begin()
+{
+ assert_validity();
+ return hash_map.begin();
+}
+
+CrawlHashTable::iterator CrawlHashTable::end()
+{
+ assert_validity();
+ return hash_map.end();
+}
+
+CrawlHashTable::const_iterator CrawlHashTable::begin() const
+{
+ assert_validity();
+ return hash_map.begin();
+}
+
+CrawlHashTable::const_iterator CrawlHashTable::end() const
+{
+ assert_validity();
+ return hash_map.end();
+}
+
+/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+
+CrawlVector::CrawlVector()
+ : type(SV_NONE), default_flags(0), max_size(VEC_MAX_SIZE)
+{
+}
+
+CrawlVector::CrawlVector(store_flags flags, vec_size _max_size)
+ : type(SV_NONE), default_flags(flags), max_size(_max_size)
+{
+ ASSERT(!(default_flags & SFLAG_UNSET));
+ ASSERT(max_size > 0);
+}
+
+CrawlVector::CrawlVector(store_val_type _type, store_flags flags,
+ vec_size _max_size)
+ : type(_type), default_flags(flags), max_size(_max_size)
+{
+ ASSERT(type >= SV_NONE && type < NUM_STORE_VAL_TYPES);
+ ASSERT(!(default_flags & SFLAG_UNSET));
+ ASSERT(max_size > 0);
+}
+
+CrawlVector::~CrawlVector()
+{
+ assert_validity();
+}
+
+//////////////////////////////
+// Read/write from/to savefile
+void CrawlVector::write(tagHeader &th) const
+{
+ assert_validity();
+ if (empty())
+ {
+ marshallByte(th, 0);
+ return;
+ }
+
+ marshallByte(th, (char) size());
+ marshallByte(th, (char) max_size);
+ marshallByte(th, static_cast<char>(type));
+ marshallByte(th, (char) default_flags);
+
+ for (vec_size i = 0; i < size(); i++)
+ {
+ CrawlStoreValue val = vector[i];
+ ASSERT(val.type != SV_NONE);
+ ASSERT(!(val.flags & SFLAG_UNSET));
+ val.write(th);
+ }
+
+ assert_validity();
+}
+
+void CrawlVector::read(tagHeader &th)
+{
+ assert_validity();
+
+ ASSERT(empty());
+ ASSERT(type == SV_NONE);
+ ASSERT(default_flags == 0);
+ ASSERT(max_size == VEC_MAX_SIZE);
+
+ vec_size _size = (vec_size) unmarshallByte(th);
+
+ if (_size == 0)
+ return;
+
+ max_size = static_cast<vec_size>(unmarshallByte(th));
+ type = static_cast<store_val_type>(unmarshallByte(th));
+ default_flags = static_cast<store_flags>(unmarshallByte(th));
+
+ ASSERT(_size <= max_size);
+
+ vector.resize(_size);
+
+ for (vec_size i = 0; i < _size; i++)
+ vector[i].read(th);
+
+ assert_validity();
+}
+
+
+//////////////////
+// Misc functions
+
+store_flags CrawlVector::get_default_flags() const
+{
+ assert_validity();
+ return default_flags;
+}
+
+store_flags CrawlVector::set_default_flags(store_flags flags)
+{
+ assert_validity();
+ ASSERT(!(flags & SFLAG_UNSET));
+ default_flags |= flags;
+
+ return default_flags;
+}
+
+store_flags CrawlVector::unset_default_flags(store_flags flags)
+{
+ assert_validity();
+ ASSERT(!(flags & SFLAG_UNSET));
+ default_flags &= ~flags;
+
+ return default_flags;
+}
+
+store_val_type CrawlVector::get_type() const
+{
+ assert_validity();
+ return type;
+}
+
+void CrawlVector::assert_validity() const
+{
+#if DEBUG
+ ASSERT(!(default_flags & SFLAG_UNSET));
+ ASSERT(max_size > 0);
+ ASSERT(max_size >= size());
+
+ for (vec_size i = 0, _size = size(); i < _size; i++)
+ {
+ const CrawlStoreValue &val = vector[i];
+
+ // A vector might be resize()'d and filled up with unset
+ // values, which are then set one by one, so we can't
+ // assert over that here.
+ if (val.type == SV_NONE || (val.flags & SFLAG_UNSET))
+ continue;
+
+ switch(val.type)
+ {
+ case SV_STR:
+ case SV_COORD:
+ case SV_ITEM:
+ ASSERT(val.val.ptr != NULL);
+ break;
+
+ case SV_HASH:
+ {
+ ASSERT(val.val.ptr != NULL);
+
+ CrawlVector* nested;
+ nested = static_cast<CrawlVector*>(val.val.ptr);
+
+ nested->assert_validity();
+ break;
+ }
+
+ case SV_VEC:
+ {
+ ASSERT(val.val.ptr != NULL);
+
+ CrawlVector* nested;
+ nested = static_cast<CrawlVector*>(val.val.ptr);
+
+ nested->assert_validity();
+ break;
+ }
+
+ default:
+ break;
+ }
+ }
+#endif
+}
+
+void CrawlVector::set_max_size(vec_size _size)
+{
+ ASSERT(_size > 0);
+ ASSERT(max_size == VEC_MAX_SIZE);
+ max_size = _size;
+
+ vector.reserve(max_size);
+}
+
+vec_size CrawlVector::get_max_size() const
+{
+ return max_size;
+}
+
+
+////////////////////////////////
+// Accessors to contained values
+
+CrawlStoreValue& CrawlVector::get_value(const vec_size &index)
+{
+ assert_validity();
+
+ ASSERT(index <= max_size);
+ ASSERT(index <= vector.size());
+
+ return vector[index];
+}
+
+const CrawlStoreValue& CrawlVector::get_value(const vec_size &index) const
+{
+ assert_validity();
+
+ ASSERT(index <= max_size);
+ ASSERT(index <= vector.size());
+
+ return vector[index];
+}
+
+CrawlStoreValue& CrawlVector::operator[] (const vec_size &index)
+{
+ return get_value(index);
+}
+
+const CrawlStoreValue& CrawlVector::operator[] (const vec_size &index) const
+{
+ return get_value(index);
+}
+
+///////////////////////////
+// std::vector style interface
+vec_size CrawlVector::size() const
+{
+ return vector.size();
+}
+
+bool CrawlVector::empty() const
+{
+ return vector.empty();
+}
+
+CrawlStoreValue& CrawlVector::pop_back()
+{
+ assert_validity();
+ ASSERT(vector.size() > 0);
+
+ CrawlStoreValue& val = vector[vector.size() - 1];
+ vector.pop_back();
+ return val;
+}
+
+void CrawlVector::push_back(CrawlStoreValue val)
+{
+ assert_validity();
+ ASSERT(vector.size() < max_size);
+ ASSERT(type == SV_NONE
+ || (val.type == SV_NONE && (val.flags & SFLAG_UNSET))
+ || (val.type == type));
+ val.flags |= default_flags;
+ if (type != SV_NONE)
+ {
+ val.type = type;
+ val.flags |= SFLAG_CONST_TYPE;
+ }
+ vector.push_back(val);
+}
+
+void CrawlVector::insert(const vec_size index, CrawlStoreValue val)
+{
+ assert_validity();
+ ASSERT(vector.size() < max_size);
+ ASSERT(type == SV_NONE
+ || (val.type == SV_NONE && (val.flags & SFLAG_UNSET))
+ || (val.type == type));
+ val.flags |= default_flags;
+ if (type != SV_NONE)
+ {
+ val.type = type;
+ val.flags |= SFLAG_CONST_TYPE;
+ }
+ vector.insert(vector.begin() + index, val);
+}
+
+void CrawlVector::resize(const vec_size _size)
+{
+ assert_validity();
+ ASSERT(max_size == VEC_MAX_SIZE);
+ ASSERT(_size < max_size);
+
+ vec_size old_size = size();
+ vector.resize(_size);
+
+ for (vec_size i = old_size; i < _size; i++)
+ {
+ vector[i].flags = SFLAG_UNSET | default_flags;
+ vector[i].type = SV_NONE;
+ }
+}
+
+void CrawlVector::erase(const vec_size index)
+{
+ assert_validity();
+ ASSERT(index <= max_size);
+ ASSERT(index <= vector.size());
+
+ vector.erase(vector.begin() + index);
+}
+
+void CrawlVector::clear()
+{
+ assert_validity();
+ ASSERT(!(default_flags & SFLAG_NO_ERASE));
+
+ for (vec_size i = 0, _size = size(); i < _size; i++)
+ ASSERT(!(vector[i].flags & SFLAG_NO_ERASE));
+
+ vector.clear();
+}
+
+CrawlVector::iterator CrawlVector::begin()
+{
+ assert_validity();
+ return vector.begin();
+}
+
+CrawlVector::iterator CrawlVector::end()
+{
+ assert_validity();
+ return vector.end();
+}
+
+CrawlVector::const_iterator CrawlVector::begin() const
+{
+ assert_validity();
+ return vector.begin();
+}
+
+CrawlVector::const_iterator CrawlVector::end() const
+{
+ assert_validity();
+ return vector.end();
+}
+
+/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+
+template <typename T, store_val_type TYPE>
+CrawlTableWrapper<T, TYPE>::CrawlTableWrapper()
+{
+ table = NULL;
+}
+
+template <typename T, store_val_type TYPE>
+CrawlTableWrapper<T, TYPE>::CrawlTableWrapper(CrawlHashTable& _table)
+{
+ wrap(_table);
+}
+
+template <typename T, store_val_type TYPE>
+CrawlTableWrapper<T, TYPE>::CrawlTableWrapper(CrawlHashTable* _table)
+{
+ wrap(_table);
+}
+
+template <typename T, store_val_type TYPE>
+void CrawlTableWrapper<T, TYPE>::wrap(CrawlHashTable& _table)
+{
+ wrap(&_table);
+}
+
+template <typename T, store_val_type TYPE>
+void CrawlTableWrapper<T, TYPE>::wrap(CrawlHashTable* _table)
+{
+ ASSERT(_table != NULL);
+ ASSERT(_table->get_type() == TYPE);
+
+ table = _table;
+}
+
+template <typename T, store_val_type TYPE>
+T& CrawlTableWrapper<T, TYPE>::operator[] (const std::string &key)
+{
+ return (T&) (*table)[key];
+}
+
+template <typename T, store_val_type TYPE>
+const T CrawlTableWrapper<T, TYPE>::operator[] (const std::string &key) const
+{
+ return (T) (*table)[key];
+}
diff --git a/crawl-ref/source/store.h b/crawl-ref/source/store.h
new file mode 100644
index 0000000000..b65298b514
--- /dev/null
+++ b/crawl-ref/source/store.h
@@ -0,0 +1,402 @@
+/*
+ * File: store.cc
+ * Summary: Saveable hash-table and vector capable of storing
+ * multiple types of data.
+ * Written by: Matthew Cline
+ *
+ * Modified for Crawl Reference by $Author$ on $Date$
+ *
+ * Change History (most recent first):
+
+ * <1> 10/5/07 MPC Created
+ */
+
+#ifndef STORE_H
+#define STORE_H
+
+#include <limits.h>
+#include <map>
+#include <string>
+#include <vector>
+
+struct tagHeader;
+class CrawlHashTable;
+class CrawlVector;
+class item_def;
+class coord_def;
+
+typedef unsigned char hash_size;
+typedef unsigned char vec_size;
+typedef unsigned char store_flags;
+
+#define VEC_MAX_SIZE 255
+#define HASH_MAX_SIZE 255
+
+// NOTE: Changing the ordering of these enums will break savefile
+// compatibility.
+enum store_val_type
+{
+ SV_NONE = 0,
+ SV_BOOL,
+ SV_BYTE,
+ SV_SHORT,
+ SV_LONG,
+ SV_FLOAT,
+ SV_STR,
+ SV_COORD,
+ SV_ITEM,
+ SV_HASH,
+ SV_VEC,
+ NUM_STORE_VAL_TYPES
+};
+
+enum store_flag_type
+{
+ SFLAG_UNSET = (1 << 0),
+ SFLAG_CONST_VAL = (1 << 1),
+ SFLAG_CONST_TYPE = (1 << 2),
+ SFLAG_NO_ERASE = (1 << 3)
+};
+
+
+// Can't just cast everything into a void pointer, since a float might
+// not fit into a pointer on all systems.
+typedef union StoreUnion StoreUnion;
+union StoreUnion
+{
+ bool boolean;
+ char byte;
+ short _short;
+ long _long;
+ float _float;
+ void* ptr;
+};
+
+
+class CrawlStoreValue
+{
+public:
+ CrawlStoreValue();
+ CrawlStoreValue(const CrawlStoreValue &other);
+
+ ~CrawlStoreValue();
+
+ // Conversion constructors
+ CrawlStoreValue(const bool val);
+ CrawlStoreValue(const char &val);
+ CrawlStoreValue(const short &val);
+ CrawlStoreValue(const long &val);
+ CrawlStoreValue(const float &val);
+ CrawlStoreValue(const std::string &val);
+ CrawlStoreValue(const char* val);
+ CrawlStoreValue(const coord_def &val);
+ CrawlStoreValue(const item_def &val);
+ CrawlStoreValue(const CrawlHashTable &val);
+ CrawlStoreValue(const CrawlVector &val);
+
+ // Only needed for doing some assertion checking.
+ CrawlStoreValue &operator = (const CrawlStoreValue &other);
+
+protected:
+ store_val_type type;
+ store_flags flags;
+ StoreUnion val;
+
+public:
+ store_flags get_flags() const;
+ store_flags set_flags(store_flags flags);
+ store_flags unset_flags(store_flags flags);
+ store_val_type get_type() const;
+
+ CrawlHashTable &new_table(store_flags flags);
+ CrawlHashTable &new_table(store_val_type type, store_flags flags = 0);
+
+ CrawlVector &new_vector(store_flags flags,
+ vec_size max_size = VEC_MAX_SIZE);
+ CrawlVector &new_vector(store_val_type type, store_flags flags = 0,
+ vec_size max_size = VEC_MAX_SIZE);
+
+ bool &get_bool();
+ char &get_byte();
+ short &get_short();
+ long &get_long();
+ float &get_float();
+ std::string &get_string();
+ coord_def &get_coord();
+ CrawlHashTable &get_table();
+ CrawlVector &get_vector();
+ item_def &get_item();
+
+ bool get_bool() const;
+ char get_byte() const;
+ short get_short() const;
+ long get_long() const;
+ float get_float() const;
+ std::string get_string() const;
+ coord_def get_coord() const;
+
+ const CrawlHashTable& get_table() const;
+ const CrawlVector& get_vector() const;
+ const item_def& get_item() const;
+
+ void set_bool(const bool val);
+ void set_byte(const char val);
+ void set_short(const short val);
+ void set_long(const long val);
+ void set_float(const float val);
+ void set_string(const std::string &val);
+ void set_coord(const coord_def &val);
+ void set_table(const CrawlHashTable &val);
+ void set_vector(const CrawlVector &val);
+ void set_item(const item_def &val);
+
+public:
+ // NOTE: All operators will assert if the alue is of the wrong
+ // type for the operation. If the value has no type yet, the
+ // operation will set it to the appropriate type. If the value
+ // has no type yet and the operation modifies the existing value
+ // rather than replacing it (i.e., ++) the value will be set to a
+ // default before the operation is done.
+
+ // If the value is a hash table or vector, the container's values
+ // can be accessed with the [] operator with the approriate key
+ // type (strings for hashes, longs for vectors).
+ CrawlStoreValue &operator [] (const std::string &key);
+ CrawlStoreValue &operator [] (const vec_size &index);
+
+ const CrawlStoreValue &operator [] (const std::string &key) const;
+ const CrawlStoreValue &operator [] (const vec_size &index) const;
+
+ // Typecast operators
+ &operator bool();
+ &operator char();
+ &operator short();
+ &operator long();
+ &operator float();
+ &operator std::string();
+ &operator coord_def();
+ &operator CrawlHashTable();
+ &operator CrawlVector();
+ &operator item_def();
+
+ operator bool() const;
+ operator char() const;
+ operator short() const;
+ operator long() const;
+ operator float() const;
+ operator std::string() const;
+ operator coord_def() const;
+
+ // Assignment operators
+ CrawlStoreValue &operator = (const bool &val);
+ CrawlStoreValue &operator = (const char &val);
+ CrawlStoreValue &operator = (const short &val);
+ CrawlStoreValue &operator = (const long &val);
+ CrawlStoreValue &operator = (const float &val);
+ CrawlStoreValue &operator = (const std::string &val);
+ CrawlStoreValue &operator = (const char* val);
+ CrawlStoreValue &operator = (const coord_def &val);
+ CrawlStoreValue &operator = (const CrawlHashTable &val);
+ CrawlStoreValue &operator = (const CrawlVector &val);
+ CrawlStoreValue &operator = (const item_def &val);
+
+ // Misc operators
+ std::string &operator += (const std::string &val);
+
+ // Prefix
+ long operator ++ ();
+ long operator -- ();
+
+ // Postfix
+ long operator ++ (int);
+ long operator -- (int);
+
+protected:
+ CrawlStoreValue(const store_flags flags,
+ const store_val_type type = SV_NONE);
+
+ void write(tagHeader &th) const;
+ void read(tagHeader &th);
+
+ void unset(bool force = false);
+
+ friend class CrawlHashTable;
+ friend class CrawlVector;
+};
+
+
+// A hash table can have a maximum of 255 key/value pairs. If you
+// want more than that you can use nested hash tables.
+//
+// By default a hash table's value data types are heterogeneous. To
+// make it homogeneous (which causes dynamic type checking) you have
+// to give a type to the hash table constructor; once it's been
+// created it's type (or lack of type) is immutable.
+//
+// An empty hash table will take up only 1 byte in the savefile. A
+// non-empty hash table will have an overhead of 3 bytes for the hash
+// table overall and 2 bytes per key/value pair, over and above the
+// number of bytes needed to store the keys and values themselves.
+class CrawlHashTable
+{
+public:
+ CrawlHashTable();
+ CrawlHashTable(store_flags flags);
+ CrawlHashTable(store_val_type type, store_flags flags = 0);
+
+ ~CrawlHashTable();
+
+ typedef std::map<std::string, CrawlStoreValue> hash_map_type;
+ typedef hash_map_type::iterator iterator;
+ typedef hash_map_type::const_iterator const_iterator;
+
+protected:
+ store_val_type type;
+ store_flags default_flags;
+ hash_map_type hash_map;
+
+ friend class CrawlStoreValue;
+
+public:
+ void write(tagHeader &th) const;
+ void read(tagHeader &th);
+
+ store_flags get_default_flags() const;
+ store_flags set_default_flags(store_flags flags);
+ store_flags unset_default_flags(store_flags flags);
+ store_val_type get_type() const;
+ bool exists(const std::string key) const;
+ void assert_validity() const;
+
+ // NOTE: If get_value() or [] is given a key which doesn't exist
+ // in the table, an unset/empty CrawlStoreValue will be created
+ // with that key and returned. If it is not then given a value
+ // then the next call to assert_validity() will fail. If the
+ // hash table has a type (rather than being heterogeneous)
+ // then trying to assign a different type to the CrawlStoreValue
+ // will assert.
+ CrawlStoreValue& get_value(const std::string &key);
+ CrawlStoreValue& operator[] (const std::string &key);
+
+ // NOTE: If the const versions of get_value() or [] are given a
+ // key which doesn't exist, they will assert.
+ const CrawlStoreValue& get_value(const std::string &key) const;
+ const CrawlStoreValue& operator[] (const std::string &key) const;
+
+ // std::map style interface
+ hash_size size() const;
+ bool empty() const;
+
+ void erase(const std::string key);
+ void clear();
+
+ iterator begin();
+ iterator end();
+
+ const_iterator begin() const;
+ const_iterator end() const;
+};
+
+// A CrawlVector is the vector version of CrawlHashTable, except that
+// a non-empty CrawlVector has one more byte of savefile overhead that
+// a hash table, and that can specify a maximum size to make it act
+// similarly to a FixedVec.
+class CrawlVector
+{
+public:
+ CrawlVector();
+ CrawlVector(store_flags flags, vec_size max_size = VEC_MAX_SIZE);
+ CrawlVector(store_val_type type, store_flags flags = 0,
+ vec_size max_size = VEC_MAX_SIZE);
+
+ ~CrawlVector();
+
+ typedef std::vector<CrawlStoreValue> vector_type;
+ typedef vector_type::iterator iterator;
+ typedef vector_type::const_iterator const_iterator;
+
+protected:
+ store_val_type type;
+ store_flags default_flags;
+ vec_size max_size;
+ vector_type vector;
+
+ friend class CrawlStoreValue;
+
+public:
+ void write(tagHeader &th) const;
+ void read(tagHeader &th);
+
+ store_flags get_default_flags() const;
+ store_flags set_default_flags(store_flags flags);
+ store_flags unset_default_flags(store_flags flags);
+ store_val_type get_type() const;
+ void assert_validity() const;
+ void set_max_size(vec_size size);
+ vec_size get_max_size() const;
+
+ CrawlStoreValue& get_value(const vec_size &index);
+ CrawlStoreValue& operator[] (const vec_size &index);
+
+ // NOTE: If the const versions of get_value() or [] are given a
+ // index which doesn't exist, they will assert.
+ const CrawlStoreValue& get_value(const vec_size &index) const;
+ const CrawlStoreValue& operator[] (const vec_size &index) const;
+
+ // std::vector style interface
+ vec_size size() const;
+ bool empty() const;
+
+ // NOTE: push_back() and insert() have val passed by value rather
+ // than by reference so that coversion constructors will work.
+ CrawlStoreValue& pop_back();
+ void push_back(CrawlStoreValue val);
+ void insert(const vec_size index, CrawlStoreValue val);
+
+ // resize() will assert if the maximum size has been set.
+ void resize(const vec_size size);
+ void erase(const vec_size index);
+ void clear();
+
+ iterator begin();
+ iterator end();
+
+ const_iterator begin() const;
+ const_iterator end() const;
+};
+
+// A wrapper for non-heterogeneous hash tables, so that the values can
+// be accessed without using get_foo(). T needs to have both normal
+// and const type-cast operators defined by CrawlStoreValue for this
+// template to work.
+template <typename T, store_val_type TYPE>
+class CrawlTableWrapper
+{
+public:
+ CrawlTableWrapper();
+ CrawlTableWrapper(CrawlHashTable& table);
+ CrawlTableWrapper(CrawlHashTable* table);
+
+protected:
+ CrawlHashTable* table;
+
+public:
+ void wrap(CrawlHashTable& table);
+ void wrap(CrawlHashTable* table);
+
+ CrawlHashTable* get_table();
+ T& operator[] (const std::string &key);
+
+ const CrawlHashTable* get_table() const;
+ const T operator[] (const std::string &key) const;
+};
+
+typedef CrawlTableWrapper<bool, SV_BOOL> CrawlBoolTable;
+typedef CrawlTableWrapper<char, SV_BYTE> CrawlByteTable;
+typedef CrawlTableWrapper<short, SV_SHORT> CrawlShortTable;
+typedef CrawlTableWrapper<long, SV_LONG> CrawlLongTable;
+typedef CrawlTableWrapper<float, SV_FLOAT> CrawlFloatTable;
+typedef CrawlTableWrapper<std::string, SV_STR> CrawlStringTable;
+typedef CrawlTableWrapper<coord_def, SV_COORD> CrawlCoordTable;
+
+#endif