00001 /** @file rutz/error_context.h */ 00002 00003 /////////////////////////////////////////////////////////////////////// 00004 // 00005 // Copyright (c) 2005-2007 University of Southern California 00006 // Rob Peters <rjpeters at usc dot edu> 00007 // 00008 // created: Thu Nov 17 16:14:06 2005 00009 // commit: $Id: error_context.h 8249 2007-04-12 06:03:40Z rjpeters $ 00010 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/rutz/error_context.h $ 00011 // 00012 // -------------------------------------------------------------------- 00013 // 00014 // This file is part of GroovX. 00015 // [http://www.klab.caltech.edu/rjpeters/groovx/] 00016 // 00017 // GroovX is free software; you can redistribute it and/or modify it 00018 // under the terms of the GNU General Public License as published by 00019 // the Free Software Foundation; either version 2 of the License, or 00020 // (at your option) any later version. 00021 // 00022 // GroovX is distributed in the hope that it will be useful, but 00023 // WITHOUT ANY WARRANTY; without even the implied warranty of 00024 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00025 // General Public License for more details. 00026 // 00027 // You should have received a copy of the GNU General Public License 00028 // along with GroovX; if not, write to the Free Software Foundation, 00029 // Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 00030 // 00031 /////////////////////////////////////////////////////////////////////// 00032 00033 #ifndef GROOVX_RUTZ_ERROR_CONTEXT_H_UTC20051118001406_DEFINED 00034 #define GROOVX_RUTZ_ERROR_CONTEXT_H_UTC20051118001406_DEFINED 00035 00036 #include "rutz/fstring.h" 00037 #include "rutz/staticstack.h" 00038 00039 namespace rutz 00040 { 00041 class error_context; 00042 class error_context_entry; 00043 } 00044 00045 /// Don't use this class directly; use the GVX_ERR_CONTEXT() macro instead. 00046 class rutz::error_context 00047 { 00048 public: 00049 /// Constructor (but use current() to get the current context) 00050 error_context(); 00051 00052 /// Destructor 00053 ~error_context(); 00054 00055 /// Get the current thread-local error context object 00056 static const rutz::error_context& current(); 00057 00058 /// Add an entry to the context stack 00059 bool add_entry(const error_context_entry* e); 00060 00061 /// Remove an entry from the context stack 00062 void remove_entry(const error_context_entry* e); 00063 00064 /// get the text of all context entries, separated by newlines 00065 rutz::fstring get_text() const; 00066 00067 /// Prepend our message (if any) to the given string 00068 /** This function is a template that is designed to work with either 00069 std::string or rutz::fstring (but without naming std::string 00070 explicitly here, we can avoid needing to #include the 50K lines of 00071 code from <string>). 00072 00073 Example usage: 00074 00075 \code 00076 std::string mymsg = "something bad happened"; 00077 rutz::error_context::current().prepend_to(mymsg); 00078 \endcode 00079 */ 00080 template <class S> 00081 inline void prepend_to(S& str) const 00082 { 00083 const rutz::fstring ctx = this->get_text(); 00084 00085 if (ctx.length() > 0) 00086 { 00087 const S orig = str; 00088 str = "error context follows (innermost last):\n"; 00089 str += ctx.c_str(); 00090 str += "\n"; 00091 str += orig; 00092 } 00093 } 00094 00095 private: 00096 error_context(const error_context&); // not implemented 00097 error_context& operator=(const error_context&); // not implemented 00098 00099 rutz::static_stack<const error_context_entry*, 256> m_entries; 00100 }; 00101 00102 /// Don't use this class directly; use the GVX_ERR_CONTEXT() macro instead. 00103 class rutz::error_context_entry 00104 { 00105 public: 00106 /// Construct an error context entry, adding it to the current error_context 00107 error_context_entry(const rutz::fstring& msg); 00108 00109 /// Destruct the error context entry, removing it from its error_context 00110 ~error_context_entry(); 00111 00112 /// Get the message associated with this entry 00113 const rutz::fstring& text() const { return m_text; } 00114 00115 private: 00116 error_context_entry(const error_context_entry&); 00117 error_context_entry& operator=(const error_context_entry&); 00118 00119 rutz::fstring m_text; 00120 00121 // context from which to remove ourselves, or null 00122 rutz::error_context* m_context; 00123 }; 00124 00125 /// Give some contextual information that can be used if an error message is needed. 00126 /** The GVX_ERR_CONTEXT() calls form a last-in/last-out stack that 00127 describes the call context at any moment, in particular at the 00128 moment that an error might occur. If an error does occur, we can 00129 capture the call context and report it to the user, (hopefully) 00130 making it easier to understand the error and debug the problem. 00131 */ 00132 #define GVX_ERR_CONTEXT(msg) \ 00133 rutz::error_context_entry e_c_object_(msg) 00134 00135 static const char __attribute__((used)) vcid_groovx_rutz_error_context_h_utc20051118001406[] = "$Id: error_context.h 8249 2007-04-12 06:03:40Z rjpeters $ $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/rutz/error_context.h $"; 00136 #endif // !GROOVX_RUTZ_ERROR_CONTEXT_H_UTC20051118001406DEFINED