OpenMW
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
esmreader.hpp
Go to the documentation of this file.
1 #ifndef OPENMW_ESM_READER_H
2 #define OPENMW_ESM_READER_H
3 
4 #include <stdint.h>
5 #include <string.h>
6 #include <cassert>
7 #include <vector>
8 #include <sstream>
9 
11 
13 
15 
16 #include "esmcommon.hpp"
17 #include "loadtes3.hpp"
18 
19 namespace ESM {
20 
21 class ESMReader
22 {
23 public:
24 
25  ESMReader();
26 
27  /*************************************************************************
28  *
29  * Information retrieval
30  *
31  *************************************************************************/
32 
33  int getVer() const { return mHeader.mData.version; }
34  int getRecordCount() const { return mHeader.mData.records; }
35  float getFVer() const { return (mHeader.mData.version == VER_12) ? 1.2f : 1.3f; }
36  const std::string getAuthor() const { return mHeader.mData.author.toString(); }
37  const std::string getDesc() const { return mHeader.mData.desc.toString(); }
38  const std::vector<Header::MasterData> &getGameFiles() const { return mHeader.mMaster; }
39  const Header& getHeader() const { return mHeader; }
40  int getFormat() const;
41  const NAME &retSubName() const { return mCtx.subName; }
42  uint32_t getSubSize() const { return mCtx.leftSub; }
43  std::string getName() const;
44 
45  /*************************************************************************
46  *
47  * Opening and closing
48  *
49  *************************************************************************/
50 
55 
57  void restoreContext(const ESM_Context &rc);
58 
62  void close();
63 
66  void openRaw(Files::IStreamPtr _esm, const std::string &name);
67 
70  void open(Files::IStreamPtr _esm, const std::string &name);
71 
72  void open(const std::string &file);
73 
74  void openRaw(const std::string &filename);
75 
77  size_t getFileOffset();
78 
79  // This is a quick hack for multiple esm/esp files. Each plugin introduces its own
80  // terrain palette, but ESMReader does not pass a reference to the correct plugin
81  // to the individual load() methods. This hack allows to pass this reference
82  // indirectly to the load() method.
83  int mIdx;
84  void setIndex(const int index) {mIdx = index; mCtx.index = index;}
85  int getIndex() {return mIdx;}
86 
87  void setGlobalReaderList(std::vector<ESMReader> *list) {mGlobalReaderList = list;}
88  std::vector<ESMReader> *getGlobalReaderList() {return mGlobalReaderList;}
89 
90  /*************************************************************************
91  *
92  * Medium-level reading shortcuts
93  *
94  *************************************************************************/
95 
96  // Read data of a given type, stored in a subrecord of a given name
97  template <typename X>
98  void getHNT(X &x, const char* name)
99  {
100  getSubNameIs(name);
101  getHT(x);
102  }
103 
104  // Optional version of getHNT
105  template <typename X>
106  void getHNOT(X &x, const char* name)
107  {
108  if(isNextSub(name))
109  getHT(x);
110  }
111 
112  // Version with extra size checking, to make sure the compiler
113  // doesn't mess up our struct padding.
114  template <typename X>
115  void getHNT(X &x, const char* name, int size)
116  {
117  assert(sizeof(X) == size);
118  getSubNameIs(name);
119  getHT(x);
120  }
121 
122  template <typename X>
123  void getHNOT(X &x, const char* name, int size)
124  {
125  assert(sizeof(X) == size);
126  if(isNextSub(name))
127  getHT(x);
128  }
129 
130  int64_t getHNLong(const char *name);
131 
132  // Get data of a given type/size, including subrecord header
133  template <typename X>
134  void getHT(X &x)
135  {
136  getSubHeader();
137  if (mCtx.leftSub != sizeof(X))
138  {
139  std::stringstream error;
140  error << "getHT(): subrecord size mismatch (requested " << sizeof(X) << ", got " << mCtx.leftSub << ")";
141  fail(error.str());
142  }
143  getT(x);
144  }
145 
146  // Version with extra size checking, to make sure the compiler
147  // doesn't mess up our struct padding.
148  template <typename X>
149  void getHT(X &x, int size)
150  {
151  assert(sizeof(X) == size);
152  getHT(x);
153  }
154 
155  // Read a string by the given name if it is the next record.
156  std::string getHNOString(const char* name);
157 
158  // Read a string with the given sub-record name
159  std::string getHNString(const char* name);
160 
161  // Read a string, including the sub-record header (but not the name)
162  std::string getHString();
163 
164  // Read the given number of bytes from a subrecord
165  void getHExact(void*p, int size);
166 
167  // Read the given number of bytes from a named subrecord
168  void getHNExact(void*p, int size, const char* name);
169 
170  /*************************************************************************
171  *
172  * Low level sub-record methods
173  *
174  *************************************************************************/
175 
176  // Get the next subrecord name and check if it matches the parameter
177  void getSubNameIs(const char* name);
178 
184  bool isNextSub(const char* name);
185 
186  bool peekNextSub(const char* name);
187 
188  // Store the current subrecord name for the next call of getSubName()
189  void cacheSubName();
190 
191  // Read subrecord name. This gets called a LOT, so I've optimized it
192  // slightly.
193  void getSubName();
194 
195  // This is specially optimized for LoadINFO.
196  bool isEmptyOrGetName();
197 
198  // Skip current sub record, including header (but not including
199  // name.)
200  void skipHSub();
201 
202  // Skip sub record and check its size
203  void skipHSubSize(int size);
204 
205  // Skip all subrecords until the given subrecord or no more subrecords remaining
206  void skipHSubUntil(const char* name);
207 
208  /* Sub-record header. This updates leftRec beyond the current
209  sub-record as well. leftSub contains size of current sub-record.
210  */
211  void getSubHeader();
212 
215  void getSubHeaderIs(int size);
216 
217  /*************************************************************************
218  *
219  * Low level record methods
220  *
221  *************************************************************************/
222 
223  // Get the next record name
224  NAME getRecName();
225 
226  // Skip the rest of this record. Assumes the name and header have
227  // already been read
228  void skipRecord();
229 
230  /* Read record header. This updatesleftFile BEYOND the data that
231  follows the header, ie beyond the entire record. You should use
232  leftRec to orient yourself inside the record itself.
233  */
235  void getRecHeader(uint32_t &flags);
236 
237  bool hasMoreRecs() const { return mCtx.leftFile > 0; }
238  bool hasMoreSubs() const { return mCtx.leftRec > 0; }
239 
240 
241  /*************************************************************************
242  *
243  * Lowest level data reading and misc methods
244  *
245  *************************************************************************/
246 
247  template <typename X>
248  void getT(X &x) { getExact(&x, sizeof(X)); }
249 
250  void getExact(void*x, int size);
251  void getName(NAME &name) { getT(name); }
252  void getUint(uint32_t &u) { getT(u); }
253 
254  // Read the next 'size' bytes and return them as a string. Converts
255  // them from native encoding to UTF8 in the process.
256  std::string getString(int size);
257 
258  void skip(int bytes);
259 
261  void fail(const std::string &msg);
262 
264  void setEncoder(ToUTF8::Utf8Encoder* encoder);
265 
267  unsigned int getRecordFlags() { return mRecordFlags; }
268 
269  size_t getFileSize() const { return mFileSize; }
270 
271 private:
273 
275 
276  unsigned int mRecordFlags;
277 
278  // Special file signifier (see SpecialFile enum above)
279 
280  // Buffer for ESM strings
281  std::vector<char> mBuffer;
282 
284 
285  std::vector<ESMReader> *mGlobalReaderList;
287 
288  size_t mFileSize;
289 
290 };
291 }
292 #endif
Files::IStreamPtr mEsm
Definition: esmreader.hpp:272
std::string getString(int size)
Definition: esmreader.cpp:328
void setEncoder(ToUTF8::Utf8Encoder *encoder)
Sets font encoder for ESM strings.
Definition: esmreader.cpp:367
std::string getHNString(const char *name)
Definition: esmreader.cpp:108
const Header & getHeader() const
Definition: esmreader.hpp:39
void openRaw(Files::IStreamPtr _esm, const std::string &name)
Definition: esmreader.cpp:62
void getHNExact(void *p, int size, const char *name)
Definition: esmreader.cpp:148
void getHNT(X &x, const char *name)
Definition: esmreader.hpp:98
int mIdx
Definition: esmreader.hpp:83
Definition: esmreader.hpp:21
unsigned int version
Definition: loadtes3.hpp:27
std::vector< char > mBuffer
Definition: esmreader.hpp:281
Definition: esmcommon.hpp:89
int list(Bsa::BSAFile &bsa, Arguments &info)
Definition: bsatool.cpp:183
unsigned int mRecordFlags
Definition: esmreader.hpp:276
NAME32 author
Definition: loadtes3.hpp:29
Data mData
Definition: loadtes3.hpp:56
uint32_t getSubSize() const
Definition: esmreader.hpp:42
int getIndex()
Definition: esmreader.hpp:85
void getHT(X &x)
Definition: esmreader.hpp:134
bool hasMoreRecs() const
Definition: esmreader.hpp:237
ESM_Context mCtx
Definition: esmreader.hpp:274
void getExact(void *x, int size)
Definition: esmreader.cpp:316
ESM_Context getContext()
Definition: esmreader.cpp:15
size_t getFileOffset()
Get the current position in the file. Make sure that the file has been opened!
Definition: esmreader.cpp:372
int64_t getHNLong(const char *name)
Definition: esmreader.cpp:94
void getSubHeader()
Definition: esmreader.cpp:248
void close()
Definition: esmreader.cpp:50
NAME getRecName()
Definition: esmreader.cpp:267
uint32_t leftRec
Definition: esmcommon.hpp:119
ESMReader()
Definition: esmreader.cpp:22
void skipHSubUntil(const char *name)
Definition: esmreader.cpp:237
bool isEmptyOrGetName()
Definition: esmreader.cpp:212
void setIndex(const int index)
Definition: esmreader.hpp:84
std::vector< MasterData > mMaster
Definition: loadtes3.hpp:58
void skipRecord()
Definition: esmreader.cpp:282
std::string getName() const
Definition: esmreader.cpp:10
NAME256 desc
Definition: loadtes3.hpp:30
void getHNT(X &x, const char *name, int size)
Definition: esmreader.hpp:115
void open(Files::IStreamPtr _esm, const std::string &name)
Definition: esmreader.cpp:77
void getUint(uint32_t &u)
Definition: esmreader.hpp:252
void getSubHeaderIs(int size)
Definition: esmreader.cpp:260
int records
Definition: loadtes3.hpp:31
size_t mFileSize
Definition: esmreader.hpp:288
size_t getFileSize() const
Definition: esmreader.hpp:269
Header mHeader
Definition: esmreader.hpp:283
void getHNOT(X &x, const char *name)
Definition: esmreader.hpp:106
void skipHSub()
Definition: esmreader.cpp:224
void getSubNameIs(const char *name)
Definition: esmreader.cpp:155
void setGlobalReaderList(std::vector< ESMReader > *list)
Definition: esmreader.hpp:87
bool hasMoreSubs() const
Definition: esmreader.hpp:238
std::string toString() const
Definition: esmcommon.hpp:58
Definition: esmcommon.hpp:116
void getSubName()
Definition: esmreader.cpp:197
boost::shared_ptr< std::istream > IStreamPtr
Definition: constrainedfilestream.hpp:20
File header record.
Definition: loadtes3.hpp:17
void fail(const std::string &msg)
Used for error handling.
Definition: esmreader.cpp:352
void skipHSubSize(int size)
Definition: esmreader.cpp:230
void skip(int bytes)
Definition: esmreader.cpp:377
NAME subName
Definition: esmcommon.hpp:121
void restoreContext(const ESM_Context &rc)
Definition: esmreader.cpp:37
int index
Definition: esmcommon.hpp:125
int getVer() const
Definition: esmreader.hpp:33
int getRecordCount() const
Definition: esmreader.hpp:34
uint32_t leftSub
Definition: esmcommon.hpp:119
size_t leftFile
Definition: esmcommon.hpp:120
const NAME & retSubName() const
Definition: esmreader.hpp:41
void getT(X &x)
Definition: esmreader.hpp:248
Definition: esmcommon.hpp:14
std::string getHString()
Definition: esmreader.cpp:114
const std::string getDesc() const
Definition: esmreader.hpp:37
float getFVer() const
Definition: esmreader.hpp:35
bool peekNextSub(const char *name)
Definition: esmreader.cpp:179
std::vector< ESMReader > * mGlobalReaderList
Definition: esmreader.hpp:285
void cacheSubName()
Definition: esmreader.cpp:190
void getRecHeader()
Definition: esmreader.hpp:234
const std::string getAuthor() const
Definition: esmreader.hpp:36
ToUTF8::Utf8Encoder * mEncoder
Definition: esmreader.hpp:286
bool isNextSub(const char *name)
Definition: esmreader.cpp:164
Definition: to_utf8.hpp:25
std::vector< ESMReader > * getGlobalReaderList()
Definition: esmreader.hpp:88
const std::vector< Header::MasterData > & getGameFiles() const
Definition: esmreader.hpp:38
void getHNOT(X &x, const char *name, int size)
Definition: esmreader.hpp:123
unsigned int getRecordFlags()
Get record flags of last record.
Definition: esmreader.hpp:267
std::string getHNOString(const char *name)
Definition: esmreader.cpp:101
void getName(NAME &name)
Definition: esmreader.hpp:251
void getHT(X &x, int size)
Definition: esmreader.hpp:149
int getFormat() const
Definition: esmreader.cpp:32
const char * name
Definition: crashcatcher.cpp:59
void getHExact(void *p, int size)
Definition: esmreader.cpp:135