From b70dea04c5f510fc4833c3c6a9c07b2bc511ab64 Mon Sep 17 00:00:00 2001 From: mutouyun Date: Wed, 8 Jan 2025 19:33:51 +0800 Subject: [PATCH] Add `system` --- include/libipc/imp/system.h | 33 +++++++++++ src/libipc/imp/system.cpp | 7 +++ src/libipc/platform/posix/system.h | 49 +++++++++++++++++ src/libipc/platform/win/system.h | 88 ++++++++++++++++++++++++++++++ test/imp/test_imp_system.cpp | 10 ++++ 5 files changed, 187 insertions(+) create mode 100644 include/libipc/imp/system.h create mode 100644 src/libipc/imp/system.cpp create mode 100644 src/libipc/platform/posix/system.h create mode 100644 src/libipc/platform/win/system.h create mode 100644 test/imp/test_imp_system.cpp diff --git a/include/libipc/imp/system.h b/include/libipc/imp/system.h new file mode 100644 index 0000000..1ecbb9c --- /dev/null +++ b/include/libipc/imp/system.h @@ -0,0 +1,33 @@ +/** + * \file libipc/system.h + * \author mutouyun (orz@orzz.org) + * \brief Isolation and encapsulation of system APIs. + */ +#pragma once + +#include +#include // std::ostream +#include + +#include "libipc/imp/export.h" +#include "libipc/imp/error.h" +#include "libipc/imp/result.h" + +namespace ipc { +namespace sys { + +/// \brief A platform-dependent error code. +LIBIPC_EXPORT std::error_code error() noexcept; + +/// \enum The name of the `conf()` argument used to inquire about its value. +/// \brief Certain options are supported, +/// or what the value is of certain configurable constants or limits. +enum class info : std::int32_t { + page_size, +}; + +/// \brief Get system configuration information at run time. +LIBIPC_EXPORT result conf(info) noexcept; + +} // namespace sys +} // namespace ipc diff --git a/src/libipc/imp/system.cpp b/src/libipc/imp/system.cpp new file mode 100644 index 0000000..c05975c --- /dev/null +++ b/src/libipc/imp/system.cpp @@ -0,0 +1,7 @@ + +#include "libipc/imp/detect_plat.h" +#if defined(LIBIPC_OS_WIN) +# include "libipc/platform/win/system.h" +#else +# include "libipc/platform/posix/system.h" +#endif diff --git a/src/libipc/platform/posix/system.h b/src/libipc/platform/posix/system.h new file mode 100644 index 0000000..cae4898 --- /dev/null +++ b/src/libipc/platform/posix/system.h @@ -0,0 +1,49 @@ +/** + * \file libipc/platform/posix/system.h + * \author mutouyun (orz@orzz.org) + */ +#pragma once + +#include +#include +#include + +#include "libipc/imp/system.h" +#include "libipc/imp/log.h" + +namespace ipc { +namespace sys { + +/** + * \brief Get the system error number. + * \see https://en.cppreference.com/w/cpp/error/generic_category + * https://man7.org/linux/man-pages/man3/errno.3.html +*/ +std::error_code error() noexcept { + return std::error_code(errno, std::generic_category()); +} + +/** + * \brief Gets configuration information at run time + * https://man7.org/linux/man-pages/man2/getpagesize.2.html + * https://man7.org/linux/man-pages/man3/sysconf.3.html + */ +result conf(info r) noexcept { + LIBIPC_LOG(); + switch (r) { + case info::page_size: { + auto val = ::sysconf(_SC_PAGESIZE); + if (val >= 0) return static_cast(val); + break; + } + default: + log.error("invalid info = ", underlyof(r)); + return std::make_error_code(std::errc::invalid_argument); + } + auto err = sys::error(); + log.error("info = ", underlyof(r), ", error = ", err); + return err; +} + +} // namespace sys +} // namespace ipc diff --git a/src/libipc/platform/win/system.h b/src/libipc/platform/win/system.h new file mode 100644 index 0000000..645de2f --- /dev/null +++ b/src/libipc/platform/win/system.h @@ -0,0 +1,88 @@ +/** + * \file libipc/platform/win/system.h + * \author mutouyun (orz@orzz.org) + */ +#pragma once + +#include +#include + +#include +#include + +#include "libipc/imp/system.h" +#include "libipc/imp/log.h" +#include "libipc/imp/codecvt.h" +#include "libipc/imp/generic.h" +#include "libipc/imp/detect_plat.h" +#include "libipc/imp/scope_exit.h" + +namespace ipc { +namespace sys { + +/** + * \brief Gets a text description of the system error + * \see https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-formatmessage + */ +std::string error_string(DWORD code) noexcept { + LIBIPC_LOG(); + LIBIPC_TRY { + LPTSTR lpErrText = NULL; + if (::FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + code, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR)&lpErrText, + 0, NULL) == 0) { + log.error("failed: FormatMessage(dwMessageId = ", code, "). error = ", ::GetLastError()); + return {}; + } + LIBIPC_SCOPE_EXIT(finally) = [lpErrText] { ::LocalFree(lpErrText); }; + 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; + } LIBIPC_CATCH(...) { + log.error("failed: FormatMessage(dwMessageId = ", code, ").", + "\n\texception: ", log::exception_string(std::current_exception())); + } + return {}; +} + +/** + * \brief Get the system error number. + * \see https://en.cppreference.com/w/cpp/error/system_category + * https://docs.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-getlasterror +*/ +std::error_code error() noexcept { + return std::error_code(::GetLastError(), std::system_category()); +} + +/** + * \brief Retrieves information about the current system. + * \see https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getsysteminfo + * https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getnativesysteminfo + */ +result conf(info r) noexcept { + LIBIPC_LOG(); + switch (r) { + case info::page_size: { + ::SYSTEM_INFO info {}; + ::GetNativeSystemInfo(&info); + return (std::int64_t)info.dwPageSize; + } + default: + log.error("invalid info = ", underlyof(r)); + return std::make_error_code(std::errc::invalid_argument); + } +} + +} // namespace sys +} // namespace ipc diff --git a/test/imp/test_imp_system.cpp b/test/imp/test_imp_system.cpp new file mode 100644 index 0000000..802ebd4 --- /dev/null +++ b/test/imp/test_imp_system.cpp @@ -0,0 +1,10 @@ + +#include "test.h" + +#include "libipc/imp/system.h" + +TEST(system, conf) { + auto ret = ipc::sys::conf(ipc::sys::info::page_size); + EXPECT_TRUE(ret); + EXPECT_EQ(ret.value(), 4096); +}