1
0
Fork 0

Compare commits

...

4 Commits

Author SHA1 Message Date
Peter Nelson 7bd019df90 Codechange: Use std::array for TemporaryStorageArray.
This removes the need for initialisation with memset().
2023-09-09 15:26:03 +01:00
Peter Nelson 9040d7813d Codechange: Use std::array and std::unique_ptr for PersistentStorageArrays.
This (mostly) avoids the need for manual memory management and copying.
2023-09-09 15:26:03 +01:00
Patric Stout c3918838f6
Fix: crash when opening a damaged base-graphics (#11275) 2023-09-09 14:06:00 +00:00
PeterN afc1ea8135
Codechange: Using alias and std::array for company expense storage. (#11273)
This simplifies passing yearly expenses to functions and use of std algorithms.
2023-09-09 13:15:53 +00:00
10 changed files with 33 additions and 52 deletions

View File

@ -92,7 +92,7 @@ struct CompanyProperties {
*/ */
bool is_ai; bool is_ai;
Money yearly_expenses[3][EXPENSES_END]; ///< Expenses of the company for the last three years, in every #ExpensesType category. std::array<Expenses, 3> yearly_expenses{}; ///< Expenses of the company for the last three years.
CompanyEconomyEntry cur_economy; ///< Economic data of the company of this quarter. CompanyEconomyEntry cur_economy; ///< Economic data of the company of this quarter.
CompanyEconomyEntry old_economy[MAX_HISTORY_QUARTERS]; ///< Economic data of the company of the last #MAX_HISTORY_QUARTERS quarters. CompanyEconomyEntry old_economy[MAX_HISTORY_QUARTERS]; ///< Economic data of the company of the last #MAX_HISTORY_QUARTERS quarters.
byte num_valid_stat_ent; ///< Number of valid statistical entries in #old_economy. byte num_valid_stat_ent; ///< Number of valid statistical entries in #old_economy.

View File

@ -750,8 +750,9 @@ static IntervalTimer<TimerGameCalendar> _companies_yearly({TimerGameCalendar::YE
{ {
/* Copy statistics */ /* Copy statistics */
for (Company *c : Company::Iterate()) { for (Company *c : Company::Iterate()) {
memmove(&c->yearly_expenses[1], &c->yearly_expenses[0], sizeof(c->yearly_expenses) - sizeof(c->yearly_expenses[0])); /* Move expenses to previous years. */
memset(&c->yearly_expenses[0], 0, sizeof(c->yearly_expenses[0])); std::rotate(std::rbegin(c->yearly_expenses), std::rbegin(c->yearly_expenses) + 1, std::rend(c->yearly_expenses));
c->yearly_expenses[0] = {};
SetWindowDirty(WC_FINANCES, c->index); SetWindowDirty(WC_FINANCES, c->index);
} }

View File

@ -229,7 +229,7 @@ static void DrawPrice(Money amount, int left, int right, int top, TextColour col
* Draw a category of expenses/revenues in the year column. * Draw a category of expenses/revenues in the year column.
* @return The income sum of the category. * @return The income sum of the category.
*/ */
static Money DrawYearCategory (const Rect &r, int start_y, ExpensesList list, const Money(&tbl)[EXPENSES_END]) static Money DrawYearCategory(const Rect &r, int start_y, ExpensesList list, const Expenses &tbl)
{ {
int y = start_y; int y = start_y;
ExpensesType et; ExpensesType et;
@ -260,7 +260,7 @@ static Money DrawYearCategory (const Rect &r, int start_y, ExpensesList list, co
* @param tbl Reference to table of amounts for \a year. * @param tbl Reference to table of amounts for \a year.
* @note The environment must provide padding at the left and right of \a r. * @note The environment must provide padding at the left and right of \a r.
*/ */
static void DrawYearColumn(const Rect &r, TimerGameCalendar::Year year, const Money (&tbl)[EXPENSES_END]) static void DrawYearColumn(const Rect &r, TimerGameCalendar::Year year, const Expenses &tbl)
{ {
int y = r.top; int y = r.top;
Money sum; Money sum;

View File

@ -172,6 +172,11 @@ enum ExpensesType : byte {
INVALID_EXPENSES = 0xFF, ///< Invalid expense type. INVALID_EXPENSES = 0xFF, ///< Invalid expense type.
}; };
/**
* Data type for storage of Money for each #ExpensesType category.
*/
using Expenses = std::array<Money, EXPENSES_END>;
/** /**
* Categories of a price bases. * Categories of a price bases.
*/ */

View File

@ -383,10 +383,7 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCompanyEconomy()
{ {
for (const Company *company : Company::Iterate()) { for (const Company *company : Company::Iterate()) {
/* Get the income. */ /* Get the income. */
Money income = 0; Money income = -std::reduce(std::begin(company->yearly_expenses[0]), std::end(company->yearly_expenses[0]));
for (uint i = 0; i < lengthof(company->yearly_expenses[0]); i++) {
income -= company->yearly_expenses[0][i];
}
Packet *p = new Packet(ADMIN_PACKET_SERVER_COMPANY_ECONOMY); Packet *p = new Packet(ADMIN_PACKET_SERVER_COMPANY_ECONOMY);

View File

@ -65,26 +65,10 @@ private:
*/ */
template <typename TYPE, uint SIZE> template <typename TYPE, uint SIZE>
struct PersistentStorageArray : BasePersistentStorageArray { struct PersistentStorageArray : BasePersistentStorageArray {
TYPE storage[SIZE]; ///< Memory to for the storage array using StorageType = std::array<TYPE, SIZE>;
TYPE *prev_storage; ///< Memory to store "old" states so we can revert them on the performance of test cases for commands etc.
/** Simply construct the array */ StorageType storage{}; ///< Memory for the storage array
PersistentStorageArray() : prev_storage(nullptr) std::unique_ptr<StorageType> prev_storage{}; ///< Temporary memory to store previous state so it can be reverted, e.g. for command tests.
{
memset(this->storage, 0, sizeof(this->storage));
}
/** And free all data related to it */
~PersistentStorageArray()
{
free(this->prev_storage);
}
/** Resets all values to zero. */
void ResetToZero()
{
memset(this->storage, 0, sizeof(this->storage));
}
/** /**
* Stores some value at a given position. * Stores some value at a given position.
@ -104,10 +88,9 @@ struct PersistentStorageArray : BasePersistentStorageArray {
/* We do not have made a backup; lets do so */ /* We do not have made a backup; lets do so */
if (AreChangesPersistent()) { if (AreChangesPersistent()) {
assert(this->prev_storage == nullptr); assert(!this->prev_storage);
} else if (this->prev_storage == nullptr) { } else if (!this->prev_storage) {
this->prev_storage = MallocT<TYPE>(SIZE); this->prev_storage = std::make_unique<StorageType>(this->storage);
memcpy(this->prev_storage, this->storage, sizeof(this->storage));
/* We only need to register ourselves when we made the backup /* We only need to register ourselves when we made the backup
* as that is the only time something will have changed */ * as that is the only time something will have changed */
@ -132,10 +115,9 @@ struct PersistentStorageArray : BasePersistentStorageArray {
void ClearChanges() void ClearChanges()
{ {
if (this->prev_storage != nullptr) { if (this->prev_storage) {
memcpy(this->storage, this->prev_storage, sizeof(this->storage)); this->storage = *this->prev_storage;
free(this->prev_storage); this->prev_storage.reset();
this->prev_storage = nullptr;
} }
} }
}; };
@ -149,17 +131,12 @@ struct PersistentStorageArray : BasePersistentStorageArray {
*/ */
template <typename TYPE, uint SIZE> template <typename TYPE, uint SIZE>
struct TemporaryStorageArray { struct TemporaryStorageArray {
TYPE storage[SIZE]; ///< Memory to for the storage array using StorageType = std::array<TYPE, SIZE>;
uint16_t init[SIZE]; ///< Storage has been assigned, if this equals 'init_key'. using StorageInitType = std::array<uint16_t, SIZE>;
uint16_t init_key; ///< Magic key to 'init'.
/** Simply construct the array */ StorageType storage{}; ///< Memory for the storage array
TemporaryStorageArray() StorageInitType init{}; ///< Storage has been assigned, if this equals 'init_key'.
{ uint16_t init_key{1}; ///< Magic key to 'init'.
memset(this->storage, 0, sizeof(this->storage)); // not exactly needed, but makes code analysers happy
memset(this->init, 0, sizeof(this->init));
this->init_key = 1;
}
/** /**
* Stores some value at a given position. * Stores some value at a given position.
@ -199,7 +176,7 @@ struct TemporaryStorageArray {
this->init_key++; this->init_key++;
if (this->init_key == 0) { if (this->init_key == 0) {
/* When init_key wraps around, we need to reset everything */ /* When init_key wraps around, we need to reset everything */
memset(this->init, 0, sizeof(this->init)); this->init = {};
this->init_key = 1; this->init_key = 1;
} }
} }

View File

@ -146,9 +146,10 @@ void RandomAccessFile::ReadBlock(void *ptr, size_t size)
* Skip \a n bytes ahead in the file. * Skip \a n bytes ahead in the file.
* @param n Number of bytes to skip reading. * @param n Number of bytes to skip reading.
*/ */
void RandomAccessFile::SkipBytes(int n) void RandomAccessFile::SkipBytes(size_t n)
{ {
int remaining = this->buffer_end - this->buffer; assert(this->buffer_end >= this->buffer);
size_t remaining = this->buffer_end - this->buffer;
if (n <= remaining) { if (n <= remaining) {
this->buffer += n; this->buffer += n;
} else { } else {

View File

@ -51,7 +51,7 @@ public:
uint32_t ReadDword(); uint32_t ReadDword();
void ReadBlock(void *ptr, size_t size); void ReadBlock(void *ptr, size_t size);
void SkipBytes(int n); void SkipBytes(size_t n);
}; };
#endif /* RANDOM_ACCESS_FILE_TYPE_H */ #endif /* RANDOM_ACCESS_FILE_TYPE_H */

View File

@ -246,7 +246,7 @@ struct INDYChunkHandler : ChunkHandler {
/* Store the old persistent storage. The GRFID will be added later. */ /* Store the old persistent storage. The GRFID will be added later. */
assert(PersistentStorage::CanAllocateItem()); assert(PersistentStorage::CanAllocateItem());
i->psa = new PersistentStorage(0, 0, 0); i->psa = new PersistentStorage(0, 0, 0);
memcpy(i->psa->storage, _old_ind_persistent_storage.storage, sizeof(_old_ind_persistent_storage.storage)); std::copy(std::begin(_old_ind_persistent_storage.storage), std::end(_old_ind_persistent_storage.storage), std::begin(i->psa->storage));
} }
if (IsSavegameVersionBefore(SLV_INDUSTRY_CARGO_REORGANISE)) LoadMoveAcceptsProduced(i); if (IsSavegameVersionBefore(SLV_INDUSTRY_CARGO_REORGANISE)) LoadMoveAcceptsProduced(i);
Industry::IncIndustryTypeCount(i->type); Industry::IncIndustryTypeCount(i->type);

View File

@ -426,7 +426,7 @@ public:
/* Store the old persistent storage. The GRFID will be added later. */ /* Store the old persistent storage. The GRFID will be added later. */
assert(PersistentStorage::CanAllocateItem()); assert(PersistentStorage::CanAllocateItem());
st->airport.psa = new PersistentStorage(0, 0, 0); st->airport.psa = new PersistentStorage(0, 0, 0);
memcpy(st->airport.psa->storage, _old_st_persistent_storage.storage, sizeof(_old_st_persistent_storage.storage)); std::copy(std::begin(_old_st_persistent_storage.storage), std::end(_old_st_persistent_storage.storage), std::begin(st->airport.psa->storage));
} }
size_t num_cargo = this->GetNumCargo(); size_t num_cargo = this->GetNumCargo();