diff options
Diffstat (limited to 'crawl-ref')
-rw-r--r-- | crawl-ref/source/acr.cc | 3 | ||||
-rw-r--r-- | crawl-ref/source/externs.h | 7 | ||||
-rw-r--r-- | crawl-ref/source/files.cc | 29 | ||||
-rw-r--r-- | crawl-ref/source/luadgn.cc | 18 | ||||
-rw-r--r-- | crawl-ref/source/mapmark.cc | 62 | ||||
-rw-r--r-- | crawl-ref/source/mapmark.h | 35 | ||||
-rw-r--r-- | crawl-ref/source/stash.cc | 8 | ||||
-rw-r--r-- | crawl-ref/source/store.cc | 12 | ||||
-rw-r--r-- | crawl-ref/source/store.h | 15 | ||||
-rw-r--r-- | crawl-ref/source/tags.cc | 469 | ||||
-rw-r--r-- | crawl-ref/source/tags.h | 137 |
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 |