From e85b8a1cf1624a9cbf3d719dd202ad57d43c2f4b Mon Sep 17 00:00:00 2001 From: Amlal El Mahrouss Date: Thu, 4 Dec 2025 06:14:14 -0500 Subject: chore: modularize OCL to OCL.core, upcoming OCL.fix Signed-off-by: Amlal El Mahrouss --- README.md | 24 +--- compile_flags.txt | 2 +- examples/fix_tag_example/CMakeLists.txt | 15 -- examples/fix_tag_example/example.cc | 31 ----- examples/hash_crc32_example/example.cc | 4 +- examples/simple_unique_socket/example.cc | 4 +- include/.keep | 0 include/ocl/allocator_op.hpp | 66 +++++++++ include/ocl/core/allocator_op.hpp | 66 --------- include/ocl/core/config.hpp | 38 ----- include/ocl/core/is_same.hpp | 108 --------------- include/ocl/core/option.hpp | 134 ------------------ include/ocl/crc_hash.hpp | 127 +++++++++++++++++ include/ocl/detail/config.hpp | 38 +++++ include/ocl/detail/net_config.hpp | 14 ++ include/ocl/fix/checksum.hpp | 14 -- include/ocl/fix/parser.hpp | 165 ---------------------- include/ocl/hashing/crc_hash.hpp | 127 ----------------- include/ocl/io/print.hpp | 77 ----------- include/ocl/is_same.hpp | 108 +++++++++++++++ include/ocl/net/unique_socket.hpp | 222 ------------------------------ include/ocl/option.hpp | 134 ++++++++++++++++++ include/ocl/print.hpp | 77 +++++++++++ include/ocl/unique_socket.hpp | 211 ++++++++++++++++++++++++++++ tests/fix_basic/CMakeLists.txt | 23 ---- tests/fix_basic/fix_test.cc | 38 ----- tests/network_basic/network_basic_test.cc | 4 +- 27 files changed, 785 insertions(+), 1086 deletions(-) delete mode 100644 examples/fix_tag_example/CMakeLists.txt delete mode 100644 examples/fix_tag_example/example.cc delete mode 100644 include/.keep create mode 100644 include/ocl/allocator_op.hpp delete mode 100644 include/ocl/core/allocator_op.hpp delete mode 100644 include/ocl/core/config.hpp delete mode 100644 include/ocl/core/is_same.hpp delete mode 100644 include/ocl/core/option.hpp create mode 100644 include/ocl/crc_hash.hpp create mode 100644 include/ocl/detail/config.hpp create mode 100644 include/ocl/detail/net_config.hpp delete mode 100644 include/ocl/fix/checksum.hpp delete mode 100644 include/ocl/fix/parser.hpp delete mode 100644 include/ocl/hashing/crc_hash.hpp delete mode 100644 include/ocl/io/print.hpp create mode 100644 include/ocl/is_same.hpp delete mode 100644 include/ocl/net/unique_socket.hpp create mode 100644 include/ocl/option.hpp create mode 100644 include/ocl/print.hpp create mode 100644 include/ocl/unique_socket.hpp delete mode 100644 tests/fix_basic/CMakeLists.txt delete mode 100644 tests/fix_basic/fix_test.cc diff --git a/README.md b/README.md index 203390e..e0aadcd 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,8 @@ -# Open C++ Library +# OCL.Core [![License: BSL](https://img.shields.io/badge/license-BSL-blue.svg)](LICENSE) -A set of containers in C++ for developers.
-You use them to speed up your development cycle for C++ applications. +Core set of containers from the OCL. ## Requirements: @@ -14,21 +13,4 @@ The OCL requires the following: - [CMake](https://cmake.org/) - [Git](https://git-scm.com/) -### Example: The Option container - -Evaluates whether an expression is passing the options. - -```cpp -#include - -int main(int argc, char** argv) -{ - auto opt = ocl::option(ocl::eval_eq(50, 50)).expect("ocl::eval_eq, does not match!"); - opt = ocl::option(ocl::eval_eq(50, 40)); - opt.expect("this time it doesn't."); - - return EXIT_SUCCESS; -} -``` - -##### (c) 2025 Amlal El Mahrouss, licensed under the Boost Software License. +##### (c) 2025 Amlal El Mahrouss and OCL Authors, licensed under the Boost Software License. diff --git a/compile_flags.txt b/compile_flags.txt index 2a37c5d..1f10106 100644 --- a/compile_flags.txt +++ b/compile_flags.txt @@ -1,4 +1,4 @@ --Iinclude/ocl +-Iinclude/ -std=c++20 -DEMBFS_28BIT_LBA -xc++ diff --git a/examples/fix_tag_example/CMakeLists.txt b/examples/fix_tag_example/CMakeLists.txt deleted file mode 100644 index b9a80db..0000000 --- a/examples/fix_tag_example/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ - -cmake_minimum_required(VERSION 3.15...3.31) - -project( - FixExample - VERSION 1.0 - LANGUAGES CXX) - -find_package(Boost REQUIRED COMPONENTS container) - -add_executable(FixExample example.cc) - -set_property(TARGET FixExample PROPERTY CXX_STANDARD 20) -target_include_directories(FixExample PUBLIC ../../include/ocl) -target_link_libraries(FixExample PRIVATE Boost::container) diff --git a/examples/fix_tag_example/example.cc b/examples/fix_tag_example/example.cc deleted file mode 100644 index ad9725b..0000000 --- a/examples/fix_tag_example/example.cc +++ /dev/null @@ -1,31 +0,0 @@ -#include -#include - -constexpr const char default_fix[] = { - '8', '=', 'F', 'I', 'X', '.', '4', '.', '2', 0x01, - '9', '=', '6', '3', 0x01, // BodyLength = 63 - '3', '5', '=', 'A', 0x01, - '4', '9', '=', 'S', 'E', 'R', 'V', 'E', 'R', 0x01, - '5', '6', '=', 'C', 'L', 'I', 'E', 'N', 'T', 0x01, - '3', '4', '=', '1', '7', '7', 0x01, - '5', '2', '=', '2', '0', '0', '9', '0', '1', '0', '7', '-', '1', '8', ':', '1', '5', ':', '1', '6', 0x01, - '9', '8', '=', '0', 0x01, - '1', '0', '8', '=', '3', '0', 0x01, - '1', '0', '=', '1', '4', '3', 0x01, 0x00 // CheckSum = 143 -}; - -int main(int argc, char** argv) -{ - ocl::fix::visitor basic_visitor; - ocl::fix::range_data fix = basic_visitor.visit(default_fix); - - ocl::io::enable_stdio_sync(false); - - ocl::io::print(":key=35\n"); - ocl::io::print(":value=", fix["35"], "\n"); - - ocl::io::print(":key=49\n"); - ocl::io::print(":value=", fix["49"], "\n"); - - return 0; -} diff --git a/examples/hash_crc32_example/example.cc b/examples/hash_crc32_example/example.cc index cddebda..bd27662 100644 --- a/examples/hash_crc32_example/example.cc +++ b/examples/hash_crc32_example/example.cc @@ -1,5 +1,5 @@ -#include -#include +#include +#include int main(int argc, char** argv) { diff --git a/examples/simple_unique_socket/example.cc b/examples/simple_unique_socket/example.cc index a0eaff2..b5bd34f 100644 --- a/examples/simple_unique_socket/example.cc +++ b/examples/simple_unique_socket/example.cc @@ -1,5 +1,5 @@ -#include -#include +#include +#include /// @brief Basic Send test int main() diff --git a/include/.keep b/include/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/include/ocl/allocator_op.hpp b/include/ocl/allocator_op.hpp new file mode 100644 index 0000000..f953391 --- /dev/null +++ b/include/ocl/allocator_op.hpp @@ -0,0 +1,66 @@ +/* + * File: allocator_op.hpp + * Purpose: Allocator System container. + * Author: Amlal El Mahrouss (amlal@nekernel.org) + * Copyright 2025, Amlal El Mahrouss, Licensed under the Boost Software License. Licensed under the BSL 1.0 license + */ + +#ifndef _OCL_ALLOCATOR_SYSTEM_HPP +#define _OCL_ALLOCATOR_SYSTEM_HPP + +#include +#include + +namespace ocl +{ + /// @note these are guidelines on allocating a resource + template + struct global_new_op final + { + inline auto operator()() -> type* + { + return new type; + } + + template + inline auto var_alloc(var_type&&... args) -> type* + { + return new type{std::forward(args)...}; + } + }; + + /// @note these are guidelines on deleting a resource + template + struct global_delete_op final + { + inline auto operator()(type* t) -> void + { + delete t; + } + }; + + template + class allocator_op + { + allocator_new alloc_op_{}; + allocator_delete free_op_{}; + + public: + allocator_op() = default; + ~allocator_op() = default; + + allocator_op& operator=(const allocator_op&) = delete; + allocator_op(const allocator_op&) = delete; + + template + auto construct(var_type&&... args) -> std::shared_ptr + { + return std::shared_ptr(alloc_op_.template var_alloc(args...), free_op_); + } + }; + + template + using allocator = allocator_op, global_delete_op>; +} // namespace ocl + +#endif // ifndef _OCL_ALLOCATOR_SYSTEM_HPP \ No newline at end of file diff --git a/include/ocl/core/allocator_op.hpp b/include/ocl/core/allocator_op.hpp deleted file mode 100644 index e25fc1c..0000000 --- a/include/ocl/core/allocator_op.hpp +++ /dev/null @@ -1,66 +0,0 @@ -/* - * File: core/allocator_op.hpp - * Purpose: Allocator System container. - * Author: Amlal El Mahrouss (amlal@nekernel.org) - * Copyright 2025, Amlal El Mahrouss, Licensed under the Boost Software License. Licensed under the BSL 1.0 license - */ - -#ifndef _OCL_ALLOCATOR_SYSTEM_HPP -#define _OCL_ALLOCATOR_SYSTEM_HPP - -#include -#include - -namespace ocl -{ - /// @note these are guidelines on allocating a resource - template - struct global_new_op final - { - inline auto operator()() -> type* - { - return new type; - } - - template - inline auto var_alloc(var_type&&... args) -> type* - { - return new type{std::forward(args)...}; - } - }; - - /// @note these are guidelines on deleting a resource - template - struct global_delete_op final - { - inline auto operator()(type* t) -> void - { - delete t; - } - }; - - template - class allocator_op - { - allocator_new alloc_op_{}; - allocator_delete free_op_{}; - - public: - allocator_op() = default; - ~allocator_op() = default; - - allocator_op& operator=(const allocator_op&) = delete; - allocator_op(const allocator_op&) = delete; - - template - auto construct(var_type&&... args) -> std::shared_ptr - { - return std::shared_ptr(alloc_op_.template var_alloc(args...), free_op_); - } - }; - - template - using allocator = allocator_op, global_delete_op>; -} // namespace ocl - -#endif // ifndef _OCL_ALLOCATOR_SYSTEM_HPP \ No newline at end of file diff --git a/include/ocl/core/config.hpp b/include/ocl/core/config.hpp deleted file mode 100644 index 13abae0..0000000 --- a/include/ocl/core/config.hpp +++ /dev/null @@ -1,38 +0,0 @@ -/* - * File: core/config.hpp - * Purpose: Config file of the OCL. - * Author: Amlal El Mahrouss (amlal@nekernel.org) - * Copyright 2025, Amlal El Mahrouss, licensed under the Boost Software License. - */ - -#pragma once - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include - -#define OCL_DEPRECATED() [[deprecated]] -#define OCL_DEPRECATED_MSG(MSG) [[deprecated(MSG)]] - -#ifdef __cplusplus -#define OCL_DECL extern "C" -/// DLL/Dylib/So specific macro. -#define OCL_EXPORT_DECL extern "C" BOOST_SYMBOL_EXPORT -#else -#define OCL_DECL -#define OCL_EXPORT_DECL -#endif - -#ifdef _WIN32 -#define OCL_USE_CRLF_ENDINGS 1 -#define OCL_WINDOWS 1 -#endif \ No newline at end of file diff --git a/include/ocl/core/is_same.hpp b/include/ocl/core/is_same.hpp deleted file mode 100644 index 27a85d0..0000000 --- a/include/ocl/core/is_same.hpp +++ /dev/null @@ -1,108 +0,0 @@ -/* - * File: is_same.hpp - * Purpose: Equivalence header. - * Author: Amlal El Mahrouss (amlal@nekernel.org) - * Copyright 2025, Amlal El Mahrouss, licensed under the Boost Software License. - */ - -#pragma once - -#include - -/// @brief OCL equivalence namespace. -namespace ocl -{ - template - struct basic_hash - { - using result_type = typename T::result_type; - using type = T; - - /// @brief hash from T's result_type. - static result_type hash() - { - return T{}.hash(); - } - }; - - template - struct is_same - { - static constexpr bool value = false; - - /// @brief check if hash matches what we expect. - constexpr bool operator()() noexcept - { - return T::hash() == U::hash(); - } - }; - - template - struct is_same - { - static constexpr bool value = true; - }; - - template - struct is_not_same - { - static constexpr bool value = true; - - constexpr bool operator()() noexcept - { - return T::hash() != U::hash(); - } - }; - - template - struct is_not_same - { - static constexpr bool value = false; - }; - - template - struct equiv_is_int8 - { - private: - T left_ = 127, right_ = 127; - - public: - using result_type = T; - - constexpr result_type hash() - { - return (left_ + right_) < 1; - } - }; - - template - struct equiv_not_int8 - { - private: - // these shall overflow if not int8. - T left_ = 127, right_ = 127; - - public: - using result_type = T; - - constexpr result_type hash() - { - return (left_ + right_) > 0; - } - }; - - template - struct equiv_is_real - { - private: - T left_ = 5, right_ = 3; - - public: - using result_type = T; - - constexpr result_type hash() - { - return left_ / right_ == 1; - } - }; -} // namespace ocl diff --git a/include/ocl/core/option.hpp b/include/ocl/core/option.hpp deleted file mode 100644 index b5a2778..0000000 --- a/include/ocl/core/option.hpp +++ /dev/null @@ -1,134 +0,0 @@ -/* - * File: option.hpp - * Author: Amlal El Mahrouss, - * Copyright 2023-2025, Amlal El Mahrouss, Licensed under the Boost Software License - */ - -#ifndef _OCL_OPT_HPP -#define _OCL_OPT_HPP - -#include -#include - -namespace ocl -{ - enum class return_type - { - invalid = 0, - okay = 100, - err, - count = err - okay + 1, - }; - - template - struct option final - { - option() = delete; - - option(const return_type& return_type) - : ret_(return_type) - { - } - - ~option() = default; - - option& operator=(const option&) = delete; - option(const option&) = delete; - - option& expect(const char_type* input) - { - if (ret_ == return_type::err) - { - throw std::runtime_error(input ? input : "option::error"); - } - - return *this; - } - - template - option& expect_or_handle(const char_type* input) - { - if (ret_ == return_type::err) - { - ErrorHandler err_handler; - err_handler(input ? input : "option::error"); - } - - return *this; - } - - private: - return_type ret_{return_type::invalid}; - }; - - template - inline return_type eval(Teller tell, Lst&&... arg) - { - return tell(std::forward(arg)...) ? return_type::okay : return_type::err; - } - - namespace detail - { - struct int_eq_teller - { - bool operator()(int a, int b) - { - return (a == b); - } - }; - - struct int_greater_than_teller - { - bool operator()(int a, int b) - { - return (a > b); - } - }; - - struct int_less_than_teller - { - bool operator()(int a, int b) - { - return (a < b); - } - }; - } // namespace detail - - template - inline return_type eval_less_than(Lst&&... arg) - { - static detail::int_less_than_teller eq; - return eq(std::forward(arg)...) ? return_type::okay : return_type::err; - } - - template - inline return_type eval_eq(Lst&&... arg) - { - static detail::int_eq_teller less_than; - return less_than(std::forward(arg)...) ? return_type::okay : return_type::err; - } - - template - inline return_type eval_greater_than(Lst&&... arg) - { - static detail::int_greater_than_teller greater_than; - return greater_than(std::forward(arg)...) ? return_type::okay : return_type::err; - } - - inline return_type eval_true() noexcept - { - return return_type::okay; - } - - inline return_type eval_false() noexcept - { - return return_type::err; - } - - inline return_type eval_invalid() noexcept - { - return return_type::invalid; - } -} // namespace ocl - -#endif /* ifndef _OCL_OPT_HPP */ \ No newline at end of file diff --git a/include/ocl/crc_hash.hpp b/include/ocl/crc_hash.hpp new file mode 100644 index 0000000..cbb757f --- /dev/null +++ b/include/ocl/crc_hash.hpp @@ -0,0 +1,127 @@ +/* + * File: crc_hash.hpp + * Purpose: Hashing module. + * Author: Amlal El Mahrouss, + * Copyright 2025, Amlal El Mahrouss, Licensed under the Boost Software License. + */ + +#ifndef _OCL_CRC32_HPP +#define _OCL_CRC32_HPP + +#include +#include +#include +#include +#include +#include +#include + +/// @brief Crc32 implementation in C++ +/// @author Amlal El Mahrouss (amlal@nekernel.org) + +namespace ocl +{ + /// @brief implements a trait object for crc hashing. + struct crc_hash_trait + { + static constexpr const std::uint16_t crc_sz_ = 256U; + + static constexpr std::uint32_t crc_array_[crc_sz_] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, + 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, + 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, + 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, + 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, + 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, + 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, + 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, + 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, + 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, + 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, + 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, + 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, + 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, + 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, + 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, + 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, + 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d}; + + static std::size_t + crc32(const char* in, std::size_t len) noexcept + { + if (!len) + return 0; + + std::uint32_t crc = 0xffffffff; + std::size_t cnt = 0; + + while ((len--) > 0) + { + crc = (crc >> 8) ^ crc_array_[(crc ^ in[cnt]) & 0xFF]; + ++cnt; + } + + return ~crc; + } + }; + + template + using string_hash_map = std::unordered_map>; + + template + using hash_map = std::unordered_map>; +} // namespace ocl + +namespace std +{ + template <> + struct hash final + { + hash() = default; + ~hash() = default; + + template + inline std::size_t operator()(T* in_) const + { + return ocl::crc_hash_trait::crc32(reinterpret_cast(in_), sizeof(T)); + } + + inline std::size_t operator()(const char* in_) const + { + return ocl::crc_hash_trait::crc32(in_, strlen(in_)); + } + + inline std::size_t operator()(const std::string& in_) const + { + return ocl::crc_hash_trait::crc32(in_.c_str(), in_.size()); + } + }; + + // Source - https://stackoverflow.com/a/68521441 + // Posted by StoryTeller - Unslander Monica, modified by community. See post 'Timeline' for change history + // Retrieved 2025-11-30, License - CC BY-SA 4.0 + + template + struct is_invocable_hash : std::bool_constant < + requires(Fn fn, ArgTypes... arg_types) + { + {std::forward(fn)(std::forward(arg_types)...)}->std::same_as>; + }>{}; + +} // namespace std + +#endif // !_OCL_CRC32_HPP \ No newline at end of file diff --git a/include/ocl/detail/config.hpp b/include/ocl/detail/config.hpp new file mode 100644 index 0000000..c3c01ea --- /dev/null +++ b/include/ocl/detail/config.hpp @@ -0,0 +1,38 @@ +/* + * File: detail/config.hpp + * Purpose: 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. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#define OCL_DEPRECATED() [[deprecated]] +#define OCL_DEPRECATED_MSG(MSG) [[deprecated(MSG)]] + +#ifdef __cplusplus +#define OCL_DECL extern "C" +/// DLL/Dylib/So specific macro. +#define OCL_EXPORT_DECL extern "C" BOOST_SYMBOL_EXPORT +#else +#define OCL_DECL +#define OCL_EXPORT_DECL +#endif + +#ifdef _WIN32 +#define OCL_USE_CRLF_ENDINGS 1 +#define OCL_WINDOWS 1 +#endif \ No newline at end of file diff --git a/include/ocl/detail/net_config.hpp b/include/ocl/detail/net_config.hpp new file mode 100644 index 0000000..be25d1f --- /dev/null +++ b/include/ocl/detail/net_config.hpp @@ -0,0 +1,14 @@ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#ifdef OCL_WINDOWS +#error !!! "Windows is not supported yet for " !!! +#endif // OCL_WINDOWS diff --git a/include/ocl/fix/checksum.hpp b/include/ocl/fix/checksum.hpp deleted file mode 100644 index 807b9b0..0000000 --- a/include/ocl/fix/checksum.hpp +++ /dev/null @@ -1,14 +0,0 @@ -/* - * File: fix/checksum.hpp - * Purpose: Financial Information Exchange checksum in C++ - * Author: Amlal El Mahrouss (amlal@nekernel.org) - * Copyright 2025, Amlal El Mahrouss, licensed under the Boost Software License. - */ - -#pragma once - -#include - -namespace ocl::fix -{ -} \ No newline at end of file diff --git a/include/ocl/fix/parser.hpp b/include/ocl/fix/parser.hpp deleted file mode 100644 index 6455601..0000000 --- a/include/ocl/fix/parser.hpp +++ /dev/null @@ -1,165 +0,0 @@ -/* - * File: fix/parser.hpp - * Purpose: Financial Information Exchange parser in C++ - * Author: Amlal El Mahrouss (amlal@nekernel.org) - * Copyright 2025, Amlal El Mahrouss, licensed under the Boost Software License. - */ - -#ifndef _OCL_FIX_PARSER_HPP -#define _OCL_FIX_PARSER_HPP - -#include -#include -#include -#include - -namespace ocl::fix -{ - class visitor; - struct range; - class range_buffer; - - /// @brief Buffer+Length structure - using range_ptr_type = range*; - - using tag_type = std::string; - using value_type = std::string; - - namespace detail - { - inline const char* begin_fix() noexcept - { - return "FIX.4.2"; - } - } // namespace detail - - struct range final - { - char* bytes_{nullptr}; - size_t length_{}; - - bool is_valid() noexcept - { - return this->bytes_ && this->length_ > 0; - } - - explicit operator bool() - { - return this->is_valid(); - } - }; - - /// @brief Convert range to usable string. - /// @note This function assumes that the range is valid and contains ASCII bytes. - inline std::string to_string(range& range) noexcept - { - if (range.length_ < 1) - return std::string{}; - - return std::string(range.bytes_, range.length_); - } - - /// @brief a range object containing the FIX packet values. - class range_buffer final - { - public: - std::size_t magic_len_{}; - std::string magic_{}; - string_hash_map message_{}; - - static inline const char* begin = detail::begin_fix(); - - explicit range_buffer() = default; - ~range_buffer() = default; - - range_buffer& operator=(const range_buffer&) = default; - range_buffer(const range_buffer&) = default; - - value_type operator[](const tag_type& key) - { - if (key.empty()) - return value_type{}; - - auto it = message_.find(key); - if (it != message_.end()) - return it->second; - - return value_type{}; - } - - bool is_valid() - { - return this->operator[]("8").empty() == false; - } - - explicit operator bool() - { - return this->is_valid(); - } - }; - - /// @brief visitor object which returns a fix::range_buffer instance. - class visitor final - { - public: - /// AMLALE: Yeah... - static constexpr const int soh = '\x01'; - static constexpr const char eq = '='; - static constexpr uint32_t base = 10U; - - explicit visitor() = default; - ~visitor() = default; - - visitor& operator=(const visitor&) = default; - visitor(const visitor&) = default; - - range_buffer operator()(const std::string& in) - { - return this->visit(in); - } - - /// @brief Visit a FIX message and parse it into a range_buffer object. - /// @param in The input FIX message as a string. - /// @warning This function may throw exceptions. - range_buffer visit(const std::string& in) - { - range_buffer ret{}; - - if (in.empty()) - return ret; - - std::string key; - - std::size_t off = 0UL; - - while (off < in.size()) - { - std::size_t eq_pos = in.find(eq, off); - if (eq_pos == std::string::npos) - break; - - std::string tag = in.substr(off, eq_pos - off); - - std::size_t soh_pos = in.find(soh, eq_pos + 1); - if (soh_pos == std::string::npos) - soh_pos = in.size(); - - std::string value = in.substr(eq_pos + 1, soh_pos - eq_pos - 1); - - if (ret.magic_.empty()) - { - ret.magic_ = value; - ret.magic_len_ = value.size(); - } - - ret.message_[tag] = value; - - off = soh_pos + 1; - } - - return ret; - } - }; -} // namespace ocl::fix - -#endif // ifndef _OCL_FIX_PARSER_HPP \ No newline at end of file diff --git a/include/ocl/hashing/crc_hash.hpp b/include/ocl/hashing/crc_hash.hpp deleted file mode 100644 index 89f3eff..0000000 --- a/include/ocl/hashing/crc_hash.hpp +++ /dev/null @@ -1,127 +0,0 @@ -/* - * File: crc_hash.hpp - * Purpose: Hashing module. - * Author: Amlal El Mahrouss, - * Copyright 2025, Amlal El Mahrouss, Licensed under the Boost Software License. - */ - -#ifndef _OCL_CRC32_HPP -#define _OCL_CRC32_HPP - -#include -#include -#include -#include -#include -#include -#include - -/// @brief Crc32 implementation in C++ -/// @author Amlal El Mahrouss (amlal@nekernel.org) - -namespace ocl -{ - /// @brief implements a trait object for crc hashing. - struct crc_hash_trait - { - static constexpr const std::uint16_t crc_sz_ = 256U; - - static constexpr std::uint32_t crc_array_[crc_sz_] = { - 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, - 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, - 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, - 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, - 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, - 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, - 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, - 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, - 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, - 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, - 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, - 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, - 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, - 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, - 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, - 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, - 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, - 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, - 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, - 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, - 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, - 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, - 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, - 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, - 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, - 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, - 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, - 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, - 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, - 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, - 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, - 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d}; - - static std::size_t - crc32(const char* in, std::size_t len) noexcept - { - if (!len) - return 0; - - std::uint32_t crc = 0xffffffff; - std::size_t cnt = 0; - - while ((len--) > 0) - { - crc = (crc >> 8) ^ crc_array_[(crc ^ in[cnt]) & 0xFF]; - ++cnt; - } - - return ~crc; - } - }; - - template - using string_hash_map = std::unordered_map>; - - template - using hash_map = std::unordered_map>; -} // namespace ocl - -namespace std -{ - template <> - struct hash final - { - hash() = default; - ~hash() = default; - - template - inline std::size_t operator()(T* in_) const - { - return ocl::crc_hash_trait::crc32(reinterpret_cast(in_), sizeof(T)); - } - - inline std::size_t operator()(const char* in_) const - { - return ocl::crc_hash_trait::crc32(in_, strlen(in_)); - } - - inline std::size_t operator()(const std::string& in_) const - { - return ocl::crc_hash_trait::crc32(in_.c_str(), in_.size()); - } - }; - - // Source - https://stackoverflow.com/a/68521441 - // Posted by StoryTeller - Unslander Monica, modified by community. See post 'Timeline' for change history - // Retrieved 2025-11-30, License - CC BY-SA 4.0 - - template - struct is_invocable_hash : std::bool_constant < - requires(Fn fn, ArgTypes... arg_types) - { - {std::forward(fn)(std::forward(arg_types)...)}->std::same_as>; - }>{}; - -} // namespace std - -#endif // !_OCL_CRC32_HPP \ No newline at end of file diff --git a/include/ocl/io/print.hpp b/include/ocl/io/print.hpp deleted file mode 100644 index aab6925..0000000 --- a/include/ocl/io/print.hpp +++ /dev/null @@ -1,77 +0,0 @@ -/* - * File: print.hpp - * Purpose: OCL Print library - * Author: Amlal El Mahrouss. (amlal@nekernel.org) - * Copyright 2025 - */ - -#ifndef _OCL_PRINT_HPP -#define _OCL_PRINT_HPP - -#include - -#include - -#define console_io_out std::cout -#define console_io_in std::cin - -namespace ocl::io -{ - template - inline void print(T fmt) noexcept - { - console_io_out << fmt; - } - - inline void print() noexcept - { - } - - template - inline void print(Args... fmt) noexcept - { - print(fmt...); - print(); - } - - template - inline void print(T fmt, Args... other) noexcept - { - console_io_out << fmt; - print(other...); - } - - namespace detail - { - inline bool is_stdio_sync = true; - } - - inline void enable_stdio_sync(const bool& enable) noexcept - { - detail::is_stdio_sync = enable; - console_io_out.sync_with_stdio(detail::is_stdio_sync); - } - - inline const bool& is_stdio_sync() - { - return detail::is_stdio_sync; - } - - inline void lf() noexcept - { -#ifdef OCL_USE_CRLF_ENDINGS - print("\r\n"); -#else - print("\n"); -#endif - } - - template - inline void println(T... fmt) noexcept - { - print(fmt...); - lf(); - } -} // namespace ocl::io - -#endif // ifndef _OCL_PRINT_HPP diff --git a/include/ocl/is_same.hpp b/include/ocl/is_same.hpp new file mode 100644 index 0000000..3e9e706 --- /dev/null +++ b/include/ocl/is_same.hpp @@ -0,0 +1,108 @@ +/* + * File: is_same.hpp + * Purpose: Equivalence header. + * Author: Amlal El Mahrouss (amlal@nekernel.org) + * Copyright 2025, Amlal El Mahrouss, licensed under the Boost Software License. + */ + +#pragma once + +#include + +/// @brief OCL equivalence namespace. +namespace ocl +{ + template + struct basic_hash + { + using result_type = typename T::result_type; + using type = T; + + /// @brief hash from T's result_type. + static result_type hash() + { + return T{}.hash(); + } + }; + + template + struct is_same + { + static constexpr bool value = false; + + /// @brief check if hash matches what we expect. + constexpr bool operator()() noexcept + { + return T::hash() == U::hash(); + } + }; + + template + struct is_same + { + static constexpr bool value = true; + }; + + template + struct is_not_same + { + static constexpr bool value = true; + + constexpr bool operator()() noexcept + { + return T::hash() != U::hash(); + } + }; + + template + struct is_not_same + { + static constexpr bool value = false; + }; + + template + struct equiv_is_int8 + { + private: + T left_ = 127, right_ = 127; + + public: + using result_type = T; + + constexpr result_type hash() + { + return (left_ + right_) < 1; + } + }; + + template + struct equiv_not_int8 + { + private: + // these shall overflow if not int8. + T left_ = 127, right_ = 127; + + public: + using result_type = T; + + constexpr result_type hash() + { + return (left_ + right_) > 0; + } + }; + + template + struct equiv_is_real + { + private: + T left_ = 5, right_ = 3; + + public: + using result_type = T; + + constexpr result_type hash() + { + return left_ / right_ == 1; + } + }; +} // namespace ocl diff --git a/include/ocl/net/unique_socket.hpp b/include/ocl/net/unique_socket.hpp deleted file mode 100644 index d5b8b49..0000000 --- a/include/ocl/net/unique_socket.hpp +++ /dev/null @@ -1,222 +0,0 @@ -/* - * File: net/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. - */ - -#pragma once - -#include - -#include -#include -#include -#include -#include -#include -#include - -#ifdef OCL_WINDOWS -#error !!! "Windows is not supported yet for " !!! -#endif // _WIN32 - -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 diff --git a/include/ocl/option.hpp b/include/ocl/option.hpp new file mode 100644 index 0000000..73cef13 --- /dev/null +++ b/include/ocl/option.hpp @@ -0,0 +1,134 @@ +/* + * File: option.hpp + * Author: Amlal El Mahrouss, + * Copyright 2023-2025, Amlal El Mahrouss, Licensed under the Boost Software License + */ + +#ifndef _OCL_OPT_HPP +#define _OCL_OPT_HPP + +#include +#include + +namespace ocl +{ + enum class return_type + { + invalid = 0, + okay = 100, + err, + count = err - okay + 1, + }; + + template + struct option final + { + option() = delete; + + option(const return_type& return_type) + : ret_(return_type) + { + } + + ~option() = default; + + option& operator=(const option&) = delete; + option(const option&) = delete; + + option& expect(const char_type* input) + { + if (ret_ == return_type::err) + { + throw std::runtime_error(input ? input : "option::error"); + } + + return *this; + } + + template + option& expect_or_handle(const char_type* input) + { + if (ret_ == return_type::err) + { + ErrorHandler err_handler; + err_handler(input ? input : "option::error"); + } + + return *this; + } + + private: + return_type ret_{return_type::invalid}; + }; + + template + inline return_type eval(Teller tell, Lst&&... arg) + { + return tell(std::forward(arg)...) ? return_type::okay : return_type::err; + } + + namespace detail + { + struct int_eq_teller + { + bool operator()(int a, int b) + { + return (a == b); + } + }; + + struct int_greater_than_teller + { + bool operator()(int a, int b) + { + return (a > b); + } + }; + + struct int_less_than_teller + { + bool operator()(int a, int b) + { + return (a < b); + } + }; + } // namespace detail + + template + inline return_type eval_less_than(Lst&&... arg) + { + static detail::int_less_than_teller eq; + return eq(std::forward(arg)...) ? return_type::okay : return_type::err; + } + + template + inline return_type eval_eq(Lst&&... arg) + { + static detail::int_eq_teller less_than; + return less_than(std::forward(arg)...) ? return_type::okay : return_type::err; + } + + template + inline return_type eval_greater_than(Lst&&... arg) + { + static detail::int_greater_than_teller greater_than; + return greater_than(std::forward(arg)...) ? return_type::okay : return_type::err; + } + + inline return_type eval_true() noexcept + { + return return_type::okay; + } + + inline return_type eval_false() noexcept + { + return return_type::err; + } + + inline return_type eval_invalid() noexcept + { + return return_type::invalid; + } +} // namespace ocl + +#endif /* ifndef _OCL_OPT_HPP */ \ No newline at end of file diff --git a/include/ocl/print.hpp b/include/ocl/print.hpp new file mode 100644 index 0000000..53c673e --- /dev/null +++ b/include/ocl/print.hpp @@ -0,0 +1,77 @@ +/* + * File: print.hpp + * Purpose: OCL Print library + * Author: Amlal El Mahrouss. (amlal@nekernel.org) + * Copyright 2025, Amlal El Mahrouss, Licensed under the Boost Software License. Licensed under the BSL 1.0 license + */ + +#ifndef _OCL_PRINT_HPP +#define _OCL_PRINT_HPP + +#include + +#include + +#define console_io_out std::cout +#define console_io_in std::cin + +namespace ocl::io +{ + template + inline void print(T fmt) noexcept + { + console_io_out << fmt; + } + + inline void print() noexcept + { + } + + template + inline void print(Args... fmt) noexcept + { + print(fmt...); + print(); + } + + template + inline void print(T fmt, Args... other) noexcept + { + console_io_out << fmt; + print(other...); + } + + namespace detail + { + inline bool is_stdio_sync = true; + } + + inline void enable_stdio_sync(const bool& enable) noexcept + { + detail::is_stdio_sync = enable; + console_io_out.sync_with_stdio(detail::is_stdio_sync); + } + + inline const bool& is_stdio_sync() + { + return detail::is_stdio_sync; + } + + inline void lf() noexcept + { +#ifdef OCL_USE_CRLF_ENDINGS + print("\r\n"); +#else + print("\n"); +#endif + } + + template + inline void println(T... fmt) noexcept + { + print(fmt...); + lf(); + } +} // namespace ocl::io + +#endif // ifndef _OCL_PRINT_HPP diff --git a/include/ocl/unique_socket.hpp b/include/ocl/unique_socket.hpp new file mode 100644 index 0000000..a8e532e --- /dev/null +++ b/include/ocl/unique_socket.hpp @@ -0,0 +1,211 @@ +/* + * 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. + */ + +#pragma once + +#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 diff --git a/tests/fix_basic/CMakeLists.txt b/tests/fix_basic/CMakeLists.txt deleted file mode 100644 index b94e3b5..0000000 --- a/tests/fix_basic/CMakeLists.txt +++ /dev/null @@ -1,23 +0,0 @@ -cmake_minimum_required(VERSION 3.10) -project(FIXTestBasic) - -include(FetchContent) -FetchContent_Declare( - googletest - URL https://github.com/google/googletest/archive/refs/tags/v1.14.0.zip -) - -# For Windows: Prevent overriding the parent project's compiler/linker settings -set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) -FetchContent_MakeAvailable(googletest) - -enable_testing() - -add_executable(FIXTestBasic fix_test.cc) -target_link_libraries(FIXTestBasic gtest_main) - -set_property(TARGET FIXTestBasic PROPERTY CXX_STANDARD 20) -target_include_directories(FIXTestBasic PUBLIC ../../include/ocl) - -include(GoogleTest) -gtest_discover_tests(FIXTestBasic) diff --git a/tests/fix_basic/fix_test.cc b/tests/fix_basic/fix_test.cc deleted file mode 100644 index fdffc9b..0000000 --- a/tests/fix_basic/fix_test.cc +++ /dev/null @@ -1,38 +0,0 @@ -/* - * File: tests/fix_test.cc - * Purpose: Custom FIX protocol tests. - * Author: Amlal El Mahrouss (amlal@nekernel.org) - * Copyright 2025, Amlal El Mahrouss, licensed under the Boost Software License. - */ - -#include -#include - -constexpr const char default_fix[] = { - '8', '=', 'F', 'I', 'X', '.', '4', '.', '2', 0x01, - '9', '=', '6', '3', 0x01, // BodyLength = 63 - '3', '5', '=', 'A', 0x01, - '4', '9', '=', 'S', 'E', 'R', 'V', 'E', 'R', 0x01, - '5', '6', '=', 'C', 'L', 'I', 'E', 'N', 'T', 0x01, - '3', '4', '=', '1', '7', '7', 0x01, - '5', '2', '=', '2', '0', '0', '9', '0', '1', '0', '7', '-', '1', '8', ':', '1', '5', ':', '1', '6', 0x01, - '9', '8', '=', '0', 0x01, - '1', '0', '8', '=', '3', '0', 0x01, - '1', '0', '=', '1', '4', '3', 0x01, 0x00 // CheckSum = 143 -}; - -ocl::fix::basic_visitor basic_visitor; -ocl::fix::basic_range_data fix = basic_visitor.visit(default_fix); - -TEST(FIXTest, FIX1) -{ - EXPECT_TRUE(fix.is_valid()); - EXPECT_TRUE(fix["35"].empty() == false && fix["35"] == "A"); - EXPECT_TRUE(fix["49"].empty() == false && fix["49"] == "SERVER"); -} - -TEST(FIXTest, FIX2) -{ - EXPECT_TRUE(fix["133"].empty() == true && fix["133"] != ""); - EXPECT_TRUE(fix["49"].empty() == false && fix["49"] != "A"); -} diff --git a/tests/network_basic/network_basic_test.cc b/tests/network_basic/network_basic_test.cc index 60316d4..24ce3b1 100644 --- a/tests/network_basic/network_basic_test.cc +++ b/tests/network_basic/network_basic_test.cc @@ -5,8 +5,8 @@ * Copyright 2025, Amlal El Mahrouss, licensed under the Boost Software License. */ -#include -#include +#include +#include #include /// @brief Basic Send test -- cgit v1.2.3