Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .clang-format
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ BraceWrapping:
AfterExternBlock: 'true'
BeforeCatch: 'true'

ColumnLimit: 125
ColumnLimit: 100
BreakInheritanceList: AfterColon
CompactNamespaces: 'false'
ConstructorInitializerAllOnOneLineOrOnePerLine: 'true'
Expand Down
12 changes: 9 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
/.idea
/cmake-build-debug
/.git
cmake-build-debug/
.git/
tests/
.vs/
out/
/out
/build

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe reorder this to look nicer and remove the duplicate build folder

build/
.idea/
41 changes: 37 additions & 4 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1,42 @@
cmake_minimum_required(VERSION 3.16.5)

project(PeachLibrary)
project(peach_library
VERSION 0.1
LANGUAGES CXX
)

set(CMAKE_CXX_STANDARD 20)
option(COMPONENT_TARGETS_ENABLED "enable individual config targets" YES)

add_library(PeachLibrary STATIC pe_exceptions/pe_exception.cpp)
add_subdirectory(exceptions)

set_target_properties(PeachLibrary PROPERTIES LINKER_LANGUAGE CXX)
include(CMakePackageConfigHelpers)

# generate the version file for the config file
write_basic_package_version_file(
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake
VERSION ${PROJECT_VERSION}
COMPATIBILITY SameMajorVersion
)

# create config file
configure_package_config_file(
config.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config.cmake
INSTALL_DESTINATION lib/cmake/${PROJECT_NAME}
NO_CHECK_REQUIRED_COMPONENTS_MACRO
)

# generate the export targets for the build tree.
# Note: The file created by this command is specific to the build
# tree and should never be installed!
export(
EXPORT ${PROJECT_NAME}-targets
FILE ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-targets.cmake
NAMESPACE ${PROJECT_NAME}::
)

# install cmake project config files
install(
FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config.cmake
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake
DESTINATION lib/cmake/${PROJECT_NAME}
)
15 changes: 15 additions & 0 deletions CMakeSettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"configurations": [
{
"name": "x64-Clang-Debug",
"generator": "Ninja",
"configurationType": "Debug",
"buildRoot": "${projectDir}\\out\\build\\${name}",
"installRoot": "${projectDir}\\out\\install\\${name}",
"cmakeCommandArgs": "",
"buildCommandArgs": "",
"ctestCommandArgs": "",
"inheritEnvironments": [ "msvc_x64_x64" ]

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Im pretty sure these files should be hidden?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would suggest to either remove this file from git or make is obvious that it is a IDE dependent file.

}
]
}
15 changes: 15 additions & 0 deletions config.cmake.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
@PACKAGE_INIT@

if(@COMPONENT_TARGETS_ENABLED@)
set(_supported_components exceptions)

foreach(_comp ${peach_library_FIND_COMPONENTS})
if(NOT _comp IN_LIST _supported_components)
set(peach_library_FOUND False)
set(peach_library_NOT_FOUND_MESSAGE "Unsupported component: ${_comp}")
endif()
include("${CMAKE_CURRENT_LIST_DIR}/peach_library-${_comp}-targets.cmake")
endforeach()
else()
include("${CMAKE_CURRENT_LIST_DIR}/peach_library-targets.cmake")
endif()
36 changes: 36 additions & 0 deletions exceptions/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
set(component exceptions)

add_library(${component} STATIC src/exception.cpp)

target_compile_features(${component} PRIVATE cxx_std_20)

target_include_directories(${component} PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
)

install(
TARGETS ${component}
EXPORT ${PROJECT_NAME}-targets
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
RUNTIME DESTINATION bin
INCLUDES DESTINATION include
)

if(COMPONENT_TARGETS_ENABLED)
# generate and install export file for this component target
install(
EXPORT ${PROJECT_NAME}-targets
FILE ${PROJECT_NAME}-${component}-targets.cmake
NAMESPACE ${PROJECT_NAME}::
DESTINATION lib/cmake/${PROJECT_NAME}
)
endif()

# install header files
install(
DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/
TYPE INCLUDE
FILES_MATCHING
PATTERN "*.hpp"
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#ifndef PEACH_BASE_EXCEPTION_HPP
#define PEACH_BASE_EXCEPTION_HPP

#include <concepts>
#include <fstream>
#include <ostream>
#include <stdexcept>
#include <string>
#include <string_view>

namespace peach::detail
{
class BaseException : virtual public std::runtime_error
{
public:
BaseException( ) = default;

// clang-format off
BaseException( const BaseException& ) noexcept = default;
BaseException(BaseException&& ) noexcept = default;

BaseException& operator=(BaseException&& ) = default;
BaseException& operator=( const BaseException& ) = delete;
// clang-format on

virtual const std::string& what_str( ) const noexcept = 0;
virtual void print_to_console( ) const noexcept = 0;

virtual ~BaseException( ) { };
};

template< typename T >
std::ostream& operator<<( std::ostream& output_file,
const T& rhs ) requires( std::derived_from< T, BaseException > )
{
output_file << rhs.what_str( );

return output_file;
}

} // namespace peach::detail

#endif // PEACH_BASE_EXCEPTION_HPP
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#ifndef PEACH_PREFIX_MANAGER_HPP
#define PEACH_PREFIX_MANAGER_HPP

#include <string>

namespace peach
{
enum class ExceptionTypes;

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the ::detail part was removed in this file, this code can now be moved into the same scope as the rest

} // namespace peach

namespace peach
{

// Short info:
// * Provides general way to set default prefix
// Link docu:
class PrefixManager

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Creating instances of this does not really make any sense. So either the constructor should be protected (for inheritance to work), or we replace the class with a namespace that stores the default prefix (preferred by me).

{
public:
PrefixManager( ) noexcept = default;

PrefixManager( const PrefixManager& ) noexcept = delete;
PrefixManager( PrefixManager&& ) noexcept = delete;

PrefixManager& operator=( PrefixManager&& ) = delete;
PrefixManager& operator=( const PrefixManager& ) = delete;

// clang-format off
static void set_default_prefix( const std::string& prefix ) noexcept
{
m_default_prefix = prefix;
}
// clang-format on

inline static std::string m_default_prefix = { "LOG" };

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this might be protected


~PrefixManager( ) noexcept = default;
};

// Short info:
// * Defines and manages a prefix for each specific ExceptionType
// Link docu:
template< ExceptionTypes V > class Prefix : private PrefixManager
{
public:
static Prefix& get( ) noexcept
{
static Prefix< V > instance { };
return instance;
}

Prefix( ) noexcept = default;

Prefix( const Prefix& ) noexcept = delete;
Prefix( Prefix&& ) noexcept = delete;

Prefix& operator=( Prefix&& ) = delete;
Prefix& operator=( const Prefix& ) = delete;

// clang-format off
void set_prefix( const std::string& prefix ) noexcept
{
m_prefix = prefix;
}

std::string get_prefix( ) const noexcept
{
if ( m_prefix.empty( ) )
return m_default_prefix;

return m_prefix;
}
// clang-format on

std::string m_prefix;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be private.


~Prefix( ) noexcept = default;
};

} // namespace peach

#endif // PEACH_PREFIX_MANAGER_HPP
84 changes: 84 additions & 0 deletions exceptions/include/peach_library/exceptions/exception.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
#ifndef PEACH_EXCEPTION_HPP
#define PEACH_EXCEPTION_HPP

#include "core/base_exception.hpp"
#include "core/prefix_manager.hpp"

#include "utils/exception_constants.hpp"
#include "utils/exception_format.hpp"

#include <iostream>
#include <source_location>
#include <stdexcept>
#include <string>
#include <type_traits>
#include <utility>

namespace peach
{
// Short info:
// * This has to be explicitly defined by the user inside the peach namespace
// Link docu:
enum class ExceptionTypes;

// Short info:
// * The method what() isnt templated in the base class, so we cannot override what()
// * First ctor handles the case when std::source_location information is wanted, second does it without
// Link docu:
template< ExceptionTypes Val > class PeachException : virtual public detail::BaseException

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see no need to use virtual inheritance here.

{
public:
template< typename... Tys >
explicit PeachException( const std::source_location sl, Tys&&... args )
: std::runtime_error { detail::format_error( sl.line( ), sl.file_name( ),
Prefix< Val >::get( ).get_prefix( ),
std::forward< Tys >( args )... ) }

{
m_err_msg = this->what( );

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are we sure this is legal?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this should be fine, as we do not overwrite what() and at this point the base std::runtime_error is fully constructed.
You should be able to omit the this->:

Suggested change
m_err_msg = this->what( );
m_err_msg = what( );

m_prefix = Prefix< Val >::get( ).get_prefix( );
}

template< typename... Tys >
explicit PeachException( Tys&&... args )
: std::runtime_error { detail::format_error( detail::constants::kNoSourceLocation, "",
Comment thread
joren-dev marked this conversation as resolved.
Prefix< Val >::get( ).get_prefix( ),
std::forward< Tys >( args )... ) }
{
m_err_msg = this->what( );
m_prefix = Prefix< Val >::get( ).get_prefix( );
}

PeachException( const PeachException& ) noexcept = default;
PeachException( PeachException&& ) noexcept = default;

PeachException& operator=( PeachException&& ) = delete;
PeachException& operator=( const PeachException& ) = delete;

void print_to_console( ) const noexcept
{
// TODO: possibly determine if compiled application has a console available!
std::cerr << m_prefix << R"(( " )" << m_err_msg.substr( 0, m_err_msg.size( ) - 2 )
<< R"( " ))" << '\n';
}
Comment on lines +58 to +63

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would actually want to get rid of this, they can already get this precise message in a string, the user can just std::cout or print however the user seems fit, saves us a lot of trouble ensuring the constraints for this method


const std::string& what_str( ) const noexcept { return m_err_msg; }

~PeachException( ) = default;

private:
std::string m_err_msg;
std::string m_prefix;
};

namespace detail
{
std::source_location
get_source_location_details( const std::source_location sl = std::source_location::current()) noexcept;
} // namespace detail

#define SL detail::get_source_location_details( )

} // namespace peach

#endif // PEACH_EXCEPTION_HPP
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#ifndef PEACH_EXCEPTION_CONSTANTS_HPP
#define PEACH_EXCEPTION_CONSTANTS_HPP

namespace peach::detail::constants
{
constexpr int kNoSourceLocation { -1 };

} // namespace peach::detail::constants

#endif // PEACH_EXCEPTION_CONSTANTS_HPP
Loading