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
|