00001
00002
00003
00004
00005
00006
00007 #ifndef TAGS_H
00008 #define TAGS_H
00009
00010 #include <cstdio>
00011 #include <stdint.h>
00012
00013 #include "tag-version.h"
00014 #include "package.h"
00015
00016 struct show_type;
00017 struct monster_info;
00018 struct map_cell;
00019
00020 enum tag_type
00021 {
00022 TAG_NO_TAG = 0,
00023 TAG_CHR = 1,
00024 TAG_YOU,
00025 TAG_LEVEL,
00026 TAG_GHOST,
00027 NUM_TAGS,
00028
00029
00030
00031 TAG_SKIP
00032 };
00033
00034 struct enum_info
00035 {
00036 void (*collect)(std::vector<std::pair<int,std::string> >& prs);
00037 int replacement;
00038
00039 struct enum_val
00040 {
00041 int value;
00042 const char *name;
00043 };
00044
00045 const enum_val *historical;
00046 tag_minor_version non_historical_first;
00047 char historic_bytes;
00048 };
00049
00050 struct enum_write_state
00051 {
00052 std::set<int> used;
00053 std::map<int, std::string> names;
00054 char store_type;
00055
00056 enum_write_state() : used(), names(), store_type(0) {}
00057 };
00058
00059 struct enum_read_state
00060 {
00061 std::map<int, int> mapping;
00062 std::map<std::string, int> names;
00063 char store_type;
00064
00065 enum_read_state() : mapping(), names(), store_type(0) {}
00066 };
00067
00068 template<typename enm> struct enum_details;
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080 class writer
00081 {
00082 public:
00083 writer(const std::string &filename, FILE* output,
00084 bool ignore_errors = false)
00085 : _filename(filename), _file(output), _chunk(0),
00086 _ignore_errors(ignore_errors), _pbuf(0), failed(false)
00087 {
00088 ASSERT(output);
00089 }
00090 writer(std::vector<unsigned char>* poutput)
00091 : _filename(), _file(0), _chunk(0), _ignore_errors(false),
00092 _pbuf(poutput), failed(false) { ASSERT(poutput); }
00093 writer(package *save, const std::string &chunkname)
00094 : _filename(), _file(0), _chunk(0), _ignore_errors(false),
00095 failed(false)
00096 {
00097 ASSERT(save);
00098 _chunk = save->writer(chunkname);
00099 }
00100
00101 ~writer() { if (_chunk) delete _chunk; }
00102
00103 void writeByte(unsigned char byte);
00104 void write(const void *data, size_t size);
00105 long tell();
00106
00107 bool succeeded() const { return !failed; }
00108
00109 private:
00110 void check_ok(bool ok);
00111
00112 private:
00113 std::string _filename;
00114 FILE* _file;
00115 chunk_writer *_chunk;
00116 bool _ignore_errors;
00117
00118 std::vector<unsigned char>* _pbuf;
00119
00120 bool failed;
00121
00122 std::map<const enum_info*, enum_write_state> used_enums;
00123 friend void marshallEnumVal(writer&, const enum_info*, int);
00124 };
00125
00126 void marshallByte (writer &, int8_t);
00127 void marshallShort (writer &, int16_t);
00128 void marshallInt (writer &, int32_t);
00129 void marshallFloat (writer &, float);
00130 void marshallUByte (writer &, uint8_t);
00131 void marshallBoolean (writer &, bool);
00132 void marshallString (writer &, const std::string &, int maxSize = 0);
00133 void marshallString4 (writer &, const std::string &);
00134 void marshallCoord (writer &, const coord_def &);
00135 void marshallItem (writer &, const item_def &);
00136 void marshallMonster (writer &, const monster&);
00137 void marshallMonsterInfo (writer &, const monster_info &);
00138 void marshallMapCell (writer &, const map_cell &);
00139
00140 void marshallEnumVal (writer &, const enum_info *, int);
00141
00142 template<typename enm>
00143 inline void marshallEnum(writer& wr, enm value)
00144 {
00145 marshallEnumVal(wr, &enum_details<enm>::desc, static_cast<int>(value));
00146 }
00147
00148 void marshallUnsigned(writer& th, uint64_t v);
00149 void marshallSigned(writer& th, int64_t v);
00150
00151
00152
00153
00154
00155 class reader
00156 {
00157 public:
00158 reader(const std::string &filename, int minorVersion = TAG_MINOR_INVALID);
00159 reader(FILE* input, int minorVersion = TAG_MINOR_INVALID)
00160 : _file(input), _chunk(0), opened_file(false), _pbuf(0),
00161 _read_offset(0), _minorVersion(minorVersion) {}
00162 reader(const std::vector<unsigned char>& input,
00163 int minorVersion = TAG_MINOR_INVALID)
00164 : _file(0), _chunk(0), opened_file(false), _pbuf(&input),
00165 _read_offset(0), _minorVersion(minorVersion) {}
00166 reader(package *save, const std::string &chunkname,
00167 int minorVersion = TAG_MINOR_INVALID);
00168 ~reader();
00169
00170 unsigned char readByte();
00171 void read(void *data, size_t size);
00172 void advance(size_t size);
00173 int getMinorVersion() const;
00174 void setMinorVersion(int minorVersion);
00175 bool valid() const;
00176 void fail_if_not_eof(const std::string &name);
00177 void close();
00178
00179 std::string filename() const { return _filename; }
00180
00181 private:
00182 std::string _filename;
00183 FILE* _file;
00184 chunk_reader *_chunk;
00185 bool opened_file;
00186 const std::vector<unsigned char>* _pbuf;
00187 unsigned int _read_offset;
00188 int _minorVersion;
00189
00190 std::map<const enum_info*, enum_read_state> seen_enums;
00191 friend int unmarshallEnumVal(reader &, const enum_info *);
00192 };
00193
00194 class short_read_exception : std::exception {};
00195
00196 int8_t unmarshallByte (reader &);
00197 int16_t unmarshallShort (reader &);
00198 int32_t unmarshallInt (reader &);
00199 float unmarshallFloat (reader &);
00200 uint8_t unmarshallUByte (reader &);
00201 bool unmarshallBoolean (reader &);
00202 std::string unmarshallString (reader &, int maxSize = 1000);
00203 void unmarshallString4 (reader &, std::string&);
00204 coord_def unmarshallCoord (reader &);
00205 void unmarshallItem (reader &, item_def &item);
00206 void unmarshallMonster (reader &, monster& item);
00207 void unmarshallMonsterInfo (reader &, monster_info &mi);
00208 void unmarshallMapCell (reader &, map_cell& cell);
00209
00210 int unmarshallEnumVal (reader &, const enum_info *);
00211
00212 template<typename enm>
00213 inline enm unmarshallEnum(writer& wr)
00214 {
00215 return static_cast<enm>(unmarshallEnumVal(wr, &enum_details<enm>::desc));
00216 }
00217
00218 uint64_t unmarshallUnsigned(reader& th);
00219 template<typename T>
00220 static inline void unmarshallUnsigned(reader& th, T& v)
00221 {
00222 v = (T)unmarshallUnsigned(th);
00223 }
00224
00225 int64_t unmarshallSigned(reader& th);
00226 template<typename T>
00227 static inline void unmarshallSigned(reader& th, T& v)
00228 {
00229 v = (T)unmarshallSigned(th);
00230 }
00231
00232
00233
00234
00235
00236 void tag_read(reader &inf, tag_type tag_id);
00237 void tag_write(tag_type tagID, writer &outf);
00238
00239
00240
00241
00242
00243 std::string make_date_string(time_t in_date);
00244
00245 #endif // TAGS_H