diff --git a/CMakeLists.txt b/CMakeLists.txt index 32e73be..0826289 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,11 +5,12 @@ set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) if (WIN32) - set(PLATFORM_SOURCES src/win32/win32_handle.cpp) - set(PLATFORM_HEADERS include/shmcpp/detail/win32_handle.hpp) + set(PLATFORM_SOURCES src/win32/handle.cpp) + set(PLATFORM_HEADERS include/shmcpp/detail/win32/handle.hpp + include/shmcpp/detail/win32/utils.hpp) else () - set(PLATFORM_SOURCES src/posix/posix_handle.cpp) - set(PLATFORM_HEADERS include/shmcpp/detail/posix_handle.hpp) + set(PLATFORM_SOURCES src/posix/handle.cpp) + set(PLATFORM_HEADERS include/shmcpp/detail/posix/handle.hpp) endif () add_library(shmcpp STATIC diff --git a/include/shmcpp/detail/handle_concept.hpp b/include/shmcpp/detail/handle_concept.hpp index 1c7da7e..e2b22f8 100644 --- a/include/shmcpp/detail/handle_concept.hpp +++ b/include/shmcpp/detail/handle_concept.hpp @@ -5,4 +5,27 @@ #ifndef SHMCPP_HANDLE_CONCEPT_HPP #define SHMCPP_HANDLE_CONCEPT_HPP -#endif //SHMCPP_HANDLE_CONCEPT_HPP \ No newline at end of file +#include +#include +#include +#include + +namespace shmcpp::detail { + template + concept Handle = + std::movable && + !std::copyable && + requires(T handle, + const std::string &name, + std::size_t size, + std::size_t offset, + std::size_t length) + { + { T::create(name, size) } -> std::same_as; + { T::open(name, size) } -> std::same_as; + { handle.map(offset, length) } -> std::same_as; + { handle.size() } -> std::convertible_to; + }; +} + +#endif //SHMCPP_HANDLE_CONCEPT_HPP diff --git a/include/shmcpp/detail/posix/handle.hpp b/include/shmcpp/detail/posix/handle.hpp new file mode 100644 index 0000000..6656e90 --- /dev/null +++ b/include/shmcpp/detail/posix/handle.hpp @@ -0,0 +1,37 @@ +// +// Created by DaLaw2 on 2026/1/3. +// + +#ifndef SHMCPP_POSIX_HANDLE_HPP +#define SHMCPP_POSIX_HANDLE_HPP + +#include + +namespace shmcpp::detail { + class PosixHandle { + int fd_; + std::size_t size_; + public: + PosixHandle() = delete; + + ~PosixHandle() noexcept; + + PosixHandle(const PosixHandle &) = delete; + + PosixHandle &operator=(const PosixHandle &) = delete; + + PosixHandle(PosixHandle &&) noexcept; + + PosixHandle &operator=(PosixHandle &&) noexcept; + + static PosixHandle create(const std::string &name, std::size_t size); + + static PosixHandle open(const std::string &name, std::size_t size); + + MappedView map(std::size_t offset, std::size_t length); + + [[nodiscard]] std::size_t size() const; + }; +} + +#endif //SHMCPP_POSIX_HANDLE_HPP diff --git a/include/shmcpp/detail/posix_handle.hpp b/include/shmcpp/detail/posix_handle.hpp deleted file mode 100644 index 5fd6137..0000000 --- a/include/shmcpp/detail/posix_handle.hpp +++ /dev/null @@ -1,8 +0,0 @@ -// -// Created by DaLaw2 on 2026/1/3. -// - -#ifndef SHMCPP_POSIX_HANDLE_HPP -#define SHMCPP_POSIX_HANDLE_HPP - -#endif //SHMCPP_POSIX_HANDLE_HPP \ No newline at end of file diff --git a/include/shmcpp/detail/win32/handle.hpp b/include/shmcpp/detail/win32/handle.hpp new file mode 100644 index 0000000..c2fa30d --- /dev/null +++ b/include/shmcpp/detail/win32/handle.hpp @@ -0,0 +1,43 @@ +// +// Created by DaLaw2 on 2026/1/3. +// + +#ifndef SHMCPP_WIN32_HANDLE_HPP +#define SHMCPP_WIN32_HANDLE_HPP + +#include +#include +#include +#include + +namespace shmcpp::detail { + class Win32Handle { + HANDLE handle_ = INVALID_HANDLE_VALUE; + std::size_t size_ = 0; + + Win32Handle(HANDLE handle, std::size_t size) noexcept; + + public: + Win32Handle() = delete; + + ~Win32Handle() noexcept; + + Win32Handle(const Win32Handle &) = delete; + + Win32Handle &operator=(const Win32Handle &) = delete; + + Win32Handle(Win32Handle &&) noexcept; + + Win32Handle &operator=(Win32Handle &&) noexcept; + + static Win32Handle create(const std::string &name, std::size_t size); + + static Win32Handle open(const std::string &name, std::size_t size); + + MappedView map(std::size_t offset, std::size_t length); + + [[nodiscard]] std::size_t size() const; + }; +} + +#endif //SHMCPP_WIN32_HANDLE_HPP diff --git a/include/shmcpp/detail/win32/utils.hpp b/include/shmcpp/detail/win32/utils.hpp new file mode 100644 index 0000000..05835fb --- /dev/null +++ b/include/shmcpp/detail/win32/utils.hpp @@ -0,0 +1,43 @@ +// +// Created by DaLaw2 on 2026/1/4. +// + +#ifndef SHMCPP_UTILS_HPP +#define SHMCPP_UTILS_HPP + +#include +#include + +namespace shmcpp::detail { + inline std::string getWindowsErrorMessage(const DWORD errorCode) noexcept { + LPSTR messageBuffer = nullptr; + + std::size_t size = FormatMessageA( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + nullptr, + errorCode, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + reinterpret_cast(&messageBuffer), + 0, + nullptr + ); + + if (size == 0) { + return "Unknown error"; + } + + std::string message(messageBuffer, size); + + LocalFree(messageBuffer); + + while (!message.empty() && (message.back() == '\n' || message.back() == '\r')) { + message.pop_back(); + } + + return message; + } +} + +#endif //SHMCPP_UTILS_HPP diff --git a/include/shmcpp/detail/win32_handle.hpp b/include/shmcpp/detail/win32_handle.hpp deleted file mode 100644 index c2ffab8..0000000 --- a/include/shmcpp/detail/win32_handle.hpp +++ /dev/null @@ -1,8 +0,0 @@ -// -// Created by DaLaw2 on 2026/1/3. -// - -#ifndef SHMCPP_WIN32_HANDLE_HPP -#define SHMCPP_WIN32_HANDLE_HPP - -#endif //SHMCPP_WIN32_HANDLE_HPP \ No newline at end of file diff --git a/include/shmcpp/mapped_view.hpp b/include/shmcpp/mapped_view.hpp index f52a57d..eed9e7b 100644 --- a/include/shmcpp/mapped_view.hpp +++ b/include/shmcpp/mapped_view.hpp @@ -5,4 +5,26 @@ #ifndef SHMCPP_MAPPED_VIEW_HPP #define SHMCPP_MAPPED_VIEW_HPP -#endif //SHMCPP_MAPPED_VIEW_HPP \ No newline at end of file +#include + +namespace shmcpp { + class MappedView { + void *data_ = nullptr; + std::size_t size_ = 0; + + public: + MappedView() = delete; + + MappedView(void *data, std::size_t size) noexcept; + + ~MappedView() noexcept; + + MappedView(const MappedView &) = delete; + + MappedView(MappedView &&) noexcept; + + MappedView &operator=(const MappedView &) noexcept; + }; +} + +#endif //SHMCPP_MAPPED_VIEW_HPP diff --git a/src/posix/handle.cpp b/src/posix/handle.cpp new file mode 100644 index 0000000..0cbd82e --- /dev/null +++ b/src/posix/handle.cpp @@ -0,0 +1,9 @@ +// +// Created by DaLaw2 on 2026/1/3. +// + +#include "shmcpp/detail/posix/handle.hpp" + +namespace shmcpp::detail { + static_assert(Handle); +} diff --git a/src/posix/posix_handle.cpp b/src/posix/posix_handle.cpp deleted file mode 100644 index cbe710b..0000000 --- a/src/posix/posix_handle.cpp +++ /dev/null @@ -1,3 +0,0 @@ -// -// Created by DaLaw2 on 2026/1/3. -// \ No newline at end of file diff --git a/src/win32/handle.cpp b/src/win32/handle.cpp new file mode 100644 index 0000000..696aa42 --- /dev/null +++ b/src/win32/handle.cpp @@ -0,0 +1,86 @@ +// +// Created by DaLaw2 on 2026/1/3. +// + +#include +#include + +#include "shmcpp/detail/win32/utils.hpp" +#include "shmcpp/detail/win32/handle.hpp" + +namespace shmcpp::detail { + Win32Handle::Win32Handle(const HANDLE handle, const std::size_t size) noexcept + : handle_(handle), size_(size) { + } + + Win32Handle::~Win32Handle() { + if (handle_ != INVALID_HANDLE_VALUE) { + CloseHandle(handle_); + } + } + + Win32Handle::Win32Handle(Win32Handle &&other) noexcept { + this->handle_ = other.handle_; + this->size_ = other.size_; + other.handle_ = INVALID_HANDLE_VALUE; + other.size_ = 0; + } + + Win32Handle &Win32Handle::operator=(Win32Handle &&other) noexcept { + if (this != &other) { + if (handle_ != INVALID_HANDLE_VALUE) { + CloseHandle(handle_); + } + this->handle_ = other.handle_; + this->size_ = other.size_; + other.handle_ = INVALID_HANDLE_VALUE; + other.size_ = 0; + } + return *this; + } + + Win32Handle Win32Handle::create(const std::string &name, const std::size_t size) { + const DWORD high = size >> 32; + const DWORD low = size & 0xFFFFFFFF; + const HANDLE handle = CreateFileMappingA( + INVALID_HANDLE_VALUE, + nullptr, + PAGE_READWRITE, + high, + low, + name.c_str() + ); + if (handle == nullptr) { + DWORD err = GetLastError(); + throw std::runtime_error( + std::format("{}: {}", err, getWindowsErrorMessage(err)) + ); + } + return Win32Handle{handle, size}; + } + + Win32Handle Win32Handle::open(const std::string &name, const std::size_t size) { + const HANDLE handle = OpenFileMappingA( + FILE_ALL_ACCESS, + FALSE, + name.c_str() + ); + if (handle == nullptr) { + DWORD err = GetLastError(); + throw std::runtime_error( + std::format("{}: {}", err, getWindowsErrorMessage(err)) + ); + } + return Win32Handle{handle, size}; + } + + MappedView Win32Handle::map(std::size_t offset, std::size_t length) { + return {}; + } + + size_t Win32Handle::size() const { + return this->size_; + } + + static_assert(Handle); +} diff --git a/src/win32/win32_handle.cpp b/src/win32/win32_handle.cpp deleted file mode 100644 index cbe710b..0000000 --- a/src/win32/win32_handle.cpp +++ /dev/null @@ -1,3 +0,0 @@ -// -// Created by DaLaw2 on 2026/1/3. -// \ No newline at end of file