root/headers/private/shared/AutoDeleter.h
/*
 * Copyright 2001-2007, Ingo Weinhold, bonefish@users.sf.net. All rights reserved.
 * Distributed under the terms of the MIT License.
 */
#ifndef _AUTO_DELETER_H
#define _AUTO_DELETER_H


/*!     Scope-based automatic deletion of objects/arrays.
        ObjectDeleter  - deletes an object
        ArrayDeleter   - deletes an array
        MemoryDeleter  - free()s malloc()ed memory
        CObjectDeleter - calls an arbitrary specified destructor function
        MethodObjectDeleter - calls an arbitrary object function in given struct ptr
        HandleDeleter  - use arbitrary handle type and destructor function
        FileDescriptorCloser - closes a file descriptor, based on HandleDeleter
*/


#include <stdlib.h>
#include <unistd.h>
#include <SupportDefs.h>

#ifndef _OS_H
extern "C" {
extern void                     debugger(const char *message);
}
#endif


namespace BPrivate {


// AutoDeleter

template<typename C, typename DeleteFunc>
class AutoDeleter {
public:
        inline AutoDeleter()
                : fObject(NULL)
        {
        }

        inline AutoDeleter(C *object)
                : fObject(object)
        {
        }

        inline ~AutoDeleter()
        {
                DeleteFunc destructor;
                destructor(fObject);
        }

        inline void SetTo(C *object)
        {
                if (object == fObject && object != NULL)
                        debugger("identical objects");

                if (object != fObject) {
                        DeleteFunc destructor;
                        destructor(fObject);
                        fObject = object;
                }
        }

        inline void Unset()
        {
                SetTo(NULL);
        }

        inline void Delete()
        {
                SetTo(NULL);
        }

        inline bool IsSet() const
        {
                return fObject != NULL;
        }

        inline C *Get() const
        {
                return fObject;
        }

        inline C *Detach()
        {
                C *object = fObject;
                fObject = NULL;
                return object;
        }

        inline C *operator->() const
        {
                return fObject;
        }

protected:
        C                       *fObject;

private:
        AutoDeleter(const AutoDeleter&);
        AutoDeleter& operator=(const AutoDeleter&);
};


// ObjectDeleter

template<typename C>
struct ObjectDelete
{
        inline void operator()(C *object)
        {
                delete object;
        }
};

template<typename C>
struct ObjectDeleter : AutoDeleter<C, ObjectDelete<C> >
{
        ObjectDeleter() : AutoDeleter<C, ObjectDelete<C> >() {}
        ObjectDeleter(C *object) : AutoDeleter<C, ObjectDelete<C> >(object) {}
};


// ArrayDeleter

template<typename C>
struct ArrayDelete
{
        inline void operator()(C *array)
        {
                delete[] array;
        }
};

template<typename C>
struct ArrayDeleter : AutoDeleter<C, ArrayDelete<C> >
{
        ArrayDeleter() : AutoDeleter<C, ArrayDelete<C> >() {}
        ArrayDeleter(C *array) : AutoDeleter<C, ArrayDelete<C> >(array) {}

        inline C& operator[](size_t index) const
        {
                return this->Get()[index];
        }
};


// MemoryDeleter

struct MemoryDelete
{
        inline void operator()(void *memory)
        {
                free(memory);
        }
};

struct MemoryDeleter : AutoDeleter<void, MemoryDelete >
{
        MemoryDeleter() : AutoDeleter<void, MemoryDelete >() {}
        MemoryDeleter(void *memory) : AutoDeleter<void, MemoryDelete >(memory) {}
};


// CObjectDeleter

template<typename Type, typename DestructorReturnType,
        DestructorReturnType (*Destructor)(Type*)>
struct CObjectDelete
{
        inline void operator()(Type *object)
        {
                if (object != NULL)
                        Destructor(object);
        }
};

template<typename Type, typename DestructorReturnType,
        DestructorReturnType (*Destructor)(Type*)>
struct CObjectDeleter
        : AutoDeleter<Type, CObjectDelete<Type, DestructorReturnType, Destructor> >
{
        typedef AutoDeleter<Type,
                CObjectDelete<Type, DestructorReturnType, Destructor> > Base;

        CObjectDeleter() : Base()
        {
        }

        CObjectDeleter(Type *object) : Base(object)
        {
        }
};


// MethodDeleter

template<typename Type, typename DestructorReturnType,
        DestructorReturnType (Type::*Destructor)()>
struct MethodDelete
{
        inline void operator()(Type *object)
        {
                if (object != NULL)
                        (object->*Destructor)();
        }
};


template<typename Type, typename DestructorReturnType,
        DestructorReturnType (Type::*Destructor)()>
struct MethodDeleter
        : AutoDeleter<Type, MethodDelete<Type, DestructorReturnType, Destructor> >
{
        typedef AutoDeleter<Type,
                MethodDelete<Type, DestructorReturnType, Destructor> > Base;

        MethodDeleter() : Base()
        {
        }

        MethodDeleter(Type *object) : Base(object)
        {
        }
};


// MethodObjectDeleter

template<typename Type, typename Table, Table **table,
        void (*Table::*Deleter)(Type*)>
struct MethodObjectDelete {
        inline void operator()(Type *object)
        {
                if (object != NULL)
                        ((**table).*Deleter)(object);
        }
};

template<typename Type, typename Table, Table **table,
        typename DestructorResult, DestructorResult (*Table::*Deleter)(Type*)>
struct MethodObjectDeleter
        : AutoDeleter<Type, MethodObjectDelete<Type, Table, table, Deleter> >
{
        typedef AutoDeleter<Type,
                MethodObjectDelete<Type, Table, table, Deleter> > Base;

        MethodObjectDeleter() : Base() {}
        MethodObjectDeleter(Type *object) : Base(object) {}
};


// HandleDeleter

struct StatusHandleChecker
{
        inline bool operator()(status_t handle)
        {
                return handle >= B_OK;
        }
};

template<typename C, typename DestructorResult,
        DestructorResult (*Destructor)(C), C nullValue = -1,
        typename Checker = StatusHandleChecker>
class HandleDeleter {
public:
        inline HandleDeleter()
                : fHandle(nullValue)
        {
        }

        inline HandleDeleter(C handle)
                : fHandle(handle)
        {
        }

        inline ~HandleDeleter()
        {
                if (IsSet())
                        Destructor(fHandle);
        }

        inline void SetTo(C handle)
        {
                if (handle != fHandle) {
                        if (IsSet())
                                Destructor(fHandle);
                        fHandle = handle;
                }
        }

        inline void Unset()
        {
                SetTo(nullValue);
        }

        inline void Delete()
        {
                SetTo(nullValue);
        }

        inline bool IsSet() const
        {
                Checker isHandleSet;
                return isHandleSet(fHandle);
        }

        inline C Get() const
        {
                return fHandle;
        }

        inline C Detach()
        {
                C handle = fHandle;
                fHandle = nullValue;
                return handle;
        }

protected:
        C                       fHandle;

private:
        HandleDeleter(const HandleDeleter&);
        HandleDeleter& operator=(const HandleDeleter&);
};


// FileDescriptorCloser

typedef HandleDeleter<int, int, close, -1> FileDescriptorCloser;


}       // namespace BPrivate


using ::BPrivate::ObjectDeleter;
using ::BPrivate::ArrayDeleter;
using ::BPrivate::MemoryDeleter;
using ::BPrivate::CObjectDeleter;
using ::BPrivate::MethodDeleter;
using ::BPrivate::MethodObjectDeleter;
using ::BPrivate::HandleDeleter;
using ::BPrivate::FileDescriptorCloser;


#endif  // _AUTO_DELETER_H