#ifndef ZYPP_BASE_EXCEPTION_H
#define ZYPP_BASE_EXCEPTION_H
-#include <cerrno>
#include <iosfwd>
+#include <string>
#include <list>
#include <stdexcept>
+#include <typeinfo>
+#include <type_traits>
+
+#include "zypp/base/Errno.h"
///////////////////////////////////////////////////////////////////
namespace zypp
* Use \ref ZYPP_THROW to throw exceptions.
*/
Exception( const std::string & msg_r );
+ /** \overload */
+ Exception( std::string && msg_r );
+
+ /** Ctor taking a message and an exception to remember as history
+ * \see \ref remember
+ * Use \ref ZYPP_THROW to throw exceptions.
+ */
+ Exception( const std::string & msg_r, const Exception & history_r );
+ /** \overload moving */
+ Exception( std::string && msg_r, const Exception & history_r );
+ /** \overload moving */
+ Exception( const std::string & msg_r, Exception && history_r );
+ /** \overload moving */
+ Exception( std::string && msg_r, Exception && history_r );
/** Dtor. */
virtual ~Exception() throw();
/** Error message provided by \ref dumpOn as string. */
std::string asString() const;
- /** Translated error message as string suitable for the user. */
+ /** Translated error message as string suitable for the user.
+ * \see \ref asUserStringHistory
+ */
std::string asUserString() const;
public:
/** Store an other Exception as history. */
void remember( const Exception & old_r );
+ /** \overload moving */
+ void remember( Exception && old_r );
/** Add some message text to the history. */
void addHistory( const std::string & msg_r );
+ /** \overload moving */
+ void addHistory( std::string && msg_r );
+
+ /** \ref addHistory from string container types (oldest first) */
+ template<class TContainer>
+ void addToHistory( const TContainer & msgc_r )
+ {
+ for ( const std::string & el : msgc_r )
+ addHistory( el );
+ }
+ /** \ref addHistory from string container types (oldest first) moving */
+ template<class TContainer>
+ void moveToHistory( TContainer && msgc_r )
+ {
+ for ( std::string & el : msgc_r )
+ addHistory( std::move(el) );
+ }
/** Iterator pointing to the most recent message. */
HistoryIterator historyBegin() const
*/
std::string historyAsString() const;
+ /** A single (multiline) string composed of \ref asUserString and \ref historyAsString. */
+ std::string asUserHistory() const;
//@}
protected:
static std::string strErrno( int errno_r );
/** Make a string from \a errno_r and \a msg_r. */
static std::string strErrno( int errno_r, const std::string & msg_r );
+ /** \overload moving */
+ static std::string strErrno( int errno_r, std::string && msg_r );
public:
/** Drop a logline on throw, catch or rethrow.
*/
static void log( const Exception & excpt_r, const CodeLocation & where_r,
const char *const prefix_r );
-
+ /** \overrload for not-Exception types thrown via ZYPP_THROW */
+ static void log( const char * typename_r, const CodeLocation & where_r,
+ const char *const prefix_r );
private:
mutable CodeLocation _where;
std::string _msg;
std::ostream & operator<<( std::ostream & str, const Exception & obj );
///////////////////////////////////////////////////////////////////
+ namespace exception_detail
+ {
+ /** SFINAE: Hide template signature unless \a TExcpt is derived from \ref Exception. */
+ template<class TExcpt>
+ using EnableIfIsException = typename std::enable_if< std::is_base_of<Exception,TExcpt>::value, int>::type;
+
+ /** SFINAE: Hide template signature if \a TExcpt is derived from \ref Exception. */
+ template<class TExcpt>
+ using EnableIfNotException = typename std::enable_if< !std::is_base_of<Exception,TExcpt>::value, int>::type;
- /** Helper for \ref ZYPP_THROW. */
- template<class _Excpt>
- void _ZYPP_THROW( const _Excpt & excpt_r, const exception_detail::CodeLocation & where_r ) __attribute__((noreturn));
- template<class _Excpt>
- void _ZYPP_THROW( const _Excpt & excpt_r, const exception_detail::CodeLocation & where_r )
+
+ /** Helper for \ref ZYPP_THROW( Exception ). */
+ template<class TExcpt, EnableIfIsException<TExcpt> = 0>
+ void do_ZYPP_THROW( const TExcpt & excpt_r, const CodeLocation & where_r ) __attribute__((noreturn));
+ template<class TExcpt, EnableIfIsException<TExcpt>>
+ void do_ZYPP_THROW( const TExcpt & excpt_r, const CodeLocation & where_r )
{
excpt_r.relocate( where_r );
Exception::log( excpt_r, where_r, "THROW: " );
throw( excpt_r );
}
- /** Helper for \ref ZYPP_THROW. */
- template<class _Excpt>
- void _ZYPP_CAUGHT( const _Excpt & excpt_r, const exception_detail::CodeLocation & where_r )
+ /** Helper for \ref ZYPP_THROW( not Exception ). */
+ template<class TExcpt, EnableIfNotException<TExcpt> = 0>
+ void do_ZYPP_THROW( const TExcpt & excpt_r, const CodeLocation & where_r ) __attribute__((noreturn));
+ template<class TExcpt, EnableIfNotException<TExcpt>>
+ void do_ZYPP_THROW( const TExcpt & excpt_r, const CodeLocation & where_r )
+ {
+ Exception::log( typeid(excpt_r).name(), where_r, "THROW: " );
+ throw( excpt_r );
+ }
+
+
+ /** Helper for \ref ZYPP_THROW( Exception ). */
+ template<class TExcpt, EnableIfIsException<TExcpt> = 0>
+ void do_ZYPP_CAUGHT( const TExcpt & excpt_r, const CodeLocation & where_r )
{
Exception::log( excpt_r, where_r, "CAUGHT: " );
}
- /** Helper for \ref ZYPP_THROW. */
- template<class _Excpt>
- void _ZYPP_RETHROW( const _Excpt & excpt_r, const exception_detail::CodeLocation & where_r ) __attribute__((noreturn));
- template<class _Excpt>
- void _ZYPP_RETHROW( const _Excpt & excpt_r, const exception_detail::CodeLocation & where_r )
+ /** Helper for \ref ZYPP_THROW( not Exception ). */
+ template<class TExcpt, EnableIfNotException<TExcpt> = 0>
+ void do_ZYPP_CAUGHT( const TExcpt & excpt_r, const CodeLocation & where_r )
+ {
+ Exception::log( typeid(excpt_r).name(), where_r, "CAUGHT: " );
+ }
+
+
+ /** Helper for \ref ZYPP_THROW( Exception ). */
+ template<class TExcpt, EnableIfIsException<TExcpt> = 0>
+ void do_ZYPP_RETHROW( const TExcpt & excpt_r, const CodeLocation & where_r ) __attribute__((noreturn));
+ template<class TExcpt, EnableIfIsException<TExcpt>>
+ void do_ZYPP_RETHROW( const TExcpt & excpt_r, const CodeLocation & where_r )
{
Exception::log( excpt_r, where_r, "RETHROW: " );
excpt_r.relocate( where_r );
throw;
}
+ /** Helper for \ref ZYPP_THROW( not Exception ). */
+ template<class TExcpt, EnableIfNotException<TExcpt> = 0>
+ void do_ZYPP_RETHROW( const TExcpt & excpt_r, const CodeLocation & where_r ) __attribute__((noreturn));
+ template<class TExcpt, EnableIfNotException<TExcpt>>
+ void do_ZYPP_RETHROW( const TExcpt & excpt_r, const CodeLocation & where_r )
+ {
+ Exception::log( excpt_r, where_r, "RETHROW: " );
+ throw;
+ }
+ } // namespace exception_detail
///////////////////////////////////////////////////////////////////
/** \defgroup ZYPP_THROW ZYPP_THROW macros
//@{
/** Drops a logline and throws the Exception. */
#define ZYPP_THROW(EXCPT)\
- _ZYPP_THROW( EXCPT, ZYPP_EX_CODELOCATION )
+ ::zypp::exception_detail::do_ZYPP_THROW( EXCPT, ZYPP_EX_CODELOCATION )
/** Drops a logline telling the Exception was caught (in order to handle it). */
#define ZYPP_CAUGHT(EXCPT)\
- _ZYPP_CAUGHT( EXCPT, ZYPP_EX_CODELOCATION )
+ ::zypp::exception_detail::do_ZYPP_CAUGHT( EXCPT, ZYPP_EX_CODELOCATION )
/** Drops a logline and rethrows, updating the CodeLocation. */
#define ZYPP_RETHROW(EXCPT)\
- _ZYPP_RETHROW( EXCPT, ZYPP_EX_CODELOCATION )
+ ::zypp::exception_detail::do_ZYPP_RETHROW( EXCPT, ZYPP_EX_CODELOCATION )
/** Throw Exception built from a message string. */