#ifndef __MRW_AUTO_HPP__ #define __MRW_AUTO_HPP__ #include // size_t #include // PROT_READ, MAP_SHARED #include // 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 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 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 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 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 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