OpenTTD
newgrf_storage.h
Go to the documentation of this file.
1 /* $Id: newgrf_storage.h 26371 2014-02-23 22:03:08Z frosch $ */
2 
3 /*
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/>.
8  */
9 
12 #ifndef NEWGRF_STORAGE_H
13 #define NEWGRF_STORAGE_H
14 
15 #include "core/pool_type.hpp"
16 #include "tile_type.h"
17 
28 };
29 
35  uint32 grfid;
36  byte feature;
38 
40 
41  static void SwitchMode(PersistentStorageMode mode, bool ignore_prev_mode = false);
42 
43 protected:
47  virtual void ClearChanges() = 0;
48 
53  static bool AreChangesPersistent() { return (gameloop || command) && !testmode; }
54 
55 private:
56  static bool gameloop;
57  static bool command;
58  static bool testmode;
59 };
60 
67 template <typename TYPE, uint SIZE>
69  TYPE storage[SIZE];
70  TYPE *prev_storage;
71 
74  {
75  memset(this->storage, 0, sizeof(this->storage));
76  }
77 
80  {
81  free(this->prev_storage);
82  }
83 
85  void ResetToZero()
86  {
87  memset(this->storage, 0, sizeof(this->storage));
88  }
89 
97  void StoreValue(uint pos, int32 value)
98  {
99  /* Out of the scope of the array */
100  if (pos >= SIZE) return;
101 
102  /* The value hasn't changed, so we pretend nothing happened.
103  * Saves a few cycles and such and it's pretty easy to check. */
104  if (this->storage[pos] == value) return;
105 
106  /* We do not have made a backup; lets do so */
107  if (AreChangesPersistent()) {
108  assert(this->prev_storage == NULL);
109  } else if (this->prev_storage == NULL) {
110  this->prev_storage = MallocT<TYPE>(SIZE);
111  memcpy(this->prev_storage, this->storage, sizeof(this->storage));
112 
113  /* We only need to register ourselves when we made the backup
114  * as that is the only time something will have changed */
116  }
117 
118  this->storage[pos] = value;
119  }
120 
126  TYPE GetValue(uint pos) const
127  {
128  /* Out of the scope of the array */
129  if (pos >= SIZE) return 0;
130 
131  return this->storage[pos];
132  }
133 
135  {
136  if (this->prev_storage != NULL) {
137  memcpy(this->storage, this->prev_storage, sizeof(this->storage));
138  free(this->prev_storage);
139  this->prev_storage = NULL;
140  }
141  }
142 };
143 
144 
151 template <typename TYPE, uint SIZE>
153  TYPE storage[SIZE];
154  uint16 init[SIZE];
155  uint16 init_key;
156 
159  {
160  memset(this->storage, 0, sizeof(this->storage)); // not exactly needed, but makes code analysers happy
161  memset(this->init, 0, sizeof(this->init));
162  this->init_key = 1;
163  }
164 
170  void StoreValue(uint pos, int32 value)
171  {
172  /* Out of the scope of the array */
173  if (pos >= SIZE) return;
174 
175  this->storage[pos] = value;
176  this->init[pos] = this->init_key;
177  }
178 
184  TYPE GetValue(uint pos) const
185  {
186  /* Out of the scope of the array */
187  if (pos >= SIZE) return 0;
188 
189  if (this->init[pos] != this->init_key) {
190  /* Unassigned since last call to ClearChanges */
191  return 0;
192  }
193 
194  return this->storage[pos];
195  }
196 
197  void ClearChanges()
198  {
199  /* Increment init_key to invalidate all storage */
200  this->init_key++;
201  if (this->init_key == 0) {
202  /* When init_key wraps around, we need to reset everything */
203  memset(this->init, 0, sizeof(this->init));
204  this->init_key = 1;
205  }
206  }
207 };
208 
210 
212 
213 typedef uint32 PersistentStorageID;
214 
215 struct PersistentStorage;
217 
218 extern PersistentStoragePool _persistent_storage_pool;
219 
223 struct PersistentStorage : PersistentStorageArray<int32, 16>, PersistentStoragePool::PoolItem<&_persistent_storage_pool> {
225  PersistentStorage(const uint32 new_grfid, byte feature, TileIndex tile)
226  {
227  this->grfid = new_grfid;
228  this->feature = feature;
229  this->tile = tile;
230  }
231 };
232 
233 assert_compile(cpp_lengthof(OldPersistentStorage, storage) == cpp_lengthof(PersistentStorage, storage));
234 
235 #define FOR_ALL_STORAGES_FROM(var, start) FOR_ALL_ITEMS_FROM(PersistentStorage, storage_index, var, start)
236 #define FOR_ALL_STORAGES(var) FOR_ALL_STORAGES_FROM(var, 0)
237 
238 #endif /* NEWGRF_STORAGE_H */