1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
|
/**
* @file
* @brief Saveable hash-table and vector capable of storing
* multiple types of data.
**/
#ifndef STORE_H
#define STORE_H
#include <limits.h>
#include <map>
#include <string>
#include <vector>
class reader;
class writer;
class CrawlHashTable;
class CrawlVector;
struct item_def;
struct coord_def;
struct level_pos;
class level_id;
class dlua_chunk;
class monster;
#include "tags.h"
typedef uint16_t vec_size;
typedef uint8_t store_flags;
#define VEC_MAX_SIZE 0xFFFF
// NOTE: Changing the ordering of these enums will break savefile
// compatibility.
enum store_val_type
{
SV_NONE = 0,
SV_BOOL,
SV_BYTE,
SV_SHORT,
SV_INT,
SV_FLOAT,
SV_STR,
SV_COORD,
SV_ITEM,
SV_HASH,
SV_VEC,
SV_LEV_ID,
SV_LEV_POS,
SV_MONST,
SV_LUA,
SV_INT64,
NUM_STORE_VAL_TYPES
};
enum store_flag_type
{
SFLAG_UNSET = (1 << 0),
SFLAG_CONST_VAL = (1 << 1),
SFLAG_CONST_TYPE = (1 << 2),
SFLAG_NO_ERASE = (1 << 3),
};
typedef union StoreUnion StoreUnion;
union StoreUnion
{
bool boolean;
char byte;
short _short;
int _int;
float _float;
int64_t _int64;
void* ptr;
};
class CrawlStoreValue
{
public:
CrawlStoreValue();
CrawlStoreValue(const CrawlStoreValue &other);
~CrawlStoreValue();
// Conversion constructors
CrawlStoreValue(const bool val);
CrawlStoreValue(const char &val);
CrawlStoreValue(const short &val);
CrawlStoreValue(const int &val);
CrawlStoreValue(const int64_t &val);
CrawlStoreValue(const float &val);
CrawlStoreValue(const string &val);
CrawlStoreValue(const char* val);
CrawlStoreValue(const coord_def &val);
CrawlStoreValue(const item_def &val);
CrawlStoreValue(const CrawlHashTable &val);
CrawlStoreValue(const CrawlVector &val);
CrawlStoreValue(const level_id &val);
CrawlStoreValue(const level_pos &val);
CrawlStoreValue(const monster& val);
CrawlStoreValue(const dlua_chunk &val);
CrawlStoreValue &operator = (const CrawlStoreValue &other);
protected:
// These first two fields need to match those in CrawlVector
store_val_type type:8;
store_flags flags;
StoreUnion val;
public:
store_flags get_flags() const;
store_flags set_flags(store_flags flags);
store_flags unset_flags(store_flags flags);
store_val_type get_type() const;
CrawlHashTable &new_table();
CrawlVector &new_vector(store_flags flags,
vec_size max_size = VEC_MAX_SIZE);
CrawlVector &new_vector(store_val_type type, store_flags flags = 0,
vec_size max_size = VEC_MAX_SIZE);
bool &get_bool();
char &get_byte();
short &get_short();
int &get_int();
int64_t &get_int64();
float &get_float();
string &get_string();
coord_def &get_coord();
CrawlHashTable &get_table();
CrawlVector &get_vector();
item_def &get_item();
level_id &get_level_id();
level_pos &get_level_pos();
monster &get_monster();
dlua_chunk &get_lua();
bool get_bool() const;
char get_byte() const;
short get_short() const;
int get_int() const;
int64_t get_int64() const;
float get_float() const;
string get_string() const;
coord_def get_coord() const;
level_id get_level_id() const;
level_pos get_level_pos() const;
const CrawlHashTable& get_table() const;
const CrawlVector& get_vector() const;
const item_def& get_item() const;
const monster& get_monster() const;
const dlua_chunk& get_lua() const;
public:
// NOTE: All operators will assert if the value is of the wrong
// type for the operation. If the value has no type yet, the
// operation will set it to the appropriate type. If the value
// has no type yet and the operation modifies the existing value
// rather than replacing it (e.g., ++) the value will be set to a
// default before the operation is done.
// If the value is a hash table or vector, the container's values
// can be accessed with the [] operator with the approriate key
// type (strings for hashes, longs for vectors).
CrawlStoreValue &operator [] (const string &key);
CrawlStoreValue &operator [] (const char *key);
CrawlStoreValue &operator [] (const vec_size &index);
const CrawlStoreValue &operator [] (const string &key) const;
const CrawlStoreValue &operator [] (const char *key) const;
const CrawlStoreValue &operator [] (const vec_size &index) const;
// Typecast operators
operator bool&();
operator char&();
operator short&();
operator int&();
operator int64_t&();
operator float&();
operator string&();
operator coord_def&();
operator CrawlHashTable&();
operator CrawlVector&();
operator item_def&();
operator level_id&();
operator level_pos&();
operator monster& ();
operator dlua_chunk&();
operator bool() const;
operator char() const;
operator short() const;
operator int() const;
operator int64_t() const;
operator float() const;
operator string() const;
operator coord_def() const;
operator level_id() const;
operator level_pos() const;
// Assignment operators
CrawlStoreValue &operator = (const bool &val);
CrawlStoreValue &operator = (const char &val);
CrawlStoreValue &operator = (const short &val);
CrawlStoreValue &operator = (const int &val);
CrawlStoreValue &operator = (const int64_t &val);
CrawlStoreValue &operator = (const float &val);
CrawlStoreValue &operator = (const string &val);
CrawlStoreValue &operator = (const char* val);
CrawlStoreValue &operator = (const coord_def &val);
CrawlStoreValue &operator = (const CrawlHashTable &val);
CrawlStoreValue &operator = (const CrawlVector &val);
CrawlStoreValue &operator = (const item_def &val);
CrawlStoreValue &operator = (const level_id &val);
CrawlStoreValue &operator = (const level_pos &val);
CrawlStoreValue &operator = (const monster& val);
CrawlStoreValue &operator = (const dlua_chunk &val);
// Misc operators
string &operator += (const string &val);
// Prefix
int operator ++ ();
int operator -- ();
// Postfix
int operator ++ (int);
int operator -- (int);
protected:
CrawlStoreValue(const store_flags flags,
const store_val_type type = SV_NONE);
void write(writer &) const;
void read(reader &);
void unset(bool force = false);
friend class CrawlHashTable;
friend class CrawlVector;
};
// By default a hash table's value data types are heterogeneous. To
// make it homogeneous (which causes dynamic type checking) you have
// to give a type to the hash table constructor; once it's been
// created its type (or lack of type) is immutable.
class CrawlHashTable
{
public:
CrawlHashTable();
CrawlHashTable(const CrawlHashTable& other);
~CrawlHashTable();
typedef map<string, CrawlStoreValue> hash_map_type;
typedef hash_map_type::iterator iterator;
typedef hash_map_type::const_iterator const_iterator;
protected:
// NOTE: Not using auto_ptr because making hash_map an auto_ptr
// causes compile weirdness in externs.h
hash_map_type *hash_map;
void init_hash_map();
friend class CrawlStoreValue;
public:
CrawlHashTable &operator = (const CrawlHashTable &other);
void write(writer &) const;
void read(reader &);
bool exists(const string &key) const;
void assert_validity() const;
// NOTE: If the const versions of get_value() or [] are given a
// key which doesn't exist, they will assert.
const CrawlStoreValue& get_value(const string &key) const;
const CrawlStoreValue& get_value(const char *key) const
{ return get_value(string(key)); }
const CrawlStoreValue& operator[] (const string &key) const
{ return get_value(key); }
const CrawlStoreValue& operator[] (const char *key) const
{ return get_value(string(key)); }
// NOTE: If get_value() or [] is given a key which doesn't exist
// in the table, an unset/empty CrawlStoreValue will be created
// with that key and returned. If it is not then given a value
// then the next call to assert_validity() will fail. If the
// hash table has a type (rather than being heterogeneous)
// then trying to assign a different type to the CrawlStoreValue
// will assert.
CrawlStoreValue& get_value(const string &key);
CrawlStoreValue& get_value(const char *key)
{ return get_value(string(key)); }
CrawlStoreValue& operator[] (const string &key)
{ return get_value(key); }
CrawlStoreValue& operator[] (const char *key)
{ return get_value(string(key)); }
// std::map style interface
unsigned int size() const;
bool empty() const;
void erase(const string key);
void erase(const char *key) { erase(string(key)); }
void clear();
const_iterator begin() const;
const_iterator end() const;
iterator begin();
iterator end();
};
// A CrawlVector is the vector version of CrawlHashTable, except that
// a non-empty CrawlVector has one more byte of savefile overhead that
// a hash table, and that can specify a maximum size to make it act
// similarly to a FixedVec.
class CrawlVector
{
public:
CrawlVector();
CrawlVector(store_flags flags, vec_size max_size = VEC_MAX_SIZE);
CrawlVector(store_val_type type, store_flags flags = 0,
vec_size max_size = VEC_MAX_SIZE);
~CrawlVector();
typedef vector<CrawlStoreValue> vector_type;
typedef vector_type::iterator iterator;
typedef vector_type::const_iterator const_iterator;
protected:
// These first two fields need to match those in CrawlStoreValue
store_val_type type:8;
store_flags default_flags;
vec_size max_size;
vector_type vec;
friend class CrawlStoreValue;
public:
void write(writer &) const;
void read(reader &);
store_flags get_default_flags() const;
store_flags set_default_flags(store_flags flags);
store_flags unset_default_flags(store_flags flags);
store_val_type get_type() const;
void assert_validity() const;
void set_max_size(vec_size size);
vec_size get_max_size() const;
// NOTE: If the const versions of get_value() or [] are given an
// index which doesn't exist, they will assert.
const CrawlStoreValue& get_value(const vec_size &index) const;
const CrawlStoreValue& operator[] (const vec_size &index) const
{ return get_value(index); }
CrawlStoreValue& get_value(const vec_size &index);
CrawlStoreValue& operator[] (const vec_size &index)
{ return get_value(index); }
// std::vector style interface
vec_size size() const;
bool empty() const;
// NOTE: push_back() and insert() have val passed by value rather
// than by reference so that conversion constructors will work.
CrawlStoreValue& pop_back();
void push_back(CrawlStoreValue val);
void insert(const vec_size index, CrawlStoreValue val);
// resize() will assert if the maximum size has been set.
void resize(const vec_size size);
void erase(const vec_size index);
void clear();
const_iterator begin() const;
const_iterator end() const;
iterator begin();
iterator end();
};
#ifdef DEBUG_PROPS
void dump_prop_accesses();
#endif
// inlines... it sucks so badly to have to pander to ancient compilers with
// no -flto
inline CrawlStoreValue &CrawlStoreValue::operator [] (const string &key)
{
return get_table().get_value(key);
}
inline CrawlStoreValue &CrawlStoreValue::operator [] (const char* key)
{
return get_table().get_value(key);
}
inline CrawlStoreValue &CrawlStoreValue::operator [] (const vec_size &index)
{
return get_vector()[index];
}
inline const CrawlStoreValue &CrawlStoreValue::operator [] (const string &key) const
{
return get_table().get_value(key);
}
inline const CrawlStoreValue &CrawlStoreValue::operator [] (const char* key) const
{
return get_table().get_value(key);
}
inline const CrawlStoreValue &CrawlStoreValue::operator [](const vec_size &index) const
{
return get_vector().get_value(index);
}
#endif
|