# 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.
@ pre # include < mrw / auto . hpp >
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.
@ pre # include < mrw / auto . hpp >
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*.
@ pre # include < mrw / auto . hpp >
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.
@ pre # include < mrw / auto . hpp >
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