# 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 */