summaryrefslogtreecommitdiff
path: root/src/newgrf_storage.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/newgrf_storage.h')
-rw-r--r--src/newgrf_storage.h176
1 files changed, 176 insertions, 0 deletions
diff --git a/src/newgrf_storage.h b/src/newgrf_storage.h
new file mode 100644
index 000000000..93aab09dc
--- /dev/null
+++ b/src/newgrf_storage.h
@@ -0,0 +1,176 @@
+/* $Id$ */
+
+/** @file newgrf_storage.h Functionality related to the temporary and persistent storage arrays for NewGRFs. */
+
+#ifndef NEWGRF_STORAGE_H
+#define NEWGRF_STORAGE_H
+
+/**
+ * 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?
+ */
+ virtual void ClearChanges(bool keep_changes) {}
+};
+
+/**
+ * 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
+ */
+ void Store(uint pos, TYPE value)
+ {
+ /* 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);
+ if (this->prev_storage == NULL) return;
+
+ 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
+ */
+ TYPE Get(uint pos)
+ {
+ /* 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
+ */
+ void Store(uint pos, TYPE value)
+ {
+ /* 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
+ */
+ TYPE Get(uint pos)
+ {
+ /* 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 */