Don't nuke git/svn information during build.
[hcoop/zz_old/debian/suphp.git] / src / SmartPtr.hpp
1 /*
2 suPHP - (c)2002-2005 Sebastian Marsching <sebastian@marsching.com>
3
4 This file is part of suPHP.
5
6 suPHP is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 suPHP is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with suPHP; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 #ifndef SUPHP_SMARTPTR_H
22
23 namespace suPHP {
24 class Environment;
25 };
26
27 #define SUPHP_SMARTPTR_H
28
29 #include <map>
30 #include <cstdlib>
31 #include "PointerException.hpp"
32
33 namespace suPHP {
34 /**
35 * Class template encapsulating pointers.
36 */
37 template<class T>
38 class SmartPtr {
39 private:
40 static std::map<T*, int> *counter;
41 T* ptr;
42
43 void increment(T* key_ptr);
44 void decrement(T* key_ptr);
45
46 public:
47 /**
48 * Constructor using NULL pointer
49 */
50 SmartPtr();
51
52 /**
53 * Constructor taking T* as argument
54 */
55 SmartPtr(T* obj_ptr);
56
57 /**
58 * Copy constructor
59 */
60 SmartPtr(const SmartPtr<T>& ref);
61
62 /**
63 * Destructor
64 */
65 ~SmartPtr();
66
67 /**
68 * Copy operator
69 */
70 const SmartPtr& operator=(const SmartPtr<T>& ref);
71
72 /**
73 * Dereference operator.
74 * Returns reference to object hold by smart pointer
75 */
76 T& operator*() const throw(PointerException);
77
78 /**
79 * Member access operator
80 */
81 T* operator->() const throw(PointerException);
82
83 /**
84 * Returns underlying pointer
85 */
86 T* get() const;
87
88 /**
89 * Returns underlying pointer and releases it
90 * from management by the SmartPtr.
91 * Throws an exception if underlying pointer is
92 * hold by more than one SmartPtr.
93 */
94 T* release() throw (PointerException);
95
96 /**
97 * Resets SmartPtr to point to another object
98 */
99 void reset(T* obj_ptr);
100
101 /**
102 * Compares to pointers.
103 * Returns true, if both point to the same object,
104 * false otherwise
105 */
106 bool operator==(const SmartPtr<T>& ref);
107
108 };
109
110 template<class T>
111 std::map<T*, int> *suPHP::SmartPtr<T>::counter;
112
113 template<class T>
114 suPHP::SmartPtr<T>::SmartPtr() {
115 if (SmartPtr<T>::counter == NULL) {
116 SmartPtr<T>::counter = new std::map<T*, int>;
117 }
118 this->ptr = NULL;
119 }
120
121 template<class T>
122 suPHP::SmartPtr<T>::SmartPtr(T* obj_ptr) {
123 if (SmartPtr<T>::counter == NULL) {
124 SmartPtr<T>::counter = new std::map<T*, int>;
125 }
126 this->ptr = obj_ptr;
127 this->increment(obj_ptr);
128 }
129
130 template<class T>
131 suPHP::SmartPtr<T>::SmartPtr(const SmartPtr<T>& ref) {
132 if (SmartPtr<T>::counter == NULL) {
133 SmartPtr<T>::counter = new std::map<T*, int>;
134 }
135 this->ptr = ref.ptr;
136 if (ref.ptr != NULL)
137 this->increment(ref.ptr);
138 }
139
140 template<class T>
141 suPHP::SmartPtr<T>::~SmartPtr() {
142 if (this->ptr != NULL)
143 this->decrement(this->ptr);
144 if (SmartPtr<T>::counter != NULL && SmartPtr<T>::counter->size() == 0) {
145 delete SmartPtr<T>::counter;
146 SmartPtr<T>::counter = NULL;
147 }
148 }
149
150 template<class T>
151 const SmartPtr<T>& suPHP::SmartPtr<T>::operator=(
152 const SmartPtr<T>& ref) {
153 this.reset(ref.ptr);
154 return *this;
155 }
156
157 template<class T>
158 T& suPHP::SmartPtr<T>::operator*() const throw (PointerException) {
159 if (this->ptr == NULL)
160 throw PointerException("Cannot dereference NULL pointer",
161 __FILE__, __LINE__);
162 return *(this->ptr);
163 }
164
165 template<class T>
166 T* suPHP::SmartPtr<T>::operator->() const throw (PointerException) {
167 if (this->ptr == NULL)
168 throw PointerException("Cannot access member of NULL pointer",
169 __FILE__, __LINE__);
170 return this->ptr;
171 }
172
173 template<class T>
174 T* suPHP::SmartPtr<T>::get() const {
175 return this->ptr;
176 }
177
178 template<class T>
179 T* suPHP::SmartPtr<T>::release() throw (PointerException) {
180 T* obj_ptr = this->ptr;
181 if (obj_ptr == NULL)
182 return NULL;
183
184 int& c = SmartPtr<T>::counter->find(obj_ptr)->second;
185
186 if (c > 1) {
187 throw PointerException(
188 "Cannot release object hold by more than one SmartPointer.",
189 __FILE__, __LINE__);
190 } else {
191 SmartPtr<T>::counter->erase(obj_ptr);
192 }
193 this->ptr = NULL;
194 return obj_ptr;
195 }
196
197 template<class T>
198 void suPHP::SmartPtr<T>::reset(T* obj_ptr) {
199 if (obj_ptr != this->ptr) {
200 this->decrement(this->ptr);
201 this->ptr = obj_ptr;
202 this->increment(obj_ptr);
203 }
204 }
205
206 template<class T>
207 void suPHP::SmartPtr<T>::increment(T* key_ptr) {
208 if (key_ptr == NULL)
209 return;
210
211 if (SmartPtr<T>::counter->find(key_ptr)
212 != SmartPtr<T>::counter->end()) {
213 (SmartPtr<T>::counter->find(key_ptr)->second)++;
214 } else {
215 std::pair<T*, int> p;
216 p.first = key_ptr;
217 p.second = 1;
218 SmartPtr<T>::counter->insert(p);
219 }
220 }
221
222 template<class T>
223 void suPHP::SmartPtr<T>::decrement(T* key_ptr) {
224 if (key_ptr == NULL)
225 return;
226
227 int& c = SmartPtr<T>::counter->find(key_ptr)->second;
228 c--;
229 if (c < 1) {
230 delete key_ptr;
231 SmartPtr<T>::counter->erase(key_ptr);
232 }
233 }
234
235 template<class T>
236 bool suPHP::SmartPtr<T>::operator==(const SmartPtr<T>& ref) {
237 if (this->get() == ref.get())
238 return true;
239 else
240 return false;
241 }
242
243 };
244
245 #endif // SUPHP_SMARTPTR_H