* apt-pkg/contrib/error.cc:
[ntk/apt.git] / apt-pkg / contrib / error.h
1 // -*- mode: cpp; mode: fold -*-
2 // Description /*{{{*/
3 // $Id: error.h,v 1.8 2001/05/07 05:06:52 jgg Exp $
4 /* ######################################################################
5
6 Global Erorr Class - Global error mechanism
7
8 This class has a single global instance. When a function needs to
9 generate an error condition, such as a read error, it calls a member
10 in this class to add the error to a stack of errors.
11
12 By using a stack the problem with a scheme like errno is removed and
13 it allows a very detailed account of what went wrong to be transmitted
14 to the UI for display. (Errno has problems because each function sets
15 errno to 0 if it didn't have an error thus eraseing erno in the process
16 of cleanup)
17
18 Several predefined error generators are provided to handle common
19 things like errno. The general idea is that all methods return a bool.
20 If the bool is true then things are OK, if it is false then things
21 should start being undone and the stack should unwind under program
22 control.
23
24 A Warning should not force the return of false. Things did not fail, but
25 they might have had unexpected problems. Errors are stored in a FIFO
26 so Pop will return the first item..
27
28 I have some thoughts about extending this into a more general UI<->
29 Engine interface, ie allowing the Engine to say 'The disk is full' in
30 a dialog that says 'Panic' and 'Retry'.. The error generator functions
31 like errno, Warning and Error return false always so this is normal:
32 if (open(..))
33 return _error->Errno(..);
34
35 This source is placed in the Public Domain, do with it what you will
36 It was originally written by Jason Gunthorpe.
37
38 ##################################################################### */
39 /*}}}*/
40 #ifndef PKGLIB_ERROR_H
41 #define PKGLIB_ERROR_H
42
43 #include <apt-pkg/macros.h>
44
45 #include <iostream>
46 #include <list>
47 #include <string>
48
49 #include <stdarg.h>
50
51 class GlobalError /*{{{*/
52 {
53 public: /*{{{*/
54 /** \brief a message can have one of following severity */
55 enum MsgType {
56 /** \brief Message will be printed instantly as it is likely that
57 this error will lead to a complete crash */
58 FATAL = 40,
59 /** \brief An error does hinder the correct execution and should be corrected */
60 ERROR = 30,
61 /** \brief indicates problem that can lead to errors later on */
62 WARNING = 20,
63 /** \brief deprecation warnings, old fallback behavior, … */
64 NOTICE = 10,
65 /** \brief for developers only in areas it is hard to print something directly */
66 DEBUG = 0
67 };
68
69 /** \brief add a fatal error message with errno to the list
70 *
71 * \param Function name of the function generating the error
72 * \param Description format string for the error message
73 *
74 * \return \b false
75 */
76 bool FatalE(const char *Function,const char *Description,...) __like_printf(3) __cold;
77
78 /** \brief add an Error message with errno to the list
79 *
80 * \param Function name of the function generating the error
81 * \param Description format string for the error message
82 *
83 * \return \b false
84 */
85 bool Errno(const char *Function,const char *Description,...) __like_printf(3) __cold;
86
87 /** \brief add a warning message with errno to the list
88 *
89 * A warning should be considered less severe than an error and
90 * may be ignored by the client.
91 *
92 * \param Function Name of the function generates the warning.
93 * \param Description Format string for the warning message.
94 *
95 * \return \b false
96 */
97 bool WarningE(const char *Function,const char *Description,...) __like_printf(3) __cold;
98
99 /** \brief add a notice message with errno to the list
100 *
101 * \param Function name of the function generating the error
102 * \param Description format string for the error message
103 *
104 * \return \b false
105 */
106 bool NoticeE(const char *Function,const char *Description,...) __like_printf(3) __cold;
107
108 /** \brief add a debug message with errno to the list
109 *
110 * \param Function name of the function generating the error
111 * \param Description format string for the error message
112 *
113 * \return \b false
114 */
115 bool DebugE(const char *Function,const char *Description,...) __like_printf(3) __cold;
116
117 /** \brief adds an errno message with the given type
118 *
119 * \param type of the error message
120 * \param Function which failed
121 * \param Description of the error
122 */
123 bool InsertErrno(MsgType const &type, const char* Function,
124 const char* Description,...) __like_printf(4) __cold;
125
126 /** \brief add an fatal error message to the list
127 *
128 * Most of the stuff we consider as "error" is also "fatal" for
129 * the user as the application will not have the expected result,
130 * but a fatal message here means that it gets printed directly
131 * to stderr in addiction to adding it to the list as the error
132 * leads sometimes to crashes and a maybe duplicated message
133 * is better than "Segfault" as the only displayed text
134 *
135 * \param Description Format string for the fatal error message.
136 *
137 * \return \b false
138 */
139 bool Fatal(const char *Description,...) __like_printf(2) __cold;
140
141 /** \brief add an Error message to the list
142 *
143 * \param Description Format string for the error message.
144 *
145 * \return \b false
146 */
147 bool Error(const char *Description,...) __like_printf(2) __cold;
148
149 /** \brief add a warning message to the list
150 *
151 * A warning should be considered less severe than an error and
152 * may be ignored by the client.
153 *
154 * \param Description Format string for the message
155 *
156 * \return \b false
157 */
158 bool Warning(const char *Description,...) __like_printf(2) __cold;
159
160 /** \brief add a notice message to the list
161 *
162 * A notice should be considered less severe than an error or a
163 * warning and can be ignored by the client without further problems
164 * for some times, but he should consider fixing the problem.
165 * This error type can be used for e.g. deprecation warnings of options.
166 *
167 * \param Description Format string for the message
168 *
169 * \return \b false
170 */
171 bool Notice(const char *Description,...) __like_printf(2) __cold;
172
173 /** \brief add a debug message to the list
174 *
175 * \param Description Format string for the message
176 *
177 * \return \b false
178 */
179 bool Debug(const char *Description,...) __like_printf(2) __cold;
180
181 /** \brief adds an error message with the given type
182 *
183 * \param type of the error message
184 * \param Description of the error
185 */
186 bool Insert(MsgType const &type, const char* Description,...) __like_printf(3) __cold;
187
188 /** \brief is an error in the list?
189 *
190 * \return \b true if an error is included in the list, \b false otherwise
191 */
192 inline bool PendingError() const {return PendingFlag;};
193
194 /** \brief is the list empty?
195 *
196 * The default checks if the list is empty or contains only notices,
197 * if you want to check if also no notices happend set the parameter
198 * flag to \b false.
199 *
200 * \param WithoutNotice does notices count, default is \b true, so no
201 *
202 * \return \b true if an the list is empty, \b false otherwise
203 */
204 bool empty(MsgType const &trashhold = WARNING) const;
205
206 /** \brief returns and removes the first (or last) message in the list
207 *
208 * \param[out] Text message of the first/last item
209 *
210 * \return \b true if the message was an error, \b false otherwise
211 */
212 bool PopMessage(std::string &Text);
213
214 /** \brief clears the list of messages */
215 void Discard();
216
217 /** \brief outputs the list of messages to the given stream
218 *
219 * Note that all messages are discarded, also the notices
220 * displayed or not.
221 *
222 * \param[out] out output stream to write the messages in
223 * \param threshold minimim level considered
224 * \param mergeStack
225 */
226 void DumpErrors(std::ostream &out, MsgType const &threshold = WARNING,
227 bool const &mergeStack = true);
228
229 /** \brief dumps the list of messages to std::cerr
230 *
231 * Note that all messages are discarded, also the notices
232 * displayed or not.
233 *
234 * \param threshold minimum level printed
235 */
236 void inline DumpErrors(MsgType const &threshold) {
237 DumpErrors(std::cerr, threshold);
238 }
239
240 // mvo: we do this instead of using a default parameter in the
241 // previous declaration to avoid a (subtle) API break for
242 // e.g. sigc++ and mem_fun0
243 /** \brief dumps the messages of type WARNING or higher to std::cerr
244 *
245 * Note that all messages are discarded, displayed or not.
246 *
247 */
248 void inline DumpErrors() {
249 DumpErrors(WARNING);
250 }
251
252 /** \brief put the current Messages into the stack
253 *
254 * All "old" messages will be pushed into a stack to
255 * them later back, but for now the Message query will be
256 * empty and performs as no messages were present before.
257 *
258 * The stack can be as deep as you want - all stack operations
259 * will only operate on the last element in the stack.
260 */
261 void PushToStack();
262
263 /** \brief throw away all current messages */
264 void RevertToStack();
265
266 /** \brief merge current and stack together */
267 void MergeWithStack();
268
269 /** \brief return the deep of the stack */
270 size_t StackCount() const {
271 return Stacks.size();
272 }
273
274 GlobalError();
275 /*}}}*/
276 private: /*{{{*/
277 struct Item {
278 std::string Text;
279 MsgType Type;
280
281 Item(char const *Text, MsgType const &Type) :
282 Text(Text), Type(Type) {};
283
284 friend std::ostream& operator<< (std::ostream &out, Item i) {
285 switch(i.Type) {
286 case FATAL:
287 case ERROR: out << "E"; break;
288 case WARNING: out << "W"; break;
289 case NOTICE: out << "N"; break;
290 case DEBUG: out << "D"; break;
291 }
292 return out << ": " << i.Text;
293 }
294 };
295
296 std::list<Item> Messages;
297 bool PendingFlag;
298
299 struct MsgStack {
300 std::list<Item> const Messages;
301 bool const PendingFlag;
302
303 MsgStack(std::list<Item> const &Messages, bool const &Pending) :
304 Messages(Messages), PendingFlag(Pending) {};
305 };
306
307 std::list<MsgStack> Stacks;
308
309 bool InsertErrno(MsgType type, const char* Function,
310 const char* Description, va_list &args,
311 int const errsv, size_t &msgSize);
312 bool Insert(MsgType type, const char* Description,
313 va_list &args, size_t &msgSize);
314 /*}}}*/
315 };
316 /*}}}*/
317
318 // The 'extra-ansi' syntax is used to help with collisions.
319 GlobalError *_GetErrorObj();
320 #define _error _GetErrorObj()
321
322 #endif