backup
[platform/upstream/libzypp.git] / zypp / base / Exception.h
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/base/Exception.h
10  *
11 */
12 #ifndef ZYPP_BASE_EXCEPTION_H
13 #define ZYPP_BASE_EXCEPTION_H
14
15 #include <cerrno>
16 #include <iosfwd>
17 #include <stdexcept>
18
19 ///////////////////////////////////////////////////////////////////
20 namespace zypp
21 { /////////////////////////////////////////////////////////////////
22   ///////////////////////////////////////////////////////////////////
23   namespace exception_detail
24   { /////////////////////////////////////////////////////////////////
25
26     /** Keep _FILE_, _FUNCTION_ and _LINE_.
27      * Construct it using the \ref ZYPP_EX_CODELOCATION macro.
28     */
29     struct CodeLocation
30     {
31       friend std::ostream & operator<<( std::ostream & str, const CodeLocation & obj );
32
33       /** Ctor */
34       CodeLocation()
35       : _line( 0 )
36       {}
37
38       /** Ctor */
39       CodeLocation( const std::string & file_r,
40                     const std::string & func_r,
41                     unsigned            line_r )
42       : _file( file_r ), _func( func_r ), _line( line_r )
43       {}
44
45       /** Location as string */
46       std::string asString() const;
47
48     private:
49       std::string _file;
50       std::string _func;
51       unsigned    _line;
52     };
53     ///////////////////////////////////////////////////////////////////
54
55     /** Create CodeLocation object storing the current location. */
56     //#define ZYPP_EX_CODELOCATION ::zypp::exception_detail::CodeLocation(__FILE__,__FUNCTION__,__LINE__)
57 #define ZYPP_EX_CODELOCATION ::zypp::exception_detail::CodeLocation(( *__FILE__ == '/' ? strrchr( __FILE__, '/' ) + 1 : __FILE__ ),__FUNCTION__,__LINE__)
58
59     /** \relates CodeLocation Stream output */
60     std::ostream & operator<<( std::ostream & str, const CodeLocation & obj );
61
62     /////////////////////////////////////////////////////////////////
63   } // namespace exception_detail
64   ///////////////////////////////////////////////////////////////////
65
66   ///////////////////////////////////////////////////////////////////
67   //
68   //    CLASS NAME : Exception
69   /** Base class for Exception.
70    *
71    * Exception offers to store a message string passed to the ctor.
72    * Derived classes may provide additional information. Overload
73    * \ref dumpOn to provide a proper error text.
74    *
75    * \li Use \ref ZYPP_THROW to throw exceptions.
76    * \li Use \ref ZYPP_CAUGHT If you caught an exceptions in order to handle it.
77    * \li Use \ref ZYPP_RETHROW to rethrow a caught exception.
78    *
79    * The use of these macros is not mandatory. but \c ZYPP_THROW and
80    * \c ZYPP_RETHROW will adjust the code location information stored in
81    * the Exception. All three macros will drop a line in the logfile.
82
83    * \code
84    *  43   try
85    *  44     {
86    *  45       try
87    *  46         {
88    *  47           ZYPP_THROW( Exception("Something bad happened.") );
89    *  48         }
90    *  49       catch ( Exception & excpt )
91    *  50         {
92    *  51           ZYPP_RETHROW( excpt );
93    *  52         }
94    *  53
95    *  54     }
96    *  55   catch ( Exception & excpt )
97    *  56     {
98    *  57       ZYPP_CAUGHT( excpt );
99    *  58     }
100    * \endcode
101    * The above produces the following log lines:
102    * \code
103    *  Main.cc(main):47 THROW:    Main.cc(main):47: Something bad happened.
104    *  Main.cc(main):51 RETHROW:  Main.cc(main):47: Something bad happened.
105    *  Main.cc(main):57 CAUGHT:   Main.cc(main):51: Something bad happened.
106    * \endcode
107    *
108    * \todo That's a draft to have a common way of throwing exceptions.
109    * Most probabely we'll finally use blocxx exceptions. Here, but not
110    * in the remaining code of zypp. If we can we should try to wrap
111    * the blocxx macros and typedef the classes in here.
112    *
113    * \todo maybe location and message stack.
114    **/
115   class Exception : public std::exception
116   {
117     friend std::ostream & operator<<( std::ostream & str, const Exception & obj );
118
119   public:
120     typedef exception_detail::CodeLocation CodeLocation;
121
122     /** Default ctor.
123      * Use \ref ZYPP_THROW to throw exceptions.
124     */
125     Exception();
126
127     /** Ctor taking a message.
128      * Use \ref ZYPP_THROW to throw exceptions.
129     */
130     Exception( const std::string & msg_r );
131
132     /** Dtor. */
133     virtual ~Exception() throw();
134
135     /** Return CodeLocation. */
136     const CodeLocation & where() const
137     { return _where; }
138
139     /** Exchange location on rethrow. */
140     void relocate( const CodeLocation & where_r ) const
141     { _where = where_r; }
142
143     /** Return the message string provided to the ctor.
144      * \note This is not neccessarily the complete error message.
145      * The whole error message is provided by \ref asString or
146      * \ref dumpOn.
147     */
148     const std::string & msg() const
149     { return _msg; }
150
151     /** Error message provided by \ref dumpOn as string. */
152     std::string asString() const;
153
154     /** Translated error message as string suitable for the user. */
155     std::string asUserString() const;
156
157   protected:
158
159     /** Overload this to print a proper error message. */
160     virtual std::ostream & dumpOn( std::ostream & str ) const;
161
162   public:
163      /** Make a string from \a errno_r. */
164     static std::string strErrno( int errno_r );
165      /** Make a string from \a errno_r and \a msg_r. */
166     static std::string strErrno( int errno_r, const std::string & msg_r );
167
168   public:
169     /** Drop a logline on throw, catch or rethrow.
170      * Used by \ref ZYPP_THROW macros.
171     */
172     static void log( const Exception & excpt_r, const CodeLocation & where_r,
173                      const char *const prefix_r );
174
175   private:
176     mutable CodeLocation _where;
177     std::string _msg;
178
179     /** Return message string. */
180     virtual const char * what() const throw()
181     { return _msg.c_str(); }
182
183     /** Called by <tt>std::ostream & operator\<\<</tt>.
184      * Prints \ref CodeLocation and the error message provided by
185      * \ref dumpOn.
186     */
187     std::ostream & dumpError( std::ostream & str ) const;
188   };
189   ///////////////////////////////////////////////////////////////////
190
191   /** \relates Exception Stream output */
192   std::ostream & operator<<( std::ostream & str, const Exception & obj );
193
194   ///////////////////////////////////////////////////////////////////
195
196   /** Helper for \ref ZYPP_THROW. */
197   template<class _Excpt>
198     void _ZYPP_THROW( const _Excpt & excpt_r, const exception_detail::CodeLocation & where_r )
199     {
200       excpt_r.relocate( where_r );
201       Exception::log( excpt_r, where_r, "THROW:   " );
202       throw( excpt_r );
203     }
204
205   /** Helper for \ref ZYPP_THROW. */
206   template<class _Excpt>
207     void _ZYPP_CAUGHT( const _Excpt & excpt_r, const exception_detail::CodeLocation & where_r )
208     {
209       Exception::log( excpt_r, where_r, "CAUGHT:  " );
210     }
211
212   /** Helper for \ref ZYPP_THROW. */
213   template<class _Excpt>
214     void _ZYPP_RETHROW( const _Excpt & excpt_r, const exception_detail::CodeLocation & where_r )
215     {
216       Exception::log( excpt_r, where_r, "RETHROW: " );
217       excpt_r.relocate( where_r );
218       throw;
219     }
220
221   ///////////////////////////////////////////////////////////////////
222
223   /** \defgroup ZYPP_THROW ZYPP_THROW macros
224    * Macros for throwing Exception.
225    * \see \ref zypp::Exception for an example.
226   */
227   //@{
228   /** Drops a logline and throws the Exception. */
229 #define ZYPP_THROW(EXCPT)\
230   _ZYPP_THROW( EXCPT, ZYPP_EX_CODELOCATION )
231
232   /** Drops a logline telling the Exception was caught (in order to handle it). */
233 #define ZYPP_CAUGHT(EXCPT)\
234   _ZYPP_CAUGHT( EXCPT, ZYPP_EX_CODELOCATION )
235
236   /** Drops a logline and rethrows, updating the CodeLocation. */
237 #define ZYPP_RETHROW(EXCPT)\
238   _ZYPP_RETHROW( EXCPT, ZYPP_EX_CODELOCATION )
239
240
241   /** Throw Exception built from a message string. */
242 #define ZYPP_THROW_MSG(EXCPTTYPE, MSG)\
243   ZYPP_THROW( EXCPTTYPE( MSG ) )
244
245   /** Throw Exception built from errno. */
246 #define ZYPP_THROW_ERRNO(EXCPTTYPE)\
247   ZYPP_THROW( EXCPTTYPE( ::zypp::Exception::strErrno(errno) ) )
248
249   /** Throw Exception built from errno provided as argument. */
250 #define ZYPP_THROW_ERRNO1(EXCPTTYPE, ERRNO)\
251   ZYPP_THROW( EXCPTTYPE( ::zypp::Exception::strErrno(ERRNO) ) )
252
253   /** Throw Exception built from errno and a message string. */
254 #define ZYPP_THROW_ERRNO_MSG(EXCPTTYPE, MSG)\
255   ZYPP_THROW( EXCPTTYPE( ::zypp::Exception::strErrno(errno,MSG) ) )
256
257   /** Throw Exception built from errno provided as argument and a message string */
258 #define ZYPP_THROW_ERRNO_MSG1(EXCPTTYPE, ERRNO,MSG)\
259   ZYPP_THROW( EXCPTTYPE( ::zypp::Exception::strErrno(ERRNO,MSG) ) )
260   //@}
261
262   /////////////////////////////////////////////////////////////////
263 } // namespace zypp
264 ///////////////////////////////////////////////////////////////////
265 #endif // ZYPP_BASE_EXCEPTION_H