|
1 /* $Id$ */ |
|
2 |
|
3 /** @file newgrf_storage.h Functionality related to the temporary and persistent storage arrays for NewGRFs. */ |
|
4 |
|
5 #ifndef NEWGRF_STORAGE_H |
|
6 #define NEWGRF_STORAGE_H |
|
7 |
|
8 /** |
|
9 * Base class for all NewGRF storage arrays. Nothing fancy, only here |
|
10 * so we have a generalised class to use. |
|
11 */ |
|
12 struct BaseStorageArray |
|
13 { |
|
14 /** The needed destructor */ |
|
15 virtual ~BaseStorageArray() {} |
|
16 |
|
17 /** |
|
18 * Clear the changes made since the last ClearChanges. |
|
19 * This can be done in two ways: |
|
20 * - saving the changes permanently |
|
21 * - reverting to the previous version |
|
22 * @param keep_changes do we save or revert the changes since the last ClearChanges? |
|
23 */ |
|
24 virtual void ClearChanges(bool keep_changes) {} |
|
25 }; |
|
26 |
|
27 /** |
|
28 * Class for persistent storage of data. |
|
29 * On ClearChanges that data is either reverted or saved. |
|
30 * @param TYPE the type of variable to store. |
|
31 * @param SIZE the size of the array. |
|
32 */ |
|
33 template <typename TYPE, uint SIZE> |
|
34 struct PersistentStorageArray : BaseStorageArray { |
|
35 TYPE storage[SIZE]; ///< Memory to for the storage array |
|
36 TYPE *prev_storage; ///< Memory to store "old" states so we can revert them on the performance of test cases for commands etc. |
|
37 |
|
38 /** Simply construct the array */ |
|
39 PersistentStorageArray() : prev_storage(NULL) |
|
40 { |
|
41 memset(this->storage, 0, sizeof(this->storage)); |
|
42 } |
|
43 |
|
44 /** And free all data related to it */ |
|
45 ~PersistentStorageArray() |
|
46 { |
|
47 free(this->prev_storage); |
|
48 } |
|
49 |
|
50 /** |
|
51 * Stores some value at a given position. |
|
52 * If there is no backup of the data that backup is made and then |
|
53 * we write the data. |
|
54 * @param pos the position to write at |
|
55 * @param value the value to write |
|
56 */ |
|
57 void Store(uint pos, TYPE value) |
|
58 { |
|
59 /* Out of the scope of the array */ |
|
60 if (pos >= SIZE) return; |
|
61 |
|
62 /* The value hasn't changed, so we pretend nothing happened. |
|
63 * Saves a few cycles and such and it's pretty easy to check. */ |
|
64 if (this->storage[pos] == value) return; |
|
65 |
|
66 /* We do not have made a backup; lets do so */ |
|
67 if (this->prev_storage != NULL) { |
|
68 this->prev_storage = MallocT<TYPE>(SIZE); |
|
69 if (this->prev_storage == NULL) return; |
|
70 |
|
71 memcpy(this->prev_storage, this->storage, sizeof(this->storage)); |
|
72 |
|
73 /* We only need to register ourselves when we made the backup |
|
74 * as that is the only time something will have changed */ |
|
75 AddChangedStorage(this); |
|
76 } |
|
77 |
|
78 this->storage[pos] = value; |
|
79 } |
|
80 |
|
81 /** |
|
82 * Gets the value from a given position. |
|
83 * @param pos the position to get the data from |
|
84 * @return the data from that position |
|
85 */ |
|
86 TYPE Get(uint pos) |
|
87 { |
|
88 /* Out of the scope of the array */ |
|
89 if (pos >= SIZE) return 0; |
|
90 |
|
91 return this->storage[pos]; |
|
92 } |
|
93 |
|
94 void ClearChanges(bool keep_changes) |
|
95 { |
|
96 assert(this->prev_storage != NULL); |
|
97 |
|
98 if (!keep_changes) { |
|
99 memcpy(this->storage, this->prev_storage, sizeof(this->storage)); |
|
100 } |
|
101 free(this->prev_storage); |
|
102 } |
|
103 }; |
|
104 |
|
105 |
|
106 /** |
|
107 * Class for temporary storage of data. |
|
108 * On ClearChanges that data is always zero-ed. |
|
109 * @param TYPE the type of variable to store. |
|
110 * @param SIZE the size of the array. |
|
111 */ |
|
112 template <typename TYPE, uint SIZE> |
|
113 struct TemporaryStorageArray : BaseStorageArray { |
|
114 TYPE storage[SIZE]; ///< Memory to for the storage array |
|
115 |
|
116 /** Simply construct the array */ |
|
117 TemporaryStorageArray() |
|
118 { |
|
119 memset(this->storage, 0, sizeof(this->storage)); |
|
120 } |
|
121 |
|
122 /** |
|
123 * Stores some value at a given position. |
|
124 * @param pos the position to write at |
|
125 * @param value the value to write |
|
126 */ |
|
127 void Store(uint pos, TYPE value) |
|
128 { |
|
129 /* Out of the scope of the array */ |
|
130 if (pos >= SIZE) return; |
|
131 |
|
132 this->storage[pos] = value; |
|
133 AddChangedStorage(this); |
|
134 } |
|
135 |
|
136 /** |
|
137 * Gets the value from a given position. |
|
138 * @param pos the position to get the data from |
|
139 * @return the data from that position |
|
140 */ |
|
141 TYPE Get(uint pos) |
|
142 { |
|
143 /* Out of the scope of the array */ |
|
144 if (pos >= SIZE) return 0; |
|
145 |
|
146 return this->storage[pos]; |
|
147 } |
|
148 |
|
149 void ClearChanges(bool keep_changes) |
|
150 { |
|
151 memset(this->storage, 0, sizeof(this->storage)); |
|
152 } |
|
153 }; |
|
154 |
|
155 /** |
|
156 * Add the changed storage array to the list of changed arrays. |
|
157 * This is done so we only have to revert/save the changed |
|
158 * arrays, which saves quite a few clears, etc. after callbacks. |
|
159 * @param storage the array that has changed |
|
160 */ |
|
161 void AddChangedStorage(BaseStorageArray *storage); |
|
162 |
|
163 |
|
164 /** |
|
165 * Clear the changes made since the last ClearStorageChanges. |
|
166 * This is done for *all* storages that have been registered to with |
|
167 * AddChangedStorage since the previous ClearStorageChanges. |
|
168 * |
|
169 * This can be done in two ways: |
|
170 * - saving the changes permanently |
|
171 * - reverting to the previous version |
|
172 * @param keep_changes do we save or revert the changes since the last ClearChanges? |
|
173 */ |
|
174 void ClearStorageChanges(bool keep_changes); |
|
175 |
|
176 #endif /* NEWGRF_STORAGE_H */ |