aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorEgor Tensin <Egor.Tensin@gmail.com>2020-10-14 03:10:23 +0300
committerEgor Tensin <Egor.Tensin@gmail.com>2020-10-14 03:10:23 +0300
commit8fe642b86c85ec45f27424108d7a5d6fae25fe25 (patch)
treed6ee95e995a2b8e4cd753f72056aa30d3cc73c8e
parentAppVeyor: reorder images, 2013 second (diff)
downloadwinapi-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--.gitmodules3
m---------3rdparty/winapi/utf80
-rw-r--r--CMakeLists.txt14
-rw-r--r--include/winapi/error.hpp35
-rw-r--r--src/error.cpp67
-rw-r--r--test/CMakeLists.txt2
-rw-r--r--test/error.cpp23
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()