summaryrefslogtreecommitdiff
path: root/src/libical/icptrholder_cxx.h
blob: bd63fe5a38d958fd4f4ed02a33fc7d8b635d8968 (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
126
127
128
129
130
131
132
133
/**
 * @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) {
 *
 * (C) COPYRIGHT 2001, Critical Path

 This library is free software; you can redistribute it and/or modify
 it under the terms of either:

    The LGPL as published by the Free Software Foundation, version
    2.1, available at: https://www.gnu.org/licenses/lgpl-2.1.html

 Or:

    The Mozilla Public License Version 2.0. You may obtain a copy of
    the License at https://www.mozilla.org/MPL/
 */

#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
    {
        assert(ptr);
        return ptr;
    }

    T &operator*()
    {
        assert(ptr);
        return *ptr;
    }

private:
    void release()
    {
        if (ptr != 0) {
            ptr->detach();
            delete ptr;

            ptr = 0;
        }
    }

    T *ptr;
};

#endif