1 /*
2  * Copyright 2006-2008 The FLWOR Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #ifndef ZORBA_STORE_ITEM_HANDLE_H
17 #define ZORBA_STORE_ITEM_HANDLE_H
18 
19 #include <string>
20 #include <sstream>
21 
22 namespace zorba
23 {
24 
25 namespace store
26 {
27 
28 
29 /*******************************************************************************
30   Template class for smart pointers-to-T objects. T must be Item or a subclass
31   of Item.
32 ********************************************************************************/
33 template<class T> class ItemHandle
34 {
35 protected:
36   T  * p;
37 
38 public:
39   union union_T
40   {
41     T** t;
42     void** v;
43   };
44 
45 public:
ItemHandle()46   ItemHandle() : p(0)
47   {
48   }
49 
ItemHandle(T * ptr)50   ItemHandle(T* ptr) : p(ptr)
51   {
52     if (p)
53       p->addReference();
54   }
55 
ItemHandle(const ItemHandle & rhs)56   ItemHandle(const ItemHandle& rhs) : p(rhs.getp())
57   {
58     if (p)
59       p->addReference();
60   }
61 
~ItemHandle()62   ~ItemHandle()
63   {
64     if (p)
65       p->removeReference();
66 
67     p = NULL; // do not remove
68   }
69 
isNull()70   bool isNull () const { return p == NULL; }
71 
setNull()72   void setNull() { p = NULL; }
73 
getp()74   T* getp() const { return p; }
75 
getp_ref()76   union_T getp_ref() { union_T u_t; u_t.t = &p; return u_t;}
77 
78   operator T* () { return getp(); }
79 
80   operator const T* () const { return getp(); }
81 
82   T* operator->() const { return p; }
83 
84   T& operator*() const { return *p; }
85 
86 	bool operator==(const ItemHandle& h) const  { return p == h.p; }
87 
88 	bool operator==(const T* pp) const { return p == pp; }
89 
90 	bool operator!=(const ItemHandle& h) const  { return p != h.p; }
91 
92 	bool operator!=(const T* pp) const { return p != pp; }
93 
94   bool operator<(const ItemHandle& h) const { return p < h.p; }
95 
96 
cast()97   template <class otherT> ItemHandle<otherT> cast() const
98   {
99     return ItemHandle<otherT> (static_cast<otherT *>(p));
100   }
101 
102   template <class otherT> operator ItemHandle<otherT> ()
103   {
104     return cast<otherT>();
105   }
106 
107   template <class otherT> operator const ItemHandle<otherT> () const
108   {
109     return cast<otherT>();
110   }
111 
112   ItemHandle& operator=(const T* rhs)
113   {
114 		if (p != rhs)
115     {
116 			if (p)
117         p->removeReference();
118 
119 			p = const_cast<T*>(rhs);
120 
121       if (p)
122         p->addReference();
123 		}
124 
125 		return *this;
126   }
127 
128   template <class otherT> ItemHandle& operator=(const otherT* rhs)
129   {
130 		if (p != rhs)
131     {
132 			if (p)
133         p->removeReference();
134 
135 			p = static_cast<T*>(const_cast<otherT*>(rhs));
136 
137       if (p)
138         p->addReference();
139 		}
140 		return *this;
141   }
142 
143   ItemHandle& operator=(const ItemHandle& rhs)
144   {
145     return assign(rhs);
146   }
147 
148 	template <class otherT> ItemHandle& operator=(const ItemHandle<otherT>& rhs)
149   {
150     return assign(rhs);
151 	}
152 
transfer(ItemHandle<otherT> & rhs)153   template <class otherT> ItemHandle& transfer(ItemHandle<otherT>& rhs)
154   {
155 		if (p != rhs.getp())
156     {
157 			if (p)
158         p->removeReference();
159 
160 			p = static_cast<T*>(rhs.getp());
161 
162 			rhs.setNull();
163 		}
164 		return *this;
165   }
166 
transfer(ItemHandle & rhs)167   ItemHandle& transfer(ItemHandle& rhs)
168   {
169 		if (p != rhs.p)
170     {
171 			if (p)
172         p->removeReference();
173 
174 			p = rhs.p;
175 
176 			rhs.p = NULL;
177 		}
178 		return *this;
179   }
180 
release()181   T* release()
182   {
183     T* tmp = p;
184     p = NULL;
185     return tmp;
186   }
187 
188 public:
debug()189 	std::string debug() const
190   {
191     std::ostringstream oss;
192     oss << "ItemHandle[refcount=" << p->getRefCount() << ']';
193     return oss.str();
194   }
195 
196 protected:
assign(const ItemHandle<otherT> & rhs)197   template <class otherT> ItemHandle& assign(const ItemHandle<otherT>& rhs)
198   {
199 		if (p != rhs.getp())
200     {
201 			if (p)
202         p->removeReference();
203 
204 			p = static_cast<T*>(rhs.getp());
205 
206       if (p)
207         p->addReference();
208 		}
209 
210 		return *this;
211   }
212 };
213 
214 
215 } // namespace store
216 } // namespace zorba
217 
218 #endif
219 
220 /*
221  * Local variables:
222  * mode: c++
223  * End:
224  */
225 /* vim:set et sw=2 ts=2: */
226