blob: 95b65e5c2b91b9d05410d62b43e5562f2b8cad2a (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
/**
* @file icptrholder_cxx.h
* @author wyau (08/29/02)
* @brief C++ template classes for managing C++ pointers returned by
* VComponent::get_..._component, VComponent::get_..._property,
* ICalProperty::get_..._value.
*
* @remarks VComponent::get... functions returns a C++ object that wraps the
* libical implementation. It is important to note that the wrapped
* implementation still belongs to the original component. To stop memory leak,
* caller must delete the pointer. However, the destructor will call the
* appropriate free function. eg. ~VComponent calls icalcomponent_free(imp).
*
* As stated previously, imp still belongs to the original component. To avoid
* freeing the wrapped "imp", caller must set the "imp" to null before deleting
* the pointer.
*
* The template class relieves the burden of memory management when used as a
* stack based object. The class holds a pointer to the C++ Wrapper.
* The destructor set the imp to null before deleting the pointer.
*
* Each C++ Wrapper instantiates a template class in its corresponding .h file.
*
* Usage example:
* VComponentTmpPtr p;// VComponentTmpPtr is an instantiation of this template
* for (p=component.get_first_component; p!= 0; p=component.get_next_component) {
*
* SPDX-FileCopyrightText: 2001, Critical Path
SPDX-License-Identifier: LGPL-2.1-only OR MPL-2.0
*/
#ifndef ICPTRHOLDER_CXX_H
#define ICPTRHOLDER_CXX_H
#include <cassert>
template < class T > class ICPointerHolder
{
public:
ICPointerHolder()
: ptr(0)
{
}
ICPointerHolder(T *p)
: ptr(p)
{
}
// copy constructor to support assignment
ICPointerHolder(const ICPointerHolder &ip)
: ptr(ip.ptr)
{
// We need to transfer ownership of ptr to this object by setting
// ip's ptr to null. Otherwise, ptr will de deleted twice.
// const ugliness requires us to do the const_cast.
ICPointerHolder *ipp = const_cast < ICPointerHolder * >(&ip);
ipp->ptr = 0;
};
~ICPointerHolder()
{
release();
}
ICPointerHolder &operator=(T *p)
{
this->release();
ptr = p;
return *this;
}
ICPointerHolder &operator=(ICPointerHolder &p)
{
this->release();
ptr = p.ptr; // this transfer ownership of the pointer
p.ptr = 0; // set it to null so the pointer won't get delete twice.
return *this;
}
bool operator!=(T *p)
{
return (ptr != p);
}
bool operator==(T *p)
{
return (ptr == p);
}
operator T *() const
{
return ptr;
}
T *operator->() const
{
icalassert(ptr);
return ptr;
}
T &operator*()
{
icalassert(ptr);
return *ptr;
}
private:
void release()
{
if (ptr != 0) {
ptr->detach();
delete ptr;
ptr = 0;
}
}
T *ptr;
};
#endif
|