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