# newgrf_storage.h

Go to the documentation of this file.

    00001 /* $Id: newgrf_storage.h 23735 2012-01-03 20:26:05Z rubidium $ */
    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
    00021 struct BaseStorageArray {
    00022   virtual ~BaseStorageArray();
    00023
    00031   virtual void ClearChanges(bool keep_changes) = 0;
    00032
    00038   virtual void StoreValue(uint pos, int32 value) = 0;
    00039 };
    00040
    00047 template <typename TYPE, uint SIZE>
    00048 struct PersistentStorageArray : BaseStorageArray {
    00049   TYPE storage[SIZE];
    00050   TYPE *prev_storage;
    00051
    00053   PersistentStorageArray() : prev_storage(NULL)
    00054   {
    00055     memset(this->storage, 0, sizeof(this->storage));
    00056   }
    00057
    00059   ~PersistentStorageArray()
    00060   {
    00061     free(this->prev_storage);
    00062   }
    00063
    00065   void ResetToZero()
    00066   {
    00067     memset(this->storage, 0, sizeof(this->storage));
    00068   }
    00069
    00077   void StoreValue(uint pos, int32 value)
    00078   {
    00079     /* Out of the scope of the array */
    00080     if (pos >= SIZE) return;
    00081
    00082     /* The value hasn't changed, so we pretend nothing happened.
    00083      * Saves a few cycles and such and it's pretty easy to check. */
    00084     if (this->storage[pos] == value) return;
    00085
    00086     /* We do not have made a backup; lets do so */
    00087     if (this->prev_storage != NULL) {
    00088       this->prev_storage = MallocT<TYPE>(SIZE);
    00089       memcpy(this->prev_storage, this->storage, sizeof(this->storage));
    00090
    00091       /* We only need to register ourselves when we made the backup
    00092        * as that is the only time something will have changed */
    00093       AddChangedStorage(this);
    00094     }
    00095
    00096     this->storage[pos] = value;
    00097   }
    00098
    00104   TYPE GetValue(uint pos) const
    00105   {
    00106     /* Out of the scope of the array */
    00107     if (pos >= SIZE) return 0;
    00108
    00109     return this->storage[pos];
    00110   }
    00111
    00116   void ClearChanges(bool keep_changes)
    00117   {
    00118     assert(this->prev_storage != NULL);
    00119
    00120     if (!keep_changes) {
    00121       memcpy(this->storage, this->prev_storage, sizeof(this->storage));
    00122     }
    00123     free(this->prev_storage);
    00124   }
    00125 };
    00126
    00127
    00134 template <typename TYPE, uint SIZE>
    00135 struct TemporaryStorageArray : BaseStorageArray {
    00136   TYPE storage[SIZE];
    00137
    00139   TemporaryStorageArray()
    00140   {
    00141     memset(this->storage, 0, sizeof(this->storage));
    00142   }
    00143
    00149   void StoreValue(uint pos, int32 value)
    00150   {
    00151     /* Out of the scope of the array */
    00152     if (pos >= SIZE) return;
    00153
    00154     this->storage[pos] = value;
    00155     AddChangedStorage(this);
    00156   }
    00157
    00163   TYPE GetValue(uint pos) const
    00164   {
    00165     /* Out of the scope of the array */
    00166     if (pos >= SIZE) return 0;
    00167
    00168     return this->storage[pos];
    00169   }
    00170
    00171   void ClearChanges(bool keep_changes)
    00172   {
    00173     memset(this->storage, 0, sizeof(this->storage));
    00174   }
    00175 };
    00176
    00177 void AddChangedStorage(BaseStorageArray *storage);
    00178 void ClearStorageChanges(bool keep_changes);
    00179
    00180
    00181 typedef PersistentStorageArray<int32, 16> OldPersistentStorage;
    00182
    00183 typedef uint32 PersistentStorageID;
    00184
    00185 struct PersistentStorage;
    00186 typedef Pool<PersistentStorage, PersistentStorageID, 1, 0xFF000> PersistentStoragePool;
    00187
    00188 extern PersistentStoragePool _persistent_storage_pool;
    00189
    00194 struct PersistentStorage : PersistentStorageArray<int32, 16>, PersistentStoragePool::PoolItem<&_persistent_storage_pool> {
    00195   uint32 grfid;
    00196
    00198   PersistentStorage(const uint32 new_grfid) : grfid(new_grfid)
    00199   {
    00200     this->prev_storage = NULL;
    00201     memset(this->storage, 0, sizeof(this->storage));
    00202   }
    00203
    00205   ~PersistentStorage()
    00206   {
    00207     free(this->prev_storage);
    00208   }
    00209 };
    00210
    00211 assert_compile(cpp_lengthof(OldPersistentStorage, storage) == cpp_lengthof(PersistentStorage, storage));
    00212
    00213 #define FOR_ALL_STORAGES_FROM(var, start) FOR_ALL_ITEMS_FROM(PersistentStorage, storage_index, var, start)
    00214 #define FOR_ALL_STORAGES(var) FOR_ALL_STORAGES_FROM(var, 0)
    00215
    00216 #endif /* NEWGRF_STORAGE_H */