summaryrefslogtreecommitdiffstats
path: root/crawl-ref
diff options
context:
space:
mode:
authorpauldubois <pauldubois@c06c8d41-db1a-0410-9941-cceddc491573>2008-03-17 05:54:42 +0000
committerpauldubois <pauldubois@c06c8d41-db1a-0410-9941-cceddc491573>2008-03-17 05:54:42 +0000
commit8ba172496400cc74a2fa7d343d9859339f1a0f5d (patch)
tree09715fca1c835aca87d0da9d629ad5f9e0157e54 /crawl-ref
parent314a2c0efb7083bc9703b6e2f6ee4e054d000cc1 (diff)
downloadcrawl-ref-8ba172496400cc74a2fa7d343d9859339f1a0f5d.tar.gz
crawl-ref-8ba172496400cc74a2fa7d343d9859339f1a0f5d.zip
Cleanup/refactoring of tags.cc. No functional changes. I've been
running with and without this patch applied for about a week, and none of my saves have broken, so I'm ready to commit it. - Tag system no longer uses one big (shared!) global buffer. This was the original impetus behind the change... - Change every use of tagHeader into reader or writer (touches a lot). - Split tagHeader into two classes: reader and writer. Turns out every place that used tagHeader only cared about reading or writing and not about tags at all. There was nothing left in tagHeader, so it disappeared along with a bunch of grotty special-case code. - Not done: merge the files.cc read/writeThing code with the tags.cc marshall/unmarshallThing code. This patch is big enough already. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@3685 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref')
-rw-r--r--crawl-ref/source/acr.cc3
-rw-r--r--crawl-ref/source/externs.h7
-rw-r--r--crawl-ref/source/files.cc29
-rw-r--r--crawl-ref/source/luadgn.cc18
-rw-r--r--crawl-ref/source/mapmark.cc62
-rw-r--r--crawl-ref/source/mapmark.h35
-rw-r--r--crawl-ref/source/stash.cc8
-rw-r--r--crawl-ref/source/store.cc12
-rw-r--r--crawl-ref/source/store.h15
-rw-r--r--crawl-ref/source/tags.cc469
-rw-r--r--crawl-ref/source/tags.h137
11 files changed, 368 insertions, 427 deletions
diff --git a/crawl-ref/source/acr.cc b/crawl-ref/source/acr.cc
index b9596abd09..a681d16089 100644
--- a/crawl-ref/source/acr.cc
+++ b/crawl-ref/source/acr.cc
@@ -3680,9 +3680,6 @@ static bool initialise(void)
you.unique_creatures.init(false);
you.unique_items.init(UNIQ_NOT_EXISTS);
- // initialise tag system before we try loading anything!
- tag_init();
-
// set up the Lua interpreter for the dungeon builder.
init_dungeon_lua();
diff --git a/crawl-ref/source/externs.h b/crawl-ref/source/externs.h
index c4fb8497b0..8c7816d79f 100644
--- a/crawl-ref/source/externs.h
+++ b/crawl-ref/source/externs.h
@@ -1293,7 +1293,8 @@ struct map_cell
};
class map_marker;
-struct tagHeader;
+class reader;
+class writer;
class map_markers
{
public:
@@ -1317,8 +1318,8 @@ public:
const std::string &key);
void clear();
- void write(tagHeader &th) const;
- void read(tagHeader &);
+ void write(writer &) const;
+ void read(reader &);
private:
typedef std::multimap<coord_def, map_marker *> dgn_marker_map;
diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc
index a1572e51cd..ec3ec235aa 100644
--- a/crawl-ref/source/files.cc
+++ b/crawl-ref/source/files.cc
@@ -619,12 +619,10 @@ static void write_version( FILE *dataFile, int majorVersion, int minorVersion,
bool extended_version )
{
// write version
- tagHeader versionTag;
- versionTag.offset = 0;
- versionTag.tagID = TAG_VERSION;
+ writer outf(dataFile);
- marshallByte(versionTag, majorVersion);
- marshallByte(versionTag, minorVersion);
+ marshallByte(outf, majorVersion);
+ marshallByte(outf, minorVersion);
// extended_version just pads the version out to four 32-bit words.
// This makes the bones file compatible with Hearse with no extra
@@ -637,22 +635,18 @@ static void write_version( FILE *dataFile, int majorVersion, int minorVersion,
// hearse.pl. Crawl-aware hearse.pl will prefix the bones file
// with the first 16-bits of the Crawl version, and the following
// 7 16-bit words set to 0.
- marshallShort(versionTag, GHOST_SIGNATURE);
+ marshallShort(outf, GHOST_SIGNATURE);
// Write the three remaining 32-bit words of padding.
for (int i = 0; i < 3; ++i)
- marshallLong(versionTag, 0);
+ marshallLong(outf, 0);
}
-
- tag_write(versionTag, dataFile);
}
static void write_tagged_file( FILE *dataFile, char majorVersion,
char minorVersion, int fileType,
bool extended_version = false )
{
- struct tagHeader th;
-
// find all relevant tags
char tags[NUM_TAGS];
tag_set_expected(tags, fileType);
@@ -664,8 +658,7 @@ static void write_tagged_file( FILE *dataFile, char majorVersion,
{
if (tags[i] == 1)
{
- tag_construct(th, i);
- tag_write(th, dataFile);
+ tag_write((tag_type)i, dataFile);
}
}
}
@@ -1575,23 +1568,21 @@ static void restore_version( FILE *restoreFile,
static void restore_tagged_file( FILE *restoreFile, int fileType,
char minorVersion )
{
- int i;
-
char tags[NUM_TAGS];
tag_set_expected(tags, fileType);
while(1)
{
- i = tag_read(restoreFile, minorVersion);
- if (i == 0) // no tag!
+ tag_type tt = tag_read(restoreFile, minorVersion);
+ if (tt == TAG_NO_TAG)
break;
- tags[i] = 0; // tag read
+ tags[tt] = 0; // tag read
if (fileType == TAGTYPE_PLAYER_NAME)
break;
}
// go through and init missing tags
- for(i=0; i<NUM_TAGS; i++)
+ for (int i=0; i<NUM_TAGS; i++)
{
if (tags[i] == 1) // expected but never read
tag_missing(i, minorVersion);
diff --git a/crawl-ref/source/luadgn.cc b/crawl-ref/source/luadgn.cc
index 57442e5d1e..ee432892be 100644
--- a/crawl-ref/source/luadgn.cc
+++ b/crawl-ref/source/luadgn.cc
@@ -1735,7 +1735,7 @@ static int file_marshall(lua_State *ls)
{
if (lua_gettop(ls) != 2)
luaL_error(ls, "Need two arguments: tag header and value");
- tagHeader &th(*static_cast<tagHeader*>( lua_touserdata(ls, 1) ));
+ writer &th(*static_cast<writer*>( lua_touserdata(ls, 1) ));
if (lua_isnumber(ls, 2))
marshallLong(th, luaL_checklong(ls, 2));
else if (lua_isstring(ls, 2))
@@ -1751,8 +1751,8 @@ static int file_marshall(lua_State *ls)
static int file_unmarshall_number(lua_State *ls)
{
if (lua_gettop(ls) != 1)
- luaL_error(ls, "Need tag header as one argument");
- tagHeader &th(*static_cast<tagHeader*>( lua_touserdata(ls, 1) ));
+ luaL_error(ls, "Need reader as one argument");
+ reader &th(*static_cast<reader*>( lua_touserdata(ls, 1) ));
lua_pushnumber(ls, unmarshallLong(th));
return (1);
}
@@ -1760,8 +1760,8 @@ static int file_unmarshall_number(lua_State *ls)
static int file_unmarshall_string(lua_State *ls)
{
if (lua_gettop(ls) != 1)
- luaL_error(ls, "Need tag header as one argument");
- tagHeader &th(*static_cast<tagHeader*>( lua_touserdata(ls, 1) ));
+ luaL_error(ls, "Need reader as one argument");
+ reader &th(*static_cast<reader*>( lua_touserdata(ls, 1) ));
lua_pushstring(ls, unmarshallString(th).c_str());
return (1);
}
@@ -1769,8 +1769,8 @@ static int file_unmarshall_string(lua_State *ls)
static int file_unmarshall_fn(lua_State *ls)
{
if (lua_gettop(ls) != 1)
- luaL_error(ls, "Need tag header as one argument");
- tagHeader &th(*static_cast<tagHeader*>( lua_touserdata(ls, 1) ));
+ luaL_error(ls, "Need reader as one argument");
+ reader &th(*static_cast<reader*>( lua_touserdata(ls, 1) ));
const std::string s(unmarshallString(th, LUA_CHUNK_MAX_SIZE));
dlua_chunk chunk = dlua_chunk::precompiled(s);
if (chunk.load(dlua))
@@ -1792,7 +1792,7 @@ static int file_marshall_meta(lua_State *ls)
if (lua_gettop(ls) != 2)
luaL_error(ls, "Need two arguments: tag header and value");
- tagHeader &th(*static_cast<tagHeader*>( lua_touserdata(ls, 1) ));
+ writer &th(*static_cast<writer*>( lua_touserdata(ls, 1) ));
lua_persist_type ptype = LPT_NONE;
if (lua_isnumber(ls, 2))
@@ -1813,7 +1813,7 @@ static int file_marshall_meta(lua_State *ls)
static int file_unmarshall_meta(lua_State *ls)
{
- tagHeader &th(*static_cast<tagHeader*>( lua_touserdata(ls, 1) ));
+ reader &th(*static_cast<reader*>( lua_touserdata(ls, 1) ));
const lua_persist_type ptype =
static_cast<lua_persist_type>(unmarshallByte(th));
switch (ptype)
diff --git a/crawl-ref/source/mapmark.cc b/crawl-ref/source/mapmark.cc
index 589e4f9082..90a5dadf48 100644
--- a/crawl-ref/source/mapmark.cc
+++ b/crawl-ref/source/mapmark.cc
@@ -50,13 +50,13 @@ void map_marker::activate(bool)
{
}
-void map_marker::write(tagHeader &outf) const
+void map_marker::write(writer &outf) const
{
marshallShort(outf, type);
marshallCoord(outf, pos);
}
-void map_marker::read(tagHeader &inf)
+void map_marker::read(reader &inf)
{
// Don't read type! The type has to be read by someone who knows how
// to look up the unmarshall function.
@@ -73,7 +73,7 @@ std::string map_marker::property(const std::string &pname) const
return ("");
}
-map_marker *map_marker::read_marker(tagHeader &inf)
+map_marker *map_marker::read_marker(reader &inf)
{
const map_marker_type type =
static_cast<map_marker_type>(unmarshallShort(inf));
@@ -110,13 +110,13 @@ map_feature_marker::map_feature_marker(
{
}
-void map_feature_marker::write(tagHeader &outf) const
+void map_feature_marker::write(writer &outf) const
{
this->map_marker::write(outf);
marshallShort(outf, feat);
}
-void map_feature_marker::read(tagHeader &inf)
+void map_feature_marker::read(reader &inf)
{
map_marker::read(inf);
feat = static_cast<dungeon_feature_type>(unmarshallShort(inf));
@@ -127,7 +127,7 @@ map_marker *map_feature_marker::clone() const
return new map_feature_marker(pos, feat);
}
-map_marker *map_feature_marker::read(tagHeader &inf, map_marker_type)
+map_marker *map_feature_marker::read(reader &inf, map_marker_type)
{
map_marker *mapf = new map_feature_marker();
mapf->read(inf);
@@ -231,9 +231,9 @@ bool map_lua_marker::get_table() const
return (lua_istable(dlua, -1));
}
-void map_lua_marker::write(tagHeader &th) const
+void map_lua_marker::write(writer &outf) const
{
- map_marker::write(th);
+ map_marker::write(outf);
lua_stack_cleaner clean(dlua);
bool init = initialised;
@@ -243,7 +243,7 @@ void map_lua_marker::write(tagHeader &th) const
init = false;
}
- marshallByte(th, init);
+ marshallByte(outf, init);
if (!init)
return;
@@ -258,7 +258,7 @@ void map_lua_marker::write(tagHeader &th) const
end(1, false, "lua_marker: couldn't save read function: %s",
reader.error.c_str());
- marshallString(th, reader.compiled_chunk());
+ marshallString(outf, reader.compiled_chunk());
// Okay, saved the reader. Now ask the writer to do its thing.
@@ -266,28 +266,28 @@ void map_lua_marker::write(tagHeader &th) const
get_table();
lua_pushstring(dlua, "write");
lua_pushlightuserdata(dlua, const_cast<map_lua_marker*>(this));
- lua_pushlightuserdata(dlua, &th);
+ lua_pushlightuserdata(dlua, &outf);
if (!dlua.callfn("dlua_marker_method", 4))
end(1, false, "lua_marker::write error: %s", dlua.error.c_str());
}
-void map_lua_marker::read(tagHeader &th)
+void map_lua_marker::read(reader &inf)
{
- map_marker::read(th);
+ map_marker::read(inf);
- if (!(initialised = unmarshallByte(th)))
+ if (!(initialised = unmarshallByte(inf)))
return;
lua_stack_cleaner cln(dlua);
// Read the Lua chunk we saved.
- const std::string compiled = unmarshallString(th, LUA_CHUNK_MAX_SIZE);
+ const std::string compiled = unmarshallString(inf, LUA_CHUNK_MAX_SIZE);
dlua_chunk chunk = dlua_chunk::precompiled(compiled);
if (chunk.load(dlua))
end(1, false, "lua_marker::read error: %s", chunk.error.c_str());
dlua_push_userdata(dlua, this, MAPMARK_METATABLE);
- lua_pushlightuserdata(dlua, &th);
+ lua_pushlightuserdata(dlua, &inf);
if (!dlua.callfn("dlua_marker_read", 3, 1))
end(1, false, "lua_marker::read error: %s", dlua.error.c_str());
@@ -295,10 +295,10 @@ void map_lua_marker::read(tagHeader &th)
check_register_table();
}
-map_marker *map_lua_marker::read(tagHeader &th, map_marker_type)
+map_marker *map_lua_marker::read(reader &inf, map_marker_type)
{
map_marker *marker = new map_lua_marker;
- marker->read(th);
+ marker->read(inf);
return (marker);
}
@@ -412,24 +412,24 @@ map_corruption_marker::map_corruption_marker(const coord_def &p,
{
}
-void map_corruption_marker::write(tagHeader &out) const
+void map_corruption_marker::write(writer &out) const
{
map_marker::write(out);
marshallShort(out, duration);
marshallShort(out, radius);
}
-void map_corruption_marker::read(tagHeader &in)
+void map_corruption_marker::read(reader &in)
{
map_marker::read(in);
duration = unmarshallShort(in);
radius = unmarshallShort(in);
}
-map_marker *map_corruption_marker::read(tagHeader &th, map_marker_type)
+map_marker *map_corruption_marker::read(reader &in, map_marker_type)
{
map_corruption_marker *mc = new map_corruption_marker();
- mc->read(th);
+ mc->read(in);
return (mc);
}
@@ -460,7 +460,7 @@ map_wiz_props_marker::map_wiz_props_marker(
{
}
-void map_wiz_props_marker::write(tagHeader &outf) const
+void map_wiz_props_marker::write(writer &outf) const
{
this->map_marker::write(outf);
marshallShort(outf, properties.size());
@@ -472,7 +472,7 @@ void map_wiz_props_marker::write(tagHeader &outf) const
}
}
-void map_wiz_props_marker::read(tagHeader &inf)
+void map_wiz_props_marker::read(reader &inf)
{
map_marker::read(inf);
@@ -515,7 +515,7 @@ map_marker *map_wiz_props_marker::clone() const
return new map_wiz_props_marker(*this);
}
-map_marker *map_wiz_props_marker::read(tagHeader &inf, map_marker_type)
+map_marker *map_wiz_props_marker::read(reader &inf, map_marker_type)
{
map_marker *mapf = new map_wiz_props_marker();
mapf->read(inf);
@@ -718,22 +718,22 @@ void map_markers::clear()
markers.clear();
}
-void map_markers::write(tagHeader &th) const
+void map_markers::write(writer &outf) const
{
// how many markers
- marshallShort(th, markers.size());
+ marshallShort(outf, markers.size());
for (dgn_marker_map::const_iterator i = markers.begin();
i != markers.end(); ++i)
{
- i->second->write(th);
+ i->second->write(outf);
}
}
-void map_markers::read(tagHeader &th)
+void map_markers::read(reader &inf)
{
clear();
- const int nmarkers = unmarshallShort(th);
+ const int nmarkers = unmarshallShort(inf);
for (int i = 0; i < nmarkers; ++i)
- if (map_marker *mark = map_marker::read_marker(th))
+ if (map_marker *mark = map_marker::read_marker(inf))
add(mark);
}
diff --git a/crawl-ref/source/mapmark.h b/crawl-ref/source/mapmark.h
index a152ac7021..b5f9ce5e3e 100644
--- a/crawl-ref/source/mapmark.h
+++ b/crawl-ref/source/mapmark.h
@@ -20,7 +20,8 @@
//////////////////////////////////////////////////////////////////////////
// Map markers
-struct tagHeader;
+class reader;
+class writer;
class map_marker
{
@@ -32,13 +33,13 @@ public:
virtual map_marker *clone() const = 0;
virtual void activate(bool verbose = true);
- virtual void write(tagHeader &) const;
- virtual void read(tagHeader &);
+ virtual void write(writer &) const;
+ virtual void read(reader &);
virtual std::string debug_describe() const = 0;
virtual std::string feature_description() const;
virtual std::string property(const std::string &pname) const;
- static map_marker *read_marker(tagHeader&);
+ static map_marker *read_marker(reader &);
static map_marker *parse_marker(const std::string &text,
const std::string &ctx = "")
throw (std::string);
@@ -49,7 +50,7 @@ public:
protected:
map_marker_type type;
- typedef map_marker *(*marker_reader)(tagHeader &, map_marker_type);
+ typedef map_marker *(*marker_reader)(reader &, map_marker_type);
typedef map_marker *(*marker_parser)(const std::string &,
const std::string &);
static marker_reader readers[NUM_MAP_MARKER_TYPES];
@@ -62,11 +63,11 @@ public:
map_feature_marker(const coord_def &pos = coord_def(0, 0),
dungeon_feature_type feat = DNGN_UNSEEN);
map_feature_marker(const map_feature_marker &other);
- void write(tagHeader &) const;
- void read(tagHeader &);
+ void write(writer &) const;
+ void read(reader &);
std::string debug_describe() const;
map_marker *clone() const;
- static map_marker *read(tagHeader &, map_marker_type);
+ static map_marker *read(reader &, map_marker_type);
static map_marker *parse(const std::string &s, const std::string &)
throw (std::string);
@@ -80,12 +81,12 @@ public:
map_corruption_marker(const coord_def &pos = coord_def(0, 0),
int dur = 0);
- void write(tagHeader &) const;
- void read(tagHeader &);
+ void write(writer &) const;
+ void read(reader &);
map_marker *clone() const;
std::string debug_describe() const;
- static map_marker *read(tagHeader &, map_marker_type);
+ static map_marker *read(reader &, map_marker_type);
public:
int duration, radius;
@@ -102,8 +103,8 @@ public:
void activate(bool verbose);
- void write(tagHeader &) const;
- void read(tagHeader &);
+ void write(writer &) const;
+ void read(reader &);
map_marker *clone() const;
std::string debug_describe() const;
std::string feature_description() const;
@@ -111,7 +112,7 @@ public:
void notify_dgn_event(const dgn_event &e);
- static map_marker *read(tagHeader &, map_marker_type);
+ static map_marker *read(reader &, map_marker_type);
static map_marker *parse(const std::string &s, const std::string &)
throw (std::string);
private:
@@ -129,14 +130,14 @@ class map_wiz_props_marker : public map_marker
public:
map_wiz_props_marker(const coord_def &pos = coord_def(0, 0));
map_wiz_props_marker(const map_wiz_props_marker &other);
- void write(tagHeader &) const;
- void read(tagHeader &);
+ void write(writer &) const;
+ void read(reader &);
std::string debug_describe() const;
std::string feature_description() const;
std::string property(const std::string &pname) const;
std::string set_property(const std::string &key, const std::string &val);
map_marker *clone() const;
- static map_marker *read(tagHeader &, map_marker_type);
+ static map_marker *read(reader &, map_marker_type);
static map_marker *parse(const std::string &s, const std::string &)
throw (std::string);
diff --git a/crawl-ref/source/stash.cc b/crawl-ref/source/stash.cc
index f862c21044..dc77699437 100644
--- a/crawl-ref/source/stash.cc
+++ b/crawl-ref/source/stash.cc
@@ -136,14 +136,14 @@ static void fully_identify_item(item_def *item)
static void save_item(FILE *file, const item_def &item)
{
- tagHeader th(file);
- marshallItem(th, item);
+ writer outf(file);
+ marshallItem(outf, item);
}
static void load_item(FILE *file, item_def &item)
{
- tagHeader th(file);
- unmarshallItem(th, item);
+ reader inf(file);
+ unmarshallItem(inf, item);
}
bool Stash::aggressive_verify = true;
diff --git a/crawl-ref/source/store.cc b/crawl-ref/source/store.cc
index ecd55b619f..6feed39058 100644
--- a/crawl-ref/source/store.cc
+++ b/crawl-ref/source/store.cc
@@ -351,7 +351,7 @@ store_val_type CrawlStoreValue::get_type() const
//////////////////////////////
// Read/write from/to savefile
-void CrawlStoreValue::write(tagHeader &th) const
+void CrawlStoreValue::write(writer &th) const
{
ASSERT(!(flags & SFLAG_UNSET));
@@ -423,7 +423,7 @@ void CrawlStoreValue::write(tagHeader &th) const
}
}
-void CrawlStoreValue::read(tagHeader &th)
+void CrawlStoreValue::read(reader &th)
{
type = static_cast<store_val_type>(unmarshallByte(th));
flags = (store_flags) unmarshallByte(th);
@@ -1038,7 +1038,7 @@ CrawlHashTable::~CrawlHashTable()
//////////////////////////////
// Read/write from/to savefile
-void CrawlHashTable::write(tagHeader &th) const
+void CrawlHashTable::write(writer &th) const
{
assert_validity();
if (empty())
@@ -1062,7 +1062,7 @@ void CrawlHashTable::write(tagHeader &th) const
assert_validity();
}
-void CrawlHashTable::read(tagHeader &th)
+void CrawlHashTable::read(reader &th)
{
assert_validity();
@@ -1327,7 +1327,7 @@ CrawlVector::~CrawlVector()
//////////////////////////////
// Read/write from/to savefile
-void CrawlVector::write(tagHeader &th) const
+void CrawlVector::write(writer &th) const
{
assert_validity();
if (empty())
@@ -1352,7 +1352,7 @@ void CrawlVector::write(tagHeader &th) const
assert_validity();
}
-void CrawlVector::read(tagHeader &th)
+void CrawlVector::read(reader &th)
{
assert_validity();
diff --git a/crawl-ref/source/store.h b/crawl-ref/source/store.h
index 727892cd02..a7e49043d7 100644
--- a/crawl-ref/source/store.h
+++ b/crawl-ref/source/store.h
@@ -19,7 +19,8 @@
#include <string>
#include <vector>
-struct tagHeader;
+class reader;
+class writer;
class CrawlHashTable;
class CrawlVector;
struct item_def;
@@ -228,8 +229,8 @@ protected:
CrawlStoreValue(const store_flags flags,
const store_val_type type = SV_NONE);
- void write(tagHeader &th) const;
- void read(tagHeader &th);
+ void write(writer &) const;
+ void read(reader &);
void unset(bool force = false);
@@ -271,8 +272,8 @@ protected:
friend class CrawlStoreValue;
public:
- void write(tagHeader &th) const;
- void read(tagHeader &th);
+ void write(writer &) const;
+ void read(reader &);
store_flags get_default_flags() const;
store_flags set_default_flags(store_flags flags);
@@ -337,8 +338,8 @@ protected:
friend class CrawlStoreValue;
public:
- void write(tagHeader &th) const;
- void read(tagHeader &th);
+ void write(writer &) const;
+ void read(reader &);
store_flags get_default_flags() const;
store_flags set_default_flags(store_flags flags);
diff --git a/crawl-ref/source/tags.cc b/crawl-ref/source/tags.cc
index 62fe026ad0..35736247de 100644
--- a/crawl-ref/source/tags.cc
+++ b/crawl-ref/source/tags.cc
@@ -13,17 +13,13 @@
/* ------------------------- how tags work ----------------------------------
-1. Tag types are enumerated in tags.h, from TAG_VERSION (more a placeholder
- than anything else, it is not actually saved as a tag) to TAG_XXX. NUM_TAGS
- is equal to the actual number of defined tags.
+1. Tag types are enumerated in tags.h.
-2. Tags are created with tag_construct(), which forwards the construction
- request appropriately. tag_write() is then used to write the tag to an
- output stream.
+2. Tags are written to a FILE* using tag_write(tag_type t). The serialization
+ request is forwarded appropriately.
-3. Tags are parsed with tag_read(), which tries to read a tag header and then
- forwards the request appropriately, returning the ID of the tag it found,
- or zero if no tag was found.
+3. Tags are read from a FILE* with tag_read(), which does not need a tag_type
+ argument. A header is read, which tells tag_read what to construct.
4. In order to know which tags are used by a particular file type, a client
calls tag_set_expected( fileType ), which sets up an array of chars.
@@ -91,9 +87,6 @@
#include "tiles.h"
#include "travel.h"
-// THE BIG IMPORTANT TAG CONSTRUCTION/PARSE BUFFER
-static char *tagBuffer = NULL;
-
// defined in overmap.cc
extern std::map<branch_type, level_id> stair_level;
extern std::map<level_pos, shop_type> shops_present;
@@ -104,128 +97,134 @@ extern std::map<level_id, std::string> level_annotations;
// temp file pairs used for file level cleanup
FixedArray < bool, MAX_LEVELS, NUM_BRANCHES > tmp_file_pairs;
-// static helpers
-static void tag_construct_you(tagHeader &th);
-static void tag_construct_you_items(tagHeader &th);
-static void tag_construct_you_dungeon(tagHeader &th);
-static void tag_construct_lost_monsters(tagHeader &th);
-static void tag_construct_lost_items(tagHeader &th);
-static void tag_read_you(tagHeader &th, char minorVersion);
-static void tag_read_you_items(tagHeader &th, char minorVersion);
-static void tag_read_you_dungeon(tagHeader &th);
-static void tag_read_lost_monsters(tagHeader &th, int minorVersion);
-static void tag_read_lost_items(tagHeader &th, int minorVersion);
-
-static void tag_construct_level(tagHeader &th);
-static void tag_construct_level_items(tagHeader &th);
-static void tag_construct_level_monsters(tagHeader &th);
-static void tag_construct_level_attitude(tagHeader &th);
-static void tag_construct_level_tiles(struct tagHeader &th);
-static void tag_read_level(tagHeader &th, char minorVersion);
-static void tag_read_level_items(tagHeader &th, char minorVersion);
-static void tag_read_level_monsters(tagHeader &th, char minorVersion);
-static void tag_read_level_attitude(tagHeader &th);
-static void tag_missing_level_attitude();
-static void tag_read_level_tiles(struct tagHeader &th);
-static void tag_missing_level_tiles();
-
-static void tag_construct_ghost(tagHeader &th);
-static void tag_read_ghost(tagHeader &th, char minorVersion);
-
-static void marshallGhost(tagHeader &th, const ghost_demon &ghost);
-static ghost_demon unmarshallGhost( tagHeader &th );
-
-static void marshallResists(tagHeader &, const mon_resist_def &);
-static void unmarshallResists(tagHeader &, mon_resist_def &);
-
-static void marshallSpells(tagHeader &, const monster_spells &);
-static void unmarshallSpells(tagHeader &, monster_spells &);
-
-static void marshall_monster(tagHeader &th, const monsters &m);
-static void unmarshall_monster(tagHeader &th, monsters &m);
-
-template<typename T, typename T_iter, typename T_marshal>
-static void marshall_iterator(tagHeader &th, T_iter beg, T_iter end,
- T_marshal marshal);
-template<typename T>
-static void unmarshall_vector(tagHeader& th, std::vector<T>& vec,
- T (*T_unmarshall)(tagHeader&));
-
-//////////////////////////////////////////////////////////////////////
-// tagHeader
-
-unsigned char tagHeader::readByte()
+// Reads input in network byte order, from a file or buffer.
+unsigned char reader::readByte()
{
- if (file)
- return static_cast<unsigned char>(fgetc(file));
+ if (_file)
+ return static_cast<unsigned char>(fgetc(_file));
else
- return tagBuffer[offset++];
+ return (*_pbuf)[_read_offset++];
}
-void tagHeader::writeByte(unsigned char ch)
+void reader::read(void *data, size_t size)
{
- if (file)
- fputc(ch, file);
+ if (_file)
+ {
+ if (data)
+ fread(data, 1, size, _file);
+ else
+ fseek(_file, (long)size, SEEK_CUR);
+ }
else
- tagBuffer[offset++] = ch;
+ {
+ ASSERT(_read_offset+size <= _pbuf->size());
+ if (data) memcpy(data, &(*_pbuf)[_read_offset], size);
+ _read_offset += size;
+ }
}
-void tagHeader::write(const void *data, size_t size)
+void writer::writeByte(unsigned char ch)
{
- if (file)
- fwrite(data, 1, size, file);
- else
- {
- memcpy(tagBuffer + offset, data, size);
- offset += size;
+ if (_file)
+ fputc(ch, _file);
+ else {
+ _pbuf->push_back(ch);
}
}
-void tagHeader::read(void *data, size_t size)
+void writer::write(const void *data, size_t size)
{
- if (file)
- fread(data, 1, size, file);
+ if (_file)
+ {
+ fwrite(data, 1, size, _file);
+ }
else
{
- memcpy(data, tagBuffer + offset, size);
- offset += size;
+ const unsigned char* cdata = static_cast<const unsigned char*>(data);
+ _pbuf->insert(_pbuf->end(), cdata, cdata+size);
}
}
-void tagHeader::advance(int skip)
-{
- if (file)
- fseek(file, skip, SEEK_CUR);
- else
- offset += skip;
-}
-//////////////////////////////////////////////////////////////////////
+// static helpers
+static void tag_construct_you(writer &th);
+static void tag_construct_you_items(writer &th);
+static void tag_construct_you_dungeon(writer &th);
+static void tag_construct_lost_monsters(writer &th);
+static void tag_construct_lost_items(writer &th);
+static void tag_read_you(reader &th, char minorVersion);
+static void tag_read_you_items(reader &th, char minorVersion);
+static void tag_read_you_dungeon(reader &th);
+static void tag_read_lost_monsters(reader &th, int minorVersion);
+static void tag_read_lost_items(reader &th, int minorVersion);
+
+static void tag_construct_level(writer &th);
+static void tag_construct_level_items(writer &th);
+static void tag_construct_level_monsters(writer &th);
+static void tag_construct_level_attitude(writer &th);
+static void tag_construct_level_tiles(writer &th);
+static void tag_read_level(reader &th, char minorVersion);
+static void tag_read_level_items(reader &th, char minorVersion);
+static void tag_read_level_monsters(reader &th, char minorVersion);
+static void tag_read_level_attitude(reader &th);
+static void tag_missing_level_attitude();
+static void tag_read_level_tiles(struct reader &th);
+static void tag_missing_level_tiles();
+
+static void tag_construct_ghost(writer &th);
+static void tag_read_ghost(reader &th, char minorVersion);
+
+static void marshallGhost(writer &th, const ghost_demon &ghost);
+static ghost_demon unmarshallGhost( reader &th );
+
+static void marshallResists(writer &, const mon_resist_def &);
+static void unmarshallResists(reader &, mon_resist_def &);
+
+static void marshallSpells(writer &, const monster_spells &);
+static void unmarshallSpells(reader &, monster_spells &);
+
+static void marshall_monster(writer &th, const monsters &m);
+static void unmarshall_monster(reader &th, monsters &m);
+
+template<typename T, typename T_iter, typename T_marshal>
+static void marshall_iterator(writer &th, T_iter beg, T_iter end,
+ T_marshal marshal);
+template<typename T>
+static void unmarshall_vector(reader& th, std::vector<T>& vec,
+ T (*T_unmarshall)(reader&));
+
// provide a wrapper for file writing, just in case.
-int write2(FILE * file, const char *buffer, unsigned int count)
+int write2(FILE * file, const void *buffer, unsigned int count)
{
return fwrite(buffer, 1, count, file);
}
// provide a wrapper for file reading, just in case.
-int read2(FILE * file, char *buffer, unsigned int count)
+int read2(FILE * file, void *buffer, unsigned int count)
{
return fread(buffer, 1, count, file);
}
-void marshallByte(tagHeader &th, char data)
+void marshallByte(writer &th, char data)
{
th.writeByte(data);
}
-char unmarshallByte(tagHeader &th)
+char unmarshallByte(reader &th)
{
return th.readByte();
}
+void marshallShort(std::vector<unsigned char>& buf, short data)
+{
+ COMPILE_CHECK(sizeof(data)==2, c1);
+ buf.push_back((unsigned char) ((data & 0xFF00) >> 8));
+ buf.push_back((unsigned char) ((data & 0x00FF) ));
+}
+
// marshall 2 byte short in network order
-void marshallShort(tagHeader &th, short data)
+void marshallShort(writer &th, short data)
{
const char b2 = (char)(data & 0x00FF);
const char b1 = (char)((data & 0xFF00) >> 8);
@@ -234,7 +233,7 @@ void marshallShort(tagHeader &th, short data)
}
// unmarshall 2 byte short in network order
-short unmarshallShort(tagHeader &th)
+short unmarshallShort(reader &th)
{
short b1 = th.readByte();
short b2 = th.readByte();
@@ -242,8 +241,17 @@ short unmarshallShort(tagHeader &th)
return data;
}
+void marshallLong(std::vector<unsigned char>& buf, long data)
+{
+ COMPILE_CHECK(sizeof(data)==4, c1);
+ buf.push_back((unsigned char) ((data & 0xFF000000) >> 24));
+ buf.push_back((unsigned char) ((data & 0x00FF0000) >> 16));
+ buf.push_back((unsigned char) ((data & 0x0000FF00) >> 8));
+ buf.push_back((unsigned char) ((data & 0x000000FF) ));
+}
+
// marshall 4 byte int in network order
-void marshallLong(tagHeader &th, long data)
+void marshallLong(writer &th, long data)
{
char b4 = (char) (data & 0x000000FF);
char b3 = (char)((data & 0x0000FF00) >> 8);
@@ -257,7 +265,7 @@ void marshallLong(tagHeader &th, long data)
}
// unmarshall 4 byte int in network order
-long unmarshallLong(tagHeader &th)
+long unmarshallLong(reader &th)
{
long b1 = th.readByte();
long b2 = th.readByte();
@@ -270,15 +278,15 @@ long unmarshallLong(tagHeader &th)
}
template<typename T>
-void marshall_as_long(tagHeader& th, const T& t)
+void marshall_as_long(writer& th, const T& t)
{
marshallLong( th, static_cast<long>(t) );
}
template<typename key, typename value>
-void marshallMap(tagHeader &th, const std::map<key,value>& data,
- void (*key_marshall)(tagHeader&, const key&),
- void (*value_marshall)(tagHeader&, const value&))
+void marshallMap(writer &th, const std::map<key,value>& data,
+ void (*key_marshall)(writer&, const key&),
+ void (*value_marshall)(writer&, const value&))
{
marshallLong( th, data.size() );
typename std::map<key,value>::const_iterator ci;
@@ -290,7 +298,7 @@ void marshallMap(tagHeader &th, const std::map<key,value>& data,
}
template<typename T_iter, typename T_marshall_t>
-static void marshall_iterator(tagHeader &th, T_iter beg, T_iter end,
+static void marshall_iterator(writer &th, T_iter beg, T_iter end,
T_marshall_t T_marshall)
{
marshallLong(th, std::distance(beg, end));
@@ -302,8 +310,8 @@ static void marshall_iterator(tagHeader &th, T_iter beg, T_iter end,
}
template<typename T>
-static void unmarshall_vector(tagHeader& th, std::vector<T>& vec,
- T (*T_unmarshall)(tagHeader&))
+static void unmarshall_vector(reader& th, std::vector<T>& vec,
+ T (*T_unmarshall)(reader&))
{
vec.clear();
const long num_to_read = unmarshallLong(th);
@@ -312,7 +320,7 @@ static void unmarshall_vector(tagHeader& th, std::vector<T>& vec,
}
template <typename T_container, typename T_inserter, typename T_unmarshall>
-static void unmarshall_container(tagHeader &th, T_container &container,
+static void unmarshall_container(reader &th, T_container &container,
T_inserter inserter, T_unmarshall unmarshal)
{
container.clear();
@@ -321,14 +329,14 @@ static void unmarshall_container(tagHeader &th, T_container &container,
(container.*inserter)(unmarshal(th));
}
-void marshall_level_id( tagHeader& th, const level_id& id )
+void marshall_level_id( writer& th, const level_id& id )
{
marshallByte(th, id.branch );
marshallLong(th, id.depth );
marshallByte(th, id.level_type);
}
-void marshall_level_pos( tagHeader& th, const level_pos& lpos )
+void marshall_level_pos( writer& th, const level_pos& lpos )
{
marshallLong(th, lpos.pos.x);
marshallLong(th, lpos.pos.y);
@@ -336,9 +344,9 @@ void marshall_level_pos( tagHeader& th, const level_pos& lpos )
}
template<typename key, typename value, typename map>
-void unmarshallMap(tagHeader& th, map& data,
- key (*key_unmarshall) (tagHeader&),
- value (*value_unmarshall)(tagHeader&) )
+void unmarshallMap(reader& th, map& data,
+ key (*key_unmarshall) (reader&),
+ value (*value_unmarshall)(reader&) )
{
long i, len = unmarshallLong(th);
key k;
@@ -351,12 +359,12 @@ void unmarshallMap(tagHeader& th, map& data,
}
template<typename T>
-T unmarshall_long_as( tagHeader& th )
+T unmarshall_long_as( reader& th )
{
return static_cast<T>(unmarshallLong(th));
}
-level_id unmarshall_level_id( tagHeader& th )
+level_id unmarshall_level_id( reader& th )
{
level_id id;
id.branch = static_cast<branch_type>(unmarshallByte(th));
@@ -365,7 +373,7 @@ level_id unmarshall_level_id( tagHeader& th )
return (id);
}
-level_pos unmarshall_level_pos( tagHeader& th )
+level_pos unmarshall_level_pos( reader& th )
{
level_pos lpos;
lpos.pos.x = unmarshallLong(th);
@@ -374,20 +382,20 @@ level_pos unmarshall_level_pos( tagHeader& th )
return lpos;
}
-void marshallCoord(tagHeader &th, const coord_def &c)
+void marshallCoord(writer &th, const coord_def &c)
{
marshallShort(th, c.x);
marshallShort(th, c.y);
}
-void unmarshallCoord(tagHeader &th, coord_def &c)
+void unmarshallCoord(reader &th, coord_def &c)
{
c.x = unmarshallShort(th);
c.y = unmarshallShort(th);
}
template <typename marshall, typename grid>
-void run_length_encode(tagHeader &th, marshall m, const grid &g,
+void run_length_encode(writer &th, marshall m, const grid &g,
int width, int height)
{
int last = 0, nlast = 0;
@@ -416,7 +424,7 @@ void run_length_encode(tagHeader &th, marshall m, const grid &g,
}
template <typename unmarshall, typename grid>
-void run_length_decode(tagHeader &th, unmarshall um, grid &g,
+void run_length_decode(reader &th, unmarshall um, grid &g,
int width, int height)
{
const int end = width * height;
@@ -445,7 +453,7 @@ union float_marshall_kludge
};
// single precision float -- marshall in network order.
-void marshallFloat(tagHeader &th, float data)
+void marshallFloat(writer &th, float data)
{
float_marshall_kludge k;
k.f_num = data;
@@ -453,7 +461,7 @@ void marshallFloat(tagHeader &th, float data)
}
// single precision float -- unmarshall in network order.
-float unmarshallFloat(tagHeader &th)
+float unmarshallFloat(reader &th)
{
float_marshall_kludge k;
k.l_num = unmarshallLong(th);
@@ -461,7 +469,7 @@ float unmarshallFloat(tagHeader &th)
}
// string -- marshall length & string data
-void marshallString(tagHeader &th, const std::string &data, int maxSize)
+void marshallString(writer &th, const std::string &data, int maxSize)
{
// allow for very long strings (well, up to 32K).
int len = data.length();
@@ -475,13 +483,13 @@ void marshallString(tagHeader &th, const std::string &data, int maxSize)
}
// To pass to marsahllMap
-static void marshall_string(tagHeader &th, const std::string &data)
+static void marshallStringNoMax(writer &th, const std::string &data)
{
marshallString(th, data);
}
// string -- unmarshall length & string data
-int unmarshallCString(tagHeader &th, char *data, int maxSize)
+int unmarshallCString(reader &th, char *data, int maxSize)
{
// get length
short len = unmarshallShort(th);
@@ -494,11 +502,11 @@ int unmarshallCString(tagHeader &th, char *data, int maxSize)
th.read(data, copylen);
data[copylen] = 0;
- th.advance(len - copylen);
+ th.read(NULL, len - copylen);
return (copylen);
}
-std::string unmarshallString(tagHeader &th, int maxSize)
+std::string unmarshallString(reader &th, int maxSize)
{
if (maxSize <= 0)
return ("");
@@ -513,13 +521,13 @@ std::string unmarshallString(tagHeader &th, int maxSize)
}
// To pass to unmarshallMap
-static std::string unmarshall_string(tagHeader &th)
+static std::string unmarshallStringNoMax(reader &th)
{
return unmarshallString(th);
}
// boolean (to avoid system-dependant bool implementations)
-void marshallBoolean(tagHeader &th, bool data)
+void marshallBoolean(writer &th, bool data)
{
char charRep = 0; // for false
if (data)
@@ -529,7 +537,7 @@ void marshallBoolean(tagHeader &th, bool data)
}
// boolean (to avoid system-dependant bool implementations)
-bool unmarshallBoolean(tagHeader &th)
+bool unmarshallBoolean(reader &th)
{
bool data;
const char read = th.readByte();
@@ -594,20 +602,12 @@ time_t parse_date_string( char buff[20] )
return (mktime( &date ));
}
-// PUBLIC TAG FUNCTIONS
-void tag_init(long largest_tag)
-{
- if (tagBuffer != NULL)
- return;
-
- tagBuffer = (char *)malloc(largest_tag);
-}
-
-void tag_construct(tagHeader &th, int tagID)
+// Write a tagged chunk of data to the FILE*.
+// tagId specifies what to write.
+void tag_write(tag_type tagID, FILE* outf)
{
- th.offset = 0;
- th.tagID = tagID;
-
+ std::vector<unsigned char> buf;
+ writer th(&buf);
switch(tagID)
{
case TAG_YOU:
@@ -645,75 +645,49 @@ void tag_construct(tagHeader &th, int tagID)
// I don't know how to make that!
break;
}
-}
-
-void tag_write(tagHeader &th, FILE *saveFile)
-{
- const int tagHdrSize = 6;
- int tagSize=0;
-
- char swap[tagHdrSize];
// make sure there is some data to write!
- if (th.offset == 0)
+ if (buf.size() == 0)
return;
- // special case: TAG_VERSION. Skip tag header.
- if (th.tagID != TAG_VERSION)
+ // Write tag header.
{
- // swap out first few bytes
- memcpy(swap, tagBuffer, tagHdrSize);
-
- // save tag size
- tagSize = th.offset;
-
- // swap in the header
- th.offset = 0;
- marshallShort(th, th.tagID);
- marshallLong(th, tagSize);
-
- // write header
- write2(saveFile, tagBuffer, th.offset);
-
- // swap real data back in
- memcpy(tagBuffer, swap, tagHdrSize);
-
- // reset tag size
- th.offset = tagSize;
+ writer tmp(outf);
+ marshallShort(tmp, tagID);
+ marshallLong(tmp, buf.size());
}
// write tag data
- write2(saveFile, tagBuffer, th.offset);
- return;
+ write2(outf, &buf[0], buf.size());
}
+// Read a single tagged chunk of data from fp into memory.
+// TAG_NO_TAG is returned if there's nothing left to read in the file
+// (or on an error).
+//
// minorVersion is available for any sub-readers that need it
// (like TAG_LEVEL_MONSTERS)
-int tag_read(FILE *fp, char minorVersion)
+tag_type tag_read(FILE *fp, char minorVersion)
{
- const int tagHdrSize = 6;
- tagHeader hdr, th;
- th.offset = 0;
-
- // read tag header
- if (read2(fp, tagBuffer, tagHdrSize) != tagHdrSize)
- return 0;
-
- // unmarshall tag type and length (not including header)
- hdr.tagID = unmarshallShort(th);
- hdr.offset = unmarshallLong(th);
-
- // sanity check
- if (hdr.tagID <= 0 || hdr.offset <= 0)
- return 0;
-
- // now reset th and read actual data
- th.offset = 0;
- if (read2(fp, tagBuffer, hdr.offset) != hdr.offset)
- return 0;
+ // Read header info and data
+ short tag_id;
+ std::vector<unsigned char> buf;
+ {
+ reader tmp(fp);
+ tag_id = unmarshallShort(tmp);
+ if (tag_id < 0) return TAG_NO_TAG;
+ const long data_size = unmarshallLong(tmp);
+ if (data_size < 0) return TAG_NO_TAG;
+
+ // Fetch data in one go
+ buf.resize(data_size);
+ if (read2(fp, &buf[0], buf.size()) != (int)buf.size())
+ return TAG_NO_TAG;
+ }
// ok, we have data now.
- switch(hdr.tagID)
+ reader th(buf);
+ switch (tag_id)
{
case TAG_YOU:
tag_read_you(th, minorVersion);
@@ -748,10 +722,11 @@ int tag_read(FILE *fp, char minorVersion)
break;
default:
// I don't know how to read that!
- return 0;
+ ASSERT(false);
+ return TAG_NO_TAG;
}
- return hdr.tagID;
+ return (tag_type)tag_id;
}
@@ -777,8 +752,8 @@ void tag_missing(int tag, char minorVersion)
case TAG_LEVEL_TILES:
tag_missing_level_tiles();
break;
- default:
- perror("Tag %d is missing; file is likely corrupt.");
+ default:
+ perror("Tag is missing; file is likely corrupt.");
end(-1);
}
}
@@ -832,7 +807,7 @@ void tag_set_expected(char tags[], int fileType)
// be restored even if a later version increases these constants.
// --------------------------- player tags (foo.sav) -------------------- //
-static void tag_construct_you(tagHeader &th)
+static void tag_construct_you(writer &th)
{
int i,j;
@@ -1009,7 +984,7 @@ static void tag_construct_you(tagHeader &th)
marshallByte(th, you.piety_hysteresis);
}
-static void tag_construct_you_items(tagHeader &th)
+static void tag_construct_you_items(writer &th)
{
int i,j;
@@ -1056,7 +1031,7 @@ static void tag_construct_you_items(tagHeader &th)
marshallBoolean(th, does_unrandart_exist(j));
}
-static void marshallPlaceInfo(tagHeader &th, PlaceInfo place_info)
+static void marshallPlaceInfo(writer &th, PlaceInfo place_info)
{
marshallLong(th, place_info.level_type);
marshallLong(th, place_info.branch);
@@ -1085,7 +1060,7 @@ static void marshallPlaceInfo(tagHeader &th, PlaceInfo place_info)
marshallFloat(th, place_info.elapsed_other);
}
-static void tag_construct_you_dungeon(tagHeader &th)
+static void tag_construct_you_dungeon(writer &th)
{
int i,j;
@@ -1116,7 +1091,7 @@ static void tag_construct_you_dungeon(tagHeader &th)
marshallMap(th, portals_present,
marshall_level_pos, marshall_as_long<portal_type>);
marshallMap(th, level_annotations,
- marshall_level_id, marshall_string);
+ marshall_level_id, marshallStringNoMax);
marshallPlaceInfo(th, you.global_info);
std::vector<PlaceInfo> list = you.get_all_place_info();
@@ -1127,26 +1102,26 @@ static void tag_construct_you_dungeon(tagHeader &th)
marshallPlaceInfo(th, list[k]);
marshall_iterator(th, you.uniq_map_tags.begin(), you.uniq_map_tags.end(),
- marshall_string);
+ marshallStringNoMax);
marshall_iterator(th, you.uniq_map_names.begin(), you.uniq_map_names.end(),
- marshall_string);
+ marshallStringNoMax);
}
-static void marshall_follower(tagHeader &th, const follower &f)
+static void marshall_follower(writer &th, const follower &f)
{
marshall_monster(th, f.mons);
for (int i = 0; i < NUM_MONSTER_SLOTS; ++i)
marshallItem(th, f.items[i]);
}
-static void unmarshall_follower(tagHeader &th, follower &f)
+static void unmarshall_follower(reader &th, follower &f)
{
unmarshall_monster(th, f.mons);
for (int i = 0; i < NUM_MONSTER_SLOTS; ++i)
unmarshallItem(th, f.items[i]);
}
-static void marshall_follower_list(tagHeader &th, const m_transit_list &mlist)
+static void marshall_follower_list(writer &th, const m_transit_list &mlist)
{
marshallShort( th, mlist.size() );
@@ -1157,7 +1132,7 @@ static void marshall_follower_list(tagHeader &th, const m_transit_list &mlist)
}
}
-static void marshall_item_list(tagHeader &th, const i_transit_list &ilist)
+static void marshall_item_list(writer &th, const i_transit_list &ilist)
{
marshallShort( th, ilist.size() );
@@ -1168,7 +1143,7 @@ static void marshall_item_list(tagHeader &th, const i_transit_list &ilist)
}
}
-static m_transit_list unmarshall_follower_list(tagHeader &th)
+static m_transit_list unmarshall_follower_list(reader &th)
{
m_transit_list mlist;
@@ -1184,7 +1159,7 @@ static m_transit_list unmarshall_follower_list(tagHeader &th)
return (mlist);
}
-static i_transit_list unmarshall_item_list(tagHeader &th)
+static i_transit_list unmarshall_item_list(reader &th)
{
i_transit_list ilist;
@@ -1200,19 +1175,19 @@ static i_transit_list unmarshall_item_list(tagHeader &th)
return (ilist);
}
-static void tag_construct_lost_monsters(tagHeader &th)
+static void tag_construct_lost_monsters(writer &th)
{
marshallMap( th, the_lost_ones, marshall_level_id,
marshall_follower_list );
}
-static void tag_construct_lost_items(tagHeader &th)
+static void tag_construct_lost_items(writer &th)
{
marshallMap( th, transiting_items, marshall_level_id,
marshall_item_list );
}
-static void tag_read_you(tagHeader &th, char minorVersion)
+static void tag_read_you(reader &th, char minorVersion)
{
char buff[20]; // For birth date
int i,j;
@@ -1388,7 +1363,7 @@ static void tag_read_you(tagHeader &th, char minorVersion)
you.piety_hysteresis = unmarshallByte(th);
}
-static void tag_read_you_items(tagHeader &th, char minorVersion)
+static void tag_read_you_items(reader &th, char minorVersion)
{
int i,j;
char count_c, count_c2;
@@ -1465,7 +1440,7 @@ static void tag_read_you_items(tagHeader &th, char minorVersion)
set_unrandart_exist(j, false);
}
-static PlaceInfo unmarshallPlaceInfo(tagHeader &th)
+static PlaceInfo unmarshallPlaceInfo(reader &th)
{
PlaceInfo place_info;
@@ -1498,7 +1473,7 @@ static PlaceInfo unmarshallPlaceInfo(tagHeader &th)
return place_info;
}
-static void tag_read_you_dungeon(tagHeader &th)
+static void tag_read_you_dungeon(reader &th)
{
int i,j;
int count_c;
@@ -1542,7 +1517,7 @@ static void tag_read_you_dungeon(tagHeader &th)
unmarshallMap(th, portals_present,
unmarshall_level_pos, unmarshall_long_as<portal_type>);
unmarshallMap(th, level_annotations,
- unmarshall_level_id, unmarshall_string);
+ unmarshall_level_id, unmarshallStringNoMax);
PlaceInfo place_info = unmarshallPlaceInfo(th);
ASSERT(place_info.is_global());
@@ -1566,14 +1541,14 @@ static void tag_read_you_dungeon(tagHeader &th)
unmarshall_container(th, you.uniq_map_tags,
(ssipair (string_set::*)(const std::string &))
&string_set::insert,
- unmarshall_string);
+ unmarshallStringNoMax);
unmarshall_container(th, you.uniq_map_names,
(ssipair (string_set::*)(const std::string &))
&string_set::insert,
- unmarshall_string);
+ unmarshallStringNoMax);
}
-static void tag_read_lost_monsters(tagHeader &th, int minorVersion)
+static void tag_read_lost_monsters(reader &th, int minorVersion)
{
the_lost_ones.clear();
@@ -1581,7 +1556,7 @@ static void tag_read_lost_monsters(tagHeader &th, int minorVersion)
unmarshall_level_id, unmarshall_follower_list);
}
-static void tag_read_lost_items(tagHeader &th, int minorVersion)
+static void tag_read_lost_items(reader &th, int minorVersion)
{
transiting_items.clear();
@@ -1591,7 +1566,7 @@ static void tag_read_lost_items(tagHeader &th, int minorVersion)
// ------------------------------- level tags ---------------------------- //
-static void tag_construct_level(tagHeader &th)
+static void tag_construct_level(writer &th)
{
marshallByte(th, env.floor_colour);
marshallByte(th, env.rock_colour);
@@ -1657,7 +1632,7 @@ static void tag_construct_level(tagHeader &th)
env.markers.write(th);
}
-void marshallItem(tagHeader &th, const item_def &item)
+void marshallItem(writer &th, const item_def &item)
{
marshallByte(th, item.base_type);
marshallByte(th, item.sub_type);
@@ -1686,7 +1661,7 @@ void marshallItem(tagHeader &th, const item_def &item)
item.props.write(th);
}
-void unmarshallItem(tagHeader &th, item_def &item)
+void unmarshallItem(reader &th, item_def &item)
{
item.base_type = static_cast<object_class_type>(unmarshallByte(th));
item.sub_type = (unsigned char) unmarshallByte(th);
@@ -1712,7 +1687,7 @@ void unmarshallItem(tagHeader &th, item_def &item)
item.props.read(th);
}
-static void tag_construct_level_items(tagHeader &th)
+static void tag_construct_level_items(writer &th)
{
// how many traps?
marshallShort(th, MAX_TRAPS);
@@ -1729,7 +1704,7 @@ static void tag_construct_level_items(tagHeader &th)
marshallItem(th, mitm[i]);
}
-static void marshall_mon_enchant(tagHeader &th, const mon_enchant &me)
+static void marshall_mon_enchant(writer &th, const mon_enchant &me)
{
marshallShort(th, me.ench);
marshallShort(th, me.degree);
@@ -1738,7 +1713,7 @@ static void marshall_mon_enchant(tagHeader &th, const mon_enchant &me)
marshallShort(th, me.maxduration);
}
-static mon_enchant unmarshall_mon_enchant(tagHeader &th)
+static mon_enchant unmarshall_mon_enchant(reader &th)
{
mon_enchant me;
me.ench = static_cast<enchant_type>( unmarshallShort(th) );
@@ -1749,7 +1724,7 @@ static mon_enchant unmarshall_mon_enchant(tagHeader &th)
return (me);
}
-static void marshall_monster(tagHeader &th, const monsters &m)
+static void marshall_monster(writer &th, const monsters &m)
{
marshallByte(th, m.ac);
marshallByte(th, m.ev);
@@ -1792,7 +1767,7 @@ static void marshall_monster(tagHeader &th, const monsters &m)
}
}
-static void tag_construct_level_monsters(tagHeader &th)
+static void tag_construct_level_monsters(writer &th)
{
// how many mons_alloc?
marshallByte(th, 20);
@@ -1808,7 +1783,7 @@ static void tag_construct_level_monsters(tagHeader &th)
marshall_monster(th, menv[i]);
}
-void tag_construct_level_attitude(tagHeader &th)
+void tag_construct_level_attitude(writer &th)
{
int i;
@@ -1822,7 +1797,7 @@ void tag_construct_level_attitude(tagHeader &th)
}
}
-void tag_construct_level_tiles(struct tagHeader &th)
+void tag_construct_level_tiles(writer &th)
{
#ifdef USE_TILE
unsigned short rle_count = 0; // for run-length encoding
@@ -1914,7 +1889,7 @@ void tag_construct_level_tiles(struct tagHeader &th)
#endif
}
-static void tag_read_level( tagHeader &th, char minorVersion )
+static void tag_read_level( reader &th, char minorVersion )
{
env.floor_colour = unmarshallByte(th);
env.rock_colour = unmarshallByte(th);
@@ -1986,7 +1961,7 @@ static void tag_read_level( tagHeader &th, char minorVersion )
env.markers.read(th);
}
-static void tag_read_level_items(tagHeader &th, char minorVersion)
+static void tag_read_level_items(reader &th, char minorVersion)
{
// how many traps?
const int trap_count = unmarshallShort(th);
@@ -2005,7 +1980,7 @@ static void tag_read_level_items(tagHeader &th, char minorVersion)
unmarshallItem(th, mitm[i]);
}
-static void unmarshall_monster(tagHeader &th, monsters &m)
+static void unmarshall_monster(reader &th, monsters &m)
{
m.ac = unmarshallByte(th);
m.ev = unmarshallByte(th);
@@ -2050,7 +2025,7 @@ static void unmarshall_monster(tagHeader &th, monsters &m)
m.check_speed();
}
-static void tag_read_level_monsters(tagHeader &th, char minorVersion)
+static void tag_read_level_monsters(reader &th, char minorVersion)
{
int i;
int count, icount;
@@ -2075,7 +2050,7 @@ static void tag_read_level_monsters(tagHeader &th, char minorVersion)
}
}
-void tag_read_level_attitude(tagHeader &th)
+void tag_read_level_attitude(reader &th)
{
int i, count;
@@ -2140,7 +2115,7 @@ void tag_missing_level_attitude()
}
}
-void tag_read_level_tiles(struct tagHeader &th)
+void tag_read_level_tiles(struct reader &th)
{
#ifdef USE_TILE
for (int i = 0; i < GXM; i++)
@@ -2227,7 +2202,7 @@ static void tag_missing_level_tiles()
// ------------------------------- ghost tags ---------------------------- //
-static void marshallResists(tagHeader &th, const mon_resist_def &res)
+static void marshallResists(writer &th, const mon_resist_def &res)
{
marshallByte(th, res.elec);
marshallByte(th, res.poison);
@@ -2243,7 +2218,7 @@ static void marshallResists(tagHeader &th, const mon_resist_def &res)
marshallByte(th, res.bludgeon);
}
-static void unmarshallResists(tagHeader &th, mon_resist_def &res)
+static void unmarshallResists(reader &th, mon_resist_def &res)
{
res.elec = unmarshallByte(th);
res.poison = unmarshallByte(th);
@@ -2259,19 +2234,19 @@ static void unmarshallResists(tagHeader &th, mon_resist_def &res)
res.bludgeon = unmarshallByte(th);
}
-static void marshallSpells(tagHeader &th, const monster_spells &spells)
+static void marshallSpells(writer &th, const monster_spells &spells)
{
for (int j = 0; j < NUM_MONSTER_SPELL_SLOTS; ++j)
marshallShort(th, spells[j]);
}
-static void unmarshallSpells(tagHeader &th, monster_spells &spells)
+static void unmarshallSpells(reader &th, monster_spells &spells)
{
for (int j = 0; j < NUM_MONSTER_SPELL_SLOTS; ++j)
spells[j] = static_cast<spell_type>( unmarshallShort(th) );
}
-static void marshallGhost(tagHeader &th, const ghost_demon &ghost)
+static void marshallGhost(writer &th, const ghost_demon &ghost)
{
marshallString(th, ghost.name.c_str(), 20);
@@ -2297,7 +2272,7 @@ static void marshallGhost(tagHeader &th, const ghost_demon &ghost)
marshallSpells(th, ghost.spells);
}
-static ghost_demon unmarshallGhost( tagHeader &th )
+static ghost_demon unmarshallGhost( reader &th )
{
ghost_demon ghost;
@@ -2327,7 +2302,7 @@ static ghost_demon unmarshallGhost( tagHeader &th )
return (ghost);
}
-static void tag_construct_ghost(tagHeader &th)
+static void tag_construct_ghost(writer &th)
{
// How many ghosts?
marshallShort(th, ghosts.size());
@@ -2336,7 +2311,7 @@ static void tag_construct_ghost(tagHeader &th)
marshallGhost(th, ghosts[i]);
}
-static void tag_read_ghost(tagHeader &th, char minorVersion)
+static void tag_read_ghost(reader &th, char minorVersion)
{
int nghosts = unmarshallShort(th);
diff --git a/crawl-ref/source/tags.h b/crawl-ref/source/tags.h
index d93d995035..fc2c176b39 100644
--- a/crawl-ref/source/tags.h
+++ b/crawl-ref/source/tags.h
@@ -18,7 +18,7 @@
enum tag_type // used during save/load process to identify data blocks
{
- TAG_VERSION = 0, // should NEVER be read in!
+ TAG_NO_TAG = 0, // should NEVER be read in!
TAG_YOU = 1, // 'you' structure
TAG_YOU_ITEMS, // your items
TAG_YOU_DUNGEON, // dungeon specs (stairs, branches, features)
@@ -41,107 +41,82 @@ enum tag_file_type // file types supported by tag system
TAGTYPE_PLAYER_NAME // Used only to read the player name
};
-struct tagHeader
-{
- short tagID;
- long offset;
+/* ***********************************************************************
+ * writer API
+ * *********************************************************************** */
- // File handle for direct file writes.
- FILE *file;
+class writer
+{
+public:
+ writer(FILE* output)
+ : _file(output), _pbuf(0) {}
+ writer(std::vector<unsigned char>* poutput)
+ : _file(0), _pbuf(poutput) {}
- tagHeader() : tagID(0), offset(0L), file(NULL) { }
- tagHeader(FILE *f) : tagID(0), offset(0L), file(f) { }
- unsigned char readByte();
void writeByte(unsigned char byte);
void write(const void *data, size_t size);
- void read(void *data, size_t size);
- void advance(int skip);
-};
-
-// last updated 22jan2001 {gdl}
-/* ***********************************************************************
- * called from: files tags
- * *********************************************************************** */
-int write2(FILE * file, const char *buffer, unsigned int count);
+private:
+ FILE* _file;
+ std::vector<unsigned char>* _pbuf;
+};
-// last updated 22jan2001 {gdl}
-/* ***********************************************************************
- * called from: files tags
- * *********************************************************************** */
-int read2(FILE * file, char *buffer, unsigned int count);
-
+void marshallByte (writer &, char );
+void marshallShort (writer &, short );
+void marshallLong (writer &, long );
+void marshallFloat (writer &, float );
+void marshallBoolean (writer &, bool );
+void marshallString (writer &, const std::string &, int maxSize = 0);
+void marshallCoord (writer &, const coord_def &);
+void marshallItem (writer &, const item_def &);
-// last updated 22jan2001 {gdl}
/* ***********************************************************************
- * called from: files tags
+ * reader API
* *********************************************************************** */
-void marshallByte(tagHeader &th, char data);
-void marshallShort(tagHeader &th, short data);
-void marshallLong(tagHeader &th, long data);
-void marshallFloat(tagHeader &th, float data);
-void marshallBoolean(tagHeader &th, bool data);
-void marshallString(tagHeader &th, const std::string &data,
- int maxSize = 0);
-void marshallCoord(tagHeader &th, const coord_def &c);
-void marshallItem(tagHeader &th, const item_def &item);
-
-// last updated 22jan2001 {gdl}
-/* ***********************************************************************
- * called from: tags files
- * *********************************************************************** */
-char unmarshallByte(tagHeader &th);
-short unmarshallShort(tagHeader &th);
-long unmarshallLong(tagHeader &th);
-float unmarshallFloat(tagHeader &th);
-bool unmarshallBoolean(tagHeader &th);
-int unmarshallCString(tagHeader &th, char *data, int maxSize);
-std::string unmarshallString(tagHeader &th, int maxSize = 1000);
-void unmarshallCoord(tagHeader &th, coord_def &c);
-void unmarshallItem(tagHeader &th, item_def &item);
-
-std::string make_date_string( time_t in_date );
-time_t parse_date_string( char[20] );
-// last updated 22jan2001 {gdl}
-/* ***********************************************************************
- * called from: acr
- * *********************************************************************** */
-void tag_init(long largest_tag = 100000);
+class reader
+{
+public:
+ reader(FILE* input)
+ : _file(input), _pbuf(0), _read_offset(0) {}
+ reader(const std::vector<unsigned char>& input)
+ : _file(0), _pbuf(&input), _read_offset(0) {}
+ unsigned char readByte();
+ void read(void *data, size_t size);
-// last updated 22jan2001 {gdl}
-/* ***********************************************************************
- * called from: files
- * *********************************************************************** */
-void tag_construct(tagHeader &th, int i);
+private:
+ FILE* _file;
+ const std::vector<unsigned char>* _pbuf;
+ unsigned int _read_offset;
+};
+char unmarshallByte (reader &);
+short unmarshallShort (reader &);
+long unmarshallLong (reader &);
+float unmarshallFloat (reader &);
+bool unmarshallBoolean (reader &);
+int unmarshallCString (reader &, char *data, int maxSize);
+std::string unmarshallString (reader &, int maxSize = 1000);
+void unmarshallCoord (reader &, coord_def &c);
+void unmarshallItem (reader &, item_def &item);
-// last updated 22jan2001 {gdl}
/* ***********************************************************************
- * called from: files
+ * Tag interface
* *********************************************************************** */
-void tag_write(tagHeader &th, FILE *saveFile);
-
-// last updated 22jan2001 {gdl}
-/* ***********************************************************************
- * called from: files
- * *********************************************************************** */
+tag_type tag_read(FILE* inf, char minorVersion);
+void tag_write(tag_type tagID, FILE* outf);
void tag_set_expected(char tags[], int fileType);
-
-
-// last updated 22jan2001 {gdl}
-/* ***********************************************************************
- * called from: files
- * *********************************************************************** */
void tag_missing(int tag, char minorVersion);
-
-// last updated 22jan2001 {gdl}
/* ***********************************************************************
- * called from: files
+ * misc
* *********************************************************************** */
-int tag_read(FILE *fp, char minorVersion);
+
+int write2(FILE * file, const void *buffer, unsigned int count);
+int read2(FILE * file, void *buffer, unsigned int count);
+std::string make_date_string( time_t in_date );
+time_t parse_date_string( char[20] );
#endif // TAGS_H