summaryrefslogtreecommitdiffstats
path: root/crawl-ref
diff options
context:
space:
mode:
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