1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4 
5   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
6   All rights reserved.
7   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
8 
9      This software is distributed WITHOUT ANY WARRANTY; without even
10      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11      PURPOSE.  See the above copyright notice for more information.
12 
13 =========================================================================*/
14 /**
15  * @class   vtkStateStorage
16  * @brief   Class to make storing and comparing state quick and easy
17  *
18  * vtkStateStorage is just a thin wrapper around std::vector<unsigned char>
19  * It is best to use this class as an ivar so that allocs do not happen
20  * too often.
21  *
22  * Example usage:
23  * @code
24  *
25  * // compute the new state in a temp ivar
26  * // note that clear does not free memory
27  * this->TempState.Clear();
28  * this->TempState.Append(act->GetProperty()->GetMTime(), "property mtime");
29  * this->TempState.Append(
30  *   this->CurrentInput ? this->CurrentInput->GetMTime() : 0, "input mtime");
31  * this->TempState.Append(
32  *   act->GetTexture() ? act->GetTexture()->GetMTime() : 0, "texture mtime");
33  *
34  * // now compare against the last state value
35  *
36  * if (this->VBOBuildState != this->TempState)
37  * {
38  *   // set the ivar to the new state
39  *   this->VBOBuildState = this->TempState;
40  *   do something...
41  * }
42  *
43  * @endcode
44  *
45  */
46 
47 #ifndef vtkStateStorage_h
48 #define vtkStateStorage_h
49 
50 #include <algorithm>
51 #include <string>
52 #include <vector>
53 
54 // uncomment the following line to add in state debugging information
55 //#define USE_STATE_DEBUGGING 1
56 #ifdef USE_STATE_DEBUGGING
57 
58 class vtkStateStorage
59 {
60 public:
vtkStateStorage()61   vtkStateStorage() {}
62 
63   // clear the storage
Clear()64   void Clear()
65   {
66     this->Storage.clear();
67     this->StorageOffsets.clear();
68     this->StorageNames.clear();
69   }
70 
71   // append a data item to the state
72   template <class T>
73   void Append(const T& value, const char* name);
74 
75   bool operator!=(const vtkStateStorage& b) const
76   {
77     // for debug we also lookup the name of what was different
78     this->WhatWasDifferent = "";
79     if (this->Storage.size() != b.Storage.size())
80     {
81       this->WhatWasDifferent = "Different state sizes";
82       return true;
83     }
84     for (size_t i = 0; i < this->Storage.size(); ++i)
85     {
86       if (this->Storage[i] != b.Storage[i])
87       {
88         size_t block = 0;
89         while (this->StorageOffsets.size() > block + 1 && this->StorageOffsets[block + 1] >= i)
90         {
91           block++;
92         }
93         this->WhatWasDifferent = this->StorageNames[block] + " was different";
94         return true;
95       }
96     }
97     return false;
98   }
99 
100   vtkStateStorage& operator=(const vtkStateStorage& b)
101   {
102     this->Storage = b.Storage;
103     this->StorageNames = b.StorageNames;
104     this->StorageOffsets = b.StorageOffsets;
105     return *this;
106   }
107 
108 protected:
109   std::vector<unsigned char> Storage;
110   std::vector<std::string> StorageNames;
111   std::vector<size_t> StorageOffsets;
112   mutable std::string WhatWasDifferent;
113 
114 private:
115   vtkStateStorage(const vtkStateStorage&) = delete;
116 };
117 
118 template <class T>
Append(const T & value,const char * name)119 inline void vtkStateStorage::Append(const T& value, const char* name)
120 {
121   this->StorageOffsets.push_back(this->Storage.size());
122   this->StorageNames.push_back(name);
123   const char* start = reinterpret_cast<const char*>(&value);
124   this->Storage.insert(this->Storage.end(), start, start + sizeof(T));
125 }
126 
127 #else // normal implementation
128 
129 class vtkStateStorage
130 {
131 public:
132   vtkStateStorage() = default;
133 
134   // clear the storage
Clear()135   void Clear() { this->Storage.clear(); }
136 
137   // append a data item to the state
138   template <class T>
139   void Append(const T& value, const char* name);
140 
141   bool operator!=(const vtkStateStorage& b) const { return this->Storage != b.Storage; }
142 
143   vtkStateStorage& operator=(const vtkStateStorage& b) = default;
144 
145 protected:
146   std::vector<unsigned char> Storage;
147 
148 private:
149   vtkStateStorage(const vtkStateStorage&) = delete;
150 };
151 
152 template <class T>
Append(const T & value,const char *)153 inline void vtkStateStorage::Append(const T& value, const char*)
154 {
155   const char* start = reinterpret_cast<const char*>(&value);
156   this->Storage.insert(this->Storage.end(), start, start + sizeof(T));
157 }
158 
159 #endif // normal implementation
160 
161 #endif // vtkStateStorage_h
162 
163 // VTK-HeaderTest-Exclude: vtkStateStorage.h
164