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