TuttleOFX  1
backtrace.hpp
Go to the documentation of this file.
00001 //
00002 //  Copyright (c) 2010 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 BOOST_BACKTRACE_HPP
00009 #define BOOST_BACKTRACE_HPP
00010 
00011 #include <boost/config.hpp>
00012 #include <stdexcept>
00013 #include <typeinfo>
00014 #include <vector>
00015 #include <iosfwd>
00016 
00017 namespace boost {
00018 
00019 namespace stack_trace {
00020         int trace(void **addresses,int size);
00021         void write_symbols(void *const *addresses,int size,std::ostream &);
00022         std::string get_symbol(void *address);
00023         std::string get_symbols(void * const *address,int size);
00024 } // stack_trace
00025 
00026 
00027 class backtrace
00028 {
00029 public:
00030         static size_t const default_stack_size = 32;
00031 
00032         backtrace(size_t frames_no = default_stack_size) 
00033         {
00034                 if(frames_no == 0)
00035                         return;
00036                 frames_.resize(frames_no,0);
00037                 int size = stack_trace::trace(&frames_.front(),frames_no);
00038                 frames_.resize(size);
00039         }
00040 
00041         virtual ~backtrace() throw()
00042         {
00043         }
00044 
00045         size_t stack_size() const
00046         {
00047                 return frames_.size();
00048         }
00049 
00050         void *return_address(unsigned frame_no) const
00051         {
00052                 if(frame_no < stack_size())
00053                         return frames_[frame_no];
00054                 return 0;
00055         }
00056 
00057         void trace_line(unsigned frame_no,std::ostream &out) const
00058         {
00059                 if(frame_no < frames_.size())
00060                         stack_trace::write_symbols(&frames_[frame_no],1,out);
00061         }
00062 
00063         std::string trace_line(unsigned frame_no) const
00064         {
00065                 if(frame_no < frames_.size())
00066                         return stack_trace::get_symbol(frames_[frame_no]);
00067                 return std::string();
00068         }
00069 
00070         std::string trace() const
00071         {
00072                 if(frames_.empty())
00073                         return std::string();
00074                 return stack_trace::get_symbols(&frames_.front(),frames_.size());
00075         }
00076 
00077         void trace(std::ostream &out) const
00078         {
00079                 if(frames_.empty())
00080                         return;
00081                 stack_trace::write_symbols(&frames_.front(),frames_.size(),out);
00082         }
00083 
00084 private:
00085         std::vector<void *> frames_;
00086 };
00087 
00088 
00089 namespace details {
00090         class trace_manip {
00091         public:
00092                 trace_manip(backtrace const *tr) :
00093                         tr_(tr)
00094                 {
00095                 }
00096                 std::ostream &write(std::ostream &out) const
00097                 {
00098                         if(tr_)
00099                                 tr_->trace(out);
00100                         return out;
00101                 }
00102         private:
00103                 backtrace const *tr_;
00104         };
00105 
00106         inline std::ostream &operator<<(std::ostream &out,details::trace_manip const &t)
00107         {
00108                 return t.write(out);
00109         }
00110 }
00111 
00112 template<typename E>
00113 details::trace_manip trace(E const &e)
00114 {
00115         backtrace const *tr = dynamic_cast<backtrace const *>(&e);
00116         return details::trace_manip(tr);
00117 }
00118 
00119 
00120 } // boost
00121 
00122 #endif
00123 // vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
00124