Files
mrw-cxx/mrw/auto.hpp

144 lines
4.8 KiB
C++
Raw Normal View History

2004-04-21 06:39:20 +00:00
#ifndef __MRW_AUTO_HPP__
#define __MRW_AUTO_HPP__
#include <sys/types.h> // size_t
#include <sys/mman.h> // PROT_READ, MAP_SHARED
#include <bfd.h> // bfd*
namespace mrw {
/** @defgroup AutoTools Classes for Automated Resource Handling
For pointers that have been allocated with @c new, you can use
std::auto_ptr to automatically free them when you leave the
context. Unfortunately there is no such thing for @c malloc
(except @c malloca that only works for a subset of problems: if
you and not a system call allocates memory), @c open and so on.
These classes can take over the resource ownership.
*/
//@{
/** @brief Automatically closes a file when destructed.
2004-04-23 16:03:29 +00:00
@pre #include <mrw/auto.hpp>
2004-04-21 06:39:20 +00:00
AutoFile works exactly like std::auto_ptr, but not for files
instead of pointers. Whenever the context of AutoFile is left,
the opened file is close. This way, resources are freed even in
case of exceptions.
*/
class AutoFile {
public:
/// @brief Construct from an opened file.
/// @note Don't close @c fd
explicit AutoFile(int fd = -1) throw(): _fd(fd) {}
/// @brief Takeover ownership from another AutoFile.
AutoFile(AutoFile& o) throw(): _fd(o.release()) {}
/// @brief Closes file if open.
~AutoFile() throw() {reset();}
/// @brief Assign new file descriptor.
/// The old file of @c this is closed if open.
AutoFile& operator=(int fd) throw() {return reset(fd);}
/// @brief Takeover ownership from another AutoFile.
/// The old file of @c this is closed if open.
AutoFile& operator=(AutoFile& other) throw() {
return reset(other.release());
}
/// @brief get the file descriptor @return file descriptor
operator const int() const throw() {
return _fd;
}
/// @brief Give away ownership of the file. @return old file descriptor
int release() throw() {
int ret(_fd); _fd=-1;
return ret;
}
/// @brief assign a new file descriptor
/** The old file of @c this is closed if open. */
AutoFile& reset(int = -1) throw();
private:
int _fd; ///< the file descriptor
};
/** @brief Automatically call @c munmap for mmaped files on destruction.
2004-04-23 16:03:29 +00:00
@pre #include <mrw/auto.hpp>
2004-04-21 06:39:20 +00:00
It's the same as std::auto_ptr, but for @c mmap instead of @c
new. When the context of @c AutoMapper is left, @c munmap is
called.
*/
class AutoMapper {
public:
AutoMapper(void* cont = 0, size_t sz = 0) throw():
_cont(cont), _sz(sz) {}
AutoMapper(int, size_t=0, void* = 0,
int = PROT_READ, int = MAP_SHARED, off_t = 0) throw();
~AutoMapper() throw();
operator const void*() const throw() {return _cont;}
AutoMapper& set(void* cont, size_t sz) throw() {
_cont=cont; _sz=sz;
return *this;
}
void* release() throw() {
void* ret(_cont); _cont=0; _sz=0;
return ret;
}
const void* last() const throw() {
return _cont && _sz ? (void*)((size_t)_cont+_sz-1) : 0;
}
private:
void* _cont;
size_t _sz;
};
/** @brief Automatically call @c bfd_close for @c bfd*.
2004-04-23 16:03:29 +00:00
@pre #include <mrw/auto.hpp>
2004-04-21 06:39:20 +00:00
It acts like a @c std::auto_ptr, but for @c bfd*, that means it
calls @c bfd_close whenever the context is left.
*/
class AutoBfd {
public:
AutoBfd(bfd* p=0) throw(): _bfd(p) {}
~AutoBfd() throw() {if (_bfd) bfd_close(_bfd);}
AutoBfd& operator=(bfd* p) throw() {
release(); _bfd=p; return *this;
}
AutoBfd& operator=(AutoBfd& o) throw() {
release(); _bfd=o.release(); return *this;
}
operator bfd*() throw() {return _bfd;}
bfd* operator->() throw() {return _bfd;}
bfd* release() throw() {bfd* res(_bfd); _bfd = 0; return res;}
private:
bfd* _bfd;
};
/** @brief Automatically calls @c free for @c malloc allocated memory.
2004-04-23 16:03:29 +00:00
@pre #include <mrw/auto.hpp>
2004-04-21 06:39:20 +00:00
It works like a @c std::auto_ptr, but for memory that was
allocated with @c malloc, not @c new. Memory is freed, whenever
the context od @c AutoFree is left.
*/
template <class T> class AutoFree {
public:
AutoFree(T* p=0) throw(): _p(p) {}
AutoFree(AutoFree& o) throw(): _p(o.release()) {}
~AutoFree() throw() {if (_p) free(_p);}
AutoFree& operator=(T* p) throw() {
release(); _p=p; return *this;
}
AutoFree& operator=(AutoFree& o) throw() {
release(); _p=o.release(); return *this;
}
operator T*() {return _p;}
operator T**() {return &_p;}
operator bool() {return _p;}
T* release() throw() {T* r(_p); _p=0; return r;}
private:
T* _p;
};
//@}
}
#endif