Imported Upstream version 17.14.0
[platform/upstream/libzypp.git] / zypp / base / Exception.h
index 5ff692f..42c4d80 100644 (file)
 #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
@@ -157,6 +161,20 @@ 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();
@@ -180,7 +198,9 @@ namespace zypp
     /** 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:
@@ -194,9 +214,28 @@ namespace zypp
 
     /** 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
@@ -226,6 +265,8 @@ namespace zypp
     */
     std::string historyAsString() const;
 
+    /** A single (multiline) string composed of \ref asUserString  and  \ref historyAsString. */
+    std::string asUserHistory() const;
     //@}
 
   protected:
@@ -238,6 +279,8 @@ namespace zypp
     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.
@@ -245,7 +288,9 @@ namespace zypp
     */
     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;
@@ -267,36 +312,75 @@ namespace zypp
   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
@@ -306,15 +390,15 @@ namespace zypp
   //@{
   /** 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. */