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
9/*!	Scope-based automatic deletion of objects/arrays.
10	ObjectDeleter  - deletes an object
11	ArrayDeleter   - deletes an array
12	MemoryDeleter  - free()s malloc()ed memory
13	CObjectDeleter - calls an arbitrary specified destructor function
14	MethodObjectDeleter - calls an arbitrary object function in given struct ptr
15	HandleDeleter  - use arbitrary handle type and destructor function
16	FileDescriptorCloser - closes a file descriptor, based on HandleDeleter
17*/
18
19
20#include <stdlib.h>
21#include <unistd.h>
22#include <SupportDefs.h>
23
24#ifndef _OS_H
25extern "C" {
26extern void			debugger(const char *message);
27}
28#endif
29
30
31namespace BPrivate {
32
33
34// AutoDeleter
35
36template<typename C, typename DeleteFunc>
37class AutoDeleter {
38public:
39	inline AutoDeleter()
40		: fObject(NULL)
41	{
42	}
43
44	inline AutoDeleter(C *object)
45		: fObject(object)
46	{
47	}
48
49	inline ~AutoDeleter()
50	{
51		DeleteFunc destructor;
52		destructor(fObject);
53	}
54
55	inline void SetTo(C *object)
56	{
57		if (object == fObject && object != NULL)
58			debugger("identical objects");
59
60		if (object != fObject) {
61			DeleteFunc destructor;
62			destructor(fObject);
63			fObject = object;
64		}
65	}
66
67	inline void Unset()
68	{
69		SetTo(NULL);
70	}
71
72	inline void Delete()
73	{
74		SetTo(NULL);
75	}
76
77	inline bool IsSet() const
78	{
79		return fObject != NULL;
80	}
81
82	inline C *Get() const
83	{
84		return fObject;
85	}
86
87	inline C *Detach()
88	{
89		C *object = fObject;
90		fObject = NULL;
91		return object;
92	}
93
94	inline C *operator->() const
95	{
96		return fObject;
97	}
98
99protected:
100	C			*fObject;
101
102private:
103	AutoDeleter(const AutoDeleter&);
104	AutoDeleter& operator=(const AutoDeleter&);
105};
106
107
108// ObjectDeleter
109
110template<typename C>
111struct ObjectDelete
112{
113	inline void operator()(C *object)
114	{
115		delete object;
116	}
117};
118
119template<typename C>
120struct ObjectDeleter : AutoDeleter<C, ObjectDelete<C> >
121{
122	ObjectDeleter() : AutoDeleter<C, ObjectDelete<C> >() {}
123	ObjectDeleter(C *object) : AutoDeleter<C, ObjectDelete<C> >(object) {}
124};
125
126
127// ArrayDeleter
128
129template<typename C>
130struct ArrayDelete
131{
132	inline void operator()(C *array)
133	{
134		delete[] array;
135	}
136};
137
138template<typename C>
139struct ArrayDeleter : AutoDeleter<C, ArrayDelete<C> >
140{
141	ArrayDeleter() : AutoDeleter<C, ArrayDelete<C> >() {}
142	ArrayDeleter(C *array) : AutoDeleter<C, ArrayDelete<C> >(array) {}
143
144	inline C& operator[](size_t index) const
145	{
146		return this->Get()[index];
147	}
148};
149
150
151// MemoryDeleter
152
153struct MemoryDelete
154{
155	inline void operator()(void *memory)
156	{
157		free(memory);
158	}
159};
160
161struct MemoryDeleter : AutoDeleter<void, MemoryDelete >
162{
163	MemoryDeleter() : AutoDeleter<void, MemoryDelete >() {}
164	MemoryDeleter(void *memory) : AutoDeleter<void, MemoryDelete >(memory) {}
165};
166
167
168// CObjectDeleter
169
170template<typename Type, typename DestructorReturnType,
171	DestructorReturnType (*Destructor)(Type*)>
172struct CObjectDelete
173{
174	inline void operator()(Type *object)
175	{
176		if (object != NULL)
177			Destructor(object);
178	}
179};
180
181template<typename Type, typename DestructorReturnType,
182	DestructorReturnType (*Destructor)(Type*)>
183struct CObjectDeleter
184	: AutoDeleter<Type, CObjectDelete<Type, DestructorReturnType, Destructor> >
185{
186	typedef AutoDeleter<Type,
187		CObjectDelete<Type, DestructorReturnType, Destructor> > Base;
188
189	CObjectDeleter() : Base()
190	{
191	}
192
193	CObjectDeleter(Type *object) : Base(object)
194	{
195	}
196};
197
198
199// MethodDeleter
200
201template<typename Type, typename DestructorReturnType,
202	DestructorReturnType (Type::*Destructor)()>
203struct MethodDelete
204{
205	inline void operator()(Type *object)
206	{
207		if (object != NULL)
208			(object->*Destructor)();
209	}
210};
211
212
213template<typename Type, typename DestructorReturnType,
214	DestructorReturnType (Type::*Destructor)()>
215struct MethodDeleter
216	: AutoDeleter<Type, MethodDelete<Type, DestructorReturnType, Destructor> >
217{
218	typedef AutoDeleter<Type,
219		MethodDelete<Type, DestructorReturnType, Destructor> > Base;
220
221	MethodDeleter() : Base()
222	{
223	}
224
225	MethodDeleter(Type *object) : Base(object)
226	{
227	}
228};
229
230
231// MethodObjectDeleter
232
233template<typename Type, typename Table, Table **table,
234	void (*Table::*Deleter)(Type*)>
235struct MethodObjectDelete {
236	inline void operator()(Type *object)
237	{
238		if (object != NULL)
239			((**table).*Deleter)(object);
240	}
241};
242
243template<typename Type, typename Table, Table **table,
244	typename DestructorResult, DestructorResult (*Table::*Deleter)(Type*)>
245struct MethodObjectDeleter
246	: AutoDeleter<Type, MethodObjectDelete<Type, Table, table, Deleter> >
247{
248	typedef AutoDeleter<Type,
249		MethodObjectDelete<Type, Table, table, Deleter> > Base;
250
251	MethodObjectDeleter() : Base() {}
252	MethodObjectDeleter(Type *object) : Base(object) {}
253};
254
255
256// HandleDeleter
257
258struct StatusHandleChecker
259{
260	inline bool operator()(status_t handle)
261	{
262		return handle >= B_OK;
263	}
264};
265
266template<typename C, typename DestructorResult,
267	DestructorResult (*Destructor)(C), C nullValue = -1,
268	typename Checker = StatusHandleChecker>
269class HandleDeleter {
270public:
271	inline HandleDeleter()
272		: fHandle(nullValue)
273	{
274	}
275
276	inline HandleDeleter(C handle)
277		: fHandle(handle)
278	{
279	}
280
281	inline ~HandleDeleter()
282	{
283		if (IsSet())
284			Destructor(fHandle);
285	}
286
287	inline void SetTo(C handle)
288	{
289		if (handle != fHandle) {
290			if (IsSet())
291				Destructor(fHandle);
292			fHandle = handle;
293		}
294	}
295
296	inline void Unset()
297	{
298		SetTo(nullValue);
299	}
300
301	inline void Delete()
302	{
303		SetTo(nullValue);
304	}
305
306	inline bool IsSet() const
307	{
308		Checker isHandleSet;
309		return isHandleSet(fHandle);
310	}
311
312	inline C Get() const
313	{
314		return fHandle;
315	}
316
317	inline C Detach()
318	{
319		C handle = fHandle;
320		fHandle = nullValue;
321		return handle;
322	}
323
324protected:
325	C			fHandle;
326
327private:
328	HandleDeleter(const HandleDeleter&);
329	HandleDeleter& operator=(const HandleDeleter&);
330};
331
332
333// FileDescriptorCloser
334
335typedef HandleDeleter<int, int, close, -1> FileDescriptorCloser;
336
337
338}	// namespace BPrivate
339
340
341using ::BPrivate::ObjectDeleter;
342using ::BPrivate::ArrayDeleter;
343using ::BPrivate::MemoryDeleter;
344using ::BPrivate::CObjectDeleter;
345using ::BPrivate::MethodDeleter;
346using ::BPrivate::MethodObjectDeleter;
347using ::BPrivate::HandleDeleter;
348using ::BPrivate::FileDescriptorCloser;
349
350
351#endif	// _AUTO_DELETER_H
352