1/*
2 * Copyright 2001-2007, Ingo Weinhold, bonefish@users.sf.net. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 */
5#ifndef _AUTO_DELETER_H
6#define _AUTO_DELETER_H
7
8/*!	Scope-based automatic deletion of objects/arrays.
9	ObjectDeleter  - deletes an object
10	ArrayDeleter   - deletes an array
11	MemoryDeleter  - free()s malloc()ed memory
12	CObjectDeleter - calls an arbitrary specified destructor function
13*/
14
15#include <stdlib.h>
16
17namespace FSShell {
18
19// AutoDeleter
20
21template<typename C, typename DeleteFunc>
22class AutoDeleter {
23public:
24	inline AutoDeleter()
25		: fObject(NULL)
26	{
27	}
28
29	inline AutoDeleter(C *object)
30		: fObject(object)
31	{
32	}
33
34	inline ~AutoDeleter()
35	{
36		fDelete(fObject);
37	}
38
39	inline void SetTo(C *object)
40	{
41		if (object != fObject) {
42			fDelete(fObject);
43			fObject = object;
44		}
45	}
46
47	inline void Unset()
48	{
49		SetTo(NULL);
50	}
51
52	inline void Delete()
53	{
54		SetTo(NULL);
55	}
56
57	inline C *Get() const
58	{
59		return fObject;
60	}
61
62	inline C *Detach()
63	{
64		C *object = fObject;
65		fObject = NULL;
66		return object;
67	}
68
69protected:
70	C			*fObject;
71	DeleteFunc	fDelete;
72};
73
74
75// ObjectDeleter
76
77template<typename C>
78struct ObjectDelete
79{
80	inline void operator()(C *object)
81	{
82		delete object;
83	}
84};
85
86template<typename C>
87struct ObjectDeleter : AutoDeleter<C, ObjectDelete<C> >
88{
89	ObjectDeleter() : AutoDeleter<C, ObjectDelete<C> >() {}
90	ObjectDeleter(C *object) : AutoDeleter<C, ObjectDelete<C> >(object) {}
91};
92
93
94// ArrayDeleter
95
96template<typename C>
97struct ArrayDelete
98{
99	inline void operator()(C *array)
100	{
101		delete[] array;
102	}
103};
104
105template<typename C>
106struct ArrayDeleter : AutoDeleter<C, ArrayDelete<C> >
107{
108	ArrayDeleter() : AutoDeleter<C, ArrayDelete<C> >() {}
109	ArrayDeleter(C *array) : AutoDeleter<C, ArrayDelete<C> >(array) {}
110};
111
112
113// MemoryDeleter
114
115struct MemoryDelete
116{
117	inline void operator()(void *memory)
118	{
119		free(memory);
120	}
121};
122
123struct MemoryDeleter : AutoDeleter<void, MemoryDelete >
124{
125	MemoryDeleter() : AutoDeleter<void, MemoryDelete >() {}
126	MemoryDeleter(void *memory) : AutoDeleter<void, MemoryDelete >(memory) {}
127};
128
129
130// CObjectDeleter
131
132template<typename Type, typename DestructorReturnType>
133struct CObjectDelete
134{
135	inline void operator()(Type *object)
136	{
137		if (fDestructor != NULL && object != NULL)
138			fDestructor(object);
139	}
140
141	template<typename Destructor>
142	inline void operator=(Destructor destructor)
143	{
144		fDestructor = destructor;
145	}
146
147private:
148	DestructorReturnType (*fDestructor)(Type*);
149};
150
151template<typename Type, typename DestructorReturnType = void>
152struct CObjectDeleter
153	: AutoDeleter<Type, CObjectDelete<Type, DestructorReturnType> >
154{
155	typedef AutoDeleter<Type, CObjectDelete<Type, DestructorReturnType> > Base;
156
157	template<typename Destructor>
158	CObjectDeleter(Destructor destructor) : Base()
159	{
160		Base::fDelete = destructor;
161	}
162
163	template<typename Destructor>
164	CObjectDeleter(Type *object, Destructor destructor) : Base(object)
165	{
166		Base::fDelete = destructor;
167	}
168};
169
170
171// MethodDeleter
172
173template<typename Type, typename DestructorReturnType>
174struct MethodDelete
175{
176	inline void operator()(Type *object)
177	{
178		if (fDestructor && object != NULL)
179			(object->*fDestructor)();
180	}
181
182	template<typename Destructor>
183	inline void operator=(Destructor destructor)
184	{
185		fDestructor = destructor;
186	}
187
188private:
189	DestructorReturnType (Type::*fDestructor)();
190};
191
192
193template<typename Type, typename DestructorReturnType = void>
194struct MethodDeleter
195	: AutoDeleter<Type, MethodDelete<Type, DestructorReturnType> >
196{
197	typedef AutoDeleter<Type, MethodDelete<Type, DestructorReturnType> > Base;
198
199	template<typename Destructor>
200	MethodDeleter(Destructor destructor) : Base()
201	{
202		Base::fDelete = destructor;
203	}
204
205	template<typename Destructor>
206	MethodDeleter(Type *object, Destructor destructor) : Base(object)
207	{
208		Base::fDelete = destructor;
209	}
210};
211
212}	// namespace FSShell
213
214using FSShell::ObjectDeleter;
215using FSShell::ArrayDeleter;
216using FSShell::MemoryDeleter;
217using FSShell::CObjectDeleter;
218using FSShell::MethodDeleter;
219
220#endif	// _AUTO_DELETER_H
221