running with and without this patch applied for about a week, and none of my saves have broken, so I'm ready to commit it.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@3685 c06c8d41-db1a-0410-9941-cceddc491573
52J7CYVAW3QCUEWA5OKWPDGOP6JZR5NJSE3JDLZFBCR7B6LH5ASAC RS24ZF3Y47QA2534EHQWZ35O2CI4JUOIVHUPRANCCNLVINSCYFXQC L3DRKFURVDCV3EJKGG6GVVQX3D5MZPICTVOKNOD3LGM2PECBA7PQC SVY2PTCLXR3KNPQAWXVXTTGCC5DR334HOAKHYO3VDDRWM2BWMALAC K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC A5H6EHZ5L5Z3BW2MIEJSDZMGTUQIJT6HSQXJVFBN5ZR55SGNNQNQC SDLKLUNFGVKDS55DDJZCBAVIB7NL3RRYPTACAY65SCUQKV6APFSAC 3PY3L3A4QRW3Z5Y7SHO4TMVOOP2VNCO27X2MX4DTOP2SADLBQUOAC IVVTHLTTLOP5TSULXJWUSSXHOKYWVU3OWKYVK45A7RIB6V34MYQAC RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC EGV2HM7SD7UQSWJGLR65NQJTUBAJ7WHLM67FMH4UFP7JRSFKREPAC 7Y5HSDFKA5TPLS2TWTRFMQVX6UXUDHXU5MUMXQSDFAIY4THQ3BIQC 7AMQN7MITMXBNVDAK5VOXTQ4TZIAOD6ZLOFJG7GQMBTY23Y2BKSAC RISMOCQM6BKK4XSIRKYLOBB2UPDYJNDAL6OGIIR5GGNZQAK5YSZAC D27U7RT2C77NEUBP6JCSQJ2DRCJVHOXUO2PFZ45VFYMEVMKI4TSAC DOZORMA366M4HB5JKSS27BMCR6ET7QNZNND2B7KV3NVEEPR5H7EAC 5ASC3STDYCNLZFEBN6UTMUCGDETHBR2OCBZCF5VIAZ5RRWLOTDYQC 7KWDC7XFNMBLSUO2HISIROBINZBX5T67LJEEXTAORXW2YZ7VWFGAC 475LL4U4ND6PTNV4XKC7WQAOJC7RF2VCCVX3DRILP2PKIBFYWE6QC 25CH7HH4LKXFIZ75YNMXS3TSXO6O27DYSOPLOD45K4OCNFWLS4LQC RBAGQ2PB7V5YAM5KSHSZR2E3MLKDSRVM5XYGI2TIXP5QMVBOQHDQC LCCGXSFIDQFIRXHGRJWOELNPQOHHCXCWXS366GOULDFPQVOKAIJAC UZ6N6HOUPGVSPC5NQROEEDWMEGJA5XUWUY2AKH5QG65AZ25PVXDAC AVCMVFA3MKCXHO6H44UK5KJNIHTGQV7UA7GYXM26VI6TXXU5ZN6QC X5WLJCJVW55SXZVP7IKP7ADCJIGNKN4PKAXFECVR6TNK7XSMZR7QC K2GMFKXUWN5R3KCW6OYVXHN47MIQZKEEIOSAU6LFFKBNKF6JBVWAC GQL5SIGBHLU3FMCE54XVGLRY5AZHRM6DUEB722REA2DPLGJSN6EQC TLO257LZSB6ZO36STDUEWJBO2LETXFKTFGXELA6Y4BZBVAEIIINAC L4RYVF46EQKMVOEADGRG4WMPVTQ6NNFGYMU4SHAH6XJIKWVHT77QC EJ4GIPFSSQCQASUMRF4CR2WPUQOTEHFRGLOYEZ7BH6YEMIR6DN4QC AUXHSGS4EFOPZ6TVZYWNVOUDO7NYKUKE3HBKGQQWTALSVFOE3HAAC DKRSOHZXL6EPSLKOKHF7GJXSZEJVY7CXGACSHWLM5B5FTRETWWCAC BW72LH6NR2NBFFKPM3YZSQEDAFNI6AQIJJ6DV4WYCOXW5JZS5Z2QC // last updated 22jan2001 {gdl}/* ************************************************************************ called from: files tags* *********************************************************************** */int write2(FILE * file, const 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* *********************************************************************** */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);
unsigned char readByte();void read(void *data, size_t size);
// 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);
private:FILE* _file;const std::vector<unsigned char>* _pbuf;unsigned int _read_offset;};
// last updated 22jan2001 {gdl}/* ************************************************************************ called from: files* *********************************************************************** */void tag_construct(tagHeader &th, int i);
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_type tag_read(FILE* inf, char minorVersion);void tag_write(tag_type tagID, FILE* outf);
// last updated 22jan2001 {gdl}/* ************************************************************************ called from: files* *********************************************************************** */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] );
1. Tag types are enumerated in tags.h, from TAG_VERSION (more a placeholderthan anything else, it is not actually saved as a tag) to TAG_XXX. NUM_TAGSis 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 constructionrequest appropriately. tag_write() is then used to write the tag to anoutput stream.
2. Tags are written to a FILE* using tag_write(tag_type t). The serializationrequest is forwarded appropriately.
3. Tags are parsed with tag_read(), which tries to read a tag header and thenforwards 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_typeargument. A header is read, which tells tag_read what to construct.
// static helpersstatic 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&));//////////////////////////////////////////////////////////////////////// tagHeaderunsigned char tagHeader::readByte()
// Reads input in network byte order, from a file or buffer.unsigned char reader::readByte()
// static helpersstatic 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();
void tagHeader::advance(int skip){if (file)fseek(file, skip, SEEK_CUR);elseoffset += skip;}
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&));
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) ));}
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&))
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&) )
if (tagBuffer != NULL)return;tagBuffer = (char *)malloc(largest_tag);}void tag_construct(tagHeader &th, int tagID){th.offset = 0;th.tagID = tagID;
std::vector<unsigned char> buf;writer th(&buf);
// swap out first few bytesmemcpy(swap, tagBuffer, tagHdrSize);// save tag sizetagSize = th.offset;// swap in the headerth.offset = 0;marshallShort(th, th.tagID);marshallLong(th, tagSize);// write headerwrite2(saveFile, tagBuffer, th.offset);// swap real data back inmemcpy(tagBuffer, swap, tagHdrSize);// reset tag sizeth.offset = tagSize;
writer tmp(outf);marshallShort(tmp, tagID);marshallLong(tmp, buf.size());
const int tagHdrSize = 6;tagHeader hdr, th;th.offset = 0;
// Read header info and datashort 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;
// read tag headerif (read2(fp, tagBuffer, tagHdrSize) != tagHdrSize)return 0;// unmarshall tag type and length (not including header)hdr.tagID = unmarshallShort(th);hdr.offset = unmarshallLong(th);
// Fetch data in one gobuf.resize(data_size);if (read2(fp, &buf[0], buf.size()) != (int)buf.size())return TAG_NO_TAG;}