From 01c28816a2ed24fc9feafcf6a63121be8311fa32 Mon Sep 17 00:00:00 2001 From: mutouyun Date: Sat, 13 Aug 2022 18:02:25 +0800 Subject: [PATCH] add: [system] add features --- include/libimp/system.h | 30 +++++++++++ src/libimp/platform/posix/system.h | 47 ++++++++++++++++++ src/libimp/platform/win/system.h | 80 ++++++++++++++++++++++++++++++ src/libimp/system.cpp | 6 +++ test/test_imp_system.cpp | 41 +++++++++++++++ 5 files changed, 204 insertions(+) create mode 100644 include/libimp/system.h create mode 100644 src/libimp/platform/posix/system.h create mode 100644 src/libimp/platform/win/system.h create mode 100644 src/libimp/system.cpp create mode 100644 test/test_imp_system.cpp diff --git a/include/libimp/system.h b/include/libimp/system.h new file mode 100644 index 0000000..208f40d --- /dev/null +++ b/include/libimp/system.h @@ -0,0 +1,30 @@ +/** + * @file libimp/system.h + * @author mutouyun (orz@orzz.org) + * @brief Isolation and encapsulation of system APIs + * @date 2022-08-07 + */ +#pragma once + +#include + +#include "libimp/def.h" +#include "libimp/export.h" +#include "libimp/result.h" + +LIBIMP_NAMESPACE_BEG_ +namespace sys { + +/** + * @brief Get/Set the system error code + */ +LIBIMP_EXPORT result_code error_code() noexcept; +LIBIMP_EXPORT void error_code(result_code) noexcept; + +/** + * @brief Gets a text description of the system error + */ +LIBIMP_EXPORT std::string error_msg(result_code) noexcept; + +} // namespace sys +LIBIMP_NAMESPACE_END_ diff --git a/src/libimp/platform/posix/system.h b/src/libimp/platform/posix/system.h new file mode 100644 index 0000000..57396a9 --- /dev/null +++ b/src/libimp/platform/posix/system.h @@ -0,0 +1,47 @@ +/** + * @file libimp/platform/posix/system.h + * @author mutouyun (orz@orzz.org) + */ +#pragma once + +#include +#include +#include + +#include +#include + +#include "libimp/system.h" +#include "libimp/log.h" + +LIBIMP_NAMESPACE_BEG_ +namespace sys { + +/** + * @brief Get the system error code + * https://man7.org/linux/man-pages/man3/errno.3.html + */ +result_code error_code() noexcept { + auto err = errno; + if (err == 0) return {true}; + return {false, std::uint64_t(err)}; +} + +/** + * @brief Set the system error code + * https://man7.org/linux/man-pages/man3/errno.3.html + */ +void error_code(result_code code) noexcept { + errno = code ? 0 : (int)code.value(); +} + +/** + * @brief Gets a text description of the system error + * https://man7.org/linux/man-pages/man3/strerror_l.3.html + */ +std::string error_msg(result_code code) noexcept { + return {}; +} + +} // namespace sys +LIBIMP_NAMESPACE_END_ diff --git a/src/libimp/platform/win/system.h b/src/libimp/platform/win/system.h new file mode 100644 index 0000000..b4c6a03 --- /dev/null +++ b/src/libimp/platform/win/system.h @@ -0,0 +1,80 @@ +/** + * @file libimp/platform/win/system.h + * @author mutouyun (orz@orzz.org) + */ +#pragma once + +#include +#include +#include + +#include +#include + +#include "libimp/system.h" +#include "libimp/log.h" +#include "libimp/codecvt.h" + +LIBIMP_NAMESPACE_BEG_ +namespace sys { + +/** + * @brief Get the system error code + * https://docs.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-getlasterror + */ +result_code error_code() noexcept { + auto err = ::GetLastError(); + if (err == ERROR_SUCCESS) return {true}; + return {false, std::uint64_t(err)}; +} + +/** + * @brief Set the system error code + * https://docs.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-setlasterror + */ +void error_code(result_code code) noexcept { + DWORD err = code ? ERROR_SUCCESS : (DWORD)code.value(); + ::SetLastError(err); +} + +/** + * @brief Gets a text description of the system error + * https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-formatmessage + */ +std::string error_msg(result_code code) noexcept { + LIBIMP_LOG_(); + try { + DWORD err = code ? ERROR_SUCCESS : (DWORD)code.value(); + LPTSTR lpErrText = NULL; + if (::FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + err, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR)&lpErrText, + 0, NULL) == 0) { + log.error("FormatMessage fails. return = {}", ::GetLastError()); + return {}; + } + LIBIMP_UNUSED auto buf_guard = std::unique_ptr, + void(*)(LPVOID)> { + lpErrText, [](LPVOID lp) { ::LocalFree(lp); } + }; + std::size_t msg_len = ::_tcslen(lpErrText); + std::size_t len = cvt_cstr(lpErrText, msg_len, (char *)nullptr, 0); + if (len == 0) { + return {}; + } + std::string ret(len, '\0'); + cvt_cstr(lpErrText, msg_len, &ret[0], ret.size()); + return ret; + } catch (std::exception const &e) { + log.failed(e.what()); + } + return {}; +} + +} // namespace sys +LIBIMP_NAMESPACE_END_ diff --git a/src/libimp/system.cpp b/src/libimp/system.cpp new file mode 100644 index 0000000..54a178f --- /dev/null +++ b/src/libimp/system.cpp @@ -0,0 +1,6 @@ +#include "libimp/detect_plat.h" +#if defined(LIBIMP_OS_WIN) +#include "libimp/platform/win/system.h" +#else +#include "libimp/platform/posix/system.h" +#endif \ No newline at end of file diff --git a/test/test_imp_system.cpp b/test/test_imp_system.cpp new file mode 100644 index 0000000..c3d61d6 --- /dev/null +++ b/test/test_imp_system.cpp @@ -0,0 +1,41 @@ + +#include "gtest/gtest.h" + +#include "libimp/system.h" +#include "libimp/detect_plat.h" +#include "libimp/codecvt.h" + +#if defined(LIBIMP_OS_WIN) +#include +#else +#endif + +TEST(system, error_code) { + EXPECT_TRUE(imp::sys::error_code()); + + imp::sys::error_code({false, 111}); + auto err = imp::sys::error_code(); + EXPECT_FALSE(err); + EXPECT_EQ(err.value(), 111); + + imp::sys::error_code({}); + EXPECT_TRUE(imp::sys::error_code()); +} + +TEST(system, error_msg) { +#if defined(LIBIMP_OS_WIN) + { + std::u16string u16_txt = u"操作成功完成。\r\n"; + std::string s_txt; + imp::cvt_sstr(u16_txt, s_txt); + EXPECT_EQ(imp::sys::error_msg({}), s_txt); + } + { + std::u16string u16_txt = u"句柄无效。\r\n"; + std::string s_txt; + imp::cvt_sstr(u16_txt, s_txt); + EXPECT_EQ(imp::sys::error_msg({false, ERROR_INVALID_HANDLE}), s_txt); + } +#else +#endif +} \ No newline at end of file