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,
133	DestructorReturnType (*Destructor)(Type*)>
134struct CObjectDelete
135{
136	inline void operator()(Type *object)
137	{
138		if (object != NULL)
139			Destructor(object);
140	}
141};
142
143template<typename Type, typename DestructorReturnType,
144	DestructorReturnType (*Destructor)(Type*)>
145struct CObjectDeleter
146	: AutoDeleter<Type, CObjectDelete<Type, DestructorReturnType, Destructor> >
147{
148	typedef AutoDeleter<Type,
149		CObjectDelete<Type, DestructorReturnType, Destructor> > Base;
150
151	CObjectDeleter() : Base()
152	{
153	}
154
155	CObjectDeleter(Type *object) : Base(object)
156	{
157	}
158};
159
160
161// MethodDeleter
162
163template<typename Type, typename DestructorReturnType>
164struct MethodDelete
165{
166	inline void operator()(Type *object)
167	{
168		if (fDestructor && object != NULL)
169			(object->*fDestructor)();
170	}
171
172	template<typename Destructor>
173	inline void operator=(Destructor destructor)
174	{
175		fDestructor = destructor;
176	}
177
178private:
179	DestructorReturnType (Type::*fDestructor)();
180};
181
182
183template<typename Type, typename DestructorReturnType = void>
184struct MethodDeleter
185	: AutoDeleter<Type, MethodDelete<Type, DestructorReturnType> >
186{
187	typedef AutoDeleter<Type, MethodDelete<Type, DestructorReturnType> > Base;
188
189	template<typename Destructor>
190	MethodDeleter(Destructor destructor) : Base()
191	{
192		Base::fDelete = destructor;
193	}
194
195	template<typename Destructor>
196	MethodDeleter(Type *object, Destructor destructor) : Base(object)
197	{
198		Base::fDelete = destructor;
199	}
200};
201
202}	// namespace FSShell
203
204using FSShell::ObjectDeleter;
205using FSShell::ArrayDeleter;
206using FSShell::MemoryDeleter;
207using FSShell::CObjectDeleter;
208using FSShell::MethodDeleter;
209
210#endif	// _AUTO_DELETER_H
211