4 * This file is part of OpenTTD.
5 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
6 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
10 /** @file newgrf_storage.h Functionality related to the temporary and persistent storage arrays for NewGRFs. */
12 #ifndef NEWGRF_STORAGE_H
13 #define NEWGRF_STORAGE_H
15 #include "core/pool_type.hpp"
16 #include "map/coord.h"
19 * Base class for all persistent NewGRF storage arrays. Nothing fancy, only here
20 * so we have a generalised access to the virtual methods.
22 struct BasePersistentStorageArray
{
23 uint32 grfid
; ///< GRFID associated to this persistent storage. A value of zero means "default".
24 byte feature
; ///< NOSAVE: Used to identify in the owner of the array in debug output.
25 TileIndex tile
; ///< NOSAVE: Used to identify in the owner of the array in debug output.
27 virtual ~BasePersistentStorageArray();
30 * Clear the changes made since the last #ClearChanges.
31 * This can be done in two ways:
32 * - saving the changes permanently
33 * - reverting to the previous version
34 * @param keep_changes do we save or revert the changes since the last #ClearChanges?
36 virtual void ClearChanges(bool keep_changes
) = 0;
40 * Class for persistent storage of data.
41 * On #ClearChanges that data is either reverted or saved.
42 * @tparam TYPE the type of variable to store.
43 * @tparam SIZE the size of the array.
45 template <typename TYPE
, uint SIZE
>
46 struct PersistentStorageArray
: BasePersistentStorageArray
{
47 TYPE storage
[SIZE
]; ///< Memory to for the storage array
48 TYPE
*prev_storage
; ///< Memory to store "old" states so we can revert them on the performance of test cases for commands etc.
50 /** Simply construct the array */
51 PersistentStorageArray() : prev_storage(NULL
)
53 memset(this->storage
, 0, sizeof(this->storage
));
56 /** And free all data related to it */
57 ~PersistentStorageArray()
59 free(this->prev_storage
);
62 /** Resets all values to zero. */
65 memset(this->storage
, 0, sizeof(this->storage
));
69 * Stores some value at a given position.
70 * If there is no backup of the data that backup is made and then
72 * @param pos the position to write at
73 * @param value the value to write
75 void StoreValue(uint pos
, int32 value
)
77 /* Out of the scope of the array */
78 if (pos
>= SIZE
) return;
80 /* The value hasn't changed, so we pretend nothing happened.
81 * Saves a few cycles and such and it's pretty easy to check. */
82 if (this->storage
[pos
] == value
) return;
84 /* We do not have made a backup; lets do so */
85 if (this->prev_storage
== NULL
) {
86 this->prev_storage
= MallocT
<TYPE
>(SIZE
);
87 memcpy(this->prev_storage
, this->storage
, sizeof(this->storage
));
89 /* We only need to register ourselves when we made the backup
90 * as that is the only time something will have changed */
91 AddChangedPersistentStorage(this);
94 this->storage
[pos
] = value
;
98 * Gets the value from a given position.
99 * @param pos the position to get the data from
100 * @return the data from that position
102 TYPE
GetValue(uint pos
) const
104 /* Out of the scope of the array */
105 if (pos
>= SIZE
) return 0;
107 return this->storage
[pos
];
111 * Clear the changes, or assign them permanently to the storage.
112 * @param keep_changes Whether to assign or ditch the changes.
114 void ClearChanges(bool keep_changes
)
116 assert(this->prev_storage
!= NULL
);
119 memcpy(this->storage
, this->prev_storage
, sizeof(this->storage
));
121 free(this->prev_storage
);
122 this->prev_storage
= NULL
;
128 * Class for temporary storage of data.
129 * On #ClearChanges that data is always zero-ed.
130 * @tparam TYPE the type of variable to store.
131 * @tparam SIZE the size of the array.
133 template <typename TYPE
, uint SIZE
>
134 struct TemporaryStorageArray
{
135 TYPE storage
[SIZE
]; ///< Memory to for the storage array
136 uint16 init
[SIZE
]; ///< Storage has been assigned, if this equals 'init_key'.
137 uint16 init_key
; ///< Magic key to 'init'.
139 /** Simply construct the array */
140 TemporaryStorageArray()
142 memset(this->storage
, 0, sizeof(this->storage
)); // not exactly needed, but makes code analysers happy
143 memset(this->init
, 0, sizeof(this->init
));
148 * Stores some value at a given position.
149 * @param pos the position to write at
150 * @param value the value to write
152 void StoreValue(uint pos
, int32 value
)
154 /* Out of the scope of the array */
155 if (pos
>= SIZE
) return;
157 this->storage
[pos
] = value
;
158 this->init
[pos
] = this->init_key
;
162 * Gets the value from a given position.
163 * @param pos the position to get the data from
164 * @return the data from that position
166 TYPE
GetValue(uint pos
) const
168 /* Out of the scope of the array */
169 if (pos
>= SIZE
) return 0;
171 if (this->init
[pos
] != this->init_key
) {
172 /* Unassigned since last call to ClearChanges */
176 return this->storage
[pos
];
181 /* Increment init_key to invalidate all storage */
183 if (this->init_key
== 0) {
184 /* When init_key wraps around, we need to reset everything */
185 memset(this->init
, 0, sizeof(this->init
));
191 void AddChangedPersistentStorage(BasePersistentStorageArray
*storage
);
192 void ClearPersistentStorageChanges(bool keep_changes
);
195 typedef PersistentStorageArray
<int32
, 16> OldPersistentStorage
;
197 typedef uint32 PersistentStorageID
;
199 struct PersistentStorage
;
200 typedef Pool
<PersistentStorage
, PersistentStorageID
, 1, 0xFF000> PersistentStoragePool
;
202 extern PersistentStoragePool _persistent_storage_pool
;
205 * Class for pooled persistent storage of data.
207 struct PersistentStorage
: PersistentStorageArray
<int32
, 16>, PersistentStoragePool::PoolItem
<&_persistent_storage_pool
> {
208 /** We don't want GCC to zero our struct! It already is zeroed and has an index! */
209 PersistentStorage(const uint32 new_grfid
, byte feature
, TileIndex tile
)
211 this->grfid
= new_grfid
;
212 this->feature
= feature
;
217 assert_compile(cpp_lengthof(OldPersistentStorage
, storage
) == cpp_lengthof(PersistentStorage
, storage
));
219 #define FOR_ALL_STORAGES_FROM(var, start) FOR_ALL_ITEMS_FROM(PersistentStorage, storage_index, var, start)
220 #define FOR_ALL_STORAGES(var) FOR_ALL_STORAGES_FROM(var, 0)
222 #endif /* NEWGRF_STORAGE_H */