2012-12-12 17:31:21 +00:00
|
|
|
#include <fc/error_report.hpp>
|
2012-12-12 18:41:33 +00:00
|
|
|
#include <fc/filesystem.hpp>
|
2012-12-13 18:08:25 +00:00
|
|
|
#include <fc/sstream.hpp>
|
|
|
|
|
#include <fc/value.hpp>
|
|
|
|
|
#include <fc/json.hpp>
|
2012-12-13 18:57:49 +00:00
|
|
|
#include <boost/exception_ptr.hpp>
|
2012-12-12 17:31:21 +00:00
|
|
|
namespace fc {
|
|
|
|
|
|
|
|
|
|
error_frame::error_frame( const fc::string& f, uint64_t l, const fc::string& m, const fc::string& d, fc::value met )
|
2012-12-12 18:41:33 +00:00
|
|
|
:desc(d),file(fc::path(f).filename().generic_string()),line(l),method(m),meta(fc::move(met)){}
|
2012-12-12 17:31:21 +00:00
|
|
|
|
|
|
|
|
error_report::error_report()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
error_frame::error_frame(const fc::error_frame& e)
|
|
|
|
|
:desc(e.desc),file(e.file),line(e.line),method(e.method),time(e.time),meta(e.meta){}
|
|
|
|
|
|
|
|
|
|
error_frame::error_frame(fc::error_frame&& e)
|
|
|
|
|
:desc(fc::move(e.desc)),
|
|
|
|
|
file(fc::move(e.file)),
|
|
|
|
|
line(e.line),
|
|
|
|
|
method(fc::move(e.method)),
|
|
|
|
|
time(e.time),
|
|
|
|
|
meta(fc::move(e.meta))
|
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
fc::error_frame& fc::error_frame::operator=(const fc::error_frame& f ) {
|
|
|
|
|
auto tmp = f;
|
|
|
|
|
fc_swap( tmp, *this );
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
fc::error_frame& fc::error_frame::operator=(fc::error_frame&& e )
|
|
|
|
|
{
|
|
|
|
|
desc=fc::move(e.desc);
|
|
|
|
|
file=fc::move(e.file);
|
|
|
|
|
line=fc::move(e.line);
|
|
|
|
|
method=fc::move(e.method);
|
|
|
|
|
time=e.time;
|
|
|
|
|
meta=fc::move(e.meta);
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
error_report::error_report( const fc::string& file, uint64_t line, const fc::string& method, const fc::string& desc, fc::value meta )
|
|
|
|
|
{
|
|
|
|
|
push_frame( file, line, method, desc, meta );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fc::error_frame& error_report::current()
|
|
|
|
|
{
|
|
|
|
|
if( !stack.size() ) stack.resize(1);
|
|
|
|
|
return stack.back();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fc::error_report& error_report::pop_frame()
|
|
|
|
|
{
|
|
|
|
|
stack.pop_back();
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fc::error_report& error_report::push_frame( const fc::string& file, uint64_t line, const fc::string& method, const fc::string& desc, fc::value meta )
|
|
|
|
|
{
|
|
|
|
|
stack.push_back( fc::error_frame( file, line, method, desc, meta ) );
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fc::error_report& error_report::append( const error_report& e )
|
|
|
|
|
{
|
|
|
|
|
// TODO: what to do about the 'failure...?'
|
|
|
|
|
stack.reserve( stack.size()+e.stack.size());
|
|
|
|
|
for( uint32_t i = 0; i < e.stack.size(); ++i ) {
|
|
|
|
|
stack.push_back( e.stack[i] );
|
|
|
|
|
}
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
2012-12-13 18:08:25 +00:00
|
|
|
fc::string error_frame::to_detail_string()const {
|
|
|
|
|
fc::stringstream ss;
|
|
|
|
|
ss << to_string() << "\n\t";
|
|
|
|
|
ss << file << ":" << line << "\t"<<method;
|
|
|
|
|
if( meta ) ss << "\t" <<fc::json::to_string(*meta);
|
|
|
|
|
return ss.str();
|
|
|
|
|
}
|
|
|
|
|
fc::string error_frame::to_string()const {
|
2013-01-15 18:08:00 +00:00
|
|
|
return substitute( desc, meta ? *meta : fc::value() );
|
2013-01-15 17:05:43 +00:00
|
|
|
}
|
|
|
|
|
#if 0
|
2012-12-13 18:08:25 +00:00
|
|
|
fc::stringstream ss;
|
2012-12-18 19:37:14 +00:00
|
|
|
size_t prev = 0;
|
2012-12-13 18:08:25 +00:00
|
|
|
auto next = desc.find( '$' );
|
2012-12-18 19:37:14 +00:00
|
|
|
while( prev != size_t(fc::string::npos) && prev < size_t(desc.size()) ) {
|
2012-12-15 15:26:03 +00:00
|
|
|
// slog( "prev: %d next %d %s", prev, next, desc.substr(prev,next).c_str() );
|
2012-12-13 18:08:25 +00:00
|
|
|
// print everything from the last pos until the first '$'
|
2012-12-18 19:37:14 +00:00
|
|
|
ss << desc.substr( prev, size_t(next-prev) );
|
2012-12-13 18:08:25 +00:00
|
|
|
|
|
|
|
|
// if we got to the end, return it.
|
|
|
|
|
if( next == string::npos ) { return ss.str(); }
|
|
|
|
|
|
|
|
|
|
// if we are not at the end, then update the start
|
|
|
|
|
prev = next + 1;
|
|
|
|
|
|
|
|
|
|
if( desc[prev] == '{' ) {
|
|
|
|
|
// if the next char is a open, then find close
|
|
|
|
|
next = desc.find( '}', prev );
|
|
|
|
|
// if we found close...
|
|
|
|
|
if( next != fc::string::npos ) {
|
|
|
|
|
// the key is between prev and next
|
|
|
|
|
fc::string key = desc.substr( prev+1, (next-prev-1) );
|
2012-12-15 15:26:03 +00:00
|
|
|
//slog( "key '%s'", key.c_str() );
|
2012-12-13 18:08:25 +00:00
|
|
|
if( meta ) {
|
|
|
|
|
auto itr = meta->find( key.c_str() );
|
|
|
|
|
if( itr != meta->end() ) {
|
2012-12-20 20:39:35 +00:00
|
|
|
if( itr->val.is_string() ) {
|
|
|
|
|
ss<<itr->val.cast<fc::string>();
|
|
|
|
|
} else {
|
|
|
|
|
ss << fc::json::to_string( itr->val );
|
|
|
|
|
}
|
2012-12-13 18:08:25 +00:00
|
|
|
} else {
|
|
|
|
|
ss << "???";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
prev = next + 1;
|
|
|
|
|
// find the next $
|
|
|
|
|
next = desc.find( '$', prev );
|
|
|
|
|
} else {
|
|
|
|
|
// we didn't find it.. continue to while...
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
ss << desc[prev];
|
|
|
|
|
++prev;
|
|
|
|
|
next = desc.find( '$', prev );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return ss.str();
|
|
|
|
|
}
|
2013-01-15 17:05:43 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
fc::string substitute( const fc::string& format, const fc::value& keys ) {
|
|
|
|
|
fc::stringstream ss;
|
|
|
|
|
size_t prev = 0;
|
|
|
|
|
auto next = format.find( '$' );
|
|
|
|
|
while( prev != size_t(fc::string::npos) && prev < size_t(format.size()) ) {
|
|
|
|
|
// slog( "prev: %d next %d %s", prev, next, format.substr(prev,next).c_str() );
|
|
|
|
|
// print everything from the last pos until the first '$'
|
|
|
|
|
ss << format.substr( prev, size_t(next-prev) );
|
|
|
|
|
|
|
|
|
|
// if we got to the end, return it.
|
|
|
|
|
if( next == string::npos ) { return ss.str(); }
|
|
|
|
|
|
|
|
|
|
// if we are not at the end, then update the start
|
|
|
|
|
prev = next + 1;
|
|
|
|
|
|
|
|
|
|
if( format[prev] == '{' ) {
|
|
|
|
|
// if the next char is a open, then find close
|
|
|
|
|
next = format.find( '}', prev );
|
|
|
|
|
// if we found close...
|
|
|
|
|
if( next != fc::string::npos ) {
|
|
|
|
|
// the key is between prev and next
|
|
|
|
|
fc::string key = format.substr( prev+1, (next-prev-1) );
|
|
|
|
|
//slog( "key '%s'", key.c_str() );
|
2013-01-15 18:08:00 +00:00
|
|
|
// if( keys ) {
|
|
|
|
|
auto itr = keys.find( key.c_str() );
|
|
|
|
|
if( itr != keys.end() ) {
|
|
|
|
|
if( itr->val.is_string() ) {
|
|
|
|
|
ss<<itr->val.cast<fc::string>();
|
|
|
|
|
} else {
|
|
|
|
|
ss << fc::json::to_string( itr->val );
|
|
|
|
|
}
|
2013-01-15 17:05:43 +00:00
|
|
|
} else {
|
|
|
|
|
ss << "???";
|
|
|
|
|
}
|
2013-01-15 18:08:00 +00:00
|
|
|
// }
|
2013-01-15 17:05:43 +00:00
|
|
|
prev = next + 1;
|
|
|
|
|
// find the next $
|
|
|
|
|
next = format.find( '$', prev );
|
|
|
|
|
} else {
|
|
|
|
|
// we didn't find it.. continue to while...
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
ss << format[prev];
|
|
|
|
|
++prev;
|
|
|
|
|
next = format.find( '$', prev );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return ss.str();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2012-12-13 18:08:25 +00:00
|
|
|
fc::string error_report::to_string()const {
|
|
|
|
|
fc::stringstream ss;
|
2012-12-18 19:37:14 +00:00
|
|
|
for( uint32_t i = 0; i < stack.size(); ++i ) {
|
2012-12-13 18:08:25 +00:00
|
|
|
ss << stack[i].to_string() << "\n";
|
|
|
|
|
}
|
|
|
|
|
return ss.str();
|
|
|
|
|
}
|
|
|
|
|
fc::string error_report::to_detail_string()const {
|
|
|
|
|
fc::stringstream ss;
|
2012-12-29 17:00:19 +00:00
|
|
|
for( uint32_t i = 0; i < stack.size(); ++i ) {
|
2012-12-13 18:08:25 +00:00
|
|
|
ss << stack[i].to_detail_string() << "\n";
|
|
|
|
|
}
|
|
|
|
|
return ss.str();
|
|
|
|
|
}
|
2012-12-13 18:57:49 +00:00
|
|
|
fc::exception_ptr error_report::copy_exception() {
|
|
|
|
|
return boost::copy_exception(*this);
|
|
|
|
|
}
|
2012-12-13 18:08:25 +00:00
|
|
|
|
2012-12-12 17:31:21 +00:00
|
|
|
} // namespace fc
|