2007-09-22 12:59:43 +00:00
|
|
|
/* $Id$ */
|
|
|
|
|
|
|
|
/** @file newgrf_storage.h Functionality related to the temporary and persistent storage arrays for NewGRFs. */
|
|
|
|
|
|
|
|
#ifndef NEWGRF_STORAGE_H
|
|
|
|
#define NEWGRF_STORAGE_H
|
|
|
|
|
2007-12-25 09:48:53 +00:00
|
|
|
#include "core/alloc_func.hpp"
|
|
|
|
|
2007-09-22 12:59:43 +00:00
|
|
|
/**
|
|
|
|
* Base class for all NewGRF storage arrays. Nothing fancy, only here
|
|
|
|
* so we have a generalised class to use.
|
|
|
|
*/
|
|
|
|
struct BaseStorageArray
|
|
|
|
{
|
|
|
|
/** The needed destructor */
|
|
|
|
virtual ~BaseStorageArray() {}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Clear the changes made since the last ClearChanges.
|
|
|
|
* This can be done in two ways:
|
|
|
|
* - saving the changes permanently
|
|
|
|
* - reverting to the previous version
|
|
|
|
* @param keep_changes do we save or revert the changes since the last ClearChanges?
|
|
|
|
*/
|
2007-09-22 13:56:38 +00:00
|
|
|
virtual void ClearChanges(bool keep_changes) = 0;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Stores some value at a given position.
|
|
|
|
* @param pos the position to write at
|
|
|
|
* @param value the value to write
|
|
|
|
*/
|
|
|
|
virtual void Store(uint pos, uint32 value) = 0;
|
2007-09-22 12:59:43 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Class for persistent storage of data.
|
|
|
|
* On ClearChanges that data is either reverted or saved.
|
|
|
|
* @param TYPE the type of variable to store.
|
|
|
|
* @param SIZE the size of the array.
|
|
|
|
*/
|
|
|
|
template <typename TYPE, uint SIZE>
|
|
|
|
struct PersistentStorageArray : BaseStorageArray {
|
|
|
|
TYPE storage[SIZE]; ///< Memory to for the storage array
|
|
|
|
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 */
|
|
|
|
PersistentStorageArray() : prev_storage(NULL)
|
|
|
|
{
|
|
|
|
memset(this->storage, 0, sizeof(this->storage));
|
|
|
|
}
|
|
|
|
|
|
|
|
/** And free all data related to it */
|
|
|
|
~PersistentStorageArray()
|
|
|
|
{
|
|
|
|
free(this->prev_storage);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Stores some value at a given position.
|
|
|
|
* If there is no backup of the data that backup is made and then
|
|
|
|
* we write the data.
|
|
|
|
* @param pos the position to write at
|
|
|
|
* @param value the value to write
|
|
|
|
*/
|
2007-09-22 13:56:38 +00:00
|
|
|
void Store(uint pos, uint32 value)
|
2007-09-22 12:59:43 +00:00
|
|
|
{
|
|
|
|
/* Out of the scope of the array */
|
|
|
|
if (pos >= SIZE) return;
|
|
|
|
|
|
|
|
/* The value hasn't changed, so we pretend nothing happened.
|
|
|
|
* Saves a few cycles and such and it's pretty easy to check. */
|
|
|
|
if (this->storage[pos] == value) return;
|
|
|
|
|
|
|
|
/* We do not have made a backup; lets do so */
|
|
|
|
if (this->prev_storage != NULL) {
|
|
|
|
this->prev_storage = MallocT<TYPE>(SIZE);
|
|
|
|
memcpy(this->prev_storage, this->storage, sizeof(this->storage));
|
|
|
|
|
|
|
|
/* We only need to register ourselves when we made the backup
|
|
|
|
* as that is the only time something will have changed */
|
|
|
|
AddChangedStorage(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
this->storage[pos] = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Gets the value from a given position.
|
|
|
|
* @param pos the position to get the data from
|
|
|
|
* @return the data from that position
|
|
|
|
*/
|
2007-09-22 13:56:38 +00:00
|
|
|
TYPE Get(uint pos) const
|
2007-09-22 12:59:43 +00:00
|
|
|
{
|
|
|
|
/* Out of the scope of the array */
|
|
|
|
if (pos >= SIZE) return 0;
|
|
|
|
|
|
|
|
return this->storage[pos];
|
|
|
|
}
|
|
|
|
|
|
|
|
void ClearChanges(bool keep_changes)
|
|
|
|
{
|
|
|
|
assert(this->prev_storage != NULL);
|
|
|
|
|
|
|
|
if (!keep_changes) {
|
|
|
|
memcpy(this->storage, this->prev_storage, sizeof(this->storage));
|
|
|
|
}
|
|
|
|
free(this->prev_storage);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Class for temporary storage of data.
|
|
|
|
* On ClearChanges that data is always zero-ed.
|
|
|
|
* @param TYPE the type of variable to store.
|
|
|
|
* @param SIZE the size of the array.
|
|
|
|
*/
|
|
|
|
template <typename TYPE, uint SIZE>
|
|
|
|
struct TemporaryStorageArray : BaseStorageArray {
|
|
|
|
TYPE storage[SIZE]; ///< Memory to for the storage array
|
|
|
|
|
|
|
|
/** Simply construct the array */
|
|
|
|
TemporaryStorageArray()
|
|
|
|
{
|
|
|
|
memset(this->storage, 0, sizeof(this->storage));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Stores some value at a given position.
|
|
|
|
* @param pos the position to write at
|
|
|
|
* @param value the value to write
|
|
|
|
*/
|
2007-09-22 13:56:38 +00:00
|
|
|
void Store(uint pos, uint32 value)
|
2007-09-22 12:59:43 +00:00
|
|
|
{
|
|
|
|
/* Out of the scope of the array */
|
|
|
|
if (pos >= SIZE) return;
|
|
|
|
|
|
|
|
this->storage[pos] = value;
|
|
|
|
AddChangedStorage(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Gets the value from a given position.
|
|
|
|
* @param pos the position to get the data from
|
|
|
|
* @return the data from that position
|
|
|
|
*/
|
2007-09-22 13:56:38 +00:00
|
|
|
TYPE Get(uint pos) const
|
2007-09-22 12:59:43 +00:00
|
|
|
{
|
|
|
|
/* Out of the scope of the array */
|
|
|
|
if (pos >= SIZE) return 0;
|
|
|
|
|
|
|
|
return this->storage[pos];
|
|
|
|
}
|
|
|
|
|
|
|
|
void ClearChanges(bool keep_changes)
|
|
|
|
{
|
|
|
|
memset(this->storage, 0, sizeof(this->storage));
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Add the changed storage array to the list of changed arrays.
|
|
|
|
* This is done so we only have to revert/save the changed
|
|
|
|
* arrays, which saves quite a few clears, etc. after callbacks.
|
|
|
|
* @param storage the array that has changed
|
|
|
|
*/
|
|
|
|
void AddChangedStorage(BaseStorageArray *storage);
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Clear the changes made since the last ClearStorageChanges.
|
|
|
|
* This is done for *all* storages that have been registered to with
|
|
|
|
* AddChangedStorage since the previous ClearStorageChanges.
|
|
|
|
*
|
|
|
|
* This can be done in two ways:
|
|
|
|
* - saving the changes permanently
|
|
|
|
* - reverting to the previous version
|
|
|
|
* @param keep_changes do we save or revert the changes since the last ClearChanges?
|
|
|
|
*/
|
|
|
|
void ClearStorageChanges(bool keep_changes);
|
|
|
|
|
|
|
|
#endif /* NEWGRF_STORAGE_H */
|