From 881039cd402fc24c43659c9727f89cffce0469fe Mon Sep 17 00:00:00 2001 From: Amlal El Mahrouss Date: Thu, 11 Dec 2025 09:47:13 +0100 Subject: chore: API cleanup and improvements. Signed-off-by: Amlal El Mahrouss --- include/ocl/detail/net_config.hpp | 22 ---- include/ocl/detail/posix/net_config.hpp | 22 ++++ include/ocl/is_same.hpp | 30 ++--- include/ocl/option.hpp | 12 +- include/ocl/posix/unique_socket.hpp | 214 ++++++++++++++++++++++++++++++++ include/ocl/print.hpp | 3 +- include/ocl/smart_ptr.hpp | 1 - include/ocl/smart_socket.hpp | 5 +- include/ocl/unique_socket.hpp | 214 -------------------------------- 9 files changed, 261 insertions(+), 262 deletions(-) delete mode 100644 include/ocl/detail/net_config.hpp create mode 100644 include/ocl/detail/posix/net_config.hpp create mode 100644 include/ocl/posix/unique_socket.hpp delete mode 100644 include/ocl/unique_socket.hpp (limited to 'include') diff --git a/include/ocl/detail/net_config.hpp b/include/ocl/detail/net_config.hpp deleted file mode 100644 index 671d4ba..0000000 --- a/include/ocl/detail/net_config.hpp +++ /dev/null @@ -1,22 +0,0 @@ -/* - * File: detail/net_config.hpp - * Purpose: Network Config file of the OCL.CORE library. - * Author: Amlal El Mahrouss (amlal@nekernel.org) - * Copyright 2025, Amlal El Mahrouss, licensed under the Boost Software License. - */ - -#ifndef __OCL_NET_CONFIG -#define __OCL_NET_CONFIG - -#include -#include -#include -#include -#include -#include - -#ifdef OCL_WINDOWS -#error !!! "Windows is not supported yet for " !!! -#endif // OCL_WINDOWS - -#endif // __OCL_NET_CONFIG \ No newline at end of file diff --git a/include/ocl/detail/posix/net_config.hpp b/include/ocl/detail/posix/net_config.hpp new file mode 100644 index 0000000..671d4ba --- /dev/null +++ b/include/ocl/detail/posix/net_config.hpp @@ -0,0 +1,22 @@ +/* + * File: detail/net_config.hpp + * Purpose: Network Config file of the OCL.CORE library. + * Author: Amlal El Mahrouss (amlal@nekernel.org) + * Copyright 2025, Amlal El Mahrouss, licensed under the Boost Software License. + */ + +#ifndef __OCL_NET_CONFIG +#define __OCL_NET_CONFIG + +#include +#include +#include +#include +#include +#include + +#ifdef OCL_WINDOWS +#error !!! "Windows is not supported yet for " !!! +#endif // OCL_WINDOWS + +#endif // __OCL_NET_CONFIG \ No newline at end of file diff --git a/include/ocl/is_same.hpp b/include/ocl/is_same.hpp index ec3eb66..2ad6db5 100644 --- a/include/ocl/is_same.hpp +++ b/include/ocl/is_same.hpp @@ -14,7 +14,7 @@ namespace ocl { template - struct basic_hash + struct basic_hash final { using result_type = typename T::result_type; using type = T; @@ -29,13 +29,10 @@ namespace ocl template struct is_same { - static constexpr bool value = false; + using left_type = T; + using right_type = T; - /// @brief check if hash matches what we expect. - constexpr bool operator()() noexcept - { - return T::hash() == U::hash(); - } + static constexpr bool value = false; }; template @@ -47,12 +44,10 @@ namespace ocl template struct is_not_same { - static constexpr bool value = true; + using left_type = T; + using right_type = T; - constexpr bool operator()() noexcept - { - return T::hash() != U::hash(); - } + static constexpr bool value = true; }; template @@ -62,7 +57,7 @@ namespace ocl }; template - struct equiv_is_int8 + struct equiv_is_int8 final { private: T left_ = 127, right_ = 127; @@ -77,7 +72,7 @@ namespace ocl }; template - struct equiv_not_int8 + struct equiv_not_int8 final { private: // these shall overflow if not int8. @@ -93,7 +88,7 @@ namespace ocl }; template - struct equiv_is_real + struct equiv_is_real final { private: T left_ = 5, right_ = 3; @@ -108,17 +103,18 @@ namespace ocl }; template - struct equiv_is + struct equiv_is final { private: T left_{}, right_{}; public: using result_type = bool; + using type = T; constexpr result_type hash() { - return (left_ / right_); + return (left_ == right_); } }; } // namespace ocl diff --git a/include/ocl/option.hpp b/include/ocl/option.hpp index 9286ef9..a73ccb0 100644 --- a/include/ocl/option.hpp +++ b/include/ocl/option.hpp @@ -21,11 +21,11 @@ namespace ocl }; template - struct option final + class option final { + public: option() = delete; - - option(const return_type& return_type) + explicit option(const return_type& return_type) : ret_(return_type) { } @@ -68,7 +68,7 @@ namespace ocl namespace detail { - struct int_eq_teller + struct int_eq_teller final { bool operator()(int a, int b) { @@ -76,7 +76,7 @@ namespace ocl } }; - struct int_greater_than_teller + struct int_greater_than_teller final { bool operator()(int a, int b) { @@ -84,7 +84,7 @@ namespace ocl } }; - struct int_less_than_teller + struct int_less_than_teller final { bool operator()(int a, int b) { diff --git a/include/ocl/posix/unique_socket.hpp b/include/ocl/posix/unique_socket.hpp new file mode 100644 index 0000000..f094e54 --- /dev/null +++ b/include/ocl/posix/unique_socket.hpp @@ -0,0 +1,214 @@ +/* + * File: unique_socket.hpp + * Purpose: RAII socket concept in modern C++ + * Author: Amlal El Mahrouss (amlal@nekernel.org) + * Copyright 2025, Amlal El Mahrouss, licensed under the Boost Software License. + */ + +#ifndef __OCL_CORE_SOCKET +#define __OCL_CORE_SOCKET + +#include +#include + +namespace ocl +{ + class unique_socket; + + inline constexpr auto socket_null = 0; + + class unique_socket final + { + public: + using socket_type = int; + using error_type = bool; + using condition_type = bool; + using socket_state = int; + + private: + socket_type socket_{}; + condition_type is_server_{false}; + error_type bad_{false}; + + public: + unique_socket() = default; + + ~unique_socket() + { + this->destroy(); + } + + unique_socket& operator=(const unique_socket&) = delete; + unique_socket(const unique_socket&) = delete; + + unique_socket& operator=(unique_socket&& other) noexcept + { + if (this != &other) + { + this->destroy(); + + socket_ = other.socket_; + is_server_ = other.is_server_; + bad_ = other.bad_; + + other.socket_ = 0; + other.bad_ = true; + } + + return *this; + } + + unique_socket(unique_socket&& other) noexcept + : socket_(other.socket_), is_server_(other.is_server_), bad_(other.bad_) + { + other.socket_ = 0; + other.bad_ = true; + } + + static constexpr auto any_address = "0.0.0.0"; + static constexpr auto backlog_count = 20U; + + const error_type& bad() + { + return bad_; + } + + unique_socket::socket_state state() noexcept + { + socket_state error = 0; + socklen_t len = sizeof(error); + getsockopt(socket_, SOL_SOCKET, SO_ERROR, &error, &len); + + return error; + } + + unique_socket accept() noexcept + { + socket_type cl_{-1}; + + if (this->is_server_) + cl_ = ::accept(socket_, nullptr, nullptr); + + unique_socket ret_sock; + ret_sock.socket_ = cl_; + + return std::move(ret_sock); + } + + unique_socket read_server_buffer(char* in, std::size_t len) + { + if (!in || !len) + return {}; + + if (!is_server_) + return {}; + + auto ret_sock = accept(); + + if (ret_sock.socket_ == -1) + throw std::invalid_argument("no connection to accept."); + + auto ret = ::recv(ret_sock.socket_, in, len, 0); + ret_sock.bad_ = ret < 0L; + + return ret_sock; + } + + void read_client_buffer(char* in, std::size_t len) + { + if (!in || !len) + return; + + if (is_server_) + return; + + auto ret = ::recv(this->socket_, in, len, 0); + this->bad_ = ret < 0L; + } + + void write_from_buffer(const char* out, std::size_t len) + { + if (!out) + return; + + if (!len) + return; + + auto ret = ::send(this->socket_, out, len, 0); + this->bad_ = ret < 0L; + } + + template + static unique_socket make_socket(const std::string& address, const bool is_server) + { + if (unique_socket sock; sock.construct(address.c_str(), is_server)) + return sock; + + throw std::invalid_argument("invalid socket argument"); + } + + private: + template + bool construct(const char* addr = unique_socket::any_address, const bool& is_server = false) noexcept + { + static_assert(af != 0, "Address family is zero"); + static_assert(kind != 0, "Kind is zero"); + + socket_ = ::socket(af, kind, 0); + is_server_ = is_server; + + if (socket_ == -1) + return false; + + struct sockaddr_in addr_; + std::memset(&addr_, 0, sizeof(struct sockaddr_in)); + + if (addr == unique_socket::any_address) + addr_.sin_addr.s_addr = INADDR_ANY; + else + addr_.sin_addr.s_addr = ::inet_addr(addr); + + addr_.sin_port = htons(port); + addr_.sin_family = af; + + if (!is_server) + { + const auto ret = ::connect(socket_, reinterpret_cast(&addr_), sizeof(addr_)); + bad_ = ret == -1; + return bad_ == false; + } + + int ret = ::bind(socket_, (struct sockaddr*)&addr_, sizeof(addr_)); + + bad_ = ret == -1; + + if (bad_) + return false; + + ret = ::listen(socket_, unique_socket::backlog_count); + + bad_ = ret == -1; + + return bad_ == false; + } + + bool destroy() noexcept + { + if (!socket_) + return false; + + ::close(socket_); + + socket_ = 0L; + + return true; + } + }; + + template + concept IsValidSocket = requires(TS& sock) { + { !sock.bad() }; + }; +} // namespace ocl + +#endif \ No newline at end of file diff --git a/include/ocl/print.hpp b/include/ocl/print.hpp index 02b3044..ea6b483 100644 --- a/include/ocl/print.hpp +++ b/include/ocl/print.hpp @@ -9,7 +9,6 @@ #define __OCL_CORE_PRINT #include - #include #define console_io_out std::cout @@ -25,6 +24,8 @@ namespace ocl::io inline void print() noexcept { + extern void lf() noexcept; + lf(); } template diff --git a/include/ocl/smart_ptr.hpp b/include/ocl/smart_ptr.hpp index 333e460..23671f1 100644 --- a/include/ocl/smart_ptr.hpp +++ b/include/ocl/smart_ptr.hpp @@ -24,7 +24,6 @@ namespace ocl /// @brief Constructs a `delete_ptr`, that is, a pointer that isn't deleted from the heap. template inline auto delete_ptr(T* object) -> auto { return shared_ptr{ object, boost::null_deleter{}}; } - } #endif // ifndef __OCL_SMART_PTR \ No newline at end of file diff --git a/include/ocl/smart_socket.hpp b/include/ocl/smart_socket.hpp index cba177c..81094fd 100644 --- a/include/ocl/smart_socket.hpp +++ b/include/ocl/smart_socket.hpp @@ -9,7 +9,10 @@ #define __OCL_SMART_SOCKET #include -#include #include +#ifdef OCL_POSIX +# include +#endif + #endif // __OCL_SMART_SOCKET \ No newline at end of file diff --git a/include/ocl/unique_socket.hpp b/include/ocl/unique_socket.hpp deleted file mode 100644 index 053b7e9..0000000 --- a/include/ocl/unique_socket.hpp +++ /dev/null @@ -1,214 +0,0 @@ -/* - * File: unique_socket.hpp - * Purpose: RAII socket concept in modern C++ - * Author: Amlal El Mahrouss (amlal@nekernel.org) - * Copyright 2025, Amlal El Mahrouss, licensed under the Boost Software License. - */ - -#ifndef __OCL_CORE_SOCKET -#define __OCL_CORE_SOCKET - -#include -#include - -namespace ocl -{ - class unique_socket; - - inline constexpr auto socket_null = 0; - - class unique_socket final - { - public: - using socket_type = int; - using error_type = bool; - using condition_type = bool; - using socket_state = int; - - private: - socket_type socket_{}; - condition_type is_server_{false}; - error_type bad_{false}; - - public: - unique_socket() = default; - - ~unique_socket() - { - this->destroy(); - } - - unique_socket& operator=(const unique_socket&) = delete; - unique_socket(const unique_socket&) = delete; - - unique_socket& operator=(unique_socket&& other) noexcept - { - if (this != &other) - { - this->destroy(); - - socket_ = other.socket_; - is_server_ = other.is_server_; - bad_ = other.bad_; - - other.socket_ = 0; - other.bad_ = true; - } - - return *this; - } - - unique_socket(unique_socket&& other) noexcept - : socket_(other.socket_), is_server_(other.is_server_), bad_(other.bad_) - { - other.socket_ = 0; - other.bad_ = true; - } - - static constexpr auto any_address = "0.0.0.0"; - static constexpr auto backlog_count = 20U; - - const error_type& bad() - { - return bad_; - } - - unique_socket::socket_state state() noexcept - { - socket_state error = 0; - socklen_t len = sizeof(error); - getsockopt(socket_, SOL_SOCKET, SO_ERROR, &error, &len); - - return error; - } - - unique_socket accept() noexcept - { - socket_type cl_{-1}; - - if (this->is_server_) - cl_ = ::accept(socket_, nullptr, nullptr); - - unique_socket ret_sock; - ret_sock.socket_ = cl_; - - return std::move(ret_sock); - } - - unique_socket read_server_buffer(char* in, std::size_t len) - { - if (!in || !len) - return {}; - - if (!is_server_) - return {}; - - auto ret_sock = accept(); - - if (ret_sock.socket_ == -1) - throw std::invalid_argument("no connection to accept."); - - auto ret = ::recv(ret_sock.socket_, in, len, 0); - ret_sock.bad_ = ret < 0L; - - return ret_sock; - } - - void read_client_buffer(char* in, std::size_t len) - { - if (!in || !len) - return; - - if (is_server_) - return; - - auto ret = ::recv(this->socket_, in, len, 0); - this->bad_ = ret < 0L; - } - - void write_from_buffer(const char* out, std::size_t len) - { - if (!out) - return; - - if (!len) - return; - - auto ret = ::send(this->socket_, out, len, 0); - this->bad_ = ret < 0L; - } - - template - static unique_socket make_socket(const std::string& address, const bool is_server) - { - if (unique_socket sock; sock.construct(address.c_str(), is_server)) - return sock; - - throw std::invalid_argument("invalid socket argument"); - } - - private: - template - bool construct(const char* addr = unique_socket::any_address, const bool& is_server = false) noexcept - { - static_assert(af != 0, "Address family is zero"); - static_assert(kind != 0, "Kind is zero"); - - socket_ = ::socket(af, kind, 0); - is_server_ = is_server; - - if (socket_ == -1) - return false; - - struct sockaddr_in addr_; - std::memset(&addr_, 0, sizeof(struct sockaddr_in)); - - if (addr == unique_socket::any_address) - addr_.sin_addr.s_addr = INADDR_ANY; - else - addr_.sin_addr.s_addr = ::inet_addr(addr); - - addr_.sin_port = htons(port); - addr_.sin_family = af; - - if (!is_server) - { - const auto ret = ::connect(socket_, reinterpret_cast(&addr_), sizeof(addr_)); - bad_ = ret == -1; - return bad_ == false; - } - - int ret = ::bind(socket_, (struct sockaddr*)&addr_, sizeof(addr_)); - - bad_ = ret == -1; - - if (bad_) - return false; - - ret = ::listen(socket_, unique_socket::backlog_count); - - bad_ = ret == -1; - - return bad_ == false; - } - - bool destroy() noexcept - { - if (!socket_) - return false; - - ::close(socket_); - - socket_ = 0L; - - return true; - } - }; - - template - concept IsValidSocket = requires(TS& sock) { - { !sock.bad() }; - }; -} // namespace ocl - -#endif \ No newline at end of file -- cgit v1.2.3