Begin work on #8 - Add exception class with backtrace support
Additionally: - Separate src and header files
This commit is contained in:
parent
23226526e3
commit
add045c405
2
.gitignore
vendored
2
.gitignore
vendored
@ -52,3 +52,5 @@ debug/*
|
||||
release/*
|
||||
.cache/*
|
||||
.DS_Store
|
||||
|
||||
*debug/
|
||||
|
@ -112,9 +112,11 @@ set_target_properties(
|
||||
CHECK_INCLUDE_FILE("execinfo.h" HAVE_EXECINFO_H)
|
||||
|
||||
if (HAVE_EXECINFO_H)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DHAVE_EXECINFO_H")
|
||||
add_definitions(-DHAVE_EXECINFO_H=1)
|
||||
endif()
|
||||
|
||||
include_directories(${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/include)
|
||||
|
||||
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/artifacts/lib)
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/artifacts/lib)
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/artifacts/bin)
|
||||
|
27
include/debuginfo.hpp
Normal file
27
include/debuginfo.hpp
Normal file
@ -0,0 +1,27 @@
|
||||
/* debuginfo.h
|
||||
* Copyright © 2020-2023 Saul D. Beniquez
|
||||
* License: Mozilla Public License v. 2.0
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#ifdef QW_DEBUG // #region
|
||||
#include <iostream>
|
||||
#define debugprint(msg) std::cout << "#*!* " << msg << std::endl
|
||||
#else
|
||||
#define debugprint(msg) ;
|
||||
#endif // #endregion
|
||||
|
||||
std::string generate_stacktrace(unsigned short framesToRemove = 1);
|
||||
|
||||
void print_cmdline(int argc, const char* argv[]);
|
||||
|
||||
// clang-format off
|
||||
// vim: set foldmethod=marker foldmarker=#region,#endregion textwidth=80 ts=8 sts=0 sw=8 noexpandtab ft=cpp.doxygen :
|
||||
|
43
include/exception.hpp
Normal file
43
include/exception.hpp
Normal file
@ -0,0 +1,43 @@
|
||||
/* exceptions.hpp
|
||||
* Copyright © 2020 Saul D. Beniquez
|
||||
* License: Mozilla Public License v. 2.0
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "debuginfo.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <exception>
|
||||
#include <optional>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
#define NOT_IMPLEMENTED std::runtime_error("Unimplemented Method");
|
||||
|
||||
#define THROW_EXCEPTION(message) \
|
||||
throw mdml::exception(message, generate_stacktrace(2))
|
||||
|
||||
namespace mdml {
|
||||
class exception : public std::exception {
|
||||
public:
|
||||
exception(
|
||||
const std::optional<std::exception> innerException = std::nullopt,
|
||||
const std::optional<std::string> backtrace = std::nullopt
|
||||
);
|
||||
const char* what() const noexcept override;
|
||||
|
||||
const char* getStacktrace() const noexcept;
|
||||
|
||||
private:
|
||||
std::optional<std::string> stacktrace;
|
||||
std::optional<std::exception> innerException;
|
||||
};
|
||||
}
|
||||
// clang-format off
|
||||
// vim: set foldmethod=marker foldmarker=@{,@} textwidth=80 ts=8 sts=0 sw=8 noexpandtab ft=cpp.doxygen :
|
@ -1,5 +1,5 @@
|
||||
|
||||
set(LIBMDML_SOURCES libmdml.cpp)
|
||||
set(LIBMDML_SOURCES libmdml.cpp exception.cpp debuginfo.cpp)
|
||||
|
||||
|
||||
add_library(mdml SHARED ${LIBMDML_SOURCES})
|
||||
|
54
src/debuginfo.cpp
Normal file
54
src/debuginfo.cpp
Normal file
@ -0,0 +1,54 @@
|
||||
/* debuginfo.h
|
||||
* Copyright © 2020-2023 Saul D. Beniquez
|
||||
* License: Mozilla Public License v. 2.0
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include "debuginfo.hpp"
|
||||
|
||||
#ifdef HAVE_EXECINFO_H
|
||||
#include <execinfo.h>
|
||||
#else
|
||||
#include <boost/stacktrace.hpp>
|
||||
#endif
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
std::string
|
||||
generate_stacktrace(unsigned short framesToRemove)
|
||||
{
|
||||
std::stringstream buffer;
|
||||
#ifdef HAVE_EXECINFO_H
|
||||
void* callstack[128];
|
||||
|
||||
int i, frames = backtrace(callstack, 128);
|
||||
char** strs = backtrace_symbols(callstack, frames);
|
||||
for (i = framesToRemove; i < frames; ++i) {
|
||||
buffer << strs[i] << std::endl;
|
||||
}
|
||||
free(strs);
|
||||
#else
|
||||
buffer << boost::stacktrace::stacktrace() << std::flush;
|
||||
#endif
|
||||
return buffer.str();
|
||||
}
|
||||
|
||||
void
|
||||
print_cmdline(int argc, const char* argv[])
|
||||
{
|
||||
int i;
|
||||
|
||||
std::cout << "Command-line received" << std::endl;
|
||||
for (i = 0; i < argc; ++i)
|
||||
std::cout << argv[i] << " ";
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
// vim: set foldmethod=marker foldmarker=#region,#endregion textwidth=80 ts=8 sts=0 sw=8 noexpandtab ft=cpp.doxygen :
|
||||
|
54
src/exception.cpp
Normal file
54
src/exception.cpp
Normal file
@ -0,0 +1,54 @@
|
||||
/* exceptions.hpp
|
||||
* Copyright © 2020 Saul D. Beniquez
|
||||
* License: Mozilla Public License v. 2.0
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include "debuginfo.hpp"
|
||||
#include "exception.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <exception>
|
||||
#include <optional>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
#define NOT_IMPLEMENTED std::runtime_error("Unimplemented Method");
|
||||
|
||||
using mdml::exception;
|
||||
|
||||
exception::exception(
|
||||
const std::optional<std::exception> innerException,
|
||||
const std::optional<std::string> backtrace
|
||||
)
|
||||
: std::exception(), stacktrace(std::nullopt), innerException(std::nullopt)
|
||||
{
|
||||
if (!backtrace.has_value()) {
|
||||
this->stacktrace = generate_stacktrace(2);
|
||||
} else {
|
||||
this->stacktrace = backtrace;
|
||||
}
|
||||
|
||||
if (innerException.has_value()) {
|
||||
this->innerException = *(innerException);
|
||||
}
|
||||
}
|
||||
|
||||
const char*
|
||||
exception::what() const noexcept
|
||||
{
|
||||
return innerException->what();
|
||||
}
|
||||
|
||||
const char*
|
||||
exception::getStacktrace() const noexcept
|
||||
{
|
||||
return stacktrace->c_str();
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
// vim: set foldmethod=marker foldmarker=@{,@} textwidth=80 ts=8 sts=0 sw=8 noexpandtab ft=cpp.doxygen :
|
@ -1,62 +0,0 @@
|
||||
/* exceptions.hpp
|
||||
* Copyright © 2020 Saul D. Beniquez
|
||||
* License: Mozilla Public License v. 2.0
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <exception>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
#define NOT_IMPLEMENTED std::runtime_error("Unimplemented Method");
|
||||
|
||||
namespace mdml {
|
||||
class exception : public std::exception {
|
||||
public:
|
||||
exception(
|
||||
const std::exception& innerException, const std::string& backtrace
|
||||
)
|
||||
: std::exception(innerException)
|
||||
, innerException(innerException)
|
||||
, stacktrace(backtrace)
|
||||
{
|
||||
}
|
||||
|
||||
const char* what() override { return innerException.what(); }
|
||||
|
||||
const char* getStacktrace() const noexcept { return stacktrace.c_str(); }
|
||||
|
||||
private:
|
||||
inline std::string generate_stacktrace()
|
||||
{
|
||||
std::stringstream buffer;
|
||||
#ifdef HAVE_EXECINFO_H
|
||||
void* callstack[128];
|
||||
|
||||
int i, frames = backtrace(callstack, 128);
|
||||
char** strs = backtrace_symbols(callstack, frames);
|
||||
for (i = 0; i < frames; ++i) {
|
||||
buffer << strs[i] << std::endl;
|
||||
}
|
||||
free(strs);
|
||||
#else
|
||||
buffer << boost::stacktrace::stacktrace() << std::flush;
|
||||
#endif
|
||||
return buffer.str();
|
||||
}
|
||||
|
||||
std::string stacktrace;
|
||||
std::exception innerException;
|
||||
};
|
||||
}
|
||||
// Macro to throw an exception with a generated stack trace
|
||||
#define THROW_EXCEPTION(message) \
|
||||
throw QWException(message, generate_stacktrace())
|
||||
|
||||
// clang-format off
|
||||
// vim: set foldmethod=marker foldmarker=#region,#endregion textwidth=80 ts=8 sts=0 sw=8 noexpandtab ft=cpp.doxygen :
|
@ -1,4 +1,4 @@
|
||||
/* libmdml.cpp
|
||||
/* libmdml.hpp
|
||||
* Copyright © 2023 Saul D. Beniquez
|
||||
* License: Mozilla Public License v. 2.0
|
||||
*
|
||||
@ -7,10 +7,9 @@
|
||||
* obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
|
||||
void print_hello() {
|
||||
std::cout << "Hello World" << std::endl;
|
||||
void
|
||||
some_function()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -7,16 +7,30 @@
|
||||
* obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include "exception.hpp"
|
||||
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <iostream>
|
||||
|
||||
#define TEST(testname) TEST_CASE(testname, TEST_SUITE_NAME)
|
||||
|
||||
namespace {
|
||||
const char* TEST_SUITE_NAME = "mdml::exceptions";
|
||||
const char* TEST_SUITE_NAME = "mdml::exceptions";
|
||||
|
||||
// @todo: move this to a runtime-test.cpp file
|
||||
TEST("Test the test framework")
|
||||
{
|
||||
REQUIRE_THROWS(
|
||||
[]() { throw std::runtime_error("Error Message"); }(),
|
||||
"Expected Error Message"
|
||||
);
|
||||
|
||||
try {
|
||||
throw mdml::exception(std::runtime_error("NOT IMPLEMENTED"));
|
||||
} catch (mdml::exception& e) {
|
||||
std::cout << e.what() << std::endl;
|
||||
}
|
||||
|
||||
} // #endregion
|
||||
|
||||
// @todo: move this to a runtime-test.cpp file
|
||||
TEST("Test the test framework")
|
||||
{
|
||||
REQUIRE( true == true );
|
||||
} // #endregion
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user