//COTD (09/27/2001) submitted by Squint [flipcode@squint.clara.co.uk] // ErrorStack.h #ifndef ErrorStack_H #define ErrorStack_H //////////////////////////////////////////////////////////////// // Class header for ErrorStack //////////////////////////////////////////////////////////////// #include #include #include class ErrorStack { private: ErrorStack() {} // Constructor virtual ~ErrorStack() {} // Destructor ErrorStack (const ErrorStack &); // Singleton so no copy constructor ErrorStack & operator= (const ErrorStack &); // Singleton so no assignment operator protected: std::vector Stack; // This stores the error messages public: static class ErrorStack * Instance () { static ErrorStack * TheInstance = 0; if(TheInstance) return TheInstance; else return (TheInstance = new class ErrorStack); } void Clear(); // This empties the stack void Push(const char * fmt, ...); // This adds an error message to the stack void Push(const std::string & str); // This adds an error message to the stack std::string Report(); // This returns a formatted string of all errors in the stack }; // These are shortcut functions for the above singleton: extern void PushError(const char * fmt, ...); extern void PushError(const std::string & str); #endif // ErrorStack_H // ErrorStack.cpp /////////////////////////////////////////////////////////////////////////////// // Class body for ErrorStack /////////////////////////////////////////////////////////////////////////////// #include "ErrorStack.h" #include using namespace std; /////////////////////////////////////////////////////////////////////////////// // Clear: // Empties the error stack. // Needs calling if you attempt to continue from an error, which may include // anywhere you choose to completely ignore one. /////////////////////////////////////////////////////////////////////////////// void ErrorStack::Clear() { Stack.clear(); } /////////////////////////////////////////////////////////////////////////////// // Push: // Adds an error message to the stack. /////////////////////////////////////////////////////////////////////////////// void ErrorStack::Push(const std::string & str) { Stack.push_back(str); } /////////////////////////////////////////////////////////////////////////////// // Push: // Adds an error message to the stack. /////////////////////////////////////////////////////////////////////////////// void ErrorStack::Push(const char *fmt, ...) { static char str[8192]; va_list argptr; va_start(argptr, fmt); vsprintf(str, fmt, argptr); va_end(argptr); Stack.push_back(str); } /////////////////////////////////////////////////////////////////////////////// // Report: // Returns the errors on the stack as a single formatted string. /////////////////////////////////////////////////////////////////////////////// string ErrorStack::Report() { string str; vector::iterator s; if(Stack.size()) { s = Stack.begin(); str = *s++; while(s != Stack.end()) { str = *s + " [" + str + "]"; ++s; } } else { str = "No Error"; } return(str); } /////////////////////////////////////////////////////////////////////////////// // The following functions are global, and exist to simplify the use of the // error stack: /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // PushError: // Pushes a string onto the error stack. /////////////////////////////////////////////////////////////////////////////// void PushError(const string & str) { ErrorStack::Instance()->Push(str); } /////////////////////////////////////////////////////////////////////////////// // PushError: // Pushes a string, which can include formatting, onto the error stack. /////////////////////////////////////////////////////////////////////////////// void PushError(const char *fmt, ...) { static char str[8192]; va_list argptr; va_start(argptr, fmt); vsprintf(str, fmt, argptr); va_end(argptr); ErrorStack::Instance()->Push(str); } // Example code #include #include "First.h" #include "ErrorStack.h" int main(int argc, char **argv) { First first; if(!(first.DoSomething())) { PushError("Do something failed"); printf("%s\n", ErrorStack::Instance()->Report().c_str()); exit(0); } return(0); } #include "Second.h" class First { protected: Second second; public: bool DoSomething(); }; #include "First.h" #include "ErrorStack.h" bool First::DoSomething() { if(second.DoSomethingElse()) { return(true); } else { PushError("Failed to do something else"); return(false); } } class Second { public: bool DoSomethingElse(); }; #include "Second.h" #include "ErrorStack.h" bool Second::DoSomethingElse() { // This always fails: PushError("This always fails"); return(false); }