1 /* -*- Mode: C++ -*- */
2 
3 /**
4  * @file    icptrholder.h
5  * @author  wyau (08/29/02)
6  * @brief   C++ template classes for managing C++ pointers returned by VComponent::get_..._component,
7  *          VComponent::get_..._property, ICalPropety::get_..._value.
8  * @remarks VComponent::get... functions returns a C++ oject that wraps the libical implementation.
9  *          It is important to note that the wrapped implementation still belongs to the orginal
10  *          component. To stop memory leak, caller must delete the pointer. However, the destructor
11  *          will call the appropriate free function. eg. ~VComponent calls icalcomponent_free(imp).
12  *          As stated previously, imp stil belongs to the original component. To avoid freeing the
13  *          wrapped "imp", caller must set the "imp" to null before deleting the pointer.
14  *
15  *          The template class relieves the burden of memory management when used as a stack based
16  *          object. The class holds a pointer to the C++ Wrapper. The destructor set the imp to
17  *          null before deleting the pointer.
18  *
19  *          Each C++ Wrapper instantiates a template class in it's corresponding .h file.
20  *
21  *          Usage example:
22  *             VComponentTmpPtr p;   // VComponentTmpPtr is an instantiation of this template
23  *             for (p=component.get_first_component; p!= NULL; p=component.get_next_component) {
24  *
25  * (C) COPYRIGHT 2001, Critical Path
26 
27  This program is free software; you can redistribute it and/or modify
28  it under the terms of either:
29 
30     The LGPL as published by the Free Software Foundation, version
31     2.1, available at: http://www.fsf.org/copyleft/lesser.html
32 
33   Or:
34 
35     The Mozilla Public License Version 1.0. You may obtain a copy of
36     the License at http://www.mozilla.org/MPL/
37  */
38 
39 #ifndef __ICPTRHOLDER_H__
40 #define __ICPTRHOLDER_H__
41 
42 template<class T> class ICPointerHolder {
43 public:
ICPointerHolder()44     ICPointerHolder() { ptr = NULL; }
ICPointerHolder(T * p)45     ICPointerHolder(T* p) { ptr = p; }
46 
47     // copy constructor to support assignment
ICPointerHolder(const ICPointerHolder & ip)48     ICPointerHolder(const ICPointerHolder& ip) {
49         ptr = ip.ptr;
50 
51         // We need to transfer ownership of ptr to this object by setting
52         // ip's ptr to null. Otherwise, ptr will de deleted twice.
53         // const ugliness requires us to do the const_cast.
54         ICPointerHolder *ipp = const_cast<ICPointerHolder*>(&ip);
55         ipp->ptr = NULL;
56     };
57 
~ICPointerHolder()58    ~ICPointerHolder() {
59         release();
60     }
61 
62     ICPointerHolder& operator=(T* p) {
63         this->release();
64         ptr = p;
65         return *this;
66     }
67 
68     ICPointerHolder& operator=(ICPointerHolder& p) {
69         this->release();
70         ptr = p.ptr;            // this transfer ownership of the pointer
71         p.ptr = NULL;           // set it to null so the pointer won't get delete twice.
72         return *this;
73     }
74 
75     int operator!=(T* p) {return (ptr != p);}
76     int operator==(T* p) {return (ptr == p);}
77 
78     operator T*() const {
79         return ptr;
80     }
81 
82     T* operator->() const {
83         assert(ptr);
84         return ptr;
85     }
86 
87     T& operator*() {
88         assert(ptr);
89         return *ptr;
90     }
91 
92 private:
release()93     void  release() {
94         if (ptr != NULL) {
95             ptr->detach();
96             delete ptr;
97             ptr = NULL;
98         }
99     }
100 
101     T*    ptr;
102 };
103 
104 #endif
105