mirror of
https://github.com/JGRennison/OpenTTD-patches.git
synced 2024-11-16 00:12:51 +00:00
Codechange: Add compile-time check that variable size matches saveload entry.
This commit is contained in:
parent
cb53fed229
commit
9f853c10b0
@ -741,6 +741,54 @@ static inline constexpr bool IsNumericType(VarType conv)
|
||||
return GetVarMemType(conv) <= SLE_VAR_U64;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return expect size in bytes of a VarType
|
||||
* @param type VarType to get size of.
|
||||
* @return size of type in bytes.
|
||||
*/
|
||||
static inline constexpr size_t SlVarSize(VarType type)
|
||||
{
|
||||
switch (GetVarMemType(type)) {
|
||||
case SLE_VAR_BL: return sizeof(bool);
|
||||
case SLE_VAR_I8: return sizeof(int8_t);
|
||||
case SLE_VAR_U8: return sizeof(uint8_t);
|
||||
case SLE_VAR_I16: return sizeof(int16_t);
|
||||
case SLE_VAR_U16: return sizeof(uint16_t);
|
||||
case SLE_VAR_I32: return sizeof(int32_t);
|
||||
case SLE_VAR_U32: return sizeof(uint32_t);
|
||||
case SLE_VAR_I64: return sizeof(int64_t);
|
||||
case SLE_VAR_U64: return sizeof(uint64_t);
|
||||
case SLE_VAR_NULL: return sizeof(void *);
|
||||
case SLE_VAR_STR: return sizeof(std::string);
|
||||
case SLE_VAR_STRQ: return sizeof(std::string);
|
||||
case SLE_VAR_NAME: return sizeof(std::string);
|
||||
default: NOT_REACHED();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a saveload cmd/type/length entry matches the size of the variable.
|
||||
* @param cmd SaveLoadType of entry.
|
||||
* @param type VarType of entry.
|
||||
* @param length Array length of entry.
|
||||
* @param size Actual size of variable.
|
||||
* @return true iff the sizes match.
|
||||
*/
|
||||
static inline constexpr bool SlCheckVarSize(SaveLoadType cmd, VarType type, size_t length, size_t size)
|
||||
{
|
||||
switch (cmd) {
|
||||
case SL_VAR: return SlVarSize(type) == size;
|
||||
case SL_REF: return sizeof(void *) == size;
|
||||
case SL_STDSTR: return SlVarSize(type) == size;
|
||||
case SL_ARR: return SlVarSize(type) * length <= size; // Partial load of array is permitted.
|
||||
case SL_DEQUE: return sizeof(std::deque<void *>) == size;
|
||||
case SL_VECTOR: return sizeof(std::vector<void *>) == size;
|
||||
case SL_REFLIST: return sizeof(std::list<void *>) == size;
|
||||
case SL_SAVEBYTE: return true;
|
||||
default: NOT_REACHED();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Storage of simple variables, references (pointers), and arrays.
|
||||
* @param cmd Load/save type. @see SaveLoadType
|
||||
@ -748,12 +796,18 @@ static inline constexpr bool IsNumericType(VarType conv)
|
||||
* @param base Name of the class or struct containing the variable.
|
||||
* @param variable Name of the variable in the class or struct referenced by \a base.
|
||||
* @param type Storage of the data in memory and in the savegame.
|
||||
* @param length Number of elements in the array.
|
||||
* @param from First savegame version that has the field.
|
||||
* @param to Last savegame version that has the field.
|
||||
* @param extra Extra data to pass to the address callback function.
|
||||
* @note In general, it is better to use one of the SLE_* macros below.
|
||||
*/
|
||||
#define SLE_GENERAL_NAME(cmd, name, base, variable, type, length, from, to, extra) SaveLoad {name, cmd, type, length, from, to, cpp_sizeof(base, variable), [] (void *b, size_t) -> void * { assert(b != nullptr); return const_cast<void *>(static_cast<const void *>(std::addressof(static_cast<base *>(b)->variable))); }, extra, nullptr}
|
||||
#define SLE_GENERAL_NAME(cmd, name, base, variable, type, length, from, to, extra) \
|
||||
SaveLoad {name, cmd, type, length, from, to, cpp_sizeof(base, variable), [] (void *b, size_t) -> void * { \
|
||||
static_assert(SlCheckVarSize(cmd, type, length, sizeof(static_cast<base *>(b)->variable))); \
|
||||
assert(b != nullptr); \
|
||||
return const_cast<void *>(static_cast<const void *>(std::addressof(static_cast<base *>(b)->variable))); \
|
||||
}, extra, nullptr}
|
||||
|
||||
/**
|
||||
* Storage of simple variables, references (pointers), and arrays with a custom name.
|
||||
@ -761,6 +815,7 @@ static inline constexpr bool IsNumericType(VarType conv)
|
||||
* @param base Name of the class or struct containing the variable.
|
||||
* @param variable Name of the variable in the class or struct referenced by \a base.
|
||||
* @param type Storage of the data in memory and in the savegame.
|
||||
* @param length Number of elements in the array.
|
||||
* @param from First savegame version that has the field.
|
||||
* @param to Last savegame version that has the field.
|
||||
* @param extra Extra data to pass to the address callback function.
|
||||
@ -966,7 +1021,10 @@ static inline constexpr bool IsNumericType(VarType conv)
|
||||
* @param extra Extra data to pass to the address callback function.
|
||||
* @note In general, it is better to use one of the SLEG_* macros below.
|
||||
*/
|
||||
#define SLEG_GENERAL(name, cmd, variable, type, length, from, to, extra) SaveLoad {name, cmd, type, length, from, to, sizeof(variable), [] (void *, size_t) -> void * { return static_cast<void *>(std::addressof(variable)); }, extra, nullptr}
|
||||
#define SLEG_GENERAL(name, cmd, variable, type, length, from, to, extra) \
|
||||
SaveLoad {name, cmd, type, length, from, to, sizeof(variable), [] (void *, size_t) -> void * { \
|
||||
static_assert(SlCheckVarSize(cmd, type, length, sizeof(variable))); \
|
||||
return static_cast<void *>(std::addressof(variable)); }, extra, nullptr}
|
||||
|
||||
/**
|
||||
* Storage of a global variable in some savegame versions.
|
||||
|
Loading…
Reference in New Issue
Block a user