//
// C++ Interface: %{MODULE}
//
// Description:
//
//
// Author: %{AUTHOR} <%{EMAIL}>, (C) %{YEAR}
//
// Copyright: See COPYING file that comes with this distribution
//
//
/** @file Error.h
* This header defines several types and functions relating to the
* handling of exceptions in STK.
*/
#ifndef TNET_Error_h
#define TNET_Error_h
#include <iostream>
#include <stdexcept>
#include <string>
#include <sstream>
#include <cstdlib>
#include <execinfo.h>
#include <cstdarg>
#include <cstdio>
// THESE MACROS TERRIBLY CLASH WITH STK!!!!
// WE MUST USE SAME MACROS!
//
//#define Error(msg) _Error_(__func__, __FILE__, __LINE__, msg)
//#define Warning(msg) _Warning_(__func__, __FILE__, __LINE__, msg)
//#define TraceLog(msg) _TraceLog_(__func__, __FILE__, __LINE__, msg)
//
#ifndef Error
#define Error(...) _Error_(__func__, __FILE__, __LINE__, __VA_ARGS__)
#endif
#ifndef PError
#define PError(...) _PError_(__func__, __FILE__, __LINE__, __VA_ARGS__)
#endif
#ifndef Warning
#define Warning(...) _Warning_(__func__, __FILE__, __LINE__, __VA_ARGS__)
#endif
#ifndef TraceLog
#define TraceLog(...) _TraceLog_(__func__, __FILE__, __LINE__, __VA_ARGS__)
#endif
namespace TNet {
/** MyException
* Custom exception class, gets the stacktrace
*/
class MyException
: public std::runtime_error
{
public:
explicit MyException(const std::string& what_arg) throw();
virtual ~MyException() throw();
const char* what() const throw()
{ return mWhat.c_str(); }
private:
std::string mWhat;
};
/**
* MyException:: implemenatation
*/
inline
MyException::
MyException(const std::string& what_arg) throw()
: std::runtime_error(what_arg)
{
mWhat = what_arg;
mWhat += "\nTHE STACKTRACE INSIDE MyException OBJECT IS:\n";
void *array[10];
size_t size;
char **strings;
size_t i;
size = backtrace (array, 10);
strings = backtrace_symbols (array, size);
//<< 0th string is the MyException ctor, so ignore and start by 1
for (i = 1; i < size; i++) {
mWhat += strings[i];
mWhat += "\n";
}
free (strings);
}
inline
MyException::
~MyException() throw()
{ }
/**
* @brief Error throwing function (with backtrace)
*/
inline void
_Error_(const char *func, const char *file, int line, const std::string &msg)
{
std::stringstream ss;
ss << "ERROR (" << func << ':' << file << ':' << line << ") " << msg;
throw MyException(ss.str());
}
/**
* @brief Throw a formatted error
*/
inline void _PError_(const char *func, const char *file, int line, const char *fmt, ...) {
va_list ap;
char msg[256];
va_start(ap, fmt);
vsnprintf(msg, sizeof msg, fmt, ap);
va_end(ap);
_Error_(func, file, line, msg);
}
/**
* @brief Warning handling function
*/
inline void
_Warning_(const char *func, const char *file, int line, const std::string &msg)
{
std::cout << "WARNING (" << func << ':' << file << ':' << line << ") " << msg << std::endl;
}
inline void
_TraceLog_(const char *func, const char *file, int line, const std::string &msg)
{
std::cout << "INFO (" << func << ':' << file << ':' << line << ") " << msg << std::endl;
std::cout.flush();
}
/**
* New kaldi error handling:
*
* class KaldiErrorMessage is invoked from the KALDI_ERROR macro.
* The destructor throws an exception.
*/
class KaldiErrorMessage {
public:
KaldiErrorMessage(const char *func, const char *file, int line) {
this->stream() << "ERROR ("
<< func << "():"
<< file << ':' << line << ") ";
}
inline std::ostream &stream() { return ss; }
~KaldiErrorMessage() { throw MyException(ss.str()); }
private:
std::ostringstream ss;
};
#define KALDI_ERR TNet::KaldiErrorMessage(__func__, __FILE__, __LINE__).stream()
} // namespace TNet
//#define TNET_Error_h
#endif