]> git.saurik.com Git - apt.git/blobdiff - apt-pkg/contrib/error.h
Bug #807012 also involves package dependencies :/.
[apt.git] / apt-pkg / contrib / error.h
index a3be6a575846938d35c82f98bc50334d903d9be0..e56999b141ed269cf43c5ff9ba874985e0e67574 100644 (file)
 #ifndef PKGLIB_ERROR_H
 #define PKGLIB_ERROR_H
 
+#include <apt-pkg/macros.h>
 
-
-#ifdef __GNUG__
-// Methods have a hidden this parameter that is visible to this attribute
-#define APT_MFORMAT1 __attribute__ ((format (printf, 2, 3)))
-#define APT_MFORMAT2 __attribute__ ((format (printf, 3, 4)))
-#else
-#define APT_MFORMAT1
-#define APT_MFORMAT2    
-#endif    
-    
+#include <iostream>
+#include <list>
 #include <string>
 
-using std::string;
+#include <stddef.h>
+#include <stdarg.h>
 
-class GlobalError
+class GlobalError                                                      /*{{{*/
 {
-   struct Item
-   {
-      string Text;
-      bool Error;
-      Item *Next;
-   };
-   
-   Item *List;
-   bool PendingFlag;
-   void Insert(Item *I);
-   
-   public:
+public:                                                                        /*{{{*/
+       /** \brief a message can have one of following severity */
+       enum MsgType {
+               /** \brief Message will be printed instantly as it is likely that
+                       this error will lead to a complete crash */
+               FATAL = 40,
+               /** \brief An error does hinder the correct execution and should be corrected */
+               ERROR = 30,
+               /** \brief indicates problem that can lead to errors later on */
+               WARNING = 20,
+               /** \brief deprecation warnings, old fallback behavior, … */
+               NOTICE = 10,
+               /** \brief for developers only in areas it is hard to print something directly */
+               DEBUG = 0
+       };
 
-   // Call to generate an error from a library call.
-   bool Errno(const char *Function,const char *Description,...) APT_MFORMAT2;
-   bool WarningE(const char *Function,const char *Description,...) APT_MFORMAT2;
+       /** \brief add a fatal error message with errno to the list
+        *
+        *  \param Function name of the function generating the error
+        *  \param Description format string for the error message
+        *
+        *  \return \b false
+        */
+       bool FatalE(const char *Function,const char *Description,...) APT_PRINTF(3) APT_COLD;
 
-   /* A warning should be considered less severe than an error, and may be
-      ignored by the client. */
-   bool Error(const char *Description,...) APT_MFORMAT1;
-   bool Warning(const char *Description,...) APT_MFORMAT1;
+       /** \brief add an Error message with errno to the list
+        *
+        *  \param Function name of the function generating the error
+        *  \param Description format string for the error message
+        *
+        *  \return \b false
+        */
+       bool Errno(const char *Function,const char *Description,...) APT_PRINTF(3) APT_COLD;
 
-   // Simple accessors
-   inline bool PendingError() {return PendingFlag;};
-   inline bool empty() {return List == 0;};
-   bool PopMessage(string &Text);
-   void Discard();
+       /** \brief add a warning message with errno to the list
+        *
+        *  A warning should be considered less severe than an error and
+        *  may be ignored by the client.
+        *
+        *  \param Function Name of the function generates the warning.
+        *  \param Description Format string for the warning message.
+        *
+        *  \return \b false
+        */
+       bool WarningE(const char *Function,const char *Description,...) APT_PRINTF(3) APT_COLD;
 
-   // Usefull routine to dump to cerr
-   void DumpErrors();
-   
-   GlobalError();
+       /** \brief add a notice message with errno to the list
+        *
+        *  \param Function name of the function generating the error
+        *  \param Description format string for the error message
+        *
+        *  \return \b false
+        */
+       bool NoticeE(const char *Function,const char *Description,...) APT_PRINTF(3) APT_COLD;
+
+       /** \brief add a debug message with errno to the list
+        *
+        *  \param Function name of the function generating the error
+        *  \param Description format string for the error message
+        *
+        *  \return \b false
+        */
+       bool DebugE(const char *Function,const char *Description,...) APT_PRINTF(3) APT_COLD;
+
+       /** \brief adds an errno message with the given type
+        *
+        * \param type of the error message
+        * \param Function which failed
+        * \param Description of the error
+        */
+       bool InsertErrno(MsgType const &type, const char* Function,
+                        const char* Description,...) APT_PRINTF(4) APT_COLD;
+
+       /** \brief adds an errno message with the given type
+        *
+        * args needs to be initialized with va_start and terminated
+        * with va_end by the caller. msgSize is also an out-parameter
+        * in case the msgSize was not enough to store the complete message.
+        *
+        * \param type of the error message
+        * \param Function which failed
+        * \param Description is the format string for args
+        * \param args list from a printf-like function
+        * \param errsv is the errno the error is for
+        * \param msgSize is the size of the char[] used to store message
+        * \return true if the message was added, false if not - the caller
+        * should call this method again in that case
+        */
+       bool InsertErrno(MsgType type, const char* Function,
+                        const char* Description, va_list &args,
+                        int const errsv, size_t &msgSize) APT_COLD;
+
+       /** \brief add an fatal error message to the list
+        *
+        *  Most of the stuff we consider as "error" is also "fatal" for
+        *  the user as the application will not have the expected result,
+        *  but a fatal message here means that it gets printed directly
+        *  to stderr in addition to adding it to the list as the error
+        *  leads sometimes to crashes and a maybe duplicated message
+        *  is better than "Segfault" as the only displayed text
+        *
+        *  \param Description Format string for the fatal error message.
+        *
+        *  \return \b false
+        */
+       bool Fatal(const char *Description,...) APT_PRINTF(2) APT_COLD;
+
+       /** \brief add an Error message to the list
+        *
+        *  \param Description Format string for the error message.
+        *
+        *  \return \b false
+        */
+       bool Error(const char *Description,...) APT_PRINTF(2) APT_COLD;
+
+       /** \brief add a warning message to the list
+        *
+        *  A warning should be considered less severe than an error and
+        *  may be ignored by the client.
+        *
+        *  \param Description Format string for the message
+        *
+        *  \return \b false
+        */
+       bool Warning(const char *Description,...) APT_PRINTF(2) APT_COLD;
+
+       /** \brief add a notice message to the list
+        *
+        *  A notice should be considered less severe than an error or a
+        *  warning and can be ignored by the client without further problems
+        *  for some times, but he should consider fixing the problem.
+        *  This error type can be used for e.g. deprecation warnings of options.
+        *
+        *  \param Description Format string for the message
+        *
+        *  \return \b false
+        */
+       bool Notice(const char *Description,...) APT_PRINTF(2) APT_COLD;
+
+       /** \brief add a debug message to the list
+        *
+        *  \param Description Format string for the message
+        *
+        *  \return \b false
+        */
+       bool Debug(const char *Description,...) APT_PRINTF(2) APT_COLD;
+
+       /** \brief adds an error message with the given type
+        *
+        * \param type of the error message
+        * \param Description of the error
+        */
+       bool Insert(MsgType const &type, const char* Description,...) APT_PRINTF(3) APT_COLD;
+
+       /** \brief adds an error message with the given type
+        *
+        * args needs to be initialized with va_start and terminated
+        * with va_end by the caller. msgSize is also an out-parameter
+        * in case the msgSize was not enough to store the complete message.
+        *
+        * \param type of the error message
+        * \param Description is the format string for args
+        * \param args list from a printf-like function
+        * \param msgSize is the size of the char[] used to store message
+        * \return true if the message was added, false if not - the caller
+        * should call this method again in that case
+        */
+       bool Insert(MsgType type, const char* Description,
+                        va_list &args, size_t &msgSize) APT_COLD;
+
+       /** \brief is an error in the list?
+        *
+        *  \return \b true if an error is included in the list, \b false otherwise
+        */
+       inline bool PendingError() const APT_PURE {return PendingFlag;};
+
+       /** \brief is the list empty?
+        *
+        *  Can be used to check if the current stack level doesn't include
+        *  anything equal or more severe than a given threshold, defaulting
+        *  to warning level for historic reasons.
+        *
+        *  \param threshold minimum level considered
+        *
+        *  \return \b true if the list is empty, \b false otherwise
+        */
+       bool empty(MsgType const &threshold = WARNING) const APT_PURE;
+
+       /** \brief returns and removes the first (or last) message in the list
+        *
+        *  \param[out] Text message of the first/last item
+        *
+        *  \return \b true if the message was an error, \b false otherwise
+        */
+       bool PopMessage(std::string &Text);
+
+       /** \brief clears the list of messages */
+       void Discard();
+
+       /** \brief outputs the list of messages to the given stream
+        *
+        *  Note that all messages are discarded, even undisplayed ones.
+        *
+        *  \param[out] out output stream to write the messages in
+        *  \param threshold minimum level considered
+        *  \param mergeStack if true recursively dumps the entire stack
+        */
+       void DumpErrors(std::ostream &out, MsgType const &threshold = WARNING,
+                       bool const &mergeStack = true);
+
+       /** \brief dumps the list of messages to std::cerr
+        *
+        *  Note that all messages are discarded, also the notices
+        *  displayed or not.
+        *
+        *  \param threshold minimum level printed
+        */
+       void inline DumpErrors(MsgType const &threshold) {
+               DumpErrors(std::cerr, threshold);
+       }
+
+        // mvo: we do this instead of using a default parameter in the
+        //      previous declaration to avoid a (subtle) API break for
+        //      e.g. sigc++ and mem_fun0
+       /** \brief dumps the messages of type WARNING or higher to std::cerr
+        *
+        *  Note that all messages are discarded, displayed or not.
+        *
+        */
+       void inline DumpErrors() {
+                DumpErrors(WARNING);
+       }
+
+       /** \brief put the current Messages into the stack
+        *
+        *  All "old" messages will be pushed into a stack to
+        *  them later back, but for now the Message query will be
+        *  empty and performs as no messages were present before.
+        *
+        * The stack can be as deep as you want - all stack operations
+        * will only operate on the last element in the stack.
+        */
+       void PushToStack();
+
+       /** \brief throw away all current messages */
+       void RevertToStack();
+
+       /** \brief merge current and stack together */
+       void MergeWithStack();
+
+       /** \brief return the deep of the stack */
+       size_t StackCount() const APT_PURE {
+               return Stacks.size();
+       }
+
+       GlobalError();
+                                                                       /*}}}*/
+private:                                                               /*{{{*/
+       struct Item {
+               std::string Text;
+               MsgType Type;
+
+               Item(char const *Text, MsgType const &Type) :
+                       Text(Text), Type(Type) {};
+
+               APT_HIDDEN friend std::ostream& operator<< (std::ostream &out, Item i) {
+                       switch(i.Type) {
+                       case FATAL:
+                       case ERROR: out << 'E'; break;
+                       case WARNING: out << 'W'; break;
+                       case NOTICE: out << 'N'; break;
+                       case DEBUG: out << 'D'; break;
+                       }
+                       out << ": ";
+                       std::string::size_type line_start = 0;
+                       std::string::size_type line_end;
+                       while ((line_end = i.Text.find_first_of("\n\r", line_start)) != std::string::npos) {
+                               if (line_start != 0)
+                                  out << std::endl << "   ";
+                               out << i.Text.substr(line_start, line_end - line_start);
+                               line_start = i.Text.find_first_not_of("\n\r", line_end + 1);
+                               if (line_start == std::string::npos)
+                                  break;
+                       }
+                       if (line_start == 0)
+                          out << i.Text;
+                       else if (line_start != std::string::npos)
+                          out << std::endl << "   " << i.Text.substr(line_start);
+                       return out;
+               }
+       };
+
+       std::list<Item> Messages;
+       bool PendingFlag;
+
+       struct MsgStack {
+               std::list<Item> Messages;
+               bool const PendingFlag;
+
+               MsgStack(std::list<Item> const &Messages, bool const &Pending) :
+                        Messages(Messages), PendingFlag(Pending) {};
+       };
+
+       std::list<MsgStack> Stacks;
+                                                                       /*}}}*/
 };
+                                                                       /*}}}*/
 
 // The 'extra-ansi' syntax is used to help with collisions. 
 GlobalError *_GetErrorObj();
 #define _error _GetErrorObj()
 
-#undef APT_MFORMAT1
-#undef APT_MFORMAT2
-
 #endif