newgrf_storage.h

Go to the documentation of this file.
00001 /* $Id: newgrf_storage.h 26175 2013-12-23 18:09:29Z frosch $ */
00002 
00003 /*
00004  * This file is part of OpenTTD.
00005  * 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.
00006  * 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.
00007  * 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/>.
00008  */
00009 
00012 #ifndef NEWGRF_STORAGE_H
00013 #define NEWGRF_STORAGE_H
00014 
00015 #include "core/pool_type.hpp"
00016 #include "tile_type.h"
00017 
00022 struct BasePersistentStorageArray {
00023   uint32 grfid;    
00024   byte feature;    
00025   TileIndex tile;  
00026 
00027   virtual ~BasePersistentStorageArray();
00028 
00036   virtual void ClearChanges(bool keep_changes) = 0;
00037 };
00038 
00045 template <typename TYPE, uint SIZE>
00046 struct PersistentStorageArray : BasePersistentStorageArray {
00047   TYPE storage[SIZE]; 
00048   TYPE *prev_storage; 
00049 
00051   PersistentStorageArray() : prev_storage(NULL)
00052   {
00053     memset(this->storage, 0, sizeof(this->storage));
00054   }
00055 
00057   ~PersistentStorageArray()
00058   {
00059     free(this->prev_storage);
00060   }
00061 
00063   void ResetToZero()
00064   {
00065     memset(this->storage, 0, sizeof(this->storage));
00066   }
00067 
00075   void StoreValue(uint pos, int32 value)
00076   {
00077     /* Out of the scope of the array */
00078     if (pos >= SIZE) return;
00079 
00080     /* The value hasn't changed, so we pretend nothing happened.
00081      * Saves a few cycles and such and it's pretty easy to check. */
00082     if (this->storage[pos] == value) return;
00083 
00084     /* We do not have made a backup; lets do so */
00085     if (this->prev_storage == NULL) {
00086       this->prev_storage = MallocT<TYPE>(SIZE);
00087       memcpy(this->prev_storage, this->storage, sizeof(this->storage));
00088 
00089       /* We only need to register ourselves when we made the backup
00090        * as that is the only time something will have changed */
00091       AddChangedPersistentStorage(this);
00092     }
00093 
00094     this->storage[pos] = value;
00095   }
00096 
00102   TYPE GetValue(uint pos) const
00103   {
00104     /* Out of the scope of the array */
00105     if (pos >= SIZE) return 0;
00106 
00107     return this->storage[pos];
00108   }
00109 
00114   void ClearChanges(bool keep_changes)
00115   {
00116     assert(this->prev_storage != NULL);
00117 
00118     if (!keep_changes) {
00119       memcpy(this->storage, this->prev_storage, sizeof(this->storage));
00120     }
00121     free(this->prev_storage);
00122     this->prev_storage = NULL;
00123   }
00124 };
00125 
00126 
00133 template <typename TYPE, uint SIZE>
00134 struct TemporaryStorageArray {
00135   TYPE storage[SIZE]; 
00136   uint16 init[SIZE];  
00137   uint16 init_key;    
00138 
00140   TemporaryStorageArray()
00141   {
00142     memset(this->storage, 0, sizeof(this->storage)); // not exactly needed, but makes code analysers happy
00143     memset(this->init, 0, sizeof(this->init));
00144     this->init_key = 1;
00145   }
00146 
00152   void StoreValue(uint pos, int32 value)
00153   {
00154     /* Out of the scope of the array */
00155     if (pos >= SIZE) return;
00156 
00157     this->storage[pos] = value;
00158     this->init[pos] = this->init_key;
00159   }
00160 
00166   TYPE GetValue(uint pos) const
00167   {
00168     /* Out of the scope of the array */
00169     if (pos >= SIZE) return 0;
00170 
00171     if (this->init[pos] != this->init_key) {
00172       /* Unassigned since last call to ClearChanges */
00173       return 0;
00174     }
00175 
00176     return this->storage[pos];
00177   }
00178 
00179   void ClearChanges()
00180   {
00181     /* Increment init_key to invalidate all storage */
00182     this->init_key++;
00183     if (this->init_key == 0) {
00184       /* When init_key wraps around, we need to reset everything */
00185       memset(this->init, 0, sizeof(this->init));
00186       this->init_key = 1;
00187     }
00188   }
00189 };
00190 
00191 void AddChangedPersistentStorage(BasePersistentStorageArray *storage);
00192 void ClearPersistentStorageChanges(bool keep_changes);
00193 
00194 
00195 typedef PersistentStorageArray<int32, 16> OldPersistentStorage;
00196 
00197 typedef uint32 PersistentStorageID;
00198 
00199 struct PersistentStorage;
00200 typedef Pool<PersistentStorage, PersistentStorageID, 1, 0xFF000> PersistentStoragePool;
00201 
00202 extern PersistentStoragePool _persistent_storage_pool;
00203 
00207 struct PersistentStorage : PersistentStorageArray<int32, 16>, PersistentStoragePool::PoolItem<&_persistent_storage_pool> {
00209   PersistentStorage(const uint32 new_grfid, byte feature, TileIndex tile)
00210   {
00211     this->grfid = new_grfid;
00212     this->feature = feature;
00213     this->tile = tile;
00214   }
00215 };
00216 
00217 assert_compile(cpp_lengthof(OldPersistentStorage, storage) == cpp_lengthof(PersistentStorage, storage));
00218 
00219 #define FOR_ALL_STORAGES_FROM(var, start) FOR_ALL_ITEMS_FROM(PersistentStorage, storage_index, var, start)
00220 #define FOR_ALL_STORAGES(var) FOR_ALL_STORAGES_FROM(var, 0)
00221 
00222 #endif /* NEWGRF_STORAGE_H */