1 /* 2 * Copyright (c) 1997 - 2001 Hansj�rg Malthaner 3 * 4 * This file is part of the Simutrans project under the artistic licence. 5 * (see licence.txt) 6 */ 7 8 #ifndef loadsave_h 9 #define loadsave_h 10 11 #include <stdio.h> 12 #include <string> 13 14 #include "../simtypes.h" 15 16 class plainstring; 17 struct file_descriptors_t; 18 19 /** 20 * loadsave_t: 21 * 22 * This class replaces the FILE when loading and saving games. 23 * <p> 24 * Hj. Malthaner, 16-Feb-2002, added zlib compression support 25 * </p> 26 * Can now read and write 3 formats: text, binary and zipped 27 * Input format is automatically detected. 28 * Output format has a default, changeable with set_savemode, but can be 29 * overwritten in wr_open. 30 * 31 * @author V. Meyer, Hj. Malthaner 32 */ 33 34 35 class loadsave_t { 36 public: 37 enum mode_t { 38 binary=0, 39 text=1, 40 xml=2, 41 zipped=4, 42 xml_zipped=6, 43 bzip2=8, 44 xml_bzip2=10 45 }; 46 47 enum file_error_t { 48 FILE_ERROR_OK=0, 49 FILE_ERROR_NOT_EXISTING, 50 FILE_ERROR_BZ_CORRUPT, 51 FILE_ERROR_GZ_CORRUPT, 52 FILE_ERROR_NO_VERSION, 53 FILE_ERROR_FUTURE_VERSION 54 }; 55 56 private: 57 file_error_t last_error; 58 int mode; ///< See mode_t 59 bool saving; 60 bool buffered; 61 unsigned curr_buff; 62 unsigned buf_pos[2]; 63 unsigned buf_len[2]; 64 char* ls_buf[2]; 65 uint32 version; ///< savegame version 66 int ident; // only for XML formatting 67 char pak_extension[64]; // name of the pak folder during savetime 68 69 std::string filename; // the current name ... 70 71 file_descriptors_t *fd; 72 73 // Hajo: putc got a name clash on my system 74 inline void lsputc(int c); 75 76 // Hajo: getc got a name clash on my system 77 inline int lsgetc(); 78 size_t write(const void * buf, size_t len); 79 size_t read(void *buf, size_t len); 80 81 void rdwr_xml_number(sint64 &s, const char *typ); 82 83 loadsave_t(const loadsave_t&); 84 loadsave_t& operator=(const loadsave_t&); 85 86 friend void *save_thread( void *ptr ); 87 friend void *load_thread( void *ptr ); 88 89 /** 90 * Reads into buffer number @p buf_num. 91 * @returns number of bytes read or -1 in case of error 92 */ 93 int fill_buffer(int buf_num); 94 95 void flush_buffer(int buf_num); 96 97 public: 98 static mode_t save_mode; ///< default to use for saving 99 static mode_t autosave_mode; ///< default to use for autosaves and network mode client temp saves 100 101 /** 102 * Parses the version information from @p version_text to a version number. 103 * @param[out] pak Pointer to a sufficiently large buffer (>= 64 chars); when the function returns, 104 * @p pak contains the pakset extension string. May be NULL. 105 * @retval 0 if an error occurred or the save cannot be loaded 106 * @retval !=0 the save version; in this case we can read the save file. 107 */ 108 static uint32 int_version(const char *version_text, char *pak); 109 110 loadsave_t(); 111 ~loadsave_t(); 112 113 bool rd_open(const char *filename); 114 bool wr_open(const char *filename, mode_t mode, const char *pak_extension, const char *savegame_version ); 115 const char *close(); 116 get_last_error()117 file_error_t get_last_error() { return last_error; } 118 set_savemode(mode_t mode)119 static void set_savemode(mode_t mode) { save_mode = mode; } set_autosavemode(mode_t mode)120 static void set_autosavemode(mode_t mode) { autosave_mode = mode; } 121 122 /** 123 * Checks end-of-file 124 * @author Hj. Malthaner 125 */ 126 bool is_eof(); 127 128 void set_buffered(bool enable); get_buf_pos(int buf_num)129 unsigned get_buf_pos(int buf_num) const { return buf_pos[buf_num]; } is_loading()130 bool is_loading() const { return !saving; } is_saving()131 bool is_saving() const { return saving; } is_zipped()132 bool is_zipped() const { return mode&zipped; } is_bzip2()133 bool is_bzip2() const { return mode&bzip2; } is_xml()134 bool is_xml() const { return mode&xml; } get_pak_extension()135 const char *get_pak_extension() const { return pak_extension; } 136 get_version_int()137 uint32 get_version_int() const { return version; } is_version_atleast(uint32 major,uint32 save_minor)138 inline bool is_version_atleast(uint32 major, uint32 save_minor) const { return !is_version_less(major, save_minor); } is_version_less(uint32 major,uint32 save_minor)139 inline bool is_version_less(uint32 major, uint32 save_minor) const { return version < major * 1000U + save_minor; } is_version_equal(uint32 major,uint32 save_minor)140 inline bool is_version_equal(uint32 major, uint32 save_minor) const { return version == major * 1000U + save_minor; } 141 142 void rdwr_byte(sint8 &c); 143 void rdwr_byte(uint8 &c); 144 void rdwr_short(sint16 &i); 145 void rdwr_short(uint16 &i); 146 void rdwr_long(sint32 &i); 147 void rdwr_long(uint32 &i); 148 void rdwr_longlong(sint64 &i); 149 void rdwr_bool(bool &i); 150 void rdwr_double(double &dbl); 151 152 void wr_obj_id(short id); 153 short rd_obj_id(); 154 void wr_obj_id(const char *id_text); 155 void rd_obj_id(char *id_buf, int size); 156 157 // s is a malloc-ed string (will be freed and newly allocated on load time!) 158 void rdwr_str(const char *&s); 159 160 // s is a buf of size given 161 void rdwr_str(char* s, size_t size); 162 163 /** 164 * Read/Write plainstring. 165 * @param str the string to be read/written 166 * @post str should not be NULL after reading. 167 */ 168 void rdwr_str(plainstring& str); 169 170 // only meaningful for XML 171 void start_tag( const char *tag ); 172 void end_tag( const char *tag ); 173 174 // use this for enum types 175 template <class X> rdwr_enum(X & x)176 void rdwr_enum(X &x) 177 { 178 sint32 int_x; 179 180 if(is_saving()) { 181 int_x = (sint32)x; 182 } 183 rdwr_long(int_x); 184 if(is_loading()) { 185 x = (X)int_x; 186 } 187 } 188 }; 189 190 191 192 // this produced semicautomatic hierarchies 193 class xml_tag_t { 194 private: 195 loadsave_t *file; 196 const char *tag; 197 public: xml_tag_t(loadsave_t * f,const char * t)198 xml_tag_t( loadsave_t *f, const char *t ) : file(f), tag(t) { file->start_tag(tag); } ~xml_tag_t()199 ~xml_tag_t() { file->end_tag(tag); } 200 }; 201 202 203 204 #endif 205