Skip to content

Commit

Permalink
ThrowableEx inherits from Throwable
Browse files Browse the repository at this point in the history
  • Loading branch information
Dan Smith committed Dec 28, 2022
1 parent 25eb3cf commit ea7d65a
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 211 deletions.
123 changes: 13 additions & 110 deletions modules/c++/except/include/except/Throwable.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ class CODA_OSS_API Throwable
void doGetBacktrace();
template<typename TThrowable>
Throwable(const Context*, const TThrowable* pT, const std::string* pMessage, bool callGetBacktrace, std::nullptr_t);
protected:
Throwable(const Context*, const Throwable* pT = nullptr, const std::string* pMessage = nullptr, bool callGetBacktrace = false);
Throwable(const Context*, const ThrowableEx* pT, const std::string* pMessage = nullptr, bool callGetBacktrace = false);

Expand Down Expand Up @@ -226,24 +227,12 @@ class CODA_OSS_API Throwable
* break existing code as "catch (const std::exception&)" will catch
* except::Throwable when it didn't before.
*/
class ThrowableEx : public std::exception // "ThrowableEx" = "Throwable exception"
// Use multiple-inheritance :-( to reduce duplicated boilerplate code.
class ThrowableEx : public Throwable // "ThrowableEx" = "Throwable exception"
#if !CODA_OSS_except_Throwable_ISA_std_exception
, public std::exception
#endif
{
void doGetBacktrace();
template <typename TThrowable>
ThrowableEx(const Context*,
const TThrowable* pT,
const std::string* pMessage,
bool callGetBacktrace,
std::nullptr_t);
ThrowableEx(const Context*,
const ThrowableEx* pT = nullptr,
const std::string* pMessage = nullptr,
bool callGetBacktrace = false);
ThrowableEx(const Context*,
const Throwable* pT,
const std::string* pMessage = nullptr,
bool callGetBacktrace = false);

public:
ThrowableEx() = default;
virtual ~ThrowableEx() = default;
Expand All @@ -252,119 +241,33 @@ class ThrowableEx : public std::exception // "ThrowableEx" = "Throwable exceptio
ThrowableEx(ThrowableEx&&) = default;
ThrowableEx& operator=(ThrowableEx&&) = default;

ThrowableEx(const Throwable&);
ThrowableEx(const Throwable& t) : Throwable(t){}

/*!
* Constructor. Takes a message
* \param message The message
*/
ThrowableEx(const std::string& message);
ThrowableEx(const std::string& message) : Throwable(message) {}

/*!
* Constructor. Takes a Context.
* \param c The Context
*/
ThrowableEx(const Context&);
ThrowableEx(const Context& ctx) : Throwable(ctx) {}

/*!
* Constructor. Takes a Throwable and a Context
* \param t The throwable
* \param c The Context
*/
ThrowableEx(const ThrowableEx&, const Context&);
ThrowableEx(const Throwable&, const Context&);

/*!
* Get the message
* \return The message
*/
std::string getMessage() const
{
return mMessage;
}

/*!
* Get the trace
* \return The trace (const)
*/
const Trace& getTrace() const noexcept
{
return mTrace;
}

/*!
* Get the trace
* \return The trace (non-const)
*/
Trace& getTrace() noexcept
{
return mTrace;
}

/*!
* Get the type id
* \return The type
*/
virtual std::string getType() const noexcept
{
return "ThrowableEx";
}

virtual std::string toString() const
{
std::ostringstream s;
s << getType() << ": " << getMessage();

const Trace& t = getTrace();
if (t.getSize() > 0)
s << ": " << t;
return s.str();
}

const std::vector<std::string>& getBacktrace() const noexcept
{
return mBacktrace;
}

// It seems that overloading constructors creates ambiguities ... so allow
// for a "fluent" way of doing this.: throw Exception(...).backtrace()
ThrowableEx& backtrace()
{
doGetBacktrace();
return *this;
}

virtual std::string toString(bool includeBacktrace) const
{
// Adding the backtrace to existing toString() output could substantally
// alter existing strings.
std::string backtrace;
if (includeBacktrace)
{
backtrace = "***** getBacktrace() *****\n";
backtrace += std::accumulate(mBacktrace.begin(),
mBacktrace.end(),
std::string());
}
return toString() + backtrace;
}
ThrowableEx(const ThrowableEx& t, const Context& ctx) : Throwable(t, ctx) {}
ThrowableEx(const Throwable& t, const Context& ctx) : Throwable(t, ctx) {}

const char* what() const noexcept final // derived classes override toString()
{
// adding this to toString() output could (significantly) alter existing display
mWhat = toString(true /*includeBacktrace*/); // call any derived toString()
return mWhat.c_str();
const Throwable* pThrowable = this;
return pThrowable->what();
}

protected:
//! The name of exception trace
Trace mTrace;
//! The name of the message the exception was thrown
std::string mMessage;

private:
mutable std::string mWhat;
std::vector<std::string> mBacktrace;
};
using Throwable11 = ThrowableEx; // keep old name around for other projects
}
Expand Down
92 changes: 0 additions & 92 deletions modules/c++/except/source/Throwable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,95 +98,3 @@ except::Throwable::Throwable(const except::ThrowableEx& t, except::Context c) :
except::Throwable::Throwable(const except::ThrowableEx& t) : Throwable(nullptr, &t)
{
}

//******************************************************************************

void except::ThrowableEx::doGetBacktrace()
{
// This could be time-consuming or generate a lot of (noisy) output; only do
// it if requested
bool supported;
(void)except::getBacktrace(supported, mBacktrace);
}

template <typename TThrowable>
except::ThrowableEx::ThrowableEx(const Context* pContext,
const TThrowable* pThrowable,
const std::string* pMessage,
bool callGetBacktrace,
std::nullptr_t)
{
if (pThrowable != nullptr)
{
// Copy t's exception stack and push c onto local one
mTrace = pThrowable->getTrace();
}

if (pContext != nullptr)
{
assert(pMessage == nullptr);

// Push context onto exception stack
mTrace.pushContext(*pContext);

// Assign c's message as our internal one
mMessage = pContext->getMessage();
}

if (pMessage != nullptr)
{
assert(pContext == nullptr);
mMessage = *pMessage;
}

// This will record a back-trace from where the Throwable object was
// instantiated. That's not necessarily where the "throw" will occur, but
// it's often the case; Throwable instances ususally aren't passed around.
// That is, hardly anybody does:
// Exception e; // Throwable instance
// might_throw(e);
// rather, the idiom is usually
// throw Exception(...); // instantiate and throw
if (callGetBacktrace)
{
doGetBacktrace();
}
}
except::ThrowableEx::ThrowableEx(const Context* pContext,
const ThrowableEx* pThrowable,
const std::string* pMessage,
bool callGetBacktrace) :
ThrowableEx(pContext, pThrowable, pMessage, callGetBacktrace, nullptr)
{
}
except::ThrowableEx::ThrowableEx(const Context* pContext,
const Throwable* pThrowable,
const std::string* pMessage,
bool callGetBacktrace) :
ThrowableEx(pContext, pThrowable, pMessage, callGetBacktrace, nullptr)
{
}

except::ThrowableEx::ThrowableEx(const std::string& message) :
ThrowableEx(nullptr, static_cast<const ThrowableEx*>(nullptr), &message)
{
}

except::ThrowableEx::ThrowableEx(const except::Context& c) : ThrowableEx(&c)
{
}

except::ThrowableEx::ThrowableEx(const except::ThrowableEx& t,
const except::Context& c) :
ThrowableEx(&c, &t)
{
}
except::ThrowableEx::ThrowableEx(const except::Throwable& t,
const except::Context& c) :
ThrowableEx(&c, &t)
{
}
except::ThrowableEx::ThrowableEx(const except::Throwable& t) :
ThrowableEx(nullptr, &t)
{
}
11 changes: 2 additions & 9 deletions modules/c++/include/TestCase.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,10 +139,6 @@ inline void specific_exception(TFunc f,
{
diePrintf(format, testName, file, func, line);
}
catch (const except::ThrowableEx&)
{
diePrintf(format, testName, file, func, line);
}
}

template <typename TFunc>
Expand Down Expand Up @@ -173,9 +169,7 @@ inline int main(TFunc f)

#define CODA_OSS_TEST_CHECK_catch_diePrintf_(X, name_) \
catch(const name_& ex) { test::diePrintf("%s: FAILED: Exception thrown: %s\n", #X, ex.what()); }
#define CODA_OSS_TEST_CHECK_catch_(X) \
CODA_OSS_TEST_CHECK_catch_diePrintf_(X, except::Throwable) \
CODA_OSS_TEST_CHECK_catch_diePrintf_(X, except::ThrowableEx)
#define CODA_OSS_TEST_CHECK_catch_(X) CODA_OSS_TEST_CHECK_catch_diePrintf_(X, except::Throwable)
#define TEST_CHECK(X) try{ X(std::string(#X)); std::cerr << #X << ": PASSED\n"; } CODA_OSS_TEST_CHECK_catch_(X)

#define TEST_ASSERT_NULL(X) if ((X) != nullptr) { test_diePrintf0("%s (%s,%s,%d): FAILED: Value should be NULL\n"); }
Expand All @@ -191,8 +185,7 @@ inline int main(TFunc f)
#define TEST_ASSERT_ALMOST_EQ_EPS(X1, X2, EPS) test::assert_almost_eq_eps(X1, X2, EPS, testName, __FILE__, SYS_FUNC, __LINE__)
#define TEST_ASSERT_ALMOST_EQ(X1, X2) TEST_ASSERT_ALMOST_EQ_EPS(X1, X2, std::numeric_limits<float>::epsilon())

#define CODA_OSS_TEST_EXCEPTION_catch_ \
catch (const except::Throwable&){} catch (const except::ThrowableEx&){}
#define CODA_OSS_TEST_EXCEPTION_catch_ catch (const except::Throwable&){}
#define TEST_EXCEPTION(X) try{ (X); test_diePrintf0("%s (%s,%s,%d): FAILED: Should have thrown exception\n"); } \
CODA_OSS_TEST_EXCEPTION_catch_
#define TEST_THROWS(X) try{ (X); test_diePrintf0("%s (%s,%s,%d): FAILED: Should have thrown exception\n"); } catch (...){}
Expand Down

0 comments on commit ea7d65a

Please sign in to comment.