newgrf_storage.h

Go to the documentation of this file.
00001 /* $Id: newgrf_storage.h 22600 2011-06-18 19:40:56Z 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/alloc_func.hpp"
00016 
00021 struct BaseStorageArray
00022 {
00023   virtual ~BaseStorageArray();
00024 
00032   virtual void ClearChanges(bool keep_changes) = 0;
00033 
00039   virtual void Store(uint pos, int32 value) = 0;
00040 };
00041 
00048 template <typename TYPE, uint SIZE>
00049 struct PersistentStorageArray : BaseStorageArray {
00050   TYPE storage[SIZE]; 
00051   TYPE *prev_storage; 
00052 
00054   PersistentStorageArray() : prev_storage(NULL)
00055   {
00056     memset(this->storage, 0, sizeof(this->storage));
00057   }
00058 
00060   ~PersistentStorageArray()
00061   {
00062     free(this->prev_storage);
00063   }
00064 
00066   void ResetToZero()
00067   {
00068     memset(this->storage, 0, sizeof(this->storage));
00069   }
00070 
00078   void Store(uint pos, int32 value)
00079   {
00080     /* Out of the scope of the array */
00081     if (pos >= SIZE) return;
00082 
00083     /* The value hasn't changed, so we pretend nothing happened.
00084      * Saves a few cycles and such and it's pretty easy to check. */
00085     if (this->storage[pos] == value) return;
00086 
00087     /* We do not have made a backup; lets do so */
00088     if (this->prev_storage != NULL) {
00089       this->prev_storage = MallocT<TYPE>(SIZE);
00090       memcpy(this->prev_storage, this->storage, sizeof(this->storage));
00091 
00092       /* We only need to register ourselves when we made the backup
00093        * as that is the only time something will have changed */
00094       AddChangedStorage(this);
00095     }
00096 
00097     this->storage[pos] = value;
00098   }
00099 
00105   TYPE Get(uint pos) const
00106   {
00107     /* Out of the scope of the array */
00108     if (pos >= SIZE) return 0;
00109 
00110     return this->storage[pos];
00111   }
00112 
00117   void ClearChanges(bool keep_changes)
00118   {
00119     assert(this->prev_storage != NULL);
00120 
00121     if (!keep_changes) {
00122       memcpy(this->storage, this->prev_storage, sizeof(this->storage));
00123     }
00124     free(this->prev_storage);
00125   }
00126 };
00127 
00128 
00135 template <typename TYPE, uint SIZE>
00136 struct TemporaryStorageArray : BaseStorageArray {
00137   TYPE storage[SIZE]; 
00138 
00140   TemporaryStorageArray()
00141   {
00142     memset(this->storage, 0, sizeof(this->storage));
00143   }
00144 
00150   void Store(uint pos, int32 value)
00151   {
00152     /* Out of the scope of the array */
00153     if (pos >= SIZE) return;
00154 
00155     this->storage[pos] = value;
00156     AddChangedStorage(this);
00157   }
00158 
00164   TYPE Get(uint pos) const
00165   {
00166     /* Out of the scope of the array */
00167     if (pos >= SIZE) return 0;
00168 
00169     return this->storage[pos];
00170   }
00171 
00172   void ClearChanges(bool keep_changes)
00173   {
00174     memset(this->storage, 0, sizeof(this->storage));
00175   }
00176 };
00177 
00178 void AddChangedStorage(BaseStorageArray *storage);
00179 void ClearStorageChanges(bool keep_changes);
00180 
00181 #endif /* NEWGRF_STORAGE_H */