CppCMS
|
00001 // 00002 // Copyright (C) 2009-2012 Artyom Beilis (Tonkikh) 00003 // 00004 // Distributed under the Boost Software License, Version 1.0. (See 00005 // accompanying file LICENSE_1_0.txt or copy at 00006 // http://www.boost.org/LICENSE_1_0.txt) 00007 // 00008 #ifndef BOOSTER_BACKTRACE_H 00009 #define BOOSTER_BACKTRACE_H 00010 00011 #include <booster/config.h> 00012 #include <stdexcept> 00013 #include <typeinfo> 00014 #include <string> 00015 #include <vector> 00016 #include <iosfwd> 00017 00018 namespace booster { 00019 00024 namespace stack_trace { 00033 BOOSTER_API int trace(void **addresses,int size); 00039 BOOSTER_API void write_symbols(void *const *addresses,int size,std::ostream &); 00043 BOOSTER_API std::string get_symbol(void *address); 00047 BOOSTER_API std::string get_symbols(void * const *address,int size); 00048 } // stack_trace 00049 00055 00056 class backtrace { 00057 public: 00058 00062 static size_t const default_stack_size = 32; 00063 00067 backtrace(size_t frames_no = default_stack_size) 00068 { 00069 if(frames_no == 0) 00070 return; 00071 frames_.resize(frames_no,0); 00072 int size = stack_trace::trace(&frames_.front(),frames_no); 00073 frames_.resize(size); 00074 } 00075 00076 virtual ~backtrace() throw() 00077 { 00078 } 00079 00083 size_t stack_size() const 00084 { 00085 return frames_.size(); 00086 } 00087 00091 void *return_address(unsigned frame_no) const 00092 { 00093 if(frame_no < stack_size()) 00094 return frames_[frame_no]; 00095 return 0; 00096 } 00097 00101 void trace_line(unsigned frame_no,std::ostream &out) const 00102 { 00103 if(frame_no < frames_.size()) 00104 stack_trace::write_symbols(&frames_[frame_no],1,out); 00105 } 00106 00110 std::string trace_line(unsigned frame_no) const 00111 { 00112 if(frame_no < frames_.size()) 00113 return stack_trace::get_symbol(frames_[frame_no]); 00114 return std::string(); 00115 } 00116 00120 std::string trace() const 00121 { 00122 if(frames_.empty()) 00123 return std::string(); 00124 return stack_trace::get_symbols(&frames_.front(),frames_.size()); 00125 } 00126 00130 void trace(std::ostream &out) const 00131 { 00132 if(frames_.empty()) 00133 return; 00134 stack_trace::write_symbols(&frames_.front(),frames_.size(),out); 00135 } 00136 00137 private: 00138 std::vector<void *> frames_; 00139 }; 00140 00144 class exception : public std::exception, public backtrace { 00145 public: 00146 }; 00147 00151 class bad_cast : public std::bad_cast, public backtrace { 00152 public: 00153 }; 00154 00158 class runtime_error: public std::runtime_error, public backtrace { 00159 public: 00160 explicit runtime_error(std::string const &s) : std::runtime_error(s) 00161 { 00162 } 00163 }; 00164 00168 class range_error: public std::range_error, public backtrace { 00169 public: 00170 explicit range_error(std::string const &s) : std::range_error(s) 00171 { 00172 } 00173 }; 00174 00178 class overflow_error: public std::overflow_error, public backtrace { 00179 public: 00180 explicit overflow_error(std::string const &s) : std::overflow_error(s) 00181 { 00182 } 00183 }; 00184 00188 class underflow_error: public std::underflow_error, public backtrace { 00189 public: 00190 explicit underflow_error(std::string const &s) : std::underflow_error(s) 00191 { 00192 } 00193 }; 00194 00198 class logic_error: public std::logic_error, public backtrace { 00199 public: 00200 explicit logic_error(std::string const &s) : std::logic_error(s) 00201 { 00202 } 00203 }; 00204 00208 class domain_error: public std::domain_error, public backtrace { 00209 public: 00210 explicit domain_error(std::string const &s) : std::domain_error(s) 00211 { 00212 } 00213 }; 00214 00218 class length_error: public std::length_error, public backtrace { 00219 public: 00220 explicit length_error(std::string const &s) : std::length_error(s) 00221 { 00222 } 00223 }; 00224 00228 class invalid_argument : public std::invalid_argument, public backtrace { 00229 public: 00230 explicit invalid_argument(std::string const &s) : std::invalid_argument(s) 00231 { 00232 } 00233 }; 00234 00238 class out_of_range : public std::out_of_range, public backtrace { 00239 public: 00240 explicit out_of_range(std::string const &s) : std::out_of_range(s) 00241 { 00242 } 00243 }; 00244 00246 namespace details { 00247 class trace_manip { 00248 public: 00249 trace_manip(backtrace const *tr) : 00250 tr_(tr) 00251 { 00252 } 00253 std::ostream &write(std::ostream &out) const 00254 { 00255 if(tr_) 00256 tr_->trace(out); 00257 return out; 00258 } 00259 private: 00260 backtrace const *tr_; 00261 }; 00262 00263 inline std::ostream &operator<<(std::ostream &out,details::trace_manip const &t) 00264 { 00265 return t.write(out); 00266 } 00267 } 00269 00284 template<typename E> 00285 details::trace_manip trace(E const &e) 00286 { 00287 backtrace const *tr = dynamic_cast<backtrace const *>(&e); 00288 return details::trace_manip(tr); 00289 } 00290 00291 00292 } // booster 00293 00294 #endif 00295 // vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 00296