diff options
Diffstat (limited to 'include')
| -rw-r--r-- | include/ocl/core/chunk_string.hpp | 121 | ||||
| -rw-r--r-- | include/ocl/core/error_handler.hpp | 47 | ||||
| -rw-r--r-- | include/ocl/core/includes.hpp | 23 | ||||
| -rw-r--r-- | include/ocl/except/error.hpp | 21 | ||||
| -rw-r--r-- | include/ocl/fix/fix.hpp | 211 | ||||
| -rw-r--r-- | include/ocl/io/print.hpp | 47 | ||||
| -rw-r--r-- | include/ocl/logic/equiv.hpp | 104 | ||||
| -rw-r--r-- | include/ocl/logic/math.hpp | 33 | ||||
| -rw-r--r-- | include/ocl/logic/opt.hpp | 134 | ||||
| -rw-r--r-- | include/ocl/memory/allocator_system.hpp | 74 | ||||
| -rw-r--r-- | include/ocl/memory/tracked_ptr.hpp | 241 | ||||
| -rw-r--r-- | include/ocl/net/modem.hpp | 173 | ||||
| -rw-r--r-- | include/ocl/net/url.hpp | 123 | ||||
| -rw-r--r-- | include/ocl/simd/basic_simd.hpp | 47 | ||||
| -rw-r--r-- | include/ocl/simd/simd.hpp | 61 | ||||
| -rw-r--r-- | include/ocl/tests/gtest.hpp | 10 | ||||
| -rw-r--r-- | include/ocl/tests/hpptest.hpp | 90 | ||||
| -rw-r--r-- | include/ocl/utility/cgi.hpp | 79 | ||||
| -rw-r--r-- | include/ocl/utility/crc32.hpp | 81 | ||||
| -rw-r--r-- | include/ocl/utility/embfs.hpp | 81 |
20 files changed, 1801 insertions, 0 deletions
diff --git a/include/ocl/core/chunk_string.hpp b/include/ocl/core/chunk_string.hpp new file mode 100644 index 0000000..1d922de --- /dev/null +++ b/include/ocl/core/chunk_string.hpp @@ -0,0 +1,121 @@ +/* +* File: core/chunk_string.hpp + * Purpose: String implementation for the OCL C++ library. + * Author: Amlal El Mahrouss (amlal@nekernel.org) + * Copyright 2025, Amlal El Mahrouss + */ + +#ifndef OCL_UTILITY_CHUNK_STRING_HPP +#define OCL_UTILITY_CHUNK_STRING_HPP + +#include <core/includes.hpp> +#include <io/print.hpp> +#include <cstring> + +namespace ocl +{ + template <typename char_type, std::size_t max_chunk_size = 8196> + class basic_chunk_string; + + template <typename char_type, std::size_t max_chunk_size> + class basic_chunk_string final + { + private: + char_type packed_chunks_[max_chunk_size] = {0}; + std::size_t chunk_total_{}; + + bool bad_{false}; + + public: + const bool& bad{bad_}; + + basic_chunk_string() = default; + + basic_chunk_string(const char_type* in) + { + this->operator+=(in); + } + + basic_chunk_string(const std::basic_string<char_type>& in) + { + this->operator+=(in); + } + + ~basic_chunk_string() = default; + + basic_chunk_string& operator=(const basic_chunk_string&) = delete; + basic_chunk_string(const basic_chunk_string&) = delete; + + public: + /// @brief Append a std::basic_string to the chunk string. + basic_chunk_string& operator+=(const char_type* in) + { + if (in == nullptr || bad_) + return *this; + + const auto& sz = std::strlen(in); + + this->operator+=(std::basic_string<char_type>(in, sz)); + + return *this; + } + + basic_chunk_string& operator+=(const std::basic_string<char_type>& in) + { + if (in.empty() || bad_) + return *this; + + if (in.size() > max_chunk_size) + { + bad_ = true; + return *this; + } + + if (chunk_total_ > max_chunk_size) + { + bad_ = true; + return *this; + } + + const auto& sz = in.size(); + const static auto size_max_chunk = max_chunk_size; + const auto& ptr = in.data(); + + if (chunk_total_ < size_max_chunk) + { + std::memcpy(packed_chunks_ + chunk_total_, ptr, sz); + chunk_total_ += sz; + } + + return *this; + } + + /// @brief Convert to basic_string or return from cache. + std::basic_string<char_type> str() const noexcept + { + static std::basic_string<char_type> ret; + const auto& sz = ret.size(); + + if (chunk_total_ > sz) + ret.clear(); + else + return ret; + + ret = packed_chunks_; + + return ret; + } + + void print() noexcept + { + ocl::io::print(packed_chunks_); + } + }; + + template <typename char_type> + inline void print(basic_chunk_string<char_type>& fmt) noexcept + { + fmt.print(); + } +} // namespace ocl +#endif // ifndef OCL_UTILITY_CHUNK_STRING_HPP diff --git a/include/ocl/core/error_handler.hpp b/include/ocl/core/error_handler.hpp new file mode 100644 index 0000000..f761d63 --- /dev/null +++ b/include/ocl/core/error_handler.hpp @@ -0,0 +1,47 @@ +/* +* File: core/basic_error_handler.hpp +* Purpose: Error handler container. +* Author: Amlal El Mahrouss (amlal@nekernel.org) +* Copyright 2025, Amlal El Mahrouss, Licensed under the Boost Software License. +*/ + +#ifndef _OCL_ERROR_HANDLER_HPP +#define _OCL_ERROR_HANDLER_HPP + +#include <core/includes.hpp> +#include <io/print.hpp> + +namespace ocl +{ + struct basic_error_handler; + + struct basic_error_handler + { + explicit basic_error_handler() = default; + virtual ~basic_error_handler() = default; + + basic_error_handler& operator=(const basic_error_handler&) = delete; + basic_error_handler(const basic_error_handler&) = delete; + + template <bool throw_too = false> + void error(const std::basic_string<char>& msg) + { + this->operator()(msg); + + if constexpr (throw_too) + { + throw std::runtime_error(msg); + } + } + + void operator()(const std::basic_string<char>& msg) + { + ocl::io::print(msg); + } + }; + + using standard_error_handler = basic_error_handler; + using error_handler_type = basic_error_handler; +} // namespace ocl + +#endif // ifndef _OCL_ERROR_HANDLER_HPP diff --git a/include/ocl/core/includes.hpp b/include/ocl/core/includes.hpp new file mode 100644 index 0000000..9ed8ffb --- /dev/null +++ b/include/ocl/core/includes.hpp @@ -0,0 +1,23 @@ +/* + * File: core/includes.hpp + * Purpose: Core includes of the OCL. + * Author: Amlal El Mahrouss (amlal@nekernel.org) + * Copyright 2025, Amlal El Mahrouss, licensed under the Boost Software License. + */ + +#pragma once + +#include <boost/config.hpp> +#include <boost/core/nvp.hpp> +#include <boost/core/demangle.hpp> +#include <boost/core/null_deleter.hpp> +#include <boost/container/allocator.hpp> + +namespace ocl +{ +#ifdef OCL_USE_UTF8 + using char_type = char8_t; +#else + using char_type = char; +#endif +} // namespace ocl
\ No newline at end of file diff --git a/include/ocl/except/error.hpp b/include/ocl/except/error.hpp new file mode 100644 index 0000000..cf038f8 --- /dev/null +++ b/include/ocl/except/error.hpp @@ -0,0 +1,21 @@ +/* + * File: opt.hpp + * Author: Amlal El Mahrouss, + * Copyright 2023-2025, Amlal El Mahrouss, Licensed under the Boost Software License + */ + +#ifndef _OCL_ERR_HPP +#define _OCL_ERR_HPP + +#include <stdexcept> +#include <core/error_handler.hpp> + +namespace ocl::error +{ + using runtime_error = std::runtime_error; + using fix_error = runtime_error; + using math_error = runtime_error; + using cgi_error = runtime_error; +} // namespace ocl::error + +#endif // _OCL_ERR_HPP
\ No newline at end of file diff --git a/include/ocl/fix/fix.hpp b/include/ocl/fix/fix.hpp new file mode 100644 index 0000000..0c6685d --- /dev/null +++ b/include/ocl/fix/fix.hpp @@ -0,0 +1,211 @@ +/* + * File: fix/fix.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 <cstddef> +#include <cassert> +#include <utility> +#include <string> +#include <vector> +#include <cstdint> +#include <sys/types.h> +#include <unistd.h> + +namespace ocl::fix +{ + template <typename char_type> + class basic_visitor; + + template <typename char_type> + struct basic_range; + + template <typename char_type> + class basic_range_data; + + /// @brief Buffer+Length structure + template <typename char_type = char> + using range_ptr_t = basic_range<char_type>; + + namespace detail + { + template <typename char_type = char> + const char_type* begin_fix() noexcept; + + template <> + inline const char* begin_fix<char>() noexcept + { + return "FIX.4.2"; + } + + template <> + inline const char16_t* begin_fix<char16_t>() noexcept + { + return u"FIX.4.2"; + } + + template <> + inline const char8_t* begin_fix<char8_t>() noexcept + { + return u8"FIX.4.2"; + } + } // namespace detail + + template <typename char_type = char> + struct basic_range final + { + char_type* bytes_{nullptr}; + size_t length_{}; + + bool is_valid() noexcept + { + return this->bytes_ && this->length_ > 0; + } + + explicit operator bool() + { + return this->is_valid(); + } + }; + + /// @brief Convert basic_range to usable string. + /// @note This function assumes that the basic_range is valid and contains ASCII bytes. + template <typename char_type = char> + inline std::basic_string<char_type> to_string(basic_range<char_type>& basic_range) noexcept + { + if (basic_range.length_ < 0) + return std::basic_string<char_type>{}; + + return std::basic_string<char_type>(basic_range.ascii_bytes_, basic_range.length_); + } + + /// @brief a basic_range object containing the FIX packet values. + template <typename char_type = char> + class basic_range_data final + { + public: + std::size_t magic_len_{}; + std::basic_string<char_type> magic_{}; + std::size_t body_len_{}; + std::vector<std::pair<std::basic_string<char_type>, std::basic_string<char_type>>> body_{}; + + static inline const char_type* begin = detail::begin_fix<char_type>(); + + explicit basic_range_data() = default; + ~basic_range_data() = default; + + basic_range_data& operator=(const basic_range_data&) = default; + basic_range_data(const basic_range_data&) = default; + + std::basic_string<char_type> operator[](const std::basic_string<char_type>& key) + { + if (key.empty()) + { + return std::basic_string<char_type>{}; + } + + for (const auto& pair : this->body_) + { + if (pair.first == key) + { + return pair.second; + } + } + + return std::basic_string<char_type>{}; + } + + bool is_valid() + { + return magic_.starts_with(basic_range_data<char_type>::begin); + } + + explicit operator bool() + { + return this->is_valid(); + } + }; + + /// @brief basic_visitor object which returns a fix::basic_range_data instance. + template <typename char_type = char> + class basic_visitor final + { + public: + static constexpr const char_type soh = '|'; + static constexpr const char_type eq = '='; + static constexpr uint32_t base = 10U; + + explicit basic_visitor() = default; + ~basic_visitor() = default; + + basic_visitor& operator=(const basic_visitor&) = default; + basic_visitor(const basic_visitor&) = default; + + basic_range<char_type> operator()(const std::basic_string<char_type>& in) + { + return this->visit(in); + } + + /// @brief Visit a FIX message and parse it into a basic_range_data object. + /// @param in The input FIX message as a string. + /// @warning This function may throw exceptions. + basic_range_data<char_type> visit(const std::basic_string<char_type>& in) + { + thread_local basic_range_data<char_type> ret{}; + + if (in.empty()) + return ret; + + std::basic_string<char_type> in_tmp{"", in.size()}; + + for (auto& ch : in) + { + if (ch != basic_visitor::soh) + { + in_tmp += ch; + continue; + } + + std::basic_string<char_type> key = in_tmp.substr(0, in_tmp.find(basic_visitor::eq)); + std::basic_string<char_type> val = in_tmp.substr(in_tmp.find(basic_visitor::eq) + 1); + + if (ret.magic_.empty()) + { + ret.magic_ = val; + ret.magic_len_ = ret.magic_.size(); + } + else + { + ret.body_.emplace_back(std::make_pair(key, val)); + ret.body_len_ += in_tmp.size(); + } + + in_tmp.clear(); + } + + in_tmp.clear(); + return ret; + } + }; + + template <typename char_type = char, typename error_handler> + inline void must_pass(basic_range_data<char_type>& basic_range, error_handler& handler) + { + if (!basic_range.is_valid()) + { + handler.template error<true>("Invalid FIX Message."); + } + } + + using fix_tag_type = std::uint32_t; + + using range_data = basic_range_data<char>; + using visitor = basic_visitor<char>; +} // namespace ocl::fix + +#endif // ifndef _OCL_FIX_PARSER_HPP
\ No newline at end of file diff --git a/include/ocl/io/print.hpp b/include/ocl/io/print.hpp new file mode 100644 index 0000000..c710156 --- /dev/null +++ b/include/ocl/io/print.hpp @@ -0,0 +1,47 @@ +/* + * 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 <iostream> + +namespace ocl::io +{ + template <typename T> + inline void print(T fmt) noexcept + { + std::cout << fmt; + } + + inline void print() noexcept + { + } + + template <typename... Args> + inline void print(Args... fmt) noexcept + { + print(fmt...); + print(); + } + + template <typename T, typename... Args> + inline void print(T fmt, Args... other) noexcept + { + std::cout << fmt; + print(other...); + } + + template <typename... T> + inline void println(T... fmt) noexcept + { + print(fmt...); + print("\n"); + } +} // namespace ocl::io + +#endif // ifndef _OCL_PRINT_HPP diff --git a/include/ocl/logic/equiv.hpp b/include/ocl/logic/equiv.hpp new file mode 100644 index 0000000..1bdb6d9 --- /dev/null +++ b/include/ocl/logic/equiv.hpp @@ -0,0 +1,104 @@ +/* + * File: equiv.hpp + * Purpose: Equivalence header. + * Author: Amlal El Mahrouss (amlal@nekernel.org) + * Copyright 2025, Amlal El Mahrouss, licensed under the Boost Software License. + */ + +#pragma once + +/// @brief OCL equivalence namespace. +namespace ocl::equiv +{ + template <typename T> + struct basic_hash_trait + { + /// @brief hash from T's result_type. + static typename T::result_type hash() + { + static T val; + return val.hash(); + } + }; + + template <typename T, typename U> + 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 <typename T> + struct is_same<T, T> + { + static constexpr bool value = true; + }; + + template <typename T, typename U> + struct is_not_same + { + static constexpr bool value = true; + + constexpr bool operator()() noexcept + { + return T::hash() != U::hash(); + } + }; + + template <typename T> + struct is_not_same<T, T> + { + static constexpr bool value = false; + }; + + template <typename T> + struct equiv_is_int8 + { + private: + T left_ = 127, right_ = 127; + + public: + using result_type = T; + + constexpr result_type hash() + { + return (left_ + right_) < 1; + } + }; + + template <typename T> + 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 <typename T> + 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::equiv diff --git a/include/ocl/logic/math.hpp b/include/ocl/logic/math.hpp new file mode 100644 index 0000000..d131ef9 --- /dev/null +++ b/include/ocl/logic/math.hpp @@ -0,0 +1,33 @@ +/* + * File: math.hpp + * Purpose: Mathematics c++ header. + * Author: Amlal El Mahrouss (amlal@nekernel.org) + * Copyright 2025, Amlal El Mahrouss, Licensed under the Boost Software License. + */ + +#pragma once + +namespace ocl +{ + template <__SIZE_TYPE__ T> + struct is_non_boolean_integer final + { + static constexpr const bool value = true; + }; + + template <> + struct is_non_boolean_integer<false> final + { + static constexpr const bool value = false; + }; + + template <> + struct is_non_boolean_integer<true> final + { + static constexpr const bool value = false; + }; + + constexpr inline auto not_a_number = __builtin_nanf(""); + constexpr inline auto positive_infinity = __builtin_inff(); + constexpr inline auto negative_infinity = -positive_infinity; +} // namespace ocl
\ No newline at end of file diff --git a/include/ocl/logic/opt.hpp b/include/ocl/logic/opt.hpp new file mode 100644 index 0000000..ba76885 --- /dev/null +++ b/include/ocl/logic/opt.hpp @@ -0,0 +1,134 @@ +/* + * File: opt.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 <except/error.hpp> +#include <utility> + +namespace ocl +{ + enum class return_type + { + invalid = 0, + okay = 100, + err, + count = err - okay + 1, + }; + + template <typename char_type = char> + struct opt final + { + explicit opt(const return_type& return_type) + : m_ret(return_type) + { + } + + opt& expect(const char_type* input) + { + if (m_ret == return_type::err) + { + throw std::runtime_error(input ? input : "opt::error"); + } + + return *this; + } + + template <typename ErrorHandler> + opt& expect_or_handle(const char_type* input) + { + if (m_ret == return_type::err) + { + ErrorHandler err_handler; + err_handler(input ? input : "opt::error"); + } + + return *this; + } + + private: + return_type m_ret{return_type::invalid}; + }; + + template <typename Teller, typename... Lst> + inline return_type eval(Teller tell, Lst&&... arg) + { + return tell(std::forward<Lst>(arg)...) ? return_type::okay : return_type::err; + } + + namespace traits + { + struct int_eq_teller + { + explicit int_eq_teller() + { + } + + bool operator()(int a, int b) + { + return (a == b); + } + }; + + struct int_greater_than_teller + { + explicit int_greater_than_teller() + { + } + + bool operator()(int a, int b) + { + return (a > b); + } + }; + + struct int_less_than_teller + { + explicit int_less_than_teller() + { + } + + bool operator()(int a, int b) + { + return (a < b); + } + }; + } // namespace traits + + template <typename... Lst> + inline return_type eval_less_than(Lst&&... arg) + { + static traits::int_less_than_teller eq; + return eq(std::forward<Lst>(arg)...) ? return_type::okay : return_type::err; + } + + template <typename... Lst> + inline return_type eval_eq(Lst&&... arg) + { + static traits::int_eq_teller less_than; + return less_than(std::forward<Lst>(arg)...) ? return_type::okay : return_type::err; + } + + template <typename... Lst> + inline return_type eval_greater_than(Lst&&... arg) + { + static traits::int_greater_than_teller greater_than; + return greater_than(std::forward<Lst>(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; + } +} // namespace ocl + +#endif /* ifndef _OCL_OPT_HPP */
\ No newline at end of file diff --git a/include/ocl/memory/allocator_system.hpp b/include/ocl/memory/allocator_system.hpp new file mode 100644 index 0000000..67e3266 --- /dev/null +++ b/include/ocl/memory/allocator_system.hpp @@ -0,0 +1,74 @@ +/* + * File: core/allocator_system.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 <core/includes.hpp> +#include <memory> + +namespace ocl +{ + template <typename type> + struct new_op final + { + inline auto operator()() -> type* + { + return new type; + } + + template <typename... var_type> + inline auto var_alloc(var_type... args) -> type* + { + return new type{args...}; + } + }; + + template <typename type> + struct delete_op final + { + inline auto operator()(type* t) -> void + { + delete t; + } + }; + + template <typename ret_type, typename allocator_new, typename allocator_delete> + class allocator_system + { + allocator_new m_alloc_{}; + allocator_delete m_free_{}; + + public: + allocator_system() = default; + ~allocator_system() = default; + + allocator_system& operator=(const allocator_system&) = delete; + allocator_system(const allocator_system&) = delete; + + ret_type* claim() noexcept + { + return m_alloc_(); + } + + template <typename... var_type> + auto construct(var_type... args) -> std::shared_ptr<ret_type> + { + return std::shared_ptr<ret_type>(m_alloc_.template var_alloc<var_type...>(args...), allocator_delete{}); + } + + void unclaim(ret_type* ptr) + { + m_free_(ptr); + } + }; + + template <typename type> + using standard_allocator_type = allocator_system<type, new_op<type>, delete_op<type>>; +} // namespace ocl + +#endif // ifndef _OCL_ALLOCATOR_SYSTEM_HPP
\ No newline at end of file diff --git a/include/ocl/memory/tracked_ptr.hpp b/include/ocl/memory/tracked_ptr.hpp new file mode 100644 index 0000000..fcaf898 --- /dev/null +++ b/include/ocl/memory/tracked_ptr.hpp @@ -0,0 +1,241 @@ +/* + * File: memory/tracked_ptr.hpp + * Purpose: Custom smart pointer implementation in C++ + * Author: Amlal El Mahrouss (amlal@nekernel.org) + * Copyright 2025, Amlal El Mahrouss, licensed under the Boost Software License. + */ + +#pragma once + +#include <cstddef> +#include <utility> +#include <new> +#include <atomic> + +#include <sys/types.h> +#include <unistd.h> +#include <signal.h> + +namespace ocl::memory +{ + template <typename T> + class tracked_allocator; + + template <typename T> + class tracked_mgr; + + template <typename T, typename Mgr> + class tracked_ptr; + + template <typename T> + class tracked_allocator + { + public: + std::atomic<size_t> allocated_count_ = 0; + std::atomic<size_t> deallocated_count_ = 0; + + public: + explicit tracked_allocator() = default; + virtual ~tracked_allocator() = default; + + tracked_allocator& operator=(const tracked_allocator&) = default; + tracked_allocator(const tracked_allocator&) = default; + + public: + using pointer_type = T*; + + template <typename... U> + void retain(pointer_type& ptr, U&&... args) + { + ptr = new T(std::forward<U>(args)...); + + if (ptr) + { + ++allocated_count_; + return; + } + + throw std::bad_alloc(); + } + + template <typename... U> + void must_retain(pointer_type& ptr, U&&... args) noexcept + { + this->retain(ptr, args...); + } + + void dispose(pointer_type& ptr) noexcept + { + if (ptr) + { + if (allocated_count_) + --allocated_count_; + + ++deallocated_count_; + + delete ptr; + ptr = nullptr; + } + } + }; + + template <typename T> + class tracked_mgr + { + private: + tracked_allocator<T> allocator_; + + public: + explicit tracked_mgr() = default; + virtual ~tracked_mgr() = default; + + tracked_mgr& operator=(const tracked_mgr&) = default; + tracked_mgr(const tracked_mgr&) = default; + + public: + using pointer_type = T*; + + const tracked_allocator<T>& allocator() noexcept + { + return allocator_; + } + + template <typename... U> + pointer_type retain(U&&... args) + { + pointer_type ptr = nullptr; + allocator_.retain(ptr, std::forward<U>(args)...); + + return ptr; + } + + template <typename... U> + pointer_type must_retain(U&&... args) noexcept + { + return this->retain(std::forward<U>(args)...); + } + + void dispose(pointer_type& ptr) noexcept + { + allocator_.dispose(ptr); + } + }; + + template <typename T, typename Mgr = tracked_mgr<T>> + class tracked_ptr + { + public: + static Mgr& manager() noexcept + { + static Mgr mgr; + return mgr; + } + + public: + template <typename... U> + tracked_ptr(U&&... args) + : ptr_(nullptr) + { + ptr_ = tracked_ptr::manager().retain(std::forward<U>(args)...); + } + + virtual ~tracked_ptr() noexcept + { + this->reset(); + } + + tracked_ptr(const tracked_ptr&) = delete; + tracked_ptr& operator=(const tracked_ptr&) = delete; + + public: + using pointer_type = T*; + + void reset() + { + if (ptr_) + { + tracked_ptr::manager().dispose(ptr_); + } + } + + pointer_type get() const + { + return ptr_; + } + + pointer_type data() + { + return ptr_; + } + + T& operator*() const + { + return *ptr_; + } + + pointer_type operator->() const + { + return ptr_; + } + + explicit operator bool() const + { + return ptr_ != nullptr; + } + + void swap(tracked_ptr& other) + { + std::swap(ptr_, other.ptr_); + } + + public: + tracked_ptr(tracked_ptr&& other) noexcept + : ptr_(other.ptr_) + { + other.ptr_ = nullptr; + } + + tracked_ptr& operator=(tracked_ptr&& other) noexcept + { + if (this != &other) + { + this->reset(); + ptr_ = other.ptr_; + other.ptr_ = nullptr; + } + + return *this; + } + + private: + pointer_type ptr_{nullptr}; + }; + + template <typename T> + inline auto make_tracked() -> tracked_ptr<T> + { + return tracked_ptr<T>(); + } + + template <typename U, typename... T> + inline auto make_tracked(T&&... arg) -> tracked_ptr<U> + { + return tracked_ptr<U>(std::forward<T>(arg)...); + } + + template <typename T> + inline void swap(tracked_ptr<T>& a, tracked_ptr<T>& b) + { + a.swap(b); + } + + /// @brief a Must Pass function is a standard way to verify a container' validity, inspired from NeKernel/VMKernel. + template <typename T, typename error_handler> + inline void must_pass(tracked_ptr<T>& ptr, error_handler handler) + { + if (ptr.manager().allocator().allocated_count_ < ptr.manager().allocator().deallocated_count_) + { + handler.template error<true>("Invalid TrackedPtr detected: Deallocated count exceeds allocated count."); + } + } +} // namespace ocl::memory diff --git a/include/ocl/net/modem.hpp b/include/ocl/net/modem.hpp new file mode 100644 index 0000000..08d5ca5 --- /dev/null +++ b/include/ocl/net/modem.hpp @@ -0,0 +1,173 @@ +/* + * File: net/modem.hpp + * Purpose: Modem 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 <tests/hpptest.hpp> + +#include <unistd.h> +#include <arpa/inet.h> +#include <sys/socket.h> +#include <string> +#include <cstddef> + +#define OCL_MODEM_INTERFACE : public ocl::net::modem + +#ifdef _WIN32 +#error !!! "Windows is not supported yet for <modem>" !!! +#endif // _WIN32 + +namespace ocl::net +{ + class modem; + + /// ============================================================================= + /// @brief Modem container concept, a container to read and write on a network stream. + /// ============================================================================= + class modem final + { + public: + using socket_type = int64_t; + using error_type = bool; + using condition_type = bool; + + private: + socket_type fd_{}; + condition_type is_server_{false}; + error_type bad_{true}; + + public: + const error_type& bad{bad_}; + + explicit modem() = default; + + ~modem() + { + this->destroy(); + } + + modem& operator=(const modem&) = delete; + modem(const modem&) = delete; + + static constexpr auto local_address_ip4 = "127.0.0.1"; + static constexpr auto local_address_ip6 = "::1"; + static constexpr const auto backlog_count = 5U; + + /// ============================================================================= + /// @brief Check if the modem is valid. + /// @return true if valid, false otherwise. + /// ============================================================================= + + bool is_valid() const noexcept + { + return this->fd_ != -1 && !this->bad_; + } + + template <typename ptr_type> + bool receive(ptr_type& out, std::size_t len) noexcept + { + static_assert(std::is_pointer<ptr_type>::value, "ptr_type is not a pointer!"); + + if (!out) + return false; + + if (!len) + return false; + + socket_type cl_{fd_}; + + if (this->is_server_) + cl_ = ::accept(fd_, nullptr, nullptr); + + auto ret = ::recv(cl_, out, len, 0); + + return ret > 0L; + } + + template <typename ptr_type> + bool transmit(ptr_type& out, std::size_t len) noexcept + { + static_assert(std::is_pointer<ptr_type>::value, "ptr_type is not a pointer!"); + + if (!out) + return false; + + if (!len) + return false; + + auto ret = ::send(fd_, out, len, 0); + + bad_ = !(ret >= 0L); + + return ret >= 0L; + } + + template <typename char_type> + bool transmit(const std::basic_string<char_type>& out) noexcept + { + if (out.empty()) + return false; + + auto ret = ::send(fd_, out.data(), out.size(), 0); + + bad_ = !(ret >= 0L); + + return ret >= 0L; + } + + template <int32_t af, int32_t kind, int32_t port> + bool construct(const char* addr = modem::local_address_ip4, const bool& is_server = false) noexcept + { + static_assert(af != 0, "Address family is zero"); + static_assert(kind != 0, "Kind is zero"); + + must_pass<af == AF_INET || af == AF_INET6>(); + must_pass<kind == SOCK_STREAM || kind == SOCK_DGRAM>(); + must_pass<(port > 0) && (port < 65536)>(); + + fd_ = ::socket(af, kind, 0); + is_server_ = is_server; + + if (fd_ == -1) + return false; + + struct sockaddr_in addr_; + std::memset(&addr_, 0, sizeof(struct sockaddr_in)); + + addr_.sin_addr.s_addr = ::inet_addr(addr); + addr_.sin_port = htons(port); + addr_.sin_family = af; + + if (!is_server) + { + const auto ret = ::connect(fd_, reinterpret_cast<struct sockaddr*>(&addr_), sizeof(addr_)); + return ret == 0L; + } + + int ret = ::bind(fd_, (struct sockaddr*)&addr_, sizeof(addr_)); + + bad_ = ret == -1; + + ::listen(fd_, modem::backlog_count); + + return bad_ == false; + } + + bool destroy() noexcept + { + if (!fd_) + return false; + + ::shutdown(fd_, SHUT_RDWR); + ::close(fd_); + + fd_ = 0L; + + return true; + } + }; +} // namespace ocl::net diff --git a/include/ocl/net/url.hpp b/include/ocl/net/url.hpp new file mode 100644 index 0000000..ebfc57a --- /dev/null +++ b/include/ocl/net/url.hpp @@ -0,0 +1,123 @@ +/* + * File: net/url.hpp + * Purpose: URL container in modern C++ + * Author: Amlal El Mahrouss (amlal@nekernel.org) + * Copyright 2025, Amlal El Mahrouss, licensed under the Boost Software License. + */ + +#pragma once + +#include <string> +#include <sstream> + +/// @author Amlal El Mahrouss (amlal@nekernel.org) +/// @brief Parse URLs (in a non-standard way). + +namespace ocl::net +{ + template <typename char_type> + class basic_url; + + /// @brief Basic URL parser container. + template <typename char_type> + class basic_url final + { + public: + using reference = basic_url&; + + enum + { + invalid = 0, + http, + https, + mailto, + ftp, + tel, + bad = 0xff, + }; + + uint32_t m_protocol_{basic_url::invalid}; + std::basic_stringstream<char_type> m_ss_{}; + std::basic_string<char_type> m_port_{""}; + + public: + explicit basic_url(const std::basic_string<char_type>& protocol) + { + if (protocol.starts_with("https://")) + { + m_protocol_ = basic_url::https; + this->operator/=(protocol.substr(std::size("https://"))); + } + else if (protocol.starts_with("http://")) + { + m_protocol_ = basic_url::http; + this->operator/=(protocol.substr(std::size("http://"))); + } + else if (protocol.starts_with("mailto:")) + { + m_protocol_ = basic_url::mailto; + this->operator/=(protocol.substr(std::size("mailto:"))); + } + else if (protocol.starts_with("tel:")) + { + m_protocol_ = basic_url::tel; + this->operator/=(protocol.substr(std::size("tel:"))); + } + else if (protocol.starts_with("ftp:")) + { + m_protocol_ = basic_url::ftp; + this->operator/=(protocol.substr(std::size("ftp:"))); + } + } + + ~basic_url() = default; + + basic_url& operator=(const basic_url&) = default; + basic_url(const basic_url&) = default; + + private: + reference operator/=(const std::basic_string<char_type>& in) + { + if (in.empty()) + return *this; + + if (in.starts_with(":")) + { + m_port_ = in.substr(1); + return *this; + } + + m_ss_ += in; + return *this; + } + + reference operator/=(const char_type& in) + { + m_ss_ += in; + return *this; + } + + explicit operator bool() + { + return this->is_valid(); + } + + public: + uint32_t protocol() const noexcept + { + return this->m_protocol_; + } + + std::basic_string<char_type> port() const noexcept + { + return this->m_port_; + } + + bool is_valid() const noexcept + { + return m_ss_.size() > 0 && this->m_protocol_ != basic_url::bad || this->m_protocol_ != basic_url::invalid; + } + }; + + using url = basic_url<char>; +} // namespace ocl::net diff --git a/include/ocl/simd/basic_simd.hpp b/include/ocl/simd/basic_simd.hpp new file mode 100644 index 0000000..a401dbd --- /dev/null +++ b/include/ocl/simd/basic_simd.hpp @@ -0,0 +1,47 @@ +/* + * File: simd/basic_simd.hpp + * Purpose: Basic SIMD backend C++ library. + * Author: Amlal El Mahrouss (amlal@nekernel.org) + * Copyright 2025, Amlal El Mahrouss, licensed under the BSL 1.0 license. + */ + +#pragma once + +#include <core/includes.hpp> + +#ifdef __x86_64__ +#include <immintrin.h> +using simd_type = __m256; +#endif + +#ifdef __aarch64__ +#include <arm_neon.h> +using simd_type = float32x4_t; +#endif + +namespace ocl::simd +{ + struct basic_simd final + { + struct simd_traits final + { + simd_type __val; + + private: + static bool bad; + friend class basic_simd; + }; + + using register_type = simd_traits; + + const bool& is_bad() noexcept + { + return register_type::bad; + } + + std::basic_string<char> isa() + { + return "basic_simd"; + } + }; +} // namespace ocl::simd diff --git a/include/ocl/simd/simd.hpp b/include/ocl/simd/simd.hpp new file mode 100644 index 0000000..711bf31 --- /dev/null +++ b/include/ocl/simd/simd.hpp @@ -0,0 +1,61 @@ +/* + * File: simd/simd.hpp + * Purpose: SIMD C++ library. + * Author: Amlal El Mahrouss (amlal@nekernel.org) + * Copyright 2025, Amlal El Mahrouss, licensed under the BSL 1.0 license. + */ + +#pragma once + +#include <core/includes.hpp> + +/// @author Amlal El Mahrouss +/// @brief Basic SIMD processor. + +namespace ocl::simd +{ + template <typename backend_type> + class real_type + { + private: + backend_type backend_; + + enum opcode + { + bad = 0, + add, + mul, + div, + invalid = 0xfff, + }; + + public: + real_type() = default; + virtual ~real_type() = default; + + real_type& operator=(const real_type&) = delete; + real_type(const real_type&) = delete; + + typename backend_type::register_type& call(const opcode& op, typename backend_type::register_type& lhs, typename backend_type::register_type& rhs) + { + switch (op) + { + case add: + return backend_.add(lhs, rhs); + case mul: + return backend_.mul(lhs, rhs); + case div: + return backend_.div(lhs, rhs); + default: + break; + } + + return backend_.is_bad(); + } + + std::basic_string<char> isa() + { + return backend_.isa(); + } + }; +} // namespace ocl::simd diff --git a/include/ocl/tests/gtest.hpp b/include/ocl/tests/gtest.hpp new file mode 100644 index 0000000..ee328b0 --- /dev/null +++ b/include/ocl/tests/gtest.hpp @@ -0,0 +1,10 @@ +/* + * File: tests/gtest.hpp + * Purpose: Google Test wrapper for the OCL library. + * Author: Amlal El Mahrouss (amlal@nekernel.org) + * Copyright 2025, Amlal El Mahrouss, licensed under the Boost Software License. + */ + +#pragma once + +#include <gtest/gtest.h> diff --git a/include/ocl/tests/hpptest.hpp b/include/ocl/tests/hpptest.hpp new file mode 100644 index 0000000..0c7b4e5 --- /dev/null +++ b/include/ocl/tests/hpptest.hpp @@ -0,0 +1,90 @@ +/* + * File: tests/hpptest.hpp + * Purpose: HPP Test wrapper for the OCL library. + * Author: Amlal El Mahrouss (amlal@nekernel.org) + * Copyright 2025, Amlal El Mahrouss, licensed under the Boost Software License. + */ + +#pragma once + +#include <io/print.hpp> +#include <cstdlib> + +namespace ocl::hpptest +{ + /// @brief Standard termination error handler, called when a test fails. + struct standard_terminate final + { + template <bool stop_execution = true> + static void error() noexcept + { + ocl::io::print("standard_terminate::error, terminating...\n"); + + if (stop_execution) + std::terminate(); + } + }; + + struct posix_terminate final + { + template <bool stop_execution = true, errno_t args> + static void error(errno_t err) noexcept + { + ocl::io::print("posix_terminate::error: expected=", strerror(args), ", got=", strerror(err), "\n"); + + if (stop_execution) + std::terminate(); + } + }; + + typedef bool condition_type; + + template <condition_type expr = true> + consteval inline void must_be() + { +#ifdef OCL_HPPTEST + OCL_HPPTEST_ASSERT(expr); +#endif // _WIN32 + } + + template <condition_type expect, typename on_fail> + inline void must_be(condition_type cond) noexcept + { + if (cond != expect) + { + on_fail::template error<true>(); + } + } + + template <errno_t expect = 0> + inline void must_be(errno_t ern) noexcept + { + if (ern != expect) + { + posix_terminate::error<true, expect>(ern); + } + } + +#ifdef _WIN32 + struct win32_terminate final + { + template <bool stop_execution = false> + static void error(HRESULT err) noexcept + { + ocl::io::print("win32_terminate::error: expected=S_OK, got=", err, "\n"); + + if (stop_execution) + std::terminate(); + } + }; + + template <HRESULT expect = S_OK> + inline void must_be(HRESULT hr) noexcept + { + if (hr != expect) + { + win32_terminate::error<true>(hr); + } + } +#endif // _WIN32 +} // namespace ocl::hpptest diff --git a/include/ocl/utility/cgi.hpp b/include/ocl/utility/cgi.hpp new file mode 100644 index 0000000..8849c2d --- /dev/null +++ b/include/ocl/utility/cgi.hpp @@ -0,0 +1,79 @@ +/* + * File: cgi.hpp + * Author: Amlal El Mahrouss, + * Copyright 2023-2025, Amlal El Mahrouss, Licensed under the Boost Software License. + */ + +#ifndef _OCL_CGI_HPP +#define _OCL_CGI_HPP + +#include <io/print.hpp> +#include <core/chunk_string.hpp> +#include <sstream> +#include <format> + +namespace ocl +{ + namespace cgi + { + /// @brief CGI Writer class, writes to stdout; as CGI expects. + template <typename char_type = char> + class basic_writer + { + private: + basic_writer& eval_(const basic_chunk_string<char_type>& mime, const basic_chunk_string<char_type>& ss) noexcept + { + std::basic_stringstream<char_type> ss_out; + + ss_out << std::format("Content-Type: {}\r\n", mime.str()); + ss_out << std::format("Server: {}\r\n", "OCL/1.0"); + ss_out << std::format("Content-Length: {}\r\n\r\n", ss.str().size()); + ss_out << ss.str(); + + io::print(ss_out.str()); + + return *this; + } + + public: + explicit basic_writer() = default; + virtual ~basic_writer() = default; + + basic_writer& operator=(const basic_writer&) = default; + basic_writer(const basic_writer&) = default; + + public: + friend void operator<<(basic_writer& self, const basic_chunk_string<char_type>& ss_in) + { + self = self.eval_("text/plain", ss_in); + } + + basic_writer& binary(const basic_chunk_string<char_type>& ss_in) + { + return this->eval_("application/octet-stream", ss_in); + } + + basic_writer& html(const basic_chunk_string<char_type>& ss_in) + { + return this->eval_("text/html", ss_in); + } + + basic_writer& xml(const basic_chunk_string<char_type>& ss_in) + { + return this->eval_("application/xml", ss_in); + } + + basic_writer& json(const basic_chunk_string<char_type>& ss_in) + { + return this->eval_("application/json", ss_in); + } + + basic_writer& js(const basic_chunk_string<char_type>& ss_in) + { + return this->eval_("text/javascript", ss_in); + } + }; + } // namespace cgi +} // namespace ocl + +#endif // ifndef _OCL_CGI_HPP diff --git a/include/ocl/utility/crc32.hpp b/include/ocl/utility/crc32.hpp new file mode 100644 index 0000000..2bcab29 --- /dev/null +++ b/include/ocl/utility/crc32.hpp @@ -0,0 +1,81 @@ +/* + * File: crc32.hpp + * Purpose: CRC32 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 <cstdint> +#include <string> +#include <cstddef> + +/// @brief Crc32 implementation in C++ +/// @author Amlal EL Mahrouss (amlal@nekernel.org) + +namespace ocl::crc32 +{ + namespace detail + { + inline constexpr const std::uint16_t crc_sz_ = 256U; + + inline 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}; + + template <typename char_type> + inline std::uint32_t + crc32(const char_type* in, size_t len) noexcept + { + if (!in || *in == 0) + return 0; + + std::uint32_t crc = 0xffffffff; + + while ((len--) > 0) + crc = (crc >> 8) ^ crc_array_[(crc ^ *(in++)) & 0xFF]; + + return ~crc; + } + } // namespace detail + + template <typename char_type = char> + inline std::uint32_t hash(const std::basic_string<char_type>& in) + { + return detail::crc32(in.c_str(), in.size()); + } +} // namespace ocl::crc32 + +#endif // !_OCL_CRC32_HPP
\ No newline at end of file diff --git a/include/ocl/utility/embfs.hpp b/include/ocl/utility/embfs.hpp new file mode 100644 index 0000000..8a716ce --- /dev/null +++ b/include/ocl/utility/embfs.hpp @@ -0,0 +1,81 @@ +/* + * File: embfs.hpp + * Purpose: Embedded File System. + * Author: Amlal El Mahrouss (amlal@nekernel.org) + * Copyright 2025, Amlal El Mahrouss, Licensed under the Boost Software License. + */ + +#ifndef _OCL_EMBFS_HPP +#define _OCL_EMBFS_HPP + +#include <cstdint> +#include <cstddef> + +/// @brief A filesystem designed for tiny storage medias. +/// @author Amlal EL Mahrouss (amlal@nekernel.org) + +namespace ocl::embfs +{ + namespace traits + { + struct embfs_superblock; + struct embfs_inode; + + inline constexpr const size_t _superblock_name_len = 16; + inline constexpr const size_t _superblock_reserve_len = 462; + + inline constexpr const size_t _inode_name_len = 128; + inline constexpr const size_t _inode_arr_len = 12; + inline constexpr const size_t _inode_lookup_len = 8; + +#if defined(EMBFS_28BIT_LBA) + typedef std::uint32_t lba_t; +#elif defined(EMBFS_48BIT_LBA) + typedef std::uint64_t lba_t; +#else + typedef std::uint32_t lba_t; +#endif + + typedef std::int16_t sword_t; + + typedef std::int32_t sdword_t; + + typedef std::uint8_t utf8_char_t; + + /// @brief Superblock data structure + struct embfs_superblock + { + sword_t s_block_mag; + sdword_t s_num_inodes; + sdword_t s_part_size; + sdword_t s_part_used; + sdword_t s_version; + sword_t s_sector_sz; + lba_t s_inode_start; + lba_t s_inode_end; + utf8_char_t s_name[_superblock_name_len]; + utf8_char_t s_reserved[_superblock_reserve_len]; + }; + + /// @brief Indexed node structure. + /// @brief i_name file name + /// @brief i_size_virt, i_size_phys: virtual and physical (sector count) size. + /// @brief i_offset direct block pointer. + /// @brief i_checksum crc32 checksum. + /// @brief i_flags_perms flags and permissions + /// @brief i_acl_* ACL to keep track of inode allocation status. + struct embfs_inode + { + utf8_char_t i_name[_inode_name_len]; + sword_t i_size_virt, i_size_phys; + lba_t i_offset[_inode_lookup_len]; + sword_t i_checksum, i_flags_perms; + lba_t i_acl_creat, i_acl_edit, i_acl_delet; + }; + + /// @brief Indexed node linear array. + typedef embfs_inode embfs_inode_arr_t[_inode_arr_len]; + } // namespace traits +} // namespace ocl::embfs + +#endif // ifndef _OCL_EMBFS_HPP
\ No newline at end of file |
