C++ Library containing a lot of needful things: Stack Trace, Command Line Parser, Resource Handling, Configuration Files, Unix Command Execution, Directories, Regular Expressions, Tokenizer, Function Trace, Standard Extensions.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

298 lines
10 KiB

/** @file
$Id$
$Date$
$Author$
@copy © Marc Wäckerlin
@license LGPL, see file <a href="license.html">COPYING</a>
$Log$
20 years ago
Revision 1.5 2004/10/11 16:05:02 marc
new AutoPtr
Revision 1.4 2004/10/07 09:24:08 marc
enhance windoze compatibility
Revision 1.3 2004/08/28 16:21:25 marc
mrw-c++-0.92 (mrw)
- new file: version.cpp
- new file header for all sources
- work around warning in mrw::auto<T>
- possibility to compile without log4cxx
- work around bugs in demangle.h and libiberty.h
- corrections in documentation
- added simple tracing mechanism
- more warnings
- small corrections in Auto<>::Free and a new test for it
- possibility to compile without stack trace
*/
#ifndef __MRW_AUTO_HPP__
#define __MRW_AUTO_HPP__
#include <sys/types.h> // size_t
#include <sys/mman.h> // munmap, PROT_READ, MAP_SHARED
#include <unistd.h> // close
#include <stdexcept>
// forward
class bfd;
extern "C" int bfd_close(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 frees a resource when destructed.
21 years ago
@pre #include <mrw/auto.hpp>
AutoResource works exactly like std::auto_ptr, but for any
resource instead of new allocated pointers. Whenever the context
of AutoResource is left, the resource is freed by a call to the
given function. This way, resources are freed even in case of
exceptions.
Declare an automated file descriptor handler, a BFD handler and
a @c malloc-/ @c free handler (all these typedefs are already
part of the library):
@code
typedef mrw::AutoResource<int, int(*)(int), &close, int, -1> AutoFile;
typedef mrw::AutoResource<bfd*, int(*)(bfd*), &bfd_close, int> AutoBfd;
template<class T> class Auto {
public:
typedef mrw::AutoResource<T, void(*)(void*), &free, int, 0> Free;
};
@endcode
@param RESOURCE_TYPE type of the resorce to manage
@param FUNCTION_PTR type of the function that frees the resource
@param FREE_FUNCTION the function that frees the resource
@param INITIAL_VALUE_TYPE type of the initial value
(pointers may have to be initialized by an integer)
@param INITIAL_VALUE value when the resource is unassigned
@param FREE_TYPE type to free, if cast is needed
*/
template<typename RESOURCE_TYPE,
typename FUNCTION_PTR,
FUNCTION_PTR FREE_FUNCTION,
typename INITIAL_VALUE_TYPE = RESOURCE_TYPE,
INITIAL_VALUE_TYPE INITIAL_VALUE = 0,
typename FREE_TYPE = RESOURCE_TYPE>
class AutoResource {
public:
/// @brief Construct from an allocated resource.
/// The resource is freed if necessary.
/// AutoResource takes over ownership of the resource.
explicit AutoResource(FREE_TYPE res = INITIAL_VALUE)
throw(std::bad_exception): _res((RESOURCE_TYPE)res) {
}
/// @brief Takeover ownership from another AutoResource.
AutoResource(AutoResource& o) throw(std::bad_exception):
_res(o.release()) {
}
/// @brief Free resource. Calls @c reset().
~AutoResource() throw(std::bad_exception) {reset();}
/// @brief Assign new resource. Calls @c reset().
/// The resource is freed if necessary.
AutoResource& operator=(RESOURCE_TYPE res) throw(std::bad_exception) {
return reset(res);
}
/// @brief Takeover ownership from another AutoResorce.
/// Calls @c reset() from @c this and @c release() from @c other.
AutoResource& operator=(AutoResource& other) throw(std::bad_exception) {
return reset(other.release());
}
/// @brief Get the resource.
operator const RESOURCE_TYPE&() const throw(std::bad_exception) {
return _res;
}
/// @brief get the resetted resource for resetting it.
/// Calls @c reset and returns the cleaned resource.
/// The intention is, that you can safely assign it a new value
/// (e.g. in an expression).
RESOURCE_TYPE& getClean() throw(std::bad_exception) {
reset();
return _res;
}
/// @brief find out, if a value is set
/// @return @c true: resource is valid
operator bool() const throw(std::bad_exception) {
return _res!=INITIAL_VALUE;
}
/// @brief Give away ownership of the resource.
/// @return old resource
RESOURCE_TYPE release() throw(std::bad_exception) {
RESOURCE_TYPE res(_res); _res=INITIAL_VALUE;
return res;
}
/// @brief Assign a new resorce.
/// The old resource of @c this is freed if necessary.
AutoResource& reset(RESOURCE_TYPE res = INITIAL_VALUE)
throw(std::bad_exception) {
if (_res!=INITIAL_VALUE) (*FREE_FUNCTION)((FREE_TYPE)_res);
_res = res;
return *this;
}
private:
RESOURCE_TYPE _res; ///< the resource to be managed
20 years ago
};
template <typename T>
class AutoPtr {
public:
/// @brief Construct from an allocated resource.
/// The resource is freed if necessary.
/// AutoPtr takes over ownership of the resource.
explicit AutoPtr(T* res = 0)
throw(std::bad_exception): _res(res) {
res = 0;
}
/// @brief Takeover ownership from another AutoPtr.
AutoPtr(AutoPtr& o) throw(std::bad_exception):
_res(o.release()) {
}
/// @brief Free resource. Calls @c reset().
~AutoPtr() throw(std::bad_exception) {reset();}
/// @brief Assign new resource. Calls @c reset().
/// The resource is freed if necessary.
AutoPtr& operator=(T* res) throw(std::bad_exception) {
return reset(res);
}
/// @brief Takeover ownership from another AutoResorce.
/// Calls @c reset() from @c this and @c release() from @c other.
AutoPtr& operator=(AutoPtr& other) throw(std::bad_exception) {
return reset(other.release());
}
/// @brief Get the resource.
operator T* const() const throw(std::bad_exception) {
return _res;
}
/// @brief get the resetted resource for resetting it.
/// Calls @c reset and returns the cleaned resource.
/// The intention is, that you can safely assign it a new value
/// (e.g. in an expression).
T* getClean() throw(std::bad_exception) {
reset();
return _res;
}
/// @brief find out, if a value is set
/// @return @c true: resource is valid
operator bool() const throw(std::bad_exception) {
return _res!=0;
}
/// @brief Give away ownership of the resource.
/// @return old resource
T* release() throw(std::bad_exception) {
T* res(_res); _res=0;
return res;
}
/// @brief Assign a new resorce.
/// The old resource of @c this is freed if necessary.
AutoPtr& reset(T* res = 0)
throw(std::bad_exception) {
delete _res;
_res = res;
return *this;
}
private:
T* _res; ///< the resource to be managed
};
/** @brief Automatically closes a file when destructed.
@pre #include <mrw/auto.hpp>
AutoFile works exactly like std::auto_ptr, but 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.
*/
typedef mrw::AutoResource<int, int(*)(int), &close, int, -1> AutoFile;
/** @brief Resorce handle for @c mmap.
It integrates pointer and size of a memory mapped file similar
to a @c std::pair.
*/
class MMapHandle {
public:
void* first;
size_t second;
/// @brief Constructor that initializes the values through a call to mmap.
MMapHandle(int, size_t=0, void* = 0,
int = PROT_READ, int = MAP_SHARED, off_t = 0)
throw(std::bad_exception);
/// @brief Reset to zero, value of int is ignored.
MMapHandle& operator=(int) throw(std::bad_exception) {
first = 0; second = 0;
return *this;
}
/// @brief Compare to zero, returns true, if i and handle are both zero.
bool operator==(int i) const throw(std::bad_exception) {
return i==0 && first==0 && second==0;
}
};
inline void munmap(MMapHandle& res) throw(std::bad_exception) {
if (res.first!=0 && res.second>0)
::munmap((char*)res.first, res.second); // char* conversion for windoze cygwin compatibility
}
/** @brief Automatically calls @c munmap on destruction for mmaped files.
21 years ago
@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.
*/
typedef mrw::AutoResource<MMapHandle, void(*)(MMapHandle&), &mrw::munmap, int>
AutoMapper;
/** @brief Automatically calls @c bfd_close for @c bfd*.
21 years ago
@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.
*/
typedef mrw::AutoResource<bfd*, int(*)(bfd*), &bfd_close, int> AutoBfd;
/** @brief Automatically calls @c free for @c malloc allocated memory.
Instanciate it as @c mrw::Auto<TYPE*>::Free.
21 years ago
@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.
@code
{ // enter context
Auto<char*>::Free cp = (char*)malloc(5);
cp.getClean() = (char*)malloc(10); // old storage of 5 bytes is freed
} // memory is freed on destruction of cp
@endcode
*/
template<class T> class Auto {
public:
typedef mrw::AutoResource<T, void(*)(void*), &free, int, 0, void*> Free;
private:
/** @internal
work around compiler warning:
"only defines private constructors and has no friends" */
friend class ThisIsADummyToEliminateWarnings;
/// Forbidden to instanciate.
Auto(); Auto(const Auto&);
};
//@}
}
#endif