error.h 9.1 KB

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