1 | /** @file scim_pointer.h |
2 | * @brief Smart pointer class interface. |
3 | * |
4 | * Provides a reference-counted-object aware smart pointer class. |
5 | * |
6 | * Most code of this file are came from Inti project. |
7 | */ |
8 | |
9 | /* |
10 | * Smart Common Input Method |
11 | * |
12 | * Copyright (c) 2002-2005 James Su <suzhe@tsinghua.org.cn> |
13 | * Copyright (c) 2002 The Inti Development Team. |
14 | * |
15 | * |
16 | * This library is free software; you can redistribute it and/or |
17 | * modify it under the terms of the GNU Lesser General Public |
18 | * License as published by the Free Software Foundation; either |
19 | * version 2 of the License, or (at your option) any later version. |
20 | * |
21 | * This library is distributed in the hope that it will be useful, |
22 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
23 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
24 | * GNU Lesser General Public License for more details. |
25 | * |
26 | * You should have received a copy of the GNU Lesser General Public |
27 | * License along with this program; if not, write to the |
28 | * Free Software Foundation, Inc., 59 Temple Place, Suite 330, |
29 | * Boston, MA 02111-1307 USA |
30 | * |
31 | * $Id: scim_pointer.h,v 1.11 2005/01/10 08:30:54 suzhe Exp $ |
32 | */ |
33 | |
34 | #ifndef __SCIM_POINTER_H |
35 | #define __SCIM_POINTER_H |
36 | |
37 | namespace scim { |
38 | |
39 | /** |
40 | * @addtogroup Accessories |
41 | * @{ |
42 | */ |
43 | |
44 | /** |
45 | * @class Pointer |
46 | * @brief Smart pointer template class. |
47 | * |
48 | * Pointer is a standard auto_ptr-like smart pointer for managing heap |
49 | * allocated reference counted objects. T must be a class derived from |
50 | * scim::ReferencedObject. |
51 | */ |
52 | |
53 | template <typename T> |
54 | class Pointer |
55 | { |
56 | T *t; |
57 | |
58 | void set(T *object) |
59 | { |
60 | if (object) |
61 | { |
62 | if (!object->is_referenced()) |
63 | object->ref(); |
64 | object->set_referenced(false); |
65 | } |
66 | if (t) |
67 | t->unref(); |
68 | t = object; |
69 | } |
70 | |
71 | template<typename T1, typename T2> |
72 | friend bool operator == (const Pointer<T1>& t1, const Pointer<T2>& t2); |
73 | |
74 | public: |
75 | //! @name Constructors |
76 | //! @{ |
77 | |
78 | Pointer(T *object = 0) : t(0) |
79 | { |
80 | set(object); |
81 | } |
82 | //!< Construct a new smart pointer. |
83 | //!< @param object - a pointer to an object allocated on the heap. |
84 | //!< |
85 | //!< <BR>Initialize a new Pointer with any dumb pointer. |
86 | |
87 | Pointer(Pointer& src) : t(0) |
88 | { |
89 | set(src.get()); |
90 | } |
91 | //!< Copy constructor. |
92 | //!< @param src - a reference to a smart pointer. |
93 | //!< |
94 | //!< <BR>Initialize a new Pointer with any compatible Pointer. |
95 | |
96 | template <typename T1> |
97 | Pointer(const Pointer<T1>& src) : t(0) |
98 | { |
99 | set(src.get()); |
100 | } |
101 | //!< Copy constructor. |
102 | //!< @param src - a Pointer to type T1 where T1 is derived from T. |
103 | //!< |
104 | //!< <BR>Initialize a new Pointer of type T from a Pointer of type T1, |
105 | //!< only if T1 is derived from T. |
106 | |
107 | ~Pointer() |
108 | { |
109 | set(0); |
110 | } |
111 | //!< Destructor. |
112 | //!< Decreases the object reference count. |
113 | |
114 | Pointer& operator=(T *object) |
115 | { |
116 | set(object); |
117 | return *this; |
118 | } |
119 | //!< Assignment operator. |
120 | //!< @param object - a pointer to an object allocated on the heap. |
121 | //!< |
122 | //!< <BR>Releases the current dumb pointer, if any and assigns <EM>object</EM> |
123 | //!< to this Pointer, incrementing its reference count. |
124 | |
125 | Pointer& operator=(const Pointer& src) |
126 | { |
127 | set(src.get()); |
128 | return *this; |
129 | } |
130 | //!< Assignment operator. |
131 | //!< @param src - a reference to a smart pointer. |
132 | //!< |
133 | //!< <BR>Releases the current dumb pointer, if any and assigns the dumb pointer |
134 | //!< managed by <EM>src</EM> to this Pointer, incrementing its reference count. |
135 | |
136 | template <typename T1> |
137 | Pointer& operator=(const Pointer<T1>& src) |
138 | { |
139 | set(src.get()); |
140 | return *this; |
141 | } |
142 | //!< Assignment operator. |
143 | //!< @param src - a Pointer to type T1 where T1 is derived from T. |
144 | //!< |
145 | //!< <BR>Releases the current dumb pointer, if any and assigns the dumb pointer |
146 | //!< of type T1 managed by <EM>src</EM> to this Pointer as a dumb pointer of type T, |
147 | //!< only if T1 is derived from T. The reference count is incremented. |
148 | |
149 | //! @} |
150 | //! @name Accessors |
151 | //! @{ |
152 | |
153 | T& operator*() const |
154 | { |
155 | return *get(); |
156 | } |
157 | //!< Dereference operator. |
158 | //!< @return a reference to the object pointed to by the dumb pointer. |
159 | |
160 | T* operator->() const |
161 | { |
162 | return get(); |
163 | } |
164 | //!< Member selection operator. |
165 | //!< @return the dumb pointer. |
166 | |
167 | operator T*() const |
168 | { |
169 | return get(); |
170 | } |
171 | //!< Conversion operator. |
172 | //!< Converts a Pointer into its dumb pointer: the C pointer it manages. |
173 | //!< Normally it is considered pretty evil to mix smart and regular pointers. |
174 | //!< In scim you can safely if you just follow the reference counting rules |
175 | //!< for each of them. You can never call delete on Pointer either because |
176 | //!< you don't call delete on scim objects; you call unref(). |
177 | |
178 | T* get() const |
179 | { |
180 | return t; |
181 | } |
182 | //!< Returns the dumb pointer; the regular C pointer managed by the Pointer. |
183 | //!< @return the dumb pointer. |
184 | |
185 | bool null() const |
186 | { |
187 | return t == 0; |
188 | } |
189 | //!< Returns true if the Pointer has no dumb pointer. |
190 | |
191 | //! @} |
192 | //! @name Methods |
193 | //! @{ |
194 | |
195 | T* release() |
196 | { |
197 | T *tmp = t; |
198 | if (tmp) |
199 | tmp->ref(); |
200 | set(0); |
201 | return tmp; |
202 | } |
203 | //!< Releases the dumb pointer. |
204 | //!< @return the regular C pointer previously managed by the Pointer. |
205 | //!< |
206 | //!< <BR>Before releasing the dumb pointer its reference count is incremented |
207 | //!< to prevent it being destroyed. You must call unref() on the pointer to |
208 | //!< prevent a memory leak. |
209 | |
210 | void reset(T *object = 0) |
211 | { |
212 | set(object); |
213 | } |
214 | //!< Sets a new dumb pointer for the Pointer to manage. |
215 | //!< @param object - the new dumb pointer. |
216 | //!< |
217 | //!< <BR>Releases the current dumb pointer, if any, and assigns <EM>object</EM> |
218 | //!< to the Pointer, incrementing its reference count. |
219 | |
220 | //! @} |
221 | }; |
222 | |
223 | //! @name Equality operators |
224 | //! @{ |
225 | |
226 | template<typename T1, typename T2> |
227 | inline bool operator == (const Pointer<T1>& t1, const Pointer<T2>& t2) |
228 | { |
229 | return t1.t == t2.t; |
230 | } |
231 | //!< Compares two Pointers. |
232 | //!< @return <EM>true</EM> if both Pointers manage to same dumb pointer. |
233 | |
234 | template<typename T1, typename T2> |
235 | inline bool operator != (const Pointer<T1>& t1, const Pointer<T2>& t2) |
236 | { |
237 | return !(t1 == t2); |
238 | } |
239 | //!< Compares two Pointers. |
240 | //!< @return <EM>true</EM> if both Pointers manage a different dumb pointer. |
241 | |
242 | //! @} |
243 | //! @name C++-style casting functions |
244 | //! @{ |
245 | |
246 | template <typename To, typename From> |
247 | inline Pointer<To> |
248 | cast_const(const Pointer<From>& from) |
249 | { |
250 | return Pointer<To>(from ? const_cast<To*>(from.get()) : 0); |
251 | } |
252 | //!< Removes the <EM>const</EM> qualifier from a managed const dumb pointer. |
253 | //!< @param from - a Pointer that manages a const dumb pointer. |
254 | //!< @return a new Pointer that manages the non-const dumb pointer. |
255 | //!< |
256 | //!< <BR>Calls <EM>const_cast</EM> on the dumb pointer and returns the non-const |
257 | //!< pointer as a new Pointer. |
258 | |
259 | template <typename To, typename From> |
260 | inline Pointer<To> |
261 | cast_dynamic(const Pointer<From>& from) |
262 | { |
263 | return Pointer<To>(dynamic_cast<To*>(from.get())); |
264 | } |
265 | //!< Casts a managed polymophic dumb pointer down or across its inheritance heirarchy. |
266 | //!< @param from - a Pointer managing a polymophic dumb pointer of type From. |
267 | //!< @return a new Pointer managing the dumb pointer as a base or sibling pointer of type <EM>To</EM>. |
268 | //!< |
269 | //!< <BR>Calls <EM>dynmaic_cast</EM> to safely cast a managed polymophic dumb pointer |
270 | //!< of type <EM>From</EM> to a base, derived or sibling class pointer of type <EM>To</EM>. |
271 | |
272 | template <typename To, typename From> |
273 | inline Pointer<To> |
274 | cast_static(const Pointer<From>& from) |
275 | { |
276 | return Pointer<To>(from ? static_cast<To*>(from.get()) : 0); |
277 | } |
278 | //!< Casts a managed dumb pointer to a pointer to a related type. |
279 | //!< @param from - a Pointer managing a dumb pointer of type From. |
280 | //!< @return a new Pointer managing the dumb pointer as a pointer of type <EM>To</EM>. |
281 | //!< |
282 | //!< <BR>Calls <EM>static_cast</EM> to cast a dumb pointer of type <EM>From</EM> to a |
283 | //!< pointer of type <EM>To</EM>. |
284 | |
285 | //! @} |
286 | |
287 | /** @} */ |
288 | |
289 | } // namespace scim |
290 | |
291 | #endif //__SCIM_POINTER_H |
292 | |
293 | /* |
294 | vi:ts=4:nowrap:ai:expandtab |
295 | */ |
296 | |