You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
361 lines
13 KiB
C++
361 lines
13 KiB
C++
//-----------------------------------------------------------------------------
|
|
// (C) Copyright 2005 - 2021 by MATRIX VISION GmbH
|
|
//
|
|
// This software is provided by MATRIX VISION GmbH "as is"
|
|
// and any express or implied warranties, including, but not limited to, the
|
|
// implied warranties of merchantability and fitness for a particular purpose
|
|
// are disclaimed.
|
|
//
|
|
// In no event shall MATRIX VISION GmbH be liable for any direct,
|
|
// indirect, incidental, special, exemplary, or consequential damages
|
|
// (including, but not limited to, procurement of substitute goods or services;
|
|
// loss of use, data, or profits; or business interruption) however caused and
|
|
// on any theory of liability, whether in contract, strict liability, or tort
|
|
// (including negligence or otherwise) arising in any way out of the use of
|
|
// this software, even if advised of the possibility of such damage.
|
|
|
|
//-----------------------------------------------------------------------------
|
|
#ifndef STLHelperH
|
|
#define STLHelperH STLHelperH
|
|
//-----------------------------------------------------------------------------
|
|
#include <algorithm>
|
|
#include <cctype>
|
|
#include <cstdio>
|
|
#include <functional>
|
|
#include <map>
|
|
#include <set>
|
|
#include <string>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
//=============================================================================
|
|
//==================== std::pair related stuff ================================
|
|
//=============================================================================
|
|
//-----------------------------------------------------------------------------
|
|
template<class _Ty1, class _Ty2>
|
|
const _Ty1& GetFirst( const std::pair<_Ty1, _Ty2>& data )
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
return data.first;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
template<class _Ty1, class _Ty2>
|
|
const _Ty2& GetSecond( const std::pair<_Ty1, _Ty2>& data )
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
return data.second;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
template<class _Ty1, class _Ty2>
|
|
void DeleteFirst( std::pair<_Ty1, _Ty2>& data )
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
delete data.first;
|
|
data.first = 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
template<class _Ty1, class _Ty2>
|
|
void DeleteSecond( std::pair<_Ty1, _Ty2>& data )
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
delete data.second;
|
|
data.second = 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
template<class _Ty1, class _Ty2>
|
|
class ContainsFirst : public std::unary_function<std::pair<_Ty1, _Ty2>, bool>
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
std::map<_Ty1, _Ty2> m_;
|
|
public:
|
|
explicit ContainsFirst( const std::map<_Ty1, _Ty2>& m ) : m_( m ) {}
|
|
bool operator()( const std::pair<_Ty1, _Ty2>& x )
|
|
{
|
|
return m_.find( x.first ) != m_.end();
|
|
}
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
template<class _Ty1, class _Ty2>
|
|
class FirstMatches : public std::unary_function<std::pair<_Ty1, _Ty2>, bool>
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
std::pair<_Ty1, _Ty2> value_;
|
|
FirstMatches<_Ty1, _Ty2>& operator=( const FirstMatches<_Ty1, _Ty2>& ); // do not allow assignments
|
|
public:
|
|
explicit FirstMatches( const std::pair<_Ty1, _Ty2>& val ) : value_( val ) {}
|
|
bool operator()( const std::pair<_Ty1, _Ty2>& x )
|
|
{
|
|
return x.first == value_.first;
|
|
}
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
template<class _Ty1, class _Ty2>
|
|
class SecondMatches : public std::unary_function<std::pair<_Ty1, _Ty2>, bool>
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
std::pair<_Ty1, _Ty2> value_;
|
|
SecondMatches<_Ty1, _Ty2>& operator=( const SecondMatches<_Ty1, _Ty2>& ); // do not allow assignments
|
|
public:
|
|
explicit SecondMatches( const std::pair<_Ty1, _Ty2>& val ) : value_( val ) {}
|
|
bool operator()( const std::pair<_Ty1, _Ty2>& x )
|
|
{
|
|
return x.second == value_.second;
|
|
}
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
template<typename _Ty1, typename _Ty2>
|
|
bool SecondSmaller( const std::pair<_Ty1, _Ty2>& a, const std::pair<_Ty1, _Ty2>& b )
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
if( a.second < b.second )
|
|
{
|
|
return true;
|
|
}
|
|
|
|
if( a.second > b.second )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return ( a.first < b.first );
|
|
}
|
|
|
|
//=============================================================================
|
|
//==================== various ================================================
|
|
//=============================================================================
|
|
//-----------------------------------------------------------------------------
|
|
template<class _Ty>
|
|
void DeleteElement( _Ty& data )
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
delete data;
|
|
data = 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
template<class _Ty>
|
|
void DeleteArrayElement( _Ty& data )
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
delete [] data;
|
|
data = 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
/// \brief Proxy reference for ObjectDeleter copying.
|
|
template<class _Ty>
|
|
struct ObjectDeleterReference
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
// construct from generic pointer to ObjectDeleter pointer
|
|
explicit ObjectDeleterReference( _Ty* rhs ) : pReference_( rhs ) {}
|
|
|
|
_Ty* pReference_; // generic pointer to ObjectDeleter pointer
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
/// \brief Simple wrapper class to make sure an object is deleted at the end of the scope
|
|
/**
|
|
* This of course could also be done using std::auto_ptr but as this template has been
|
|
* declared deprecated it causes new compilers to spit out warnings/failures.
|
|
*
|
|
* The nice way of doing this would be by the use of std::unique_ptr these days but then
|
|
* the client code would force people to have a C++11 or greater compliant compiler...
|
|
*/
|
|
template<class _Ty>
|
|
class ObjectDeleter
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
_Ty* pObject_;
|
|
public:
|
|
explicit ObjectDeleter( _Ty* pObject = 0 ) : pObject_( pObject ) {}
|
|
/// \brief Pass ownership to the new object.
|
|
ObjectDeleter( ObjectDeleter<_Ty>& rhs ) : pObject_( rhs.release() ) {}
|
|
~ObjectDeleter()
|
|
{
|
|
DeleteElement( pObject_ );
|
|
}
|
|
/// \brief Pass ownership. Old buffer on the left hand side object is
|
|
/// freed, the lhs object takes ownership of the pointer of the rhs object.
|
|
ObjectDeleter<_Ty>& operator=( ObjectDeleter<_Ty>& rhs )
|
|
{
|
|
if( this != &rhs )
|
|
{
|
|
DeleteElement( pObject_ );
|
|
pObject_ = rhs.release();
|
|
}
|
|
return *this;
|
|
}
|
|
template<class _Other>
|
|
operator ObjectDeleterReference<_Other>()
|
|
{
|
|
// convert to compatible ObjectDeleterReference
|
|
_Other* p = pObject_; // test implicit conversion
|
|
ObjectDeleterReference<_Other> reference( p );
|
|
pObject_ = 0; // pass ownership to ObjectDeleterReference
|
|
return ( reference );
|
|
}
|
|
ObjectDeleter<_Ty>& operator=( ObjectDeleterReference<_Ty> rhs )
|
|
{
|
|
// assign compatible rhs.pReference_ (assume pointer)
|
|
_Ty* p = rhs.pReference_;
|
|
rhs.pReference_ = 0;
|
|
reset( p );
|
|
return ( *this );
|
|
}
|
|
operator _Ty* ()
|
|
{
|
|
return pObject_;
|
|
}
|
|
_Ty* operator->()
|
|
{
|
|
return pObject_;
|
|
}
|
|
_Ty* get( void )
|
|
{
|
|
return pObject_;
|
|
}
|
|
const _Ty* get( void ) const
|
|
{
|
|
return pObject_;
|
|
}
|
|
_Ty* release( void )
|
|
{
|
|
_Ty* p = pObject_;
|
|
pObject_ = 0;
|
|
return p;
|
|
}
|
|
void reset( _Ty* pObject = 0 )
|
|
{
|
|
if( pObject_ != pObject )
|
|
{
|
|
DeleteElement( pObject_ );
|
|
pObject_ = pObject;
|
|
}
|
|
}
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
/// This could in theory be accomplished with a call to the for_each template:
|
|
///
|
|
/// for_each( s.begin(), s.end(), ptr_fun(DeleteElement<_Ty*>) );
|
|
///
|
|
/// But some ports of the STL always return const_iterators for sets (e.g. gcc 4.1.2)
|
|
template<class _Ty>
|
|
void ClearSetWithHeapAllocatedKeys( std::set<_Ty>& s )
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
typename std::set<_Ty>::iterator it = s.begin();
|
|
typename std::set<_Ty>::iterator itEnd = s.end();
|
|
while( it != itEnd )
|
|
{
|
|
delete *it;
|
|
++it;
|
|
}
|
|
s.clear();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
/// \brief Assigns a new value to a variable when this objects goes out of scope.
|
|
///
|
|
/// Can be useful if a variable must be set to a defined value at the end of a
|
|
/// code block that might rise an exception.
|
|
template<class T>
|
|
class VarScopeMod
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
T& var_;
|
|
T valAtEndOfScope_;
|
|
VarScopeMod( const VarScopeMod& ); // do not allow copy constructor
|
|
VarScopeMod& operator=( const VarScopeMod& ); // do not allow assignments
|
|
public:
|
|
explicit VarScopeMod( T& var, T valAtEndOfScope ) : var_( var ), valAtEndOfScope_( valAtEndOfScope ) {}
|
|
explicit VarScopeMod( T& var, T valWithinScope, T valAtEndOfScope ) : var_( var ), valAtEndOfScope_( valAtEndOfScope )
|
|
{
|
|
var = valWithinScope;
|
|
}
|
|
~VarScopeMod()
|
|
{
|
|
var_ = valAtEndOfScope_;
|
|
}
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
template<class T>
|
|
void removeDuplicates( T& container )
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
std::sort( container.begin(), container.end() );
|
|
typename T::iterator it = std::unique( container.begin(), container.end() );
|
|
container.erase( it, container.end() );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
template<class _Elem>
|
|
_Elem mv_tolower( _Elem c )
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
return static_cast<_Elem>( tolower( c ) );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
template<class _Elem, class _Traits, class _Ax>
|
|
void makeLowerCase(
|
|
/// The string to convert
|
|
std::basic_string<_Elem, _Traits, _Ax>& s )
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
std::transform( s.begin(), s.end(), s.begin(), std::ptr_fun<_Elem, _Elem>( mv_tolower ) );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
template<class _Elem, class _Traits, class _Ax>
|
|
std::basic_string<_Elem, _Traits, _Ax> makeLowerCase(
|
|
/// The string to convert
|
|
const std::basic_string<_Elem, _Traits, _Ax>& s )
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
std::basic_string<_Elem, _Traits, _Ax> lc( s );
|
|
std::transform( lc.begin(), lc.end(), lc.begin(), std::ptr_fun<_Elem, _Elem>( mv_tolower ) );
|
|
return lc;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
template<class _Elem>
|
|
_Elem mv_toupper( _Elem c )
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
return static_cast<_Elem>( toupper( c ) );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
template<class _Elem, class _Traits, class _Ax>
|
|
void makeUpperCase(
|
|
/// The string to convert
|
|
std::basic_string<_Elem, _Traits, _Ax>& s )
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
std::transform( s.begin(), s.end(), s.begin(), std::ptr_fun<_Elem, _Elem>( mv_toupper ) );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
template<class _Elem, class _Traits, class _Ax>
|
|
std::basic_string<_Elem, _Traits, _Ax> makeUpperCase(
|
|
/// The string to convert
|
|
const std::basic_string<_Elem, _Traits, _Ax>& s )
|
|
//-----------------------------------------------------------------------------
|
|
{
|
|
std::basic_string<_Elem, _Traits, _Ax> uc( s );
|
|
std::transform( uc.begin(), uc.end(), uc.begin(), std::ptr_fun<_Elem, _Elem>( mv_toupper ) );
|
|
return uc;
|
|
}
|
|
|
|
#endif // STLHelperH
|