/* * File: tags.h * Summary: Auxilary functions to make savefile versioning simpler. * Written by: Gordon Lipford */ #ifndef TAGS_H #define TAGS_H #include #include struct show_type; enum tag_type // used during save/load process to identify data blocks { 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) TAG_LEVEL, // various grids & clouds TAG_LEVEL_ITEMS, // items/traps TAG_LEVEL_MONSTERS, // monsters TAG_GHOST, // ghost TAG_LEVEL_ATTITUDE, // monster attitudes TAG_LOST_MONSTERS, // monsters in transit TAG_LEVEL_TILES, NUM_TAGS }; enum tag_file_type // file types supported by tag system { TAGTYPE_PLAYER = 0, // Foo.sav TAGTYPE_LEVEL, // Foo.00a, .01a, etc. TAGTYPE_GHOST, // bones.xxx TAGTYPE_PLAYER_NAME // Used only to read the player name }; // Let CDO updaters know if the syntax changes. #define TAG_MAJOR_START 5 #define TAG_MAJOR_VERSION 16 // Minor version will be reset to zero when major version changes. enum tag_minor_version { TAG_MINOR_RESET = 0, // Minor tags were reset TAG_MINOR_VERSION = 0 // Current version. (Keep equal to max.) }; struct enum_info { void (*collect)(std::vector >& prs); int replacement; struct enum_val { int value; const char *name; }; const enum_val *historical; tag_minor_version non_historical_first; char historic_bytes; }; struct enum_write_state { std::set used; std::map names; char store_type; enum_write_state() : used(), names(), store_type(0) {} }; struct enum_read_state { std::map mapping; std::map names; char store_type; enum_read_state() : mapping(), names(), store_type(0) {} }; template struct enum_details; // TO ADD A NEW ENUM UNDER THE UMBRELLA OF marshallEnum: // * Create an enum_info instance // * Instanciate the enum_details template // * Change existing serialization to use marshallEnum // * Bump minor version /* *********************************************************************** * writer API * *********************************************************************** */ class writer { public: writer(FILE* output) : _file(output), _pbuf(0) {} writer(std::vector* poutput) : _file(0), _pbuf(poutput) {} void writeByte(unsigned char byte); void write(const void *data, size_t size); long tell(); private: FILE* _file; std::vector* _pbuf; std::map used_enums; friend void marshallEnumVal(writer&, const enum_info*, int); }; void marshallByte (writer &, const char& ); void marshallShort (writer &, int16_t ); void marshallLong (writer &, int32_t ); void marshallFloat (writer &, float ); void marshallBoolean (writer &, bool ); void marshallString (writer &, const std::string &, int maxSize = 0); void marshallString4 (writer &, const std::string &); void marshallCoord (writer &, const coord_def &); void marshallItem (writer &, const item_def &); void marshallMonster (writer &, const monsters &); void marshallShowtype (writer &, const show_type &); void marshallEnumVal (writer &, const enum_info *, int); template inline void marshallEnum(writer& wr, enm value) { marshallEnumVal(wr, &enum_details::desc, static_cast(value)); } /* *********************************************************************** * reader API * *********************************************************************** */ class reader { public: reader(FILE* input, char minorVersion = TAG_MINOR_VERSION) : _file(input), _pbuf(0), _read_offset(0), _minorVersion(minorVersion) {} reader(const std::vector& input, char minorVersion = TAG_MINOR_VERSION) : _file(0), _pbuf(&input), _read_offset(0), _minorVersion(minorVersion) {} unsigned char readByte(); void read(void *data, size_t size); char getMinorVersion(); private: FILE* _file; const std::vector* _pbuf; unsigned int _read_offset; char _minorVersion; std::map seen_enums; friend int unmarshallEnumVal(reader &, const enum_info *); }; char unmarshallByte (reader &); int16_t unmarshallShort (reader &); int32_t unmarshallLong (reader &); float unmarshallFloat (reader &); bool unmarshallBoolean (reader &); int unmarshallCString (reader &, char *data, int maxSize); std::string unmarshallString (reader &, int maxSize = 1000); void unmarshallString4 (reader &, std::string&); void unmarshallCoord (reader &, coord_def &c); void unmarshallItem (reader &, item_def &item); void unmarshallMonster (reader &, monsters &item); show_type unmarshallShowtype (reader &); int unmarshallEnumVal (reader &, const enum_info *); template inline enm unmarshallEnum(writer& wr) { return static_cast(unmarshallEnumVal(wr, &enum_details::desc)); } /* *********************************************************************** * Tag interface * *********************************************************************** */ tag_type tag_read(FILE* inf, char minorVersion); void tag_write(tag_type tagID, FILE* outf); void tag_set_expected(char tags[], int fileType); void tag_missing(int tag, char minorVersion); /* *********************************************************************** * misc * *********************************************************************** */ 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