1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/base/Exception.h
12 #ifndef ZYPP_BASE_EXCEPTION_H
13 #define ZYPP_BASE_EXCEPTION_H
20 #include "zypp/base/Errno.h"
22 ///////////////////////////////////////////////////////////////////
24 { /////////////////////////////////////////////////////////////////
25 ///////////////////////////////////////////////////////////////////
26 namespace exception_detail
27 { /////////////////////////////////////////////////////////////////
29 /** Keep _FILE_, _FUNCTION_ and _LINE_.
30 * Construct it using the \ref ZYPP_EX_CODELOCATION macro.
34 friend std::ostream & operator<<( std::ostream & str, const CodeLocation & obj );
42 CodeLocation( const std::string & file_r,
43 const std::string & func_r,
45 : _file( file_r ), _func( func_r ), _line( line_r )
48 /** Location as string */
49 std::string asString() const;
56 ///////////////////////////////////////////////////////////////////
58 /** Create CodeLocation object storing the current location. */
59 //#define ZYPP_EX_CODELOCATION ::zypp::exception_detail::CodeLocation(__FILE__,__FUNCTION__,__LINE__)
60 #define ZYPP_EX_CODELOCATION ::zypp::exception_detail::CodeLocation(( *__FILE__ == '/' ? strrchr( __FILE__, '/' ) + 1 : __FILE__ ),__FUNCTION__,__LINE__)
62 /** \relates CodeLocation Stream output */
63 std::ostream & operator<<( std::ostream & str, const CodeLocation & obj );
65 /////////////////////////////////////////////////////////////////
66 } // namespace exception_detail
67 ///////////////////////////////////////////////////////////////////
69 ///////////////////////////////////////////////////////////////////
71 // CLASS NAME : Exception
72 /** Base class for Exception.
74 * Exception offers to store a message string passed to the ctor.
75 * Derived classes may provide additional information. Overload
76 * \ref dumpOn to provide a proper error text.
78 * \li Use \ref ZYPP_THROW to throw exceptions.
79 * \li Use \ref ZYPP_CAUGHT If you caught an exceptions in order to handle it.
80 * \li Use \ref ZYPP_RETHROW to rethrow a caught exception.
82 * The use of these macros is not mandatory. but \c ZYPP_THROW and
83 * \c ZYPP_RETHROW will adjust the code location information stored in
84 * the Exception. All three macros will drop a line in the logfile.
91 * 47 ZYPP_THROW( Exception("Something bad happened.") );
93 * 49 catch ( Exception & excpt )
95 * 51 ZYPP_RETHROW( excpt );
99 * 55 catch ( Exception & excpt )
101 * 57 ZYPP_CAUGHT( excpt );
104 * The above produces the following log lines:
106 * Main.cc(main):47 THROW: Main.cc(main):47: Something bad happened.
107 * Main.cc(main):51 RETHROW: Main.cc(main):47: Something bad happened.
108 * Main.cc(main):57 CAUGHT: Main.cc(main):51: Something bad happened.
112 * Class Exception now offers a history list of message strings.
113 * These messages should describe what lead to the exception.
115 * The Exceptions message itself is NOT included in the history.
117 * Rethrow, remembering an old exception:
123 * catch( const Exception & olderr_r )
125 * ZYPP_CAUGHT( olderr_r )
126 * HighLevelException newerr( "Something failed." );
127 * newerr.rember( olderr_r );
128 * ZYPP_THROW( newerr );
132 * Print an Exception followed by it's history if available:
135 * ERR << error << endl << error.historyAsString();
138 * \todo That's a draft to have a common way of throwing exceptions.
139 * Most probabely we'll finally use blocxx exceptions. Here, but not
140 * in the remaining code of zypp. If we can we should try to wrap
141 * the blocxx macros and typedef the classes in here.
143 class Exception : public std::exception
145 friend std::ostream & operator<<( std::ostream & str, const Exception & obj );
148 typedef exception_detail::CodeLocation CodeLocation;
149 typedef std::list<std::string> History;
150 typedef History::const_iterator HistoryIterator;
151 typedef History::size_type HistorySize;
154 * Use \ref ZYPP_THROW to throw exceptions.
158 /** Ctor taking a message.
159 * Use \ref ZYPP_THROW to throw exceptions.
161 Exception( const std::string & msg_r );
163 /** Ctor taking a message and an exception to remember as history
165 * Use \ref ZYPP_THROW to throw exceptions.
167 Exception( const std::string & msg_r, const Exception & history_r );
170 virtual ~Exception() throw();
172 /** Return CodeLocation. */
173 const CodeLocation & where() const
176 /** Exchange location on rethrow. */
177 void relocate( const CodeLocation & where_r ) const
178 { _where = where_r; }
180 /** Return the message string provided to the ctor.
181 * \note This is not necessarily the complete error message.
182 * The whole error message is provided by \ref asString or
185 const std::string & msg() const
188 /** Error message provided by \ref dumpOn as string. */
189 std::string asString() const;
191 /** Translated error message as string suitable for the user.
192 * \see \ref asUserStringHistory
194 std::string asUserString() const;
197 /** \name History list of message strings.
198 * Maintain a simple list of individual error messages, that lead
199 * to this Exception. The Exceptions message itself is not included
200 * in the history. The History list stores the most recent message
205 /** Store an other Exception as history. */
206 void remember( const Exception & old_r );
208 /** Add some message text to the history. */
209 void addHistory( const std::string & msg_r );
211 /** Iterator pointing to the most recent message. */
212 HistoryIterator historyBegin() const
213 { return _history.begin(); }
215 /** Iterator pointing behind the last message. */
216 HistoryIterator historyEnd() const
217 { return _history.end(); }
219 /** Whether the history list is empty. */
220 bool historyEmpty() const
221 { return _history.empty(); }
223 /** The size of the history list. */
224 HistorySize historySize() const
225 { return _history.size(); }
227 /** The history as string. Empty if \ref historyEmpty.
231 * - most recent message
237 std::string historyAsString() const;
239 /** A single (multiline) string composed of \ref asUserString and \ref historyAsString. */
240 std::string asUserHistory() const;
245 /** Overload this to print a proper error message. */
246 virtual std::ostream & dumpOn( std::ostream & str ) const;
249 /** Make a string from \a errno_r. */
250 static std::string strErrno( int errno_r );
251 /** Make a string from \a errno_r and \a msg_r. */
252 static std::string strErrno( int errno_r, const std::string & msg_r );
255 /** Drop a logline on throw, catch or rethrow.
256 * Used by \ref ZYPP_THROW macros.
258 static void log( const Exception & excpt_r, const CodeLocation & where_r,
259 const char *const prefix_r );
262 mutable CodeLocation _where;
266 /** Return message string. */
267 virtual const char * what() const throw()
268 { return _msg.c_str(); }
270 /** Called by <tt>std::ostream & operator\<\<</tt>.
271 * Prints \ref CodeLocation and the error message provided by
274 std::ostream & dumpError( std::ostream & str ) const;
276 ///////////////////////////////////////////////////////////////////
278 /** \relates Exception Stream output */
279 std::ostream & operator<<( std::ostream & str, const Exception & obj );
281 ///////////////////////////////////////////////////////////////////
282 namespace exception_detail
284 /** Helper for \ref ZYPP_THROW. */
285 template<class TExcpt>
286 void do_ZYPP_THROW( const TExcpt & excpt_r, const CodeLocation & where_r ) __attribute__((noreturn));
287 template<class TExcpt>
288 void do_ZYPP_THROW( const TExcpt & excpt_r, const CodeLocation & where_r )
290 excpt_r.relocate( where_r );
291 Exception::log( excpt_r, where_r, "THROW: " );
295 /** Helper for \ref ZYPP_THROW. */
296 template<class TExcpt>
297 void do_ZYPP_CAUGHT( const TExcpt & excpt_r, const CodeLocation & where_r )
299 Exception::log( excpt_r, where_r, "CAUGHT: " );
302 /** Helper for \ref ZYPP_THROW. */
303 template<class TExcpt>
304 void do_ZYPP_RETHROW( const TExcpt & excpt_r, const CodeLocation & where_r ) __attribute__((noreturn));
305 template<class TExcpt>
306 void do_ZYPP_RETHROW( const TExcpt & excpt_r, const CodeLocation & where_r )
308 Exception::log( excpt_r, where_r, "RETHROW: " );
309 excpt_r.relocate( where_r );
312 } // namespace exception_detail
313 ///////////////////////////////////////////////////////////////////
315 /** \defgroup ZYPP_THROW ZYPP_THROW macros
316 * Macros for throwing Exception.
317 * \see \ref zypp::Exception for an example.
320 /** Drops a logline and throws the Exception. */
321 #define ZYPP_THROW(EXCPT)\
322 ::zypp::exception_detail::do_ZYPP_THROW( EXCPT, ZYPP_EX_CODELOCATION )
324 /** Drops a logline telling the Exception was caught (in order to handle it). */
325 #define ZYPP_CAUGHT(EXCPT)\
326 ::zypp::exception_detail::do_ZYPP_CAUGHT( EXCPT, ZYPP_EX_CODELOCATION )
328 /** Drops a logline and rethrows, updating the CodeLocation. */
329 #define ZYPP_RETHROW(EXCPT)\
330 ::zypp::exception_detail::do_ZYPP_RETHROW( EXCPT, ZYPP_EX_CODELOCATION )
333 /** Throw Exception built from a message string. */
334 #define ZYPP_THROW_MSG(EXCPTTYPE, MSG)\
335 ZYPP_THROW( EXCPTTYPE( MSG ) )
337 /** Throw Exception built from errno. */
338 #define ZYPP_THROW_ERRNO(EXCPTTYPE)\
339 ZYPP_THROW( EXCPTTYPE( ::zypp::Exception::strErrno(errno) ) )
341 /** Throw Exception built from errno provided as argument. */
342 #define ZYPP_THROW_ERRNO1(EXCPTTYPE, ERRNO)\
343 ZYPP_THROW( EXCPTTYPE( ::zypp::Exception::strErrno(ERRNO) ) )
345 /** Throw Exception built from errno and a message string. */
346 #define ZYPP_THROW_ERRNO_MSG(EXCPTTYPE, MSG)\
347 ZYPP_THROW( EXCPTTYPE( ::zypp::Exception::strErrno(errno,MSG) ) )
349 /** Throw Exception built from errno provided as argument and a message string */
350 #define ZYPP_THROW_ERRNO_MSG1(EXCPTTYPE, ERRNO,MSG)\
351 ZYPP_THROW( EXCPTTYPE( ::zypp::Exception::strErrno(ERRNO,MSG) ) )
354 /////////////////////////////////////////////////////////////////
356 ///////////////////////////////////////////////////////////////////
357 #endif // ZYPP_BASE_EXCEPTION_H