diff options
author | Egor Tensin <Egor.Tensin@gmail.com> | 2020-10-14 03:10:23 +0300 |
---|---|---|
committer | Egor Tensin <Egor.Tensin@gmail.com> | 2020-10-14 03:10:23 +0300 |
commit | 8fe642b86c85ec45f27424108d7a5d6fae25fe25 (patch) | |
tree | d6ee95e995a2b8e4cd753f72056aa30d3cc73c8e | |
parent | AppVeyor: reorder images, 2013 second (diff) | |
download | winapi-common-8fe642b86c85ec45f27424108d7a5d6fae25fe25.tar.gz winapi-common-8fe642b86c85ec45f27424108d7a5d6fae25fe25.zip |
add error-handling functions
They are almost exact copies from my pdb-repo project at
https://github.com/egor-tensin/pdb-repo/tree/fa2afec5e7af45e7f1440b2d32c2a4e63dad6a62
I'm currently thinking about renaming it to winapi-debug BTW.
-rw-r--r-- | .gitmodules | 3 | ||||
m--------- | 3rdparty/winapi/utf8 | 0 | ||||
-rw-r--r-- | CMakeLists.txt | 14 | ||||
-rw-r--r-- | include/winapi/error.hpp | 35 | ||||
-rw-r--r-- | src/error.cpp | 67 | ||||
-rw-r--r-- | test/CMakeLists.txt | 2 | ||||
-rw-r--r-- | test/error.cpp | 23 |
7 files changed, 139 insertions, 5 deletions
diff --git a/.gitmodules b/.gitmodules index d65ecb9..9ea0616 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "cmake"] path = cmake url = https://github.com/egor-tensin/cmake-common.git +[submodule "3rdparty/winapi/utf8"] + path = 3rdparty/winapi/utf8 + url = https://github.com/egor-tensin/winapi-utf8.git diff --git a/3rdparty/winapi/utf8 b/3rdparty/winapi/utf8 new file mode 160000 +Subproject c84f4ae675396ab5443ec01a21eefc1fdd870d3 diff --git a/CMakeLists.txt b/CMakeLists.txt index 4ffa5a5..d1f8a37 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,12 +4,18 @@ project(winapi_common CXX) include(cmake/common.cmake) -find_package(Boost REQUIRED) +file(GLOB_RECURSE winapi_common_include "include/*.hpp") +file(GLOB winapi_common_src "src/*.cpp") +add_library(winapi_common ${winapi_common_include} ${winapi_common_src}) +target_include_directories(winapi_common PUBLIC include/) + +add_subdirectory(3rdparty/winapi/utf8) +target_link_libraries(winapi_common PRIVATE winapi_utf8) -add_library(winapi_common INTERFACE) -target_include_directories(winapi_common INTERFACE include/) -target_link_libraries(winapi_common INTERFACE Boost::disable_autolinking Boost::boost) +find_package(Boost REQUIRED) +target_link_libraries(winapi_common PUBLIC Boost::boost) +install(TARGETS winapi_common ARCHIVE DESTINATION lib) install(DIRECTORY include/winapi DESTINATION include) if(WINAPI_COMMON_TESTS) diff --git a/include/winapi/error.hpp b/include/winapi/error.hpp new file mode 100644 index 0000000..4b3f1e0 --- /dev/null +++ b/include/winapi/error.hpp @@ -0,0 +1,35 @@ +// Copyright (c) 2020 Egor Tensin <Egor.Tensin@gmail.com> +// This file is part of the "winapi-common" project. +// For details, see https://github.com/egor-tensin/winapi-common. +// Distributed under the MIT License. + +#pragma once + +#include <boost/config.hpp> + +#include <windows.h> + +#include <string> +#include <system_error> + +namespace winapi { +namespace error { + +class CategoryWindows : public std::error_category { +public: + CategoryWindows() = default; + + const char* name() const BOOST_NOEXCEPT_OR_NOTHROW { return "Windows"; } + + std::string message(int) const; +}; + +inline const CategoryWindows& category_windows() { + static const CategoryWindows instance; + return instance; +} + +std::system_error windows(DWORD code, const char* function); + +} // namespace error +} // namespace winapi diff --git a/src/error.cpp b/src/error.cpp new file mode 100644 index 0000000..ff755b6 --- /dev/null +++ b/src/error.cpp @@ -0,0 +1,67 @@ +// Copyright (c) 2020 Egor Tensin <Egor.Tensin@gmail.com> +// This file is part of the "winapi-common" project. +// For details, see https://github.com/egor-tensin/winapi-common. +// Distributed under the MIT License. + +#include <winapi/error.hpp> +#include <winapi/utf8.hpp> + +#include <windows.h> + +#include <sstream> +#include <string> +#include <system_error> + +namespace winapi { +namespace error { +namespace { + +std::wstring trim_trailing_newline(const std::wstring& s) { + const auto last_pos = s.find_last_not_of(L"\r\n"); + if (std::wstring::npos == last_pos) + return {}; + return s.substr(0, last_pos + 1); +} + +std::string build_what(DWORD code, const char* function) { + std::ostringstream what; + what << "Function " << function << " failed with error code " << code; + return what.str(); +} + +std::string format_message(int code) { + wchar_t* buf; + + const auto len = ::FormatMessageW( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + code, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + reinterpret_cast<wchar_t*>(&buf), + 0, + NULL); + + if (0 == len) { + ::LocalFree(buf); + return "Couldn't format the error message"; + } + + std::wstring msg{buf, len}; + ::LocalFree(buf); + return narrow(trim_trailing_newline(msg)); +} + +} // namespace + +std::string CategoryWindows::message(int code) const { + return format_message(code); +} + +std::system_error windows(DWORD code, const char* function) { + static_assert(sizeof(DWORD) == sizeof(int), "Aren't DWORDs the same size as ints?"); + return std::system_error{ + static_cast<int>(code), category_windows(), build_what(code, function)}; +} + +} // namespace error +} // namespace winapi diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 3c23426..4c09bcd 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,6 +1,6 @@ find_package(Boost REQUIRED COMPONENTS unit_test_framework) -add_executable(unit_tests main.cpp handle.cpp) +add_executable(unit_tests main.cpp error.cpp handle.cpp) target_link_libraries(unit_tests PRIVATE winapi_common) target_link_libraries(unit_tests PRIVATE Boost::disable_autolinking Boost::unit_test_framework) set_target_properties(unit_tests PROPERTIES OUTPUT_NAME winapi-common-unit-tests) diff --git a/test/error.cpp b/test/error.cpp new file mode 100644 index 0000000..f70d95d --- /dev/null +++ b/test/error.cpp @@ -0,0 +1,23 @@ +// Copyright (c) 2020 Egor Tensin <Egor.Tensin@gmail.com> +// This file is part of the "winapi-common" project. +// For details, see https://github.com/egor-tensin/winapi-common. +// Distributed under the MIT License. + +#include <winapi/error.hpp> + +#include <boost/test/unit_test.hpp> + +#include <windows.h> + +#include <string> + +BOOST_AUTO_TEST_SUITE(error_tests) + +BOOST_AUTO_TEST_CASE(file_not_found) { + const std::string actual{winapi::error::windows(ERROR_FILE_NOT_FOUND, "CreateFileW").what()}; + BOOST_TEST(actual == + "Function CreateFileW failed with error code 2: The system cannot find the file " + "specified."); +} + +BOOST_AUTO_TEST_SUITE_END() |