From fb74ba4fb709f554ad3aca6ffadcfd166f31b298 Mon Sep 17 00:00:00 2001 From: Max Qian Date: Sat, 27 Apr 2024 21:07:19 +0800 Subject: [PATCH 1/4] update -- rewrite atom-algorithm and atom-async -- remove experiment folder --- src/atom/algorithm/CMakeLists.txt | 1 + src/atom/algorithm/_component.cpp | 0 src/atom/algorithm/_pybind.cpp | 16 +- src/atom/algorithm/_script.hpp | 21 +- src/atom/algorithm/algorithm.cpp | 4 +- src/atom/algorithm/algorithm.hpp | 32 +- src/atom/algorithm/algorithm.inl | 40 + src/atom/algorithm/base.cpp | 4 +- src/atom/algorithm/base.hpp | 4 +- src/atom/algorithm/convolve.cpp | 332 ++++-- src/atom/algorithm/convolve.hpp | 117 +- src/atom/algorithm/fraction.cpp | 4 +- src/atom/algorithm/fraction.hpp | 4 +- src/atom/algorithm/hash.hpp | 4 +- src/atom/algorithm/huffman.cpp | 4 +- src/atom/algorithm/huffman.hpp | 4 +- src/atom/algorithm/math.cpp | 4 +- src/atom/algorithm/math.hpp | 4 +- src/atom/algorithm/md5.cpp | 4 +- src/atom/algorithm/md5.hpp | 4 +- src/atom/algorithm/meson.build | 3 +- src/atom/algorithm/mhash.cpp | 18 +- src/atom/algorithm/mhash.hpp | 11 +- src/atom/algorithm/xmake.lua | 1 + src/atom/async/CMakeLists.txt | 11 +- src/atom/async/_pybind.cpp | 77 +- src/atom/async/async.hpp | 6 +- src/atom/async/{async_impl.hpp => async.inl} | 60 +- src/atom/async/lock.cpp | 4 +- src/atom/async/lock.hpp | 4 +- src/atom/async/meson.build | 74 +- src/atom/async/pool.hpp | 71 +- src/atom/async/queue.hpp | 6 +- src/atom/async/queue.inl | 4 +- src/atom/async/thread_wrapper.hpp | 2 + src/atom/async/timer.cpp | 4 +- src/atom/async/timer.hpp | 4 +- src/atom/async/trigger.hpp | 4 +- .../async/{trigger_impl.hpp => trigger.inl} | 13 +- src/atom/async/xmake.lua | 83 +- src/atom/components/component.hpp | 2 +- src/atom/components/dispatch.hpp | 2 +- src/atom/components/templates/shared.cpp | 2 +- src/atom/components/var.hpp | 2 +- src/atom/connection/_pybind.cpp | 2 +- src/atom/connection/fifoclient.cpp | 4 +- src/atom/connection/fifoclient.hpp | 4 +- src/atom/connection/fifoserver.cpp | 4 +- src/atom/connection/fifoserver.hpp | 4 +- src/atom/connection/shared_memory.hpp | 4 +- src/atom/connection/sockethub.cpp | 4 +- src/atom/connection/sockethub.hpp | 4 +- src/atom/connection/sshclient.cpp | 4 +- src/atom/connection/sshclient.hpp | 4 +- src/atom/connection/udp_server.cpp | 4 +- src/atom/connection/udp_server.hpp | 4 +- src/atom/driver/config/basic.cpp | 345 ------ src/atom/driver/config/basic.hpp | 146 --- src/atom/driver/config/basic_p.hpp | 47 - src/atom/driver/config/blob.cpp | 73 -- src/atom/driver/config/blob.hpp | 49 - src/atom/driver/config/blob_p.hpp | 35 - src/atom/driver/config/macros.hpp | 177 --- src/atom/driver/config/number.cpp | 65 - src/atom/driver/config/number.hpp | 45 - src/atom/driver/config/number_p.hpp | 36 - src/atom/driver/config/properties.cpp | 160 --- src/atom/driver/config/properties.hpp | 95 -- src/atom/driver/config/properties_p.hpp | 34 - src/atom/driver/config/property.cpp | 406 ------- src/atom/driver/config/property.hpp | 147 --- src/atom/driver/config/property_p.hpp | 65 - src/atom/driver/config/switch.cpp | 118 -- src/atom/driver/config/switch.hpp | 68 -- src/atom/driver/config/switch_p.hpp | 44 - src/atom/driver/config/text.cpp | 54 - src/atom/driver/config/text.hpp | 42 - src/atom/driver/config/text_p.hpp | 36 - src/atom/driver/config/traits.hpp | 79 -- src/atom/driver/config/view.cpp | 294 ----- src/atom/driver/config/view.hpp | 1053 ----------------- src/atom/error/_script.hpp | 2 +- src/atom/error/error_stack.cpp | 4 +- src/atom/error/error_stack.hpp | 7 +- src/atom/error/exception.cpp | 8 +- src/atom/error/exception.hpp | 6 +- src/atom/event/CMakeLists.txt | 158 --- src/atom/event/LICENSE | 201 ---- src/atom/event/README.md | 122 -- src/atom/event/eventloop.cpp | 546 --------- src/atom/event/eventloop.hpp | 311 ----- src/atom/event/kev.cpp | 170 --- src/atom/event/kev.hpp | 287 ----- src/atom/event/kevdefs.hpp | 94 -- src/atom/event/kmconf.hpp | 52 - src/atom/event/kmtypes.hpp | 58 - src/atom/event/poll/CVPoll.cpp | 76 -- src/atom/event/poll/EPoll.cpp | 197 --- src/atom/event/poll/KQueue.cpp | 259 ---- src/atom/event/poll/Notifier.cpp | 77 -- src/atom/event/poll/RunLoop.mm | 309 ----- src/atom/event/poll/SelectPoll.cpp | 237 ---- src/atom/event/poll/VPoll.cpp | 229 ---- src/atom/event/poll/WinPoll.cpp | 223 ---- src/atom/event/poll/event_notifier.hpp | 73 -- src/atom/event/poll/iocp.cpp | 159 --- src/atom/event/poll/iopoll.hpp | 123 -- src/atom/event/poll/notifier.hpp | 40 - src/atom/event/poll/pipe_notifier.hpp | 86 -- src/atom/event/poll/socket_notifier.hpp | 118 -- src/atom/event/timer.cpp | 430 ------- src/atom/event/timer.hpp | 163 --- src/atom/event/utils/defer.hpp | 54 - src/atom/event/utils/destroy_detector.hpp | 72 -- src/atom/event/utils/kmobject.hpp | 48 - src/atom/event/utils/kmqueue.hpp | 223 ---- src/atom/event/utils/kmtrace.cpp | 165 --- src/atom/event/utils/kmtrace.hpp | 79 -- src/atom/event/utils/skutils.hpp | 217 ---- src/atom/event/utils/utils.cpp | 894 -------------- src/atom/event/utils/utils.hpp | 168 --- src/atom/experiment/CMakeLists.txt | 70 -- src/atom/experiment/meson.build | 50 - src/atom/experiment/xmake.lua | 65 - src/atom/{type => function}/abi.hpp | 0 .../{experiment => function}/bind_first.hpp | 0 .../{experiment => function}/callable.hpp | 0 .../{experiment => function}/decorate.hpp | 0 .../{experiment => function}/func_traits.hpp | 0 src/atom/{experiment => function}/invoke.hpp | 0 .../{experiment => function}/type_info.hpp | 0 src/atom/{experiment => memory}/memory.hpp | 2 +- src/atom/{experiment => memory}/object.hpp | 0 .../{experiment => memory}/short_alloc.hpp | 0 src/atom/server/commander.hpp | 2 +- src/atom/server/daemon.cpp | 4 +- src/atom/server/daemon.hpp | 4 +- src/atom/server/global_ptr.hpp | 2 +- src/atom/server/variables.hpp | 2 +- src/atom/{experiment => system}/platform.cpp | 0 src/atom/{experiment => system}/platform.hpp | 0 src/atom/{experiment => type}/any.hpp | 0 src/atom/{experiment => type}/flatmap.hpp | 0 src/atom/type/flatset.hpp | 2 + src/atom/type/ini.cpp | 51 +- src/atom/type/ini.hpp | 13 +- src/atom/type/{ini_impl.hpp => ini.inl} | 13 +- src/atom/{experiment => type}/iter.hpp | 0 src/atom/{experiment => type}/list.hpp | 0 src/atom/{experiment => type}/noncopyable.hpp | 0 src/atom/{experiment => type}/optional.hpp | 0 .../{experiment => type}/short_string.cpp | 0 .../{experiment => type}/short_string.hpp | 0 .../{experiment => type}/stack_vector.hpp | 0 .../sstring.hpp => type/static_string.hpp} | 0 .../{experiment => type}/static_vector.hpp | 0 src/atom/{experiment => type}/string.cpp | 0 src/atom/{experiment => type}/string.hpp | 0 src/atom/{experiment => utils}/anyutils.hpp | 10 +- src/atom/{experiment => utils}/ranges.hpp | 0 src/atom/utils/switch.hpp | 2 +- src/atom/{experiment => utils}/to_string.hpp | 0 162 files changed, 720 insertions(+), 11151 deletions(-) delete mode 100644 src/atom/algorithm/_component.cpp create mode 100644 src/atom/algorithm/algorithm.inl rename src/atom/async/{async_impl.hpp => async.inl} (76%) rename src/atom/async/{trigger_impl.hpp => trigger.inl} (95%) delete mode 100644 src/atom/driver/config/basic.cpp delete mode 100644 src/atom/driver/config/basic.hpp delete mode 100644 src/atom/driver/config/basic_p.hpp delete mode 100644 src/atom/driver/config/blob.cpp delete mode 100644 src/atom/driver/config/blob.hpp delete mode 100644 src/atom/driver/config/blob_p.hpp delete mode 100644 src/atom/driver/config/macros.hpp delete mode 100644 src/atom/driver/config/number.cpp delete mode 100644 src/atom/driver/config/number.hpp delete mode 100644 src/atom/driver/config/number_p.hpp delete mode 100644 src/atom/driver/config/properties.cpp delete mode 100644 src/atom/driver/config/properties.hpp delete mode 100644 src/atom/driver/config/properties_p.hpp delete mode 100644 src/atom/driver/config/property.cpp delete mode 100644 src/atom/driver/config/property.hpp delete mode 100644 src/atom/driver/config/property_p.hpp delete mode 100644 src/atom/driver/config/switch.cpp delete mode 100644 src/atom/driver/config/switch.hpp delete mode 100644 src/atom/driver/config/switch_p.hpp delete mode 100644 src/atom/driver/config/text.cpp delete mode 100644 src/atom/driver/config/text.hpp delete mode 100644 src/atom/driver/config/text_p.hpp delete mode 100644 src/atom/driver/config/traits.hpp delete mode 100644 src/atom/driver/config/view.cpp delete mode 100644 src/atom/driver/config/view.hpp delete mode 100644 src/atom/event/CMakeLists.txt delete mode 100644 src/atom/event/LICENSE delete mode 100644 src/atom/event/README.md delete mode 100644 src/atom/event/eventloop.cpp delete mode 100644 src/atom/event/eventloop.hpp delete mode 100644 src/atom/event/kev.cpp delete mode 100644 src/atom/event/kev.hpp delete mode 100644 src/atom/event/kevdefs.hpp delete mode 100644 src/atom/event/kmconf.hpp delete mode 100644 src/atom/event/kmtypes.hpp delete mode 100644 src/atom/event/poll/CVPoll.cpp delete mode 100644 src/atom/event/poll/EPoll.cpp delete mode 100644 src/atom/event/poll/KQueue.cpp delete mode 100644 src/atom/event/poll/Notifier.cpp delete mode 100644 src/atom/event/poll/RunLoop.mm delete mode 100644 src/atom/event/poll/SelectPoll.cpp delete mode 100644 src/atom/event/poll/VPoll.cpp delete mode 100644 src/atom/event/poll/WinPoll.cpp delete mode 100644 src/atom/event/poll/event_notifier.hpp delete mode 100644 src/atom/event/poll/iocp.cpp delete mode 100644 src/atom/event/poll/iopoll.hpp delete mode 100644 src/atom/event/poll/notifier.hpp delete mode 100644 src/atom/event/poll/pipe_notifier.hpp delete mode 100644 src/atom/event/poll/socket_notifier.hpp delete mode 100644 src/atom/event/timer.cpp delete mode 100644 src/atom/event/timer.hpp delete mode 100644 src/atom/event/utils/defer.hpp delete mode 100644 src/atom/event/utils/destroy_detector.hpp delete mode 100644 src/atom/event/utils/kmobject.hpp delete mode 100644 src/atom/event/utils/kmqueue.hpp delete mode 100644 src/atom/event/utils/kmtrace.cpp delete mode 100644 src/atom/event/utils/kmtrace.hpp delete mode 100644 src/atom/event/utils/skutils.hpp delete mode 100644 src/atom/event/utils/utils.cpp delete mode 100644 src/atom/event/utils/utils.hpp delete mode 100644 src/atom/experiment/CMakeLists.txt delete mode 100644 src/atom/experiment/meson.build delete mode 100644 src/atom/experiment/xmake.lua rename src/atom/{type => function}/abi.hpp (100%) rename src/atom/{experiment => function}/bind_first.hpp (100%) rename src/atom/{experiment => function}/callable.hpp (100%) rename src/atom/{experiment => function}/decorate.hpp (100%) rename src/atom/{experiment => function}/func_traits.hpp (100%) rename src/atom/{experiment => function}/invoke.hpp (100%) rename src/atom/{experiment => function}/type_info.hpp (100%) rename src/atom/{experiment => memory}/memory.hpp (99%) rename src/atom/{experiment => memory}/object.hpp (100%) rename src/atom/{experiment => memory}/short_alloc.hpp (100%) rename src/atom/{experiment => system}/platform.cpp (100%) rename src/atom/{experiment => system}/platform.hpp (100%) rename src/atom/{experiment => type}/any.hpp (100%) rename src/atom/{experiment => type}/flatmap.hpp (100%) rename src/atom/type/{ini_impl.hpp => ini.inl} (90%) rename src/atom/{experiment => type}/iter.hpp (100%) rename src/atom/{experiment => type}/list.hpp (100%) rename src/atom/{experiment => type}/noncopyable.hpp (100%) rename src/atom/{experiment => type}/optional.hpp (100%) rename src/atom/{experiment => type}/short_string.cpp (100%) rename src/atom/{experiment => type}/short_string.hpp (100%) rename src/atom/{experiment => type}/stack_vector.hpp (100%) rename src/atom/{experiment/sstring.hpp => type/static_string.hpp} (100%) rename src/atom/{experiment => type}/static_vector.hpp (100%) rename src/atom/{experiment => type}/string.cpp (100%) rename src/atom/{experiment => type}/string.hpp (100%) rename src/atom/{experiment => utils}/anyutils.hpp (97%) rename src/atom/{experiment => utils}/ranges.hpp (100%) rename src/atom/{experiment => utils}/to_string.hpp (100%) diff --git a/src/atom/algorithm/CMakeLists.txt b/src/atom/algorithm/CMakeLists.txt index ee460e74..4e9fed16 100644 --- a/src/atom/algorithm/CMakeLists.txt +++ b/src/atom/algorithm/CMakeLists.txt @@ -24,6 +24,7 @@ set(${PROJECT_NAME}_SOURCES # Headers set(${PROJECT_NAME}_HEADERS algorithm.hpp + algorithm.inl base.hpp convolve.hpp fraction.hpp diff --git a/src/atom/algorithm/_component.cpp b/src/atom/algorithm/_component.cpp deleted file mode 100644 index e69de29b..00000000 diff --git a/src/atom/algorithm/_pybind.cpp b/src/atom/algorithm/_pybind.cpp index 8e6ef5f7..acc41066 100644 --- a/src/atom/algorithm/_pybind.cpp +++ b/src/atom/algorithm/_pybind.cpp @@ -28,8 +28,7 @@ Description: Python Binding of Atom-Algorithm namespace py = pybind11; -using namespace Atom::Algorithm; -using namespace Atom::Utils; +using namespace atom::algorithm; PYBIND11_MODULE(atom_algorithm, m) { m.doc() = "Atom Algorithm Python Binding"; @@ -63,6 +62,15 @@ PYBIND11_MODULE(atom_algorithm, m) { py::arg("input"), py::arg("kernel"), py::arg("numThreads") = 1); m.def("deconvolve2D", &deconvolve2D, "Perform two-dimensional deconvolution"); + m.def("DFT2D", &DFT2D, "Perform two-dimensional discrete Fourier transform", + py::arg("signal"), py::arg("numThreads") = 1); + m.def("IDFT2D", &IDFT2D, + "Perform two-dimensional inverse discrete Fourier transform", + py::arg("spectrum"), py::arg("numThreads") = 1); + m.def("generate_gaussian_kernel", &generateGaussianKernel, + "Generate a Gaussian kernel for convolution"); + m.def("apply_gaussian_filter", &applyGaussianFilter, + "Apply a Gaussian filter to an image"); py::class_(m, "Fraction") .def(py::init()) @@ -112,6 +120,8 @@ PYBIND11_MODULE(atom_algorithm, m) { m.def("murmur3_hash", &murmur3Hash, "Murmur3 Hash"); m.def("murmur3_hash64", &murmur3Hash64, "Murmur3 Hash64"); - m.def("hexstring_from_data", py::overload_cast(&hexstringFromData), "Hexstring from Data"); + m.def("hexstring_from_data", + py::overload_cast(&hexstringFromData), + "Hexstring from Data"); m.def("data_from_hexstring", &dataFromHexstring, "Data from Hexstring"); } diff --git a/src/atom/algorithm/_script.hpp b/src/atom/algorithm/_script.hpp index d41011fa..dde9227a 100644 --- a/src/atom/algorithm/_script.hpp +++ b/src/atom/algorithm/_script.hpp @@ -1,3 +1,17 @@ +/* + * _script.cpp + * + * Copyright (C) 2023-2024 Max Qian + */ + +/************************************************* + +Date: 2024-4-13 + +Description: Carbon Binding of Atom-Algorithm + +**************************************************/ + #include "carbon/carbon.hpp" #include "algorithm.hpp" @@ -10,8 +24,7 @@ #include "md5.hpp" #include "mhash.hpp" -using namespace Atom::Algorithm; -using namespace Atom::Utils; +using namespace atom::algorithm; namespace Atom::_Script::Algorithm { /** @@ -55,6 +68,10 @@ Carbon::ModulePtr bootstrap( m->add(Carbon::fun(&deconvolve), "deconvolve"); m->add(Carbon::fun(&convolve2D), "convolve2d"); m->add(Carbon::fun(&deconvolve2D), "deconvolve2d"); + m->add(Carbon::fun(&DFT2D), "dft2d"); + m->add(Carbon::fun(&IDFT2D), "idft2d"); + m->add(Carbon::fun(&generateGaussianKernel), "generate_gaussian_kernel"); + m->add(Carbon::fun(&applyGaussianFilter), "apply_gaussian_filter"); m->add(user_type(), "Fraction"); m->add(Carbon::fun(&Fraction::operator+=), "+="); diff --git a/src/atom/algorithm/algorithm.cpp b/src/atom/algorithm/algorithm.cpp index ddbb8576..068e92f5 100644 --- a/src/atom/algorithm/algorithm.cpp +++ b/src/atom/algorithm/algorithm.cpp @@ -2,7 +2,7 @@ #include -namespace Atom::Algorithm { +namespace atom::algorithm { KMP::KMP(std::string_view pattern) : pattern_(pattern) { failure_ = ComputeFailureFunction(pattern_); @@ -161,4 +161,4 @@ void BoyerMoore::ComputeGoodSuffixShift() { } } -} // namespace Atom::Algorithm \ No newline at end of file +} // namespace atom::algorithm \ No newline at end of file diff --git a/src/atom/algorithm/algorithm.hpp b/src/atom/algorithm/algorithm.hpp index 94095af3..9b79d30d 100644 --- a/src/atom/algorithm/algorithm.hpp +++ b/src/atom/algorithm/algorithm.hpp @@ -22,7 +22,7 @@ Description: A collection of algorithms for C++ #include #include -namespace Atom::Algorithm { +namespace atom::algorithm { /** * @brief The KMP class implements the Knuth-Morris-Pratt string searching * algorithm. @@ -126,34 +126,20 @@ class BloomFilter { * @param num_hash_functions The number of hash functions to use for the * Bloom filter. */ - explicit BloomFilter(std::size_t num_hash_functions) - : m_num_hash_functions(num_hash_functions) {} + explicit BloomFilter(std::size_t num_hash_functions); /** * @brief Inserts an element into the Bloom filter. * @param element The element to insert. */ - void insert(std::string_view element) { - for (std::size_t i = 0; i < m_num_hash_functions; ++i) { - std::size_t hash_value = hash(element, i); - m_bits.set(hash_value % N); - } - } + void insert(std::string_view element); /** * @brief Checks if an element might be present in the Bloom filter. * @param element The element to check. * @return True if the element might be present, false otherwise. */ - bool contains(std::string_view element) const { - for (std::size_t i = 0; i < m_num_hash_functions; ++i) { - std::size_t hash_value = hash(element, i); - if (!m_bits.test(hash_value % N)) { - return false; - } - } - return true; - } + bool contains(std::string_view element) const; private: std::bitset m_bits; /**< The bitset representing the Bloom filter. */ @@ -165,13 +151,7 @@ class BloomFilter { * @param seed The seed value for the hash function. * @return The hash value of the element. */ - std::size_t hash(std::string_view element, std::size_t seed) const { - std::size_t hash_value = seed; - for (char c : element) { - hash_value = hash_value * 31 + static_cast(c); - } - return hash_value; - } + std::size_t hash(std::string_view element, std::size_t seed) const; }; /** @@ -216,6 +196,6 @@ class BoyerMoore { bad_char_shift_; /**< The bad character shift table. */ std::vector good_suffix_shift_; /**< The good suffix shift table. */ }; -} // namespace Atom::Algorithm +} // namespace atom::algorithm #endif diff --git a/src/atom/algorithm/algorithm.inl b/src/atom/algorithm/algorithm.inl new file mode 100644 index 00000000..da8f445e --- /dev/null +++ b/src/atom/algorithm/algorithm.inl @@ -0,0 +1,40 @@ +#ifndef ATOM_ALGORITHM_ALGORITHM_INL +#define ATOM_ALGORITHM_ALGORITHM_INL + +#include "algorithm.hpp" + +namespace atom::algorithm { +template +BloomFilter::BloomFilter(std::size_t num_hash_functions) + : m_num_hash_functions(num_hash_functions) {} + +template +void BloomFilter::insert(std::string_view element) { + for (std::size_t i = 0; i < m_num_hash_functions; ++i) { + std::size_t hash_value = hash(element, i); + m_bits.set(hash_value % N); + } +} + +template +bool BloomFilter::contains(std::string_view element) const { + for (std::size_t i = 0; i < m_num_hash_functions; ++i) { + std::size_t hash_value = hash(element, i); + if (!m_bits.test(hash_value % N)) { + return false; + } + } + return true; +} + +template +std::size_t BloomFilter::hash(std::string_view element, std::size_t seed) const { + std::size_t hash_value = seed; + for (char c : element) { + hash_value = hash_value * 31 + static_cast(c); + } + return hash_value; +} +} // namespace atom::algorithm + +#endif \ No newline at end of file diff --git a/src/atom/algorithm/base.cpp b/src/atom/algorithm/base.cpp index 0f8d1f21..1c18c517 100644 --- a/src/atom/algorithm/base.cpp +++ b/src/atom/algorithm/base.cpp @@ -27,7 +27,7 @@ Description: A collection of algorithms for C++ #include #endif -namespace Atom::Algorithm { +namespace atom::algorithm { std::string base16Encode(const std::vector &data) { std::stringstream ss; ss << std::hex << std::uppercase << std::setfill('0'); @@ -380,4 +380,4 @@ std::string xorEncrypt(std::string_view plaintext, uint8_t key) { std::string xorDecrypt(std::string_view ciphertext, uint8_t key) { return xorEncrypt(ciphertext, key); } -} // namespace Atom::Algorithm \ No newline at end of file +} // namespace atom::algorithm \ No newline at end of file diff --git a/src/atom/algorithm/base.hpp b/src/atom/algorithm/base.hpp index c9bd3240..ae8feb57 100644 --- a/src/atom/algorithm/base.hpp +++ b/src/atom/algorithm/base.hpp @@ -19,7 +19,7 @@ Description: A collection of algorithms for C++ #include #include -namespace Atom::Algorithm { +namespace atom::algorithm { /** * @brief Encodes a vector of unsigned characters into a Base16 string. * @@ -157,6 +157,6 @@ base128Decode(std::string_view encoded); [[nodiscard("The result of xorDecrypt is not used.")]] std::string xorDecrypt( std::string_view ciphertext, uint8_t key); -} // namespace Atom::Algorithm +} // namespace atom::algorithm #endif diff --git a/src/atom/algorithm/convolve.cpp b/src/atom/algorithm/convolve.cpp index feb5d537..0417b529 100644 --- a/src/atom/algorithm/convolve.cpp +++ b/src/atom/algorithm/convolve.cpp @@ -15,20 +15,27 @@ and deconvolution. #include "convolve.hpp" -#include +#include +#include #include -namespace Atom::Algorithm { +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +#include "atom/error/exception.hpp" + +namespace atom::algorithm { std::vector convolve(const std::vector &input, const std::vector &kernel) { - int input_size = input.size(); - int kernel_size = kernel.size(); - int output_size = input_size + kernel_size - 1; + auto input_size = input.size(); + auto kernel_size = kernel.size(); + auto output_size = input_size + kernel_size - 1; std::vector output(output_size, 0.0); - for (int i = 0; i < output_size; i++) { - for (int j = 0; j < kernel_size; j++) { - if (i - j >= 0 && i - j < input_size) { + for (std::size_t i = 0; i < output_size; ++i) { + for (std::size_t j = 0; j < kernel_size; ++j) { + if (i >= j && (i - j) < input_size) { output[i] += input[i - j] * kernel[j]; } } @@ -39,13 +46,17 @@ std::vector convolve(const std::vector &input, std::vector deconvolve(const std::vector &input, const std::vector &kernel) { - int input_size = input.size(); - int kernel_size = kernel.size(); - int output_size = input_size - kernel_size + 1; + auto input_size = input.size(); + auto kernel_size = kernel.size(); + if (kernel_size > input_size) { + THROW_EXCEPTION("Kernel size cannot be larger than input size."); + } + + auto output_size = input_size - kernel_size + 1; std::vector output(output_size, 0.0); - for (int i = 0; i < output_size; i++) { - for (int j = 0; j < kernel_size; j++) { + for (std::size_t i = 0; i < output_size; ++i) { + for (std::size_t j = 0; j < kernel_size; ++j) { output[i] += input[i + j] * kernel[j]; } } @@ -55,40 +66,44 @@ std::vector deconvolve(const std::vector &input, std::vector> convolve2D( const std::vector> &input, - const std::vector> &kernel, int numThreads = 1) { - int inputRows = input.size(); - int inputCols = input[0].size(); - int kernelRows = kernel.size(); - int kernelCols = kernel[0].size(); + const std::vector> &kernel, int numThreads) { + auto inputRows = input.size(); + auto inputCols = input[0].size(); + auto kernelRows = kernel.size(); + auto kernelCols = kernel[0].size(); - // 将输入矩阵和卷积核矩阵扩展到相同的大小,使用0填充 + // Extend input and kernel matrices with zeros std::vector> extendedInput( inputRows + kernelRows - 1, - std::vector(inputCols + kernelCols - 1, 0)); + std::vector(inputCols + kernelCols - 1, 0.0)); std::vector> extendedKernel( inputRows + kernelRows - 1, - std::vector(inputCols + kernelCols - 1, 0)); + std::vector(inputCols + kernelCols - 1, 0.0)); - for (int i = 0; i < inputRows; ++i) { - for (int j = 0; j < inputCols; ++j) { + // Center the input in the extended input matrix + for (std::size_t i = 0; i < inputRows; ++i) { + for (std::size_t j = 0; j < inputCols; ++j) { extendedInput[i + kernelRows / 2][j + kernelCols / 2] = input[i][j]; } } - for (int i = 0; i < kernelRows; ++i) { - for (int j = 0; j < kernelCols; ++j) { + // Center the kernel in the extended kernel matrix + for (std::size_t i = 0; i < kernelRows; ++i) { + for (std::size_t j = 0; j < kernelCols; ++j) { extendedKernel[i][j] = kernel[i][j]; } } - // 计算卷积结果 - std::vector> output(inputRows, - std::vector(inputCols, 0)); + // Prepare output matrix + std::vector> output( + inputRows, std::vector(inputCols, 0.0)); + // Function to compute a block of the convolution auto computeBlock = [&](int blockStartRow, int blockEndRow) { for (int i = blockStartRow; i < blockEndRow; ++i) { - for (int j = kernelCols / 2; j < inputCols + kernelCols / 2; ++j) { - double sum = 0; + for (std::size_t j = kernelCols / 2; j < inputCols + kernelCols / 2; + ++j) { + double sum = 0.0; for (int k = -kernelRows / 2; k <= kernelRows / 2; ++k) { for (int l = -kernelCols / 2; l <= kernelCols / 2; ++l) { sum += extendedInput[i + k][j + l] * @@ -101,103 +116,50 @@ std::vector> convolve2D( } }; - if (numThreads == 1) { - computeBlock(kernelRows / 2, inputRows + kernelRows / 2); - } else { - std::vector threads(numThreads); + // Use multiple threads if requested + if (numThreads > 1) { + std::vector threads; int blockSize = (inputRows + numThreads - 1) / numThreads; int blockStartRow = kernelRows / 2; + for (int i = 0; i < numThreads; ++i) { - int blockEndRow = - std::min(blockStartRow + blockSize, inputRows + kernelRows / 2); - threads[i] = std::thread(computeBlock, blockStartRow, blockEndRow); + int blockEndRow = std::min( + blockStartRow + blockSize, inputRows + kernelRows / 2); + threads.emplace_back(computeBlock, blockStartRow, blockEndRow); blockStartRow = blockEndRow; } + for (auto &thread : threads) { thread.join(); } + } else { + // Single-threaded execution + computeBlock(kernelRows / 2, inputRows + kernelRows / 2); } return output; } -// 二维离散傅里叶变换(2D DFT) -std::vector>> DFT2D( - const std::vector> &signal) { - int M = signal.size(); - int N = signal[0].size(); - std::vector>> X( - M, std::vector>(N, {0, 0})); - - for (int u = 0; u < M; ++u) { - for (int v = 0; v < N; ++v) { - std::complex sum(0, 0); - for (int m = 0; m < M; ++m) { - for (int n = 0; n < N; ++n) { - double theta = 2 * M_PI * - (u * m / static_cast(M) + - v * n / static_cast(N)); - std::complex w(cos(theta), -sin(theta)); - sum += signal[m][n] * w; - } - } - X[u][v] = sum; - } - } - - return X; -} - -// 二维离散傅里叶逆变换(2D IDFT) -std::vector> IDFT2D( - const std::vector>> &spectrum) { - int M = spectrum.size(); - int N = spectrum[0].size(); - std::vector> x(M, std::vector(N, 0)); - - for (int m = 0; m < M; ++m) { - for (int n = 0; n < N; ++n) { - std::complex sum(0, 0); - for (int u = 0; u < M; ++u) { - for (int v = 0; v < N; ++v) { - double theta = 2 * M_PI * - (u * m / static_cast(M) + - v * n / static_cast(N)); - std::complex w(cos(theta), sin(theta)); - sum += spectrum[u][v] * w; - } - } - x[m][n] = real(sum) / (M * N); - } - } - - return x; -} - -// 二维反卷积函数 std::vector> deconvolve2D( const std::vector> &signal, - const std::vector> &kernel) { - // 获取信号和卷积核的维度 + const std::vector> &kernel, int numThreads) { int M = signal.size(); int N = signal[0].size(); int K = kernel.size(); int L = kernel[0].size(); - // 将信号和卷积核扩展到相同的大小,使用0填充 + // 扩展信号和卷积核到相同的大小 std::vector> extendedSignal( M + K - 1, std::vector(N + L - 1, 0)); std::vector> extendedKernel( M + K - 1, std::vector(N + L - 1, 0)); - // 将信号复制到扩展后的信号数组中 + // 复制原始信号和卷积核到扩展矩阵中 for (int i = 0; i < M; ++i) { for (int j = 0; j < N; ++j) { extendedSignal[i][j] = signal[i][j]; } } - - // 将卷积核复制到扩展后的卷积核数组中 for (int i = 0; i < K; ++i) { for (int j = 0; j < L; ++j) { extendedKernel[i][j] = kernel[i][j]; @@ -205,15 +167,20 @@ std::vector> deconvolve2D( } // 计算信号和卷积核的二维DFT - auto X = DFT2D(extendedSignal); - auto H = DFT2D(extendedKernel); + auto DFT2DWrapper = [&](const std::vector> &input) { + return DFT2D(input, + numThreads); // Assume DFT2D supports multithreading + }; + + auto X = DFT2DWrapper(extendedSignal); + auto H = DFT2DWrapper(extendedKernel); // 对卷积核的频谱进行修正 std::vector>> G( - M, std::vector>(N, {0, 0})); + M + K - 1, std::vector>(N + L - 1)); double alpha = 0.1; // 防止分母为0 - for (int u = 0; u < M; ++u) { - for (int v = 0; v < N; ++v) { + for (int u = 0; u < M + K - 1; ++u) { + for (int v = 0; v < N + L - 1; ++v) { if (std::abs(H[u][v]) > alpha) { G[u][v] = std::conj(H[u][v]) / (std::norm(H[u][v]) + alpha); } else { @@ -224,15 +191,16 @@ std::vector> deconvolve2D( // 计算反卷积结果 std::vector>> Y( - M, std::vector>(N, {0, 0})); - for (int u = 0; u < M; ++u) { - for (int v = 0; v < N; ++v) { + M + K - 1, std::vector>(N + L - 1)); + for (int u = 0; u < M + K - 1; ++u) { + for (int v = 0; v < N + L - 1; ++v) { Y[u][v] = G[u][v] * X[u][v]; } } - auto y = IDFT2D(Y); - // 取出结果的前M行、前N列 + auto y = IDFT2D(Y, numThreads); + + // 提取有效结果 std::vector> result(M, std::vector(N, 0)); for (int i = 0; i < M; ++i) { for (int j = 0; j < N; ++j) { @@ -242,4 +210,152 @@ std::vector> deconvolve2D( return result; } -} // namespace Atom::Algorithm + +// 二维离散傅里叶变换(2D DFT) +std::vector>> DFT2D( + const std::vector> &signal, int numThreads) { + const int M = signal.size(); + const int N = signal[0].size(); + std::vector>> X( + M, std::vector>(N, {0, 0})); + + // Lambda function to compute the DFT for a block of rows + auto computeDFT = [&](int startRow, int endRow) { + for (int u = startRow; u < endRow; ++u) { + for (int v = 0; v < N; ++v) { + std::complex sum(0, 0); + for (int m = 0; m < M; ++m) { + for (int n = 0; n < N; ++n) { + double theta = -2 * M_PI * + ((u * m / static_cast(M)) + + (v * n / static_cast(N))); + std::complex w(cos(theta), sin(theta)); + sum += signal[m][n] * w; + } + } + X[u][v] = sum; + } + } + }; + + // Multithreading support + if (numThreads > 1) { + std::vector threads; + int rowsPerThread = M / numThreads; + for (int i = 0; i < numThreads; ++i) { + int startRow = i * rowsPerThread; + int endRow = (i == numThreads - 1) ? M : startRow + rowsPerThread; + threads.emplace_back(computeDFT, startRow, endRow); + } + for (auto &thread : threads) { + thread.join(); + } + } else { + // Single-threaded execution + computeDFT(0, M); + } + + return X; +} + +// 二维离散傅里叶逆变换(2D IDFT) +std::vector> IDFT2D( + const std::vector>> &spectrum, + int numThreads) { + const int M = spectrum.size(); + const int N = spectrum[0].size(); + std::vector> x(M, std::vector(N, 0.0)); + + // Lambda function to compute the IDFT for a block of rows + auto computeIDFT = [&](int startRow, int endRow) { + for (int m = startRow; m < endRow; ++m) { + for (int n = 0; n < N; ++n) { + std::complex sum(0.0, 0.0); + for (int u = 0; u < M; ++u) { + for (int v = 0; v < N; ++v) { + double theta = 2 * M_PI * + ((u * m / static_cast(M)) + + (v * n / static_cast(N))); + std::complex w(cos(theta), sin(theta)); + sum += spectrum[u][v] * w; + } + } + x[m][n] = real(sum) / (M * N); // Normalize by dividing by M*N + } + } + }; + + // Multithreading support + if (numThreads > 1) { + std::vector threads; + int rowsPerThread = M / numThreads; + for (int i = 0; i < numThreads; ++i) { + int startRow = i * rowsPerThread; + int endRow = (i == numThreads - 1) ? M : startRow + rowsPerThread; + threads.emplace_back(computeIDFT, startRow, endRow); + } + for (auto &thread : threads) { + thread.join(); + } + } else { + // Single-threaded execution + computeIDFT(0, M); + } + + return x; +} + +std::vector> generateGaussianKernel(int size, + double sigma) { + std::vector> kernel(size, std::vector(size)); + double sum = 0.0; + int center = size / 2; + + for (int i = 0; i < size; ++i) { + for (int j = 0; j < size; ++j) { + kernel[i][j] = exp(-0.5 * (pow((i - center) / sigma, 2.0) + + pow((j - center) / sigma, 2.0))) / + (2 * M_PI * sigma * sigma); + sum += kernel[i][j]; + } + } + + // 归一化,确保权重和为1 + for (int i = 0; i < size; ++i) { + for (int j = 0; j < size; ++j) { + kernel[i][j] /= sum; + } + } + + return kernel; +} + +std::vector> applyGaussianFilter( + const std::vector> &image, + const std::vector> &kernel) { + int imageHeight = image.size(); + int imageWidth = image[0].size(); + int kernelSize = kernel.size(); + int kernelRadius = kernelSize / 2; + std::vector> filteredImage( + imageHeight, std::vector(imageWidth, 0)); + + for (int i = 0; i < imageHeight; ++i) { + for (int j = 0; j < imageWidth; ++j) { + double sum = 0.0; + for (int k = -kernelRadius; k <= kernelRadius; ++k) { + for (int l = -kernelRadius; l <= kernelRadius; ++l) { + int x = std::max(0, std::min(i + k, imageHeight - 1)); + int y = std::max(0, std::min(j + l, imageWidth - 1)); + sum += image[x][y] * + kernel[kernelRadius + k][kernelRadius + l]; + } + } + filteredImage[i][j] = sum; + } + } + + return filteredImage; +} + +} // namespace atom::algorithm diff --git a/src/atom/algorithm/convolve.hpp b/src/atom/algorithm/convolve.hpp index f4f06f95..739467d9 100644 --- a/src/atom/algorithm/convolve.hpp +++ b/src/atom/algorithm/convolve.hpp @@ -16,51 +16,118 @@ and deconvolution. #ifndef ATOM_ALGORITHM_CONVOLVE_HPP #define ATOM_ALGORITHM_CONVOLVE_HPP +#include #include -namespace Atom::Algorithm { +namespace atom::algorithm { /** - * @brief Perform one-dimensional convolution. + * @brief Performs 1D convolution operation. + * + * This function convolves the input signal with the given kernel. * * @param input The input signal. * @param kernel The convolution kernel. - * @return The result of the convolution. + * @return The convolved signal. */ -[[nodiscard]] [[maybe_unused]] std::vector convolve( - const std::vector &input, const std::vector &kernel); +[[nodiscard("The result of convolve is not used.")]] std::vector +convolve(const std::vector &input, const std::vector &kernel); /** - * @brief Perform one-dimensional deconvolution. + * @brief Performs 1D deconvolution operation. + * + * This function deconvolves the input signal with the given kernel. * * @param input The input signal. * @param kernel The deconvolution kernel. - * @return The result of the deconvolution. + * @return The deconvolved signal. + */ +[[nodiscard("The result of deconvolve is not used.")]] std::vector +deconvolve(const std::vector &input, const std::vector &kernel); + +/** + * @brief Performs 2D convolution operation. + * + * This function convolves the input image with the given kernel. + * + * @param input The input image. + * @param kernel The convolution kernel. + * @param numThreads Number of threads for parallel execution (default: 1). + * @return The convolved image. + */ +[[nodiscard( + "The result of convolve2D is not used.")]] std::vector> +convolve2D(const std::vector> &input, + const std::vector> &kernel, int numThreads = 1); + +/** + * @brief Performs 2D deconvolution operation. + * + * This function deconvolves the input image with the given kernel. + * + * @param signal The input image. + * @param kernel The deconvolution kernel. + * @param numThreads Number of threads for parallel execution (default: 1). + * @return The deconvolved image. */ -[[nodiscard]] [[maybe_unused]] std::vector deconvolve( - const std::vector &input, const std::vector &kernel); +[[nodiscard("The result of deconvolve2D is not used.")]] std::vector< + std::vector> +deconvolve2D(const std::vector> &signal, + const std::vector> &kernel, + int numThreads = 1); /** - * @brief Perform two-dimensional convolution. + * @brief Performs 2D Discrete Fourier Transform (DFT). + * + * This function computes the 2D DFT of the input image. + * + * @param signal The input image. + * @param numThreads Number of threads for parallel execution (default: 1). + * @return The 2D DFT spectrum. + */ +[[nodiscard("The result of DFT2D is not used.")]] std::vector< + std::vector>> +DFT2D(const std::vector> &signal, int numThreads = 1); + +/** + * @brief Performs 2D Inverse Discrete Fourier Transform (IDFT). + * + * This function computes the 2D IDFT of the input spectrum. * - * @param input The 2D input signal. - * @param kernel The 2D convolution kernel. - * @param numThreads The number of threads to use for parallel computation. - * @return The result of the 2D convolution. + * @param spectrum The input spectrum. + * @param numThreads Number of threads for parallel execution (default: 1). + * @return The 2D IDFT image. */ -[[nodiscard]] [[maybe_unused]] std::vector> convolve2D( - const std::vector> &input, - const std::vector> &kernel, int numThreads); +[[nodiscard( + "The result of IDFT2D is not used.")]] std::vector> +IDFT2D(const std::vector>> &spectrum, + int numThreads = 1); /** - * @brief Perform two-dimensional deconvolution. + * @brief Generates a Gaussian kernel for 2D convolution. + * + * This function generates a Gaussian kernel for 2D convolution. + * + * @param size The size of the kernel. + * @param sigma The standard deviation of the Gaussian distribution. + * @return The generated Gaussian kernel. + */ +[[nodiscard("The result of generateGaussianKernel is not used.")]] std::vector< + std::vector> +generateGaussianKernel(int size, double sigma); + +/** + * @brief Applies a Gaussian filter to an image. + * + * This function applies a Gaussian filter to an image. * - * @param signal The 2D input signal. - * @param kernel The 2D deconvolution kernel. - * @return The result of the 2D deconvolution. + * @param image The input image. + * @param kernel The Gaussian kernel. + * @return The filtered image. */ -[[nodiscard]] [[maybe_unused]] std::vector> deconvolve2D( - const std::vector> &signal, - const std::vector> &kernel); -} // namespace Atom::Algorithm +[[nodiscard("The result of applyGaussianFilter is not used.")]] std::vector< + std::vector> +applyGaussianFilter(const std::vector> &image, + const std::vector> &kernel); +} // namespace atom::algorithm #endif diff --git a/src/atom/algorithm/fraction.cpp b/src/atom/algorithm/fraction.cpp index 85814d3f..c784dccd 100644 --- a/src/atom/algorithm/fraction.cpp +++ b/src/atom/algorithm/fraction.cpp @@ -4,7 +4,7 @@ #include #include -namespace Atom::Algorithm { +namespace atom::algorithm { int Fraction::gcd(int a, int b) { return std::gcd(a, b); } @@ -112,4 +112,4 @@ std::istream &operator>>(std::istream &is, Fraction &f) { return is; } -} // namespace Atom::Algorithm +} // namespace atom::algorithm diff --git a/src/atom/algorithm/fraction.hpp b/src/atom/algorithm/fraction.hpp index 9530852b..2a8b581d 100644 --- a/src/atom/algorithm/fraction.hpp +++ b/src/atom/algorithm/fraction.hpp @@ -19,7 +19,7 @@ Description: Implementation of fraction class #include #include -namespace Atom::Algorithm { +namespace atom::algorithm { /** * @brief Represents a fraction with numerator and denominator. */ @@ -178,6 +178,6 @@ class Fraction { friend std::istream& operator>>(std::istream& is, Fraction& f); }; -} // namespace Atom::Algorithm +} // namespace atom::algorithm #endif diff --git a/src/atom/algorithm/hash.hpp b/src/atom/algorithm/hash.hpp index 58394575..5830949c 100644 --- a/src/atom/algorithm/hash.hpp +++ b/src/atom/algorithm/hash.hpp @@ -24,7 +24,7 @@ Description: A collection of hash algorithms #include #include -namespace Atom::Algorithm { +namespace atom::algorithm { /** * @brief Concept to check if a type is hashable. * @@ -259,6 +259,6 @@ inline uint32_t quickHash(const void* data, size_t size) { return h; } -} // namespace Atom::Algorithm +} // namespace atom::algorithm #endif diff --git a/src/atom/algorithm/huffman.cpp b/src/atom/algorithm/huffman.cpp index 8de64f49..881ded77 100644 --- a/src/atom/algorithm/huffman.cpp +++ b/src/atom/algorithm/huffman.cpp @@ -27,7 +27,7 @@ Description: Simple implementation of Huffman encoding #include -namespace Atom::Algorithm { +namespace atom::algorithm { // 定义优先队列中的比较函数 struct Compare { bool operator()(HuffmanNode *a, HuffmanNode *b) { @@ -115,4 +115,4 @@ std::string decompressText(const std::string &compressedText, return decompressedText; } -} // namespace Atom::Algorithm +} // namespace atom::algorithm diff --git a/src/atom/algorithm/huffman.hpp b/src/atom/algorithm/huffman.hpp index 780d3f5d..c29befcf 100644 --- a/src/atom/algorithm/huffman.hpp +++ b/src/atom/algorithm/huffman.hpp @@ -29,7 +29,7 @@ Description: Simple implementation of Huffman encoding #include #include -namespace Atom::Algorithm { +namespace atom::algorithm { /** * @brief 哈夫曼树节点 * @@ -88,6 +88,6 @@ std::string compressText( */ std::string decompressText(const std::string &compressedText, HuffmanNode *root); -} // namespace Atom::Algorithm +} // namespace atom::algorithm #endif \ No newline at end of file diff --git a/src/atom/algorithm/math.cpp b/src/atom/algorithm/math.cpp index f4253829..69d5d5a8 100644 --- a/src/atom/algorithm/math.cpp +++ b/src/atom/algorithm/math.cpp @@ -17,7 +17,7 @@ Description: Extra Math Library #include #include -namespace Atom::Algorithm { +namespace atom::algorithm { #if defined(__GNUC__) && defined(__SIZEOF_INT128__) uint64_t mulDiv64(uint64_t operant, uint64_t multiplier, @@ -117,4 +117,4 @@ uint64_t safeDiv(uint64_t a, uint64_t b) { return a / b; } -} // namespace Atom::Algorithm +} // namespace atom::algorithm diff --git a/src/atom/algorithm/math.hpp b/src/atom/algorithm/math.hpp index 1c392a6b..57764a20 100644 --- a/src/atom/algorithm/math.hpp +++ b/src/atom/algorithm/math.hpp @@ -17,7 +17,7 @@ Description: Extra Math Library #include -namespace Atom::Algorithm { +namespace atom::algorithm { /** * @brief Performs a 64-bit multiplication followed by division. * @@ -116,6 +116,6 @@ uint64_t safeSub(uint64_t a, uint64_t b); * @return The result of a / b, or 0 if there is a division by zero. */ uint64_t safeDiv(uint64_t a, uint64_t b); -} // namespace Atom::Algorithm +} // namespace atom::algorithm #endif \ No newline at end of file diff --git a/src/atom/algorithm/md5.cpp b/src/atom/algorithm/md5.cpp index c57efc89..4df5de7c 100644 --- a/src/atom/algorithm/md5.cpp +++ b/src/atom/algorithm/md5.cpp @@ -18,7 +18,7 @@ Description: Self implemented MD5 algorithm. #include #include -namespace Atom::Algorithm { +namespace atom::algorithm { constexpr uint32_t T[64] = { 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, @@ -151,4 +151,4 @@ std::string MD5::encrypt(const std::string &input) { md5.update(input); return md5.finalize(); } -} // namespace Atom::Algorithm \ No newline at end of file +} // namespace atom::algorithm \ No newline at end of file diff --git a/src/atom/algorithm/md5.hpp b/src/atom/algorithm/md5.hpp index 6944e71d..ad3a0e0c 100644 --- a/src/atom/algorithm/md5.hpp +++ b/src/atom/algorithm/md5.hpp @@ -20,7 +20,7 @@ Description: Self implemented MD5 algorithm. #include -namespace Atom::Algorithm { +namespace atom::algorithm { /** * @brief The MD5 class for calculating MD5 hash of input data. */ @@ -97,6 +97,6 @@ class MD5 { std::vector _buffer; /**< Buffer for input data. */ }; -} // namespace Atom::Algorithm +} // namespace atom::algorithm #endif // MD5_H diff --git a/src/atom/algorithm/meson.build b/src/atom/algorithm/meson.build index 3118c1be..cf433492 100644 --- a/src/atom/algorithm/meson.build +++ b/src/atom/algorithm/meson.build @@ -12,6 +12,7 @@ sources = [ ] headers = [ 'algorithm.hpp', + 'algorithm.inl' 'base.hpp', 'convolve.hpp', 'fraction.hpp', @@ -31,7 +32,7 @@ atom_algorithm_obj = library('atom_algorithm_obj', atom_algorithm_static = static_library('atom_algorithm_static', atom_algorithm_obj) # Set version properties -version = '1.0.0' # You should define your version here +version = '1.0.0' soversion = '1' atom_algorithm_static.version = version diff --git a/src/atom/algorithm/mhash.cpp b/src/atom/algorithm/mhash.cpp index e0c855ee..5797899b 100644 --- a/src/atom/algorithm/mhash.cpp +++ b/src/atom/algorithm/mhash.cpp @@ -14,20 +14,22 @@ Description: Implementation of murmur3 hash and quick hash #include "mhash.hpp" -#include -#include -#include -#include -#include #include #include +#include #include +#include #include +#include #include #include -#include -namespace Atom::Utils { +#include +#include +#include +#include + +namespace atom::algorithm { uint32_t fmix32(uint32_t h) noexcept { h ^= h >> 16; h *= 0x85ebca6b; @@ -152,4 +154,4 @@ std::string dataFromHexstring(const std::string &hexstring) { return result; } -} // namespace Atom::Utils +} // namespace atom::algorithm diff --git a/src/atom/algorithm/mhash.hpp b/src/atom/algorithm/mhash.hpp index cff1097c..d562a078 100644 --- a/src/atom/algorithm/mhash.hpp +++ b/src/atom/algorithm/mhash.hpp @@ -1,5 +1,5 @@ /* - * hash_util.hpp + * mhash.hpp * * Copyright (C) 2023-2024 Max Qian */ @@ -12,16 +12,15 @@ Description: Implementation of murmur3 hash and quick hash **************************************************/ -#ifndef ATOM_UTILS_HASH_UTIL_HPP -#define ATOM_UTILS_HASH_UTIL_HPP +#ifndef ATOM_ALGORITHM_MHASH_HPP +#define ATOM_ALGORITHM_MHASH_HPP #include #include -#include #include #include -namespace Atom::Utils { +namespace atom::algorithm { /** * @brief Calculates the MurmurHash3 hash value for a given string. * @@ -71,6 +70,6 @@ void hexstringFromData(const void *data, size_t len, char *output); * hexadecimal string. */ [[nodiscard]] std::string dataFromHexstring(const std::string &data); -} // namespace Atom::Utils +} // namespace atom::algorithm #endif \ No newline at end of file diff --git a/src/atom/algorithm/xmake.lua b/src/atom/algorithm/xmake.lua index d8a9d533..ea635330 100644 --- a/src/atom/algorithm/xmake.lua +++ b/src/atom/algorithm/xmake.lua @@ -26,6 +26,7 @@ local sources = { -- Headers local headers = { "algorithm.hpp", + "algorithm.inl" "base.hpp", "convolve.hpp", "fraction.hpp", diff --git a/src/atom/async/CMakeLists.txt b/src/atom/async/CMakeLists.txt index ba669cf5..83f8eb55 100644 --- a/src/atom/async/CMakeLists.txt +++ b/src/atom/async/CMakeLists.txt @@ -1,7 +1,7 @@ # CMakeLists.txt for Atom-Async # This project is licensed under the terms of the GPL3 license. # -# Project Name: Atom-Task +# Project Name: Atom-Async # Description: Async Implementation of Lithium Server and Driver # Author: Max Qian # License: GPL3 @@ -18,14 +18,19 @@ set(${PROJECT_NAME}_SOURCES # Headers set(${PROJECT_NAME}_HEADERS async.hpp - async_impl.hpp + async.inl lock.hpp + pool.hpp queue.hpp queue.inl thread_wrapper.hpp timer.hpp trigger.hpp - trigger_impl.hpp + trigger.inl +) + +set(${PROJECT_NAME}_LIBS + loguru ) # Build Object Library diff --git a/src/atom/async/_pybind.cpp b/src/atom/async/_pybind.cpp index c12fcbdf..b98adf74 100644 --- a/src/atom/async/_pybind.cpp +++ b/src/atom/async/_pybind.cpp @@ -18,14 +18,13 @@ Description: Python Binding of Atom-Async #include #include "async.hpp" -#include "queue.hpp" #include "thread_wrapper.hpp" #include "timer.hpp" #include "trigger.hpp" namespace py = pybind11; -using namespace Atom::Async; +using namespace atom::async; template void start_wrapper(Thread& thread, Callable&& func, Args&&... args) { @@ -51,8 +50,6 @@ void bind_thread(py::module& m) { "Gets the underlying std::stop_source object.") .def("get_stop_token", &Thread::get_stop_token, "Gets the underlying std::stop_token object.") - //.def_property_readonly("thread", &Thread::get_thread, - // "Gets the underlying std::jthread object.") .def("__enter__", [](Thread& self) -> Thread& { return self; }) .def("__exit__", [](Thread& self, py::object, py::object, py::object) { self.join(); }) @@ -93,62 +90,6 @@ void bind_timer(py::module& m) { "Gets the number of scheduled tasks."); } -/* -// TODO: Fix this -template -void bind_thread_safe_queue(py::module& m, const std::string& name) { - py::class_>(m, name.c_str()) - .def(py::init<>()) - .def("put", &ThreadSafeQueue::put) - .def("take", &ThreadSafeQueue::take) - .def("destroy", &ThreadSafeQueue::destroy) - .def("size", &ThreadSafeQueue::size) - .def("empty", &ThreadSafeQueue::empty) - .def("clear", &ThreadSafeQueue::clear) - .def("front", &ThreadSafeQueue::front) - .def("back", &ThreadSafeQueue::back) - .def("emplace", &ThreadSafeQueue::template emplace) - .def("waitFor", &ThreadSafeQueue::template waitFor) - .def("waitUntilEmpty", &ThreadSafeQueue::waitUntilEmpty) - .def("extractIf", &ThreadSafeQueue::template extractIf) - .def("sort", &ThreadSafeQueue::template sort); -} - -// Bind AsyncWorker class -template -void bind_async_worker(py::module& m, const std::string& name) { - py::class_>(m, name.c_str()) - .def(py::init<>()) - //.def("StartAsync", - // &AsyncWorker::template StartAsync) - .def("GetResult", &AsyncWorker::GetResult) - .def("Cancel", &AsyncWorker::Cancel) - .def("IsDone", &AsyncWorker::IsDone) - .def("IsActive", &AsyncWorker::IsActive) - .def("Validate", &AsyncWorker::Validate) - .def("SetCallback", &AsyncWorker::SetCallback) - .def("SetTimeout", &AsyncWorker::SetTimeout) - .def("WaitForCompletion", &AsyncWorker::WaitForCompletion); -} - -// Bind AsyncWorkerManager class -template -void bind_async_worker_manager(py::module& m, const std::string& name) { - py::class_>(m, name.c_str()) - .def(py::init<>()) - .def( - "CreateWorker", - &AsyncWorkerManager::template CreateWorker) - .def("CancelAll", &AsyncWorkerManager::CancelAll) - .def("AllDone", &AsyncWorkerManager::AllDone) - .def("WaitForAll", &AsyncWorkerManager::WaitForAll) - .def("IsDone", &AsyncWorkerManager::IsDone) - .def("Cancel", &AsyncWorkerManager::Cancel); -} -*/ - PYBIND11_MODULE(atom_async, m) { m.doc() = "Atom Async Python Binding"; @@ -163,23 +104,7 @@ PYBIND11_MODULE(atom_async, m) { .def("cancel_trigger", &Trigger::cancelTrigger) .def("cancel_all_triggers", &Trigger::cancelAllTriggers); - - bind_thread(m); bind_timer_task(m); bind_timer(m); - - /* - bind_thread_safe_queue(m, "ThreadSafeQueueInt"); - bind_thread_safe_queue(m, "ThreadSafeQueueDouble"); - bind_thread_safe_queue(m, "ThreadSafeQueueString"); - - bind_async_worker(m, "AsyncWorkerInt"); - bind_async_worker(m, "AsyncWorkerFloat"); - bind_async_worker(m, "AsyncWorkerString"); - - bind_async_worker_manager(m, "AsyncWorkerManagerInt"); - bind_async_worker_manager(m, "AsyncWorkerManagerFloat"); - bind_async_worker_manager(m, "AsyncWorkerManagerString"); - */ } diff --git a/src/atom/async/async.hpp b/src/atom/async/async.hpp index ecb29c4e..2cb62790 100644 --- a/src/atom/async/async.hpp +++ b/src/atom/async/async.hpp @@ -27,7 +27,7 @@ Description: A simple but useful async worker manager #include "atom/error/exception.hpp" -namespace Atom::Async { +namespace atom::async { /** * @brief Class for performing asynchronous tasks. * @@ -213,8 +213,8 @@ std::future()(std::declval()...))> asyncRetry( template ReturnType getWithTimeout(std::future &future, std::chrono::milliseconds timeout); -} // namespace Atom::Async +} // namespace atom::async -#include "async_impl.hpp" +#include "async.inl" #endif diff --git a/src/atom/async/async_impl.hpp b/src/atom/async/async.inl similarity index 76% rename from src/atom/async/async_impl.hpp rename to src/atom/async/async.inl index 0696698f..34921e13 100644 --- a/src/atom/async/async_impl.hpp +++ b/src/atom/async/async.inl @@ -1,5 +1,5 @@ /* - * async_impl.hpp + * async.inl * * Copyright (C) 2023-2024 Max Qian */ @@ -12,10 +12,12 @@ Description: A simple but useful async worker manager **************************************************/ -#ifndef ATOM_ASYNC_ASYNC_IMPL_HPP -#define ATOM_ASYNC_ASYNC_IMPL_HPP +#ifndef ATOM_ASYNC_ASYNC_INL +#define ATOM_ASYNC_ASYNC_INL -namespace Atom::Async { +#include "async.hpp" + +namespace atom::async { template template void AsyncWorker::StartAsync(Func &&func, Args &&...args) { @@ -137,13 +139,11 @@ void AsyncWorkerManager::Cancel( } template -[[nodiscard]] std::future< - decltype(std::declval()(std::declval()...))> -asyncRetry(Func &&func, int attemptsLeft, std::chrono::milliseconds delay, - Args &&...args) { - static_assert(std::is_void()( - std::declval()...))>::value == false, - "Func must return a value"); + requires std::invocable +[[nodiscard]] auto asyncRetry(Func &&func, int attemptsLeft, + std::chrono::milliseconds delay, Args &&...args) { + using ReturnType = std::invoke_result_t; + static_assert(!std::is_void_v, "Func must return a value"); if (attemptsLeft <= 1) { // 最后一次尝试,直接执行 @@ -157,11 +157,16 @@ asyncRetry(Func &&func, int attemptsLeft, std::chrono::milliseconds delay, try { // 立即获取结果,如果有异常会在这里抛出 - auto result = attempt.get(); - // 如果成功,则直接返回一个已经有结果的 future - return std::async( - std::launch::deferred, - [result]() -> decltype(func(args...)) { return result; }); + if constexpr (std::is_same_v) { + attempt.get(); + return std::async(std::launch::deferred, []() {}); + } else { + auto result = attempt.get(); + return std::async(std::launch::deferred, + [result = std::move(result)]() mutable { + return std::move(result); + }); + } } catch (...) { if (attemptsLeft <= 1) { // 所有尝试都失败,重新抛出最后一次的异常 @@ -175,9 +180,24 @@ asyncRetry(Func &&func, int attemptsLeft, std::chrono::milliseconds delay, } } -template -ReturnType getWithTimeout(std::future &future, - std::chrono::milliseconds timeout) { +template +[[nodiscard]] T getWithTimeout(std::future &future, + std::chrono::milliseconds timeout) { + static_assert(!std::is_void_v, "T must not be void"); + + if (future.wait_for(timeout) == std::future_status::ready) { + return future.get(); + } else { + throw std::runtime_error( + "Timeout occurred while waiting for future result"); + } +} + +template +[[nodiscard]] T getWithTimeout(std::future &future, + std::chrono::duration timeout) { + static_assert(!std::is_void_v, "T must not be void"); + if (future.wait_for(timeout) == std::future_status::ready) { return future.get(); } else { @@ -185,6 +205,6 @@ ReturnType getWithTimeout(std::future &future, "Timeout occurred while waiting for future result"); } } -} // namespace Atom::Async +} // namespace atom::async #endif \ No newline at end of file diff --git a/src/atom/async/lock.cpp b/src/atom/async/lock.cpp index 4743ce16..24c88d10 100644 --- a/src/atom/async/lock.cpp +++ b/src/atom/async/lock.cpp @@ -14,7 +14,7 @@ Description: Some useful spinlock implementations #include "lock.hpp" -namespace Atom::Async { +namespace atom::async { void Spinlock::lock() { while (flag_.test_and_set(std::memory_order_acquire)) { cpu_relax(); @@ -42,4 +42,4 @@ void UnfairSpinlock::lock() { } void UnfairSpinlock::unlock() { flag_.clear(std::memory_order_release); } -} // namespace Atom::Async \ No newline at end of file +} // namespace atom::async \ No newline at end of file diff --git a/src/atom/async/lock.hpp b/src/atom/async/lock.hpp index 78a7bc76..c7fd5f25 100644 --- a/src/atom/async/lock.hpp +++ b/src/atom/async/lock.hpp @@ -18,7 +18,7 @@ Description: Some useful spinlock implementations #include #include -namespace Atom::Async { +namespace atom::async { // Pause instruction to prevent excess processor bus usage #if defined(_MSC_VER) @@ -219,6 +219,6 @@ class ScopedUnfairLock { ScopedUnfairLock &operator=(const ScopedUnfairLock &) = delete; }; -} // namespace Atom::Async +} // namespace atom::async #endif \ No newline at end of file diff --git a/src/atom/async/meson.build b/src/atom/async/meson.build index 135445ff..1ff1d269 100644 --- a/src/atom/async/meson.build +++ b/src/atom/async/meson.build @@ -1,49 +1,57 @@ -project('Atom-Async', 'cpp') +project('atom-async', 'cpp') -# Define sources and headers -sources = [ +# Set sources +sources = files( 'lock.cpp', - 'timer.cpp' -] -headers = [ + 'timer.cpp', +) + +# Set headers +headers = files( 'async.hpp', - 'async_impl.hpp', + 'async.inl', 'lock.hpp', + 'pool.hpp', 'queue.hpp', 'queue.inl', 'thread_wrapper.hpp', 'timer.hpp', 'trigger.hpp', - 'trigger_impl.hpp' + 'trigger.inl', +) + +# Set libraries +libs = [ + 'loguru', ] -# Create object library -atom_async_obj = library('atom_async_obj', +# Build Object Library +atom_async_obj = static_library( + 'atom_async_obj', sources + headers, - cpp_std: c_std + include_directories: '.', + pic: true, + dependencies: libs, ) -# Link with necessary libraries -atom_async_obj_link_libs = ['loguru'] -atom_async_obj.link_with(atom_async_obj_link_libs) - -# Create static library -atom_async_static = static_library('atom_async_static', atom_async_obj) - -# Set version properties -version = '1.0.0' # You should define your version here -soversion = '1' - -atom_async_static.version = version -atom_async_static.soversion = soversion -atom_async_static.basename = 'Atom-Async' +# Build Static Library +atom_async = static_library( + 'atom_async', + sources: [], + dependencies: [atom_async_obj], + version: '1.0.0', # Replace with your version + soversion: '1', # Replace with your SO version +) # Install target -install_targets(atom_async_static) - -# Check if Python support is enabled -atom_build_python = get_option('atom_build_python') - -if atom_build_python - pybind11_module('atom_async_py' '_pybind.cpp' link_with : [atom_async_static]) -endif +install_data(atom_async, install_dir: meson.install_root() / 'lib') + +# Optional: Build Python bindings +if get_option('atom_build_python') + pybind11_dep = dependency('pybind11') + pybind11_add_module( + 'atom_async_py', + 'pybind.cpp', + dependencies: [atom_async, pybind11_dep], + ) +endif \ No newline at end of file diff --git a/src/atom/async/pool.hpp b/src/atom/async/pool.hpp index 9c04dcb0..8799182d 100644 --- a/src/atom/async/pool.hpp +++ b/src/atom/async/pool.hpp @@ -19,15 +19,14 @@ Description: A very simple thread pool for preload #include #include #include +#include #include #include +#include #include #include -namespace Atom::Async { -/** - * @brief 线程池 - */ +namespace atom::async { class ThreadPool { public: /** @@ -37,21 +36,19 @@ class ThreadPool { * * @param n_threads 线程池大小 */ - ThreadPool(std::size_t n_threads) : stop(false) { + explicit ThreadPool(std::size_t n_threads) : stop(false) { for (std::size_t i = 0; i < n_threads; ++i) { threads.emplace_back([this] { - for (;;) { - std::function task; - { - std::unique_lock lock(queue_mutex); - condition.wait( - lock, [this] { return stop || !tasks.empty(); }); - if (stop && tasks.empty()) { - return; - } - task = std::move(tasks.front()); - tasks.pop(); + while (true) { + std::unique_lock lock(queue_mutex); + condition.wait(lock, + [this] { return stop || !tasks.empty(); }); + if (stop && tasks.empty()) { + return; } + auto task = std::move(tasks.front()); + tasks.pop(); + lock.unlock(); task(); } }); @@ -69,7 +66,7 @@ class ThreadPool { stop = true; } condition.notify_all(); - for (std::thread &thread : threads) { + for (auto &thread : threads) { thread.join(); } } @@ -88,14 +85,13 @@ class ThreadPool { * @return 返回一个 std::future 对象,用于查询任务完成情况 */ template - auto enqueue(F &&f, Args &&...args) - -> std::future::type> { - using return_type = typename std::result_of::type; + auto enqueue(F &&f, Args &&...args) { + using return_type = std::invoke_result_t; auto task = std::make_shared>( std::bind(std::forward(f), std::forward(args)...)); - std::future res = task->get_future(); + auto res = task->get_future(); { std::unique_lock lock(queue_mutex); @@ -103,20 +99,47 @@ class ThreadPool { throw std::runtime_error("enqueue on stopped ThreadPool"); } - tasks.emplace([task] { (*task)(); }); + tasks.emplace([task = std::move(task)]() { (*task)(); }); } condition.notify_one(); return res; } + /** + * @brief 等待所有任务完成。 + * + * 该函数会等待任务队列中的所有任务完成,然后返回。 + */ + void wait() { + std::unique_lock lock(queue_mutex); + condition.wait(lock, [this] { return tasks.empty(); }); + } + + /** + * @brief 返回线程池中的线程数量。 + * + * @return 线程池中的线程数量 + */ + std::size_t size() const { return threads.size(); } + + /** + * @brief 返回任务队列中待执行的任务数量。 + * + * @return 任务队列中待执行的任务数量 + */ + std::size_t taskCount() const { + std::unique_lock lock(queue_mutex); + return tasks.size(); + } + private: std::vector threads; ///< 线程池中的线程列表 std::queue> tasks; ///< 任务队列 - std::mutex queue_mutex; ///< 任务队列的互斥锁 + mutable std::mutex queue_mutex; ///< 任务队列的互斥锁 std::condition_variable condition; ///< 任务队列的条件变量 bool stop; ///< 停止标志位 }; -} // namespace Atom::Async +} // namespace atom::async #endif \ No newline at end of file diff --git a/src/atom/async/queue.hpp b/src/atom/async/queue.hpp index e94002f2..e182c81e 100644 --- a/src/atom/async/queue.hpp +++ b/src/atom/async/queue.hpp @@ -24,9 +24,9 @@ Description: A simple thread safe queue #include #include -#include "atom/experiment/noncopyable.hpp" +#include "atom/type/noncopyable.hpp" -namespace Atom::Async { +namespace atom::async { /** * @brief A thread-safe queue data structure that supports concurrent access * from multiple threads. @@ -151,7 +151,7 @@ class ThreadSafeQueue : public NonCopyable { ///< nullptr on take() when empty. }; -} // namespace Atom::Async +} // namespace atom::async #include "queue.inl" diff --git a/src/atom/async/queue.inl b/src/atom/async/queue.inl index f026f202..206f0abd 100644 --- a/src/atom/async/queue.inl +++ b/src/atom/async/queue.inl @@ -5,7 +5,7 @@ #include -namespace Atom::Async { +namespace atom::async { template void ThreadSafeQueue::put(T element) { { @@ -201,6 +201,6 @@ std::vector> ThreadSafeQueue::groupBy( } */ -} // namespace Atom::Async +} // namespace atom::async #endif \ No newline at end of file diff --git a/src/atom/async/thread_wrapper.hpp b/src/atom/async/thread_wrapper.hpp index e87ec8a3..cfb6a51f 100644 --- a/src/atom/async/thread_wrapper.hpp +++ b/src/atom/async/thread_wrapper.hpp @@ -25,6 +25,7 @@ Description: A simple wrapper of std::jthread #include #include +namespace atom::async { /** * @brief A wrapper class for managing a C++20 jthread. * @@ -159,5 +160,6 @@ class Thread { private: std::jthread thread_; ///< The underlying jthread object. }; +} // namespace atom::async #endif diff --git a/src/atom/async/timer.cpp b/src/atom/async/timer.cpp index 9f5f3db5..e2904d88 100644 --- a/src/atom/async/timer.cpp +++ b/src/atom/async/timer.cpp @@ -14,7 +14,7 @@ Description: Timer class for C++ #include "timer.hpp" -namespace Atom::Async { +namespace atom::async { TimerTask::TimerTask(std::function func, unsigned int delay, int repeatCount, int priority) : m_func(func), @@ -122,4 +122,4 @@ int Timer::getTaskCount() const { std::unique_lock lock(m_mutex); return m_taskQueue.size(); } -} // namespace Atom::Async +} // namespace atom::async diff --git a/src/atom/async/timer.hpp b/src/atom/async/timer.hpp index d16a4643..e99386db 100644 --- a/src/atom/async/timer.hpp +++ b/src/atom/async/timer.hpp @@ -26,7 +26,7 @@ Description: Timer class for C++ #include #include -namespace Atom::Async { +namespace atom::async { /** * @brief Represents a task to be scheduled and executed by the Timer. */ @@ -232,6 +232,6 @@ template void Timer::setCallback(Function &&func) { m_callback = std::forward(func); } -} // namespace Atom::Async +} // namespace atom::async #endif diff --git a/src/atom/async/trigger.hpp b/src/atom/async/trigger.hpp index 883fd770..569f615c 100644 --- a/src/atom/async/trigger.hpp +++ b/src/atom/async/trigger.hpp @@ -30,6 +30,7 @@ Description: Trigger class for C++ #include #endif +namespace atom::async { /** * @brief The Trigger class provides a mechanism to register callbacks for * specific events and trigger those callbacks when the events occur. @@ -127,7 +128,8 @@ class Trigger { m_callbacks; /**< Hash map to store registered callbacks for events. */ #endif }; +} // namespace atom::async -#include "trigger_impl.hpp" +#include "trigger.inl" #endif diff --git a/src/atom/async/trigger_impl.hpp b/src/atom/async/trigger.inl similarity index 95% rename from src/atom/async/trigger_impl.hpp rename to src/atom/async/trigger.inl index fa22d1dd..576efef1 100644 --- a/src/atom/async/trigger_impl.hpp +++ b/src/atom/async/trigger.inl @@ -15,17 +15,9 @@ Description: Trigger class for C++ #ifndef ATOM_ASYNC_TRIGGER_IMPL_HPP #define ATOM_ASYNC_TRIGGER_IMPL_HPP -#include -#include -#include -#include -#include -#include -#include -#include -#include - +#include "trigger.hpp" +namespace atom::async { template void Trigger::registerCallback(const std::string &event, const Callback &callback, @@ -118,5 +110,6 @@ void Trigger::cancelAllTriggers() { std::lock_guard lock(m_mutex); m_callbacks.clear(); } +} // namespace atom::async #endif diff --git a/src/atom/async/xmake.lua b/src/atom/async/xmake.lua index 5bcc6bfd..6af35683 100644 --- a/src/atom/async/xmake.lua +++ b/src/atom/async/xmake.lua @@ -8,52 +8,41 @@ add_rules("mode.debug", "mode.release") +-- Set project name set_project("atom-async") -set_languages("cxx20") - --- 设置CMake最低版本 -cmake_minimum_required("version" 3.20) - --- 设置项目名称和描述 -set_project_name("atom-async") -set_project_description("Async Implementation of Lithium Server and Driver") - --- 添加源文件 -add_files("lock.cpp") -add_files("timer.cpp") - --- 添加头文件 -add_header_files("async.hpp") -add_header_files("async_impl.hpp") -add_header_files("lock.hpp") -add_header_files("queue.hpp") -add_header_files("queue.inl") -add_header_files("thread_wrapper.hpp") -add_header_files("timer.hpp") -add_header_files("trigger.hpp") -add_header_files("trigger_impl.hpp") - --- 创建对象库 -obj_library("atom_async_object" srcs _all_) -set_property("atom_async_object", {position_independent = true}) -target_link_libraries("atom_async_object" "loguru") - --- 创建静态库 -static_library("atom_async" srcs _all_ dependencies "atom_async_object") - --- 链接必要的库 -target_link_libraries("atom_async" "atom_async_object" ${CMAKE_THREAD_LIBS_INIT}) -target_include_directories("atom_async" include_path ".") - --- 设置版本和输出文件名 -set_property("atom_async", {version = CMAKE_HYDROGEN_VERSION_STRING, so_version = HYDROGEN_SOVERSION, output_name = "atom_async"}) - --- 安装目标 -install_target("atom_async" arch "lib" dest "lib") - --- 如果构建Python模块 -if (ATOM_BUILD_PYTHON) - pybind11_add_module("atom_async_py" srcs "_pybind.cpp") - target_link_libraries("atom_async_py" "atom_async") -endif() \ No newline at end of file +-- Set languages +set_languages("cxx17") + +-- Set source files +add_files("lock.cpp", "timer.cpp") + +-- Set header files +add_headerfiles("*.hpp", "*.inl") + +-- Set link libraries +add_linkdirs("path/to/loguru/library") -- Replace with actual path to loguru library +add_links("loguru") + +-- Build static library +target("atom-async") + set_kind("static") + add_deps("atom-async-object") + add_files("lock.cpp", "timer.cpp") + add_headerfiles("*.hpp", "*.inl") + add_includedirs(".") + add_linkdirs(".") + add_links("loguru") + +-- Build object library +target("atom-async-object") + set_kind("object") + add_files("lock.cpp", "timer.cpp") + add_headerfiles("*.hpp", "*.inl") + add_includedirs(".") + add_linkdirs(".") + add_links("loguru") + +-- Install target +set_configvar("xmake", "installdir", "/path/to/installation/directory") -- Replace with actual installation directory +add_installfiles("build/lib/*.a", {prefixdir = "lib"}) diff --git a/src/atom/components/component.hpp b/src/atom/components/component.hpp index b07a0242..65e6737b 100644 --- a/src/atom/components/component.hpp +++ b/src/atom/components/component.hpp @@ -26,7 +26,7 @@ Description: Basic Component Definition #include "configor.hpp" -#include "atom/experiment/noncopyable.hpp" +#include "atom/type/noncopyable.hpp" #include "atom/experiment/type_info.hpp" class Component : public std::enable_shared_from_this, public NonCopyable { diff --git a/src/atom/components/dispatch.hpp b/src/atom/components/dispatch.hpp index 1c05edd2..58ea76c6 100644 --- a/src/atom/components/dispatch.hpp +++ b/src/atom/components/dispatch.hpp @@ -23,7 +23,7 @@ #include #include -#include "atom/experiment/noncopyable.hpp" +#include "atom/type/noncopyable.hpp" #include "atom/type/pointer.hpp" #include "proxy.hpp" diff --git a/src/atom/components/templates/shared.cpp b/src/atom/components/templates/shared.cpp index 35aa75c4..b8c9863e 100644 --- a/src/atom/components/templates/shared.cpp +++ b/src/atom/components/templates/shared.cpp @@ -6,7 +6,7 @@ #include "atom/type/message.hpp" #include "atom/utils/string.hpp" -using namespace Atom::Error; +using namespace atom::error; SharedComponent::SharedComponent(const std::string &name) : Component(name) { m_handleFunction = [shared_this = diff --git a/src/atom/components/var.hpp b/src/atom/components/var.hpp index d481c590..f780b1e4 100644 --- a/src/atom/components/var.hpp +++ b/src/atom/components/var.hpp @@ -17,7 +17,7 @@ #endif #include "atom/error/exception.hpp" -#include "atom/experiment/noncopyable.hpp" +#include "atom/type/noncopyable.hpp" #include "atom/type/trackable.hpp" #include "atom/utils/cstring.hpp" diff --git a/src/atom/connection/_pybind.cpp b/src/atom/connection/_pybind.cpp index 5351d1a8..44e74fb2 100644 --- a/src/atom/connection/_pybind.cpp +++ b/src/atom/connection/_pybind.cpp @@ -25,7 +25,7 @@ Description: Python Binding of Atom-Connection #endif namespace py = pybind11; -using namespace Atom::Connection; +using namespace atom::connection; template void bind_shared_memory(py::module &m, const std::string &type_name) { diff --git a/src/atom/connection/fifoclient.cpp b/src/atom/connection/fifoclient.cpp index 1df396a1..f4e87ecc 100644 --- a/src/atom/connection/fifoclient.cpp +++ b/src/atom/connection/fifoclient.cpp @@ -19,7 +19,7 @@ Description: FIFO CLient #include #include -namespace Atom::Connection { +namespace atom::connection { FifoClient::FifoClient(const std::string& fifoPath) : m_fifoPath(fifoPath) { #ifdef _WIN32 m_fifo = CreateFile(m_fifoPath.c_str(), GENERIC_READ | GENERIC_WRITE, 0, @@ -76,4 +76,4 @@ std::string FifoClient::read() { return data; } -} // namespace Atom::Connection +} // namespace atom::connection diff --git a/src/atom/connection/fifoclient.hpp b/src/atom/connection/fifoclient.hpp index 640791bb..77779211 100644 --- a/src/atom/connection/fifoclient.hpp +++ b/src/atom/connection/fifoclient.hpp @@ -26,7 +26,7 @@ Description: FIFO CLient #include #endif -namespace Atom::Connection { +namespace atom::connection { /** * @brief The FifoClient class provides functionality to connect to a FIFO * (First In First Out) pipe, write data to the pipe, and read data from @@ -69,6 +69,6 @@ class FifoClient { #endif std::string m_fifoPath; /**< The path to the FIFO pipe. */ }; -} // namespace Atom::Connection +} // namespace atom::connection #endif // FIFOSERVER_H diff --git a/src/atom/connection/fifoserver.cpp b/src/atom/connection/fifoserver.cpp index 870cfaed..24176f4b 100644 --- a/src/atom/connection/fifoserver.cpp +++ b/src/atom/connection/fifoserver.cpp @@ -27,7 +27,7 @@ Description: FIFO Server #include #endif -namespace Atom::Connection { +namespace atom::connection { FIFOServer::FIFOServer(const std::string& fifo_path) : fifo_path_(fifo_path) { // 创建 FIFO 文件 @@ -90,4 +90,4 @@ void FIFOServer::serverLoop() { #endif } } -} // namespace Atom::Connection +} // namespace atom::connection diff --git a/src/atom/connection/fifoserver.hpp b/src/atom/connection/fifoserver.hpp index a836b196..7ae6611c 100644 --- a/src/atom/connection/fifoserver.hpp +++ b/src/atom/connection/fifoserver.hpp @@ -21,7 +21,7 @@ Description: FIFO Server #include #include -namespace Atom::Connection { +namespace atom::connection { /** * @brief A class representing a server for handling FIFO messages. @@ -62,6 +62,6 @@ class FIFOServer { message_cv_; /**< Condition variable for message synchronization. */ }; -} // namespace Atom::Connection +} // namespace atom::connection #endif // ATOM_CONNECTION_FIFOSERVER_HPP diff --git a/src/atom/connection/shared_memory.hpp b/src/atom/connection/shared_memory.hpp index 213785b9..da42e46b 100644 --- a/src/atom/connection/shared_memory.hpp +++ b/src/atom/connection/shared_memory.hpp @@ -32,7 +32,7 @@ Description: Inter-process shared memory for local driver communication. #include #endif -namespace Atom::Connection { +namespace atom::connection { /** * @brief 实现共享内存,可用于进程间通信 */ @@ -260,6 +260,6 @@ template bool SharedMemory::isOccupied() const { return flag_->test_and_set(); } -} // namespace Atom::Connection +} // namespace atom::connection #endif diff --git a/src/atom/connection/sockethub.cpp b/src/atom/connection/sockethub.cpp index 488d614d..d9e01f81 100644 --- a/src/atom/connection/sockethub.cpp +++ b/src/atom/connection/sockethub.cpp @@ -25,7 +25,7 @@ Description: SocketHub类用于管理socket连接的类。 typedef int SOCKET; #endif -namespace Atom::Connection { +namespace atom::connection { SocketHub::SocketHub() : running(false) {} SocketHub::~SocketHub() { stop(); } @@ -213,4 +213,4 @@ void SocketHub::cleanupSocket() { clientThreads.clear(); } -} // namespace Atom::Connection +} // namespace atom::connection diff --git a/src/atom/connection/sockethub.hpp b/src/atom/connection/sockethub.hpp index 702fc5dc..ce5a940f 100644 --- a/src/atom/connection/sockethub.hpp +++ b/src/atom/connection/sockethub.hpp @@ -31,7 +31,7 @@ Description: SocketHub类用于管理socket连接的类。 #include #endif -namespace Atom::Connection { +namespace atom::connection { /** * @class SocketHub * @brief 用于管理socket连接的类。 @@ -175,6 +175,6 @@ class SocketHub { */ void cleanupSocket(); }; -} // namespace Atom::Connection +} // namespace atom::connection #endif \ No newline at end of file diff --git a/src/atom/connection/sshclient.cpp b/src/atom/connection/sshclient.cpp index 67ce491b..a80969dc 100644 --- a/src/atom/connection/sshclient.cpp +++ b/src/atom/connection/sshclient.cpp @@ -14,7 +14,7 @@ Description: SSH客户端连接和文件操作类。 #include "sshclient.hpp" -namespace Atom::Connection { +namespace atom::connection { SSHClient::SSHClient(const std::string &host, int port = 22) : m_host(host), m_port(port), @@ -289,4 +289,4 @@ void SSHClient::UploadFile(const std::string &local_path, fclose(fp); sftp_close(file); } -} // namespace Atom::Connection +} // namespace atom::connection diff --git a/src/atom/connection/sshclient.hpp b/src/atom/connection/sshclient.hpp index bd85fe9b..47944306 100644 --- a/src/atom/connection/sshclient.hpp +++ b/src/atom/connection/sshclient.hpp @@ -26,7 +26,7 @@ Description: SSH客户端连接和文件操作类。 #include #include -namespace Atom::Connection { +namespace atom::connection { /** * @class SSHClient * @brief A class for SSH client connection and file operations. @@ -161,6 +161,6 @@ class SSHClient { ssh_session m_ssh_session; sftp_session m_sftp_session; }; -} // namespace Atom::Connection +} // namespace atom::connection #endif \ No newline at end of file diff --git a/src/atom/connection/udp_server.cpp b/src/atom/connection/udp_server.cpp index be919cb6..1d902682 100644 --- a/src/atom/connection/udp_server.cpp +++ b/src/atom/connection/udp_server.cpp @@ -16,7 +16,7 @@ Description: A simple UDP server. #include "atom/log/loguru.hpp" -namespace Atom::Connection { +namespace atom::connection { UdpSocketHub::UdpSocketHub() : m_running(false), m_serverSocket(INVALID_SOCKET) {} @@ -139,4 +139,4 @@ void UdpSocketHub::handleMessages() { } } -} // namespace Atom::Connection +} // namespace atom::connection diff --git a/src/atom/connection/udp_server.hpp b/src/atom/connection/udp_server.hpp index b4dc2029..df6cf491 100644 --- a/src/atom/connection/udp_server.hpp +++ b/src/atom/connection/udp_server.hpp @@ -41,7 +41,7 @@ using socklen_t = int; using SOCKET = int; #endif -namespace Atom::Connection { +namespace atom::connection { /** * @class UdpSocketHub * @brief A simple UDP socket server class that handles incoming messages and @@ -157,6 +157,6 @@ class UdpSocketHub { */ void handleMessages(); }; -} // namespace Atom::Connection +} // namespace atom::connection #endif \ No newline at end of file diff --git a/src/atom/driver/config/basic.cpp b/src/atom/driver/config/basic.cpp deleted file mode 100644 index 4851428c..00000000 --- a/src/atom/driver/config/basic.cpp +++ /dev/null @@ -1,345 +0,0 @@ -/* - * basic.cpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2024-3-16 - -Description: Basic property class - -*************************************************/ - -#include "basic.hpp" -#include "basic_p.hpp" - -#include - -namespace Atom::Driver { - -template -PropertyBasicPrivateTemplate::PropertyBasicPrivateTemplate(size_t count) - : PropertyContainer{*new PropertyView()}, - PropertyPrivate(&this->typedProperty), - raw{false}, - widgets(count) { - this->typedProperty.setWidgets(widgets.data(), widgets.size()); -} - -template -PropertyBasicPrivateTemplate::PropertyBasicPrivateTemplate( - RawPropertyType *rawProperty) - : PropertyContainer{*PropertyView::cast(rawProperty)}, - PropertyPrivate(PropertyView::cast(rawProperty)), - raw{true} {} - -template -PropertyBasicPrivateTemplate::~PropertyBasicPrivateTemplate() { - if (!raw) - delete &this->typedProperty; -} - -template -PropertyBasic::~PropertyBasic() {} - -template -PropertyBasic::PropertyBasic(PropertyBasicPrivate &dd) : Property(dd) {} - -template -PropertyBasic::PropertyBasic(const std::shared_ptr &dd) - : Property(std::static_pointer_cast(dd)) {} - -template -void PropertyBasic::setDeviceName(const std::string &name) { - D_PTR(PropertyBasic); - d->typedProperty.setDeviceName(name); -} - -template -void PropertyBasic::setName(const std::string &name) { - D_PTR(PropertyBasic); - d->typedProperty.setName(name); -} - -template -void PropertyBasic::setLabel(const std::string &label) { - D_PTR(PropertyBasic); - d->typedProperty.setLabel(label); -} - -template -void PropertyBasic::setGroupName(const std::string &name) { - D_PTR(PropertyBasic); - d->typedProperty.setGroupName(name); -} - -template -void PropertyBasic::setPermission(IPerm permission) { - D_PTR(PropertyBasic); - d->typedProperty.setPermission(permission); -} - -template -void PropertyBasic::setTimeout(double timeout) { - D_PTR(PropertyBasic); - d->typedProperty.setTimeout(timeout); -} - -template -void PropertyBasic::setState(IPState state) { - D_PTR(PropertyBasic); - d->typedProperty.setState(state); -} - -template -void PropertyBasic::setTimestamp(const std::string ×tamp) { - D_PTR(PropertyBasic); - d->typedProperty.setTimestamp(timestamp); -} - -template -std::string PropertyBasic::getDeviceName() const { - D_PTR(const PropertyBasic); - return d->typedProperty.getDeviceName(); -} - -template -std::string PropertyBasic::getName() const { - D_PTR(const PropertyBasic); - return d->typedProperty.getName(); -} - -template -std::string PropertyBasic::getLabel() const { - D_PTR(const PropertyBasic); - return d->typedProperty.getLabel(); -} - -template -std::string PropertyBasic::getGroupName() const { - D_PTR(const PropertyBasic); - return d->typedProperty.getGroupName(); -} - -template -IPerm PropertyBasic::getPermission() const { - D_PTR(const PropertyBasic); - return d->typedProperty.getPermission(); -} - -template -std::string PropertyBasic::getPermissionAsString() const { - D_PTR(const PropertyBasic); - return d->typedProperty.getPermissionAsString(); -} - -template -double PropertyBasic::getTimeout() const { - D_PTR(const PropertyBasic); - return d->typedProperty.getTimeout(); -} - -template -IPState PropertyBasic::getState() const { - D_PTR(const PropertyBasic); - return d->typedProperty.getState(); -} - -template -std::string PropertyBasic::getStateAsString() const { - D_PTR(const PropertyBasic); - return d->typedProperty.getStateAsString(); -} - -template -std::string PropertyBasic::getTimestamp() const { - D_PTR(const PropertyBasic); - return d->typedProperty.getTimestamp(); -} - -template -bool PropertyBasic::isEmpty() const { - D_PTR(const PropertyBasic); - return d->typedProperty.isEmpty(); -} - -template -bool PropertyBasic::isNameMatch(const std::string &otherName) const { - D_PTR(const PropertyBasic); - return d->typedProperty.isNameMatch(otherName); -} - -template -bool PropertyBasic::isLabelMatch(const std::string &otherLabel) const { - D_PTR(const PropertyBasic); - return d->typedProperty.isLabelMatch(otherLabel); -} - -template -bool PropertyBasic::load() { - D_PTR(const PropertyBasic); - return d->typedProperty.load(); -} - -template -void PropertyBasic::save(FILE *f) const { - D_PTR(const PropertyBasic); - d->typedProperty.save(f); -} - -template -void PropertyBasic::vapply(std::string format, va_list args) const { - D_PTR(const PropertyBasic); - d->typedProperty.vapply(format, args); -} - -template -void PropertyBasic::vdefine(std::string format, va_list args) const { - D_PTR(const PropertyBasic); - d->typedProperty.vdefine(format, args); -} - -template -void PropertyBasic::apply(std::string format, ...) const { - D_PTR(const PropertyBasic); - va_list ap; - va_start(ap, format); - d->typedProperty.vapply(format, ap); - va_end(ap); -} - -template -void PropertyBasic::define(std::string format, ...) const { - D_PTR(const PropertyBasic); - va_list ap; - va_start(ap, format); - d->typedProperty.vdefine(format, ap); - va_end(ap); -} - -template -void PropertyBasic::apply() const { - D_PTR(const PropertyBasic); - d->typedProperty.apply(); -} - -template -void PropertyBasic::define() const { - D_PTR(const PropertyBasic); - d->typedProperty.define(); -} - -template -WidgetView *PropertyBasic::findWidgetByName(std::string name) const { - D_PTR(const PropertyBasic); - return d->typedProperty.findWidgetByName(name); -} - -template -int PropertyBasic::findWidgetIndexByName(std::string name) const { - auto it = findWidgetByName(name); - return int(it == nullptr ? -1 : it - begin()); -} - -template -size_t PropertyBasic::size() const { - D_PTR(const PropertyBasic); - return d->typedProperty.count(); -} - -template -void PropertyBasic::resize(size_t size) { - D_PTR(PropertyBasic); - assert(d->raw == false); - d->widgets.resize(size); - d->typedProperty.setWidgets(d->widgets.data(), d->widgets.size()); -} - -template -void PropertyBasic::reserve(size_t size) { - D_PTR(PropertyBasic); - assert(d->raw == false); - d->widgets.reserve(size); - d->typedProperty.setWidgets(d->widgets.data(), d->widgets.size()); -} - -template -void PropertyBasic::shrink_to_fit() { - D_PTR(PropertyBasic); - assert(d->raw == false); - d->widgets.shrink_to_fit(); - d->typedProperty.setWidgets(d->widgets.data(), d->widgets.size()); -} - -template -void PropertyBasic::push(WidgetView &&item) { - D_PTR(PropertyBasic); - assert(d->raw == false); - item.setParent(&d->typedProperty); - d->widgets.push_back(std::move(item)); - d->typedProperty.setWidgets(d->widgets.data(), d->widgets.size()); -} - -template -void PropertyBasic::push(const WidgetView &item) { - push(std::move(WidgetView(item))); -} - -template -const WidgetView *PropertyBasic::at(size_t index) const { - D_PTR(const PropertyBasic); - return d->typedProperty.at(index); -} - -template -WidgetView &PropertyBasic::operator[](int index) const { - D_PTR(const PropertyBasic); - assert(index >= 0); - return *d->typedProperty.at(index); -} - -template -WidgetView *PropertyBasic::begin() { - D_PTR(PropertyBasic); - return d->typedProperty.begin(); -} - -template -WidgetView *PropertyBasic::end() { - D_PTR(PropertyBasic); - return d->typedProperty.end(); -} - -template -const WidgetView *PropertyBasic::begin() const { - D_PTR(const PropertyBasic); - return d->typedProperty.begin(); -} - -template -const WidgetView *PropertyBasic::end() const { - D_PTR(const PropertyBasic); - return d->typedProperty.end(); -} - -template -PropertyView *PropertyBasic::operator&() { - D_PTR(PropertyBasic); - return &d->typedProperty; -} - -template class PropertyBasicPrivateTemplate; -template class PropertyBasicPrivateTemplate; -template class PropertyBasicPrivateTemplate; -template class PropertyBasicPrivateTemplate; -template class PropertyBasicPrivateTemplate; - -template class PropertyBasic; -template class PropertyBasic; -template class PropertyBasic; -template class PropertyBasic; -template class PropertyBasic; - -} // namespace Atom::Driver diff --git a/src/atom/driver/config/basic.hpp b/src/atom/driver/config/basic.hpp deleted file mode 100644 index d07946ea..00000000 --- a/src/atom/driver/config/basic.hpp +++ /dev/null @@ -1,146 +0,0 @@ -/* - * basic.hpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2024-3-16 - -Description: Basic property class - -*************************************************/ - -#ifndef ATOM_DRIVER_PROPERTY_BASIC_HPP -#define ATOM_DRIVER_PROPERTY_BASIC_HPP - -#include -#include "macros.hpp" -#include "property.hpp" - - -namespace Atom::Driver { - -using WidgetText = Atom::Driver::WidgetViewText; -using WidgetNumber = Atom::Driver::WidgetViewNumber; -using WidgetSwitch = Atom::Driver::WidgetViewSwitch; -using WidgetLight = Atom::Driver::WidgetViewLight; -using WidgetBlob = Atom::Driver::WidgetViewBlob; - -template -class PropertyBasicPrivateTemplate; - -template -class PropertyBasic : public Atom::Driver::Property { - using PropertyBasicPrivate = PropertyBasicPrivateTemplate; - DECLARE_PRIVATE(PropertyBasic) -public: - using ViewType = T; - -public: - ~PropertyBasic(); - -public: - void setDeviceName(const std::string &name); - void setName(const std::string &name); - void setLabel(const std::string &label); - void setGroupName(const std::string &name); - void setPermission(IPerm permission); - void setTimeout(double timeout); - void setState(IPState state); - - void setTimestamp(const std::string ×tamp); - -public: - std::string getDeviceName() const; - std::string getName() const; - std::string getLabel() const; - std::string getGroupName() const; - - IPerm getPermission() const; - std::string getPermissionAsString() const; - - double getTimeout() const; - IPState getState() const; - std::string getStateAsString() const; - - std::string getTimestamp() const; - -public: - bool isEmpty() const; - - bool isNameMatch(const std::string &otherName) const; - - bool isLabelMatch(const std::string &otherLabel) const; - -public: - /** - * @brief load Attempt to load property values from configuration file. - * @return True if value was read successfully from file, false otherwise. - */ - bool load(); - - /** - * @brief save Save property to configuration file. - * @param f Pointer to existing open configuration file. - */ - void save(FILE *f) const; - - void vapply(std::string format, va_list args) const; - void vdefine(std::string format, va_list args) const; - - void apply(std::string format, ...) const ATTRIBUTE_FORMAT_PRINTF(2, 3); - void define(std::string format, ...) const ATTRIBUTE_FORMAT_PRINTF(2, 3); - - void apply() const; - void define() const; - -protected: - PropertyView *operator&(); - -public: - size_t size() const; - size_t count() const { return size(); } - -public: - void reserve(size_t size); - void resize(size_t size); - - void shrink_to_fit(); - - void push(WidgetView &&item); - void push(const WidgetView &item); - - const WidgetView *at(size_t index) const; - - WidgetView &operator[](int index) const; - -public: // STL-style iterators - WidgetView *begin(); - WidgetView *end(); - const WidgetView *begin() const; - const WidgetView *end() const; - - template - WidgetView *find_if(Predicate pred) { - return std::find_if(begin(), end(), pred); - } - - template - const WidgetView *find_if(Predicate pred) const { - return std::find_if(begin(), end(), pred); - } - -public: - WidgetView *findWidgetByName(std::string name) const; - int findWidgetIndexByName(std::string name) const; - -protected: - PropertyBasic(PropertyBasicPrivate &dd); - PropertyBasic(const std::shared_ptr &dd); -}; - -} // namespace Atom::Driver - -#endif diff --git a/src/atom/driver/config/basic_p.hpp b/src/atom/driver/config/basic_p.hpp deleted file mode 100644 index 2a14074b..00000000 --- a/src/atom/driver/config/basic_p.hpp +++ /dev/null @@ -1,47 +0,0 @@ -/* - * basic_p.hpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2024-3-16 - -Description: Basic property class - -*************************************************/ - -#ifndef ATOM_DRIVER_PROPERTY_BASIC_P_HPP -#define ATOM_DRIVER_PROPERTY_BASIC_P_HPP - -#include "property_p.hpp" -#include "view.hpp" - -#include -#include - -namespace Atom::Driver { - -template -struct PropertyContainer { - PropertyView &typedProperty; -}; -template -class PropertyBasicPrivateTemplate : public PropertyContainer, - public PropertyPrivate { -public: - using RawPropertyType = typename WidgetTraits::PropertyType; - using BasicPropertyType = PropertyBasicPrivateTemplate; - -public: - PropertyBasicPrivateTemplate(size_t count); - PropertyBasicPrivateTemplate(RawPropertyType *rawProperty); - virtual ~PropertyBasicPrivateTemplate(); - -public: - bool raw; - std::vector> widgets; -}; - -} // namespace Atom::Driver diff --git a/src/atom/driver/config/blob.cpp b/src/atom/driver/config/blob.cpp deleted file mode 100644 index ca287c11..00000000 --- a/src/atom/driver/config/blob.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/* - * blob.cpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2024-3-16 - -Description: Blob property class - -*************************************************/ - -#include "blob.hpp" -#include "blob_p.hpp" - -namespace Atom::Driver -{ - -PropertyBlobPrivate::PropertyBlobPrivate(size_t count) - : PropertyBasicPrivateTemplate(count) -{ } - -PropertyBlobPrivate::~PropertyBlobPrivate() -{ - for (auto &it: widgets) - { - auto blob = it.getBlob(); - if (blob != nullptr && deleter != nullptr) - { - deleter(blob); - } - } -} - -PropertyBlob::PropertyBlob(size_t count) - : PropertyBasic(*new PropertyBlobPrivate(count)) -{ } - -PropertyBlob::PropertyBlob(Atom::Driver::Property property) - : PropertyBasic(property_private_cast(property.d_ptr)) -{ } - -PropertyBlob::~PropertyBlob() -{ } - -void PropertyBlob::setBlobDeleter(const std::function &deleter) -{ - D_PTR(PropertyBlob); - d->deleter = deleter; -} - -bool PropertyBlob::update( - const int sizes[], const int blobsizes[], const char * const blobs[], const char * const formats[], - const char * const names[], int n -) -{ - D_PTR(PropertyBlob); - return d->typedProperty.update(sizes, blobsizes, blobs, formats, names, n) && (emitUpdate(), true); -} - -void PropertyBlob::fill( - const char *device, const char *name, const char *label, const char *group, - IPerm permission, double timeout, IPState state -) -{ - D_PTR(PropertyBlob); - d->typedProperty.setWidgets(d->widgets.data(), d->widgets.size()); - d->typedProperty.fill(device, name, label, group, permission, timeout, state); -} - -} diff --git a/src/atom/driver/config/blob.hpp b/src/atom/driver/config/blob.hpp deleted file mode 100644 index e3cd86c4..00000000 --- a/src/atom/driver/config/blob.hpp +++ /dev/null @@ -1,49 +0,0 @@ -/* - * blob.hpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2024-3-16 - -Description: Blob property class - -*************************************************/ - -#pragma once - -#include "indipropertybasic.h" - -namespace INDI { - -class PropertyBlobPrivate; -class PropertyBlob : public INDI::PropertyBasic { - DECLARE_PRIVATE(PropertyBlob) -public: - PropertyBlob(size_t count); - PropertyBlob(INDI::Property property); - ~PropertyBlob(); - -public: - /** - * @brief Set the Blob Deleter function - * You can define a function to release the memory of the elements. - * The function will be executed when the PropertyBlob is destroyed - * - * @param deleter function to release the memory of a given item - */ - void setBlobDeleter(const std::function &deleter); - -public: - bool update(const int sizes[], const int blobsizes[], - const char *const blobs[], const char *const formats[], - const char *const names[], int n); - - void fill(const char *device, const char *name, const char *label, - const char *group, IPerm permission, double timeout, - IPState state); -}; - -} // namespace INDI diff --git a/src/atom/driver/config/blob_p.hpp b/src/atom/driver/config/blob_p.hpp deleted file mode 100644 index 434c924b..00000000 --- a/src/atom/driver/config/blob_p.hpp +++ /dev/null @@ -1,35 +0,0 @@ -/* - * blob_p.hpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2024-3-16 - -Description: Blob property class - -*************************************************/ - -#ifndef ATOM_DRIVER_PROPERTY_BLOB_P_HPP -#define ATOM_DRIVER_PROPERTY_BLOB_P_HPP - -#include "propertybasic_p.hpp" - -#include "basic_p.hpp" -#include "view.hpp" - -namespace Atom::Driver { - -class PropertyBlobPrivate : public PropertyBasicPrivateTemplate { -public: - PropertyBlobPrivate(size_t count); - PropertyBlobPrivate(RawPropertyType *p) : BasicPropertyType(p) {} - virtual ~PropertyBlobPrivate(); - -public: - std::function deleter; -}; - -} // namespace Atom::Driver diff --git a/src/atom/driver/config/macros.hpp b/src/atom/driver/config/macros.hpp deleted file mode 100644 index fc551cb8..00000000 --- a/src/atom/driver/config/macros.hpp +++ /dev/null @@ -1,177 +0,0 @@ -/* - * macros.hpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2024-3-16 - -Description: Property Macros - -*************************************************/ - -#ifndef ATOM_DRIVER_PROPERTY_MACROS_HPP -#define ATOM_DRIVER_PROPERTY_MACROS_HPP - -/** - * @brief Unused variable - * - * Indicates to the compiler that the parameter with the specified name is not - * used in the body of a function. This can be used to suppress compiler - * warnings while allowing functions to be defined with meaningful parameter - * names in their signatures. - * - */ -#ifndef INDI_UNUSED -#define INDI_UNUSED(x) (void)x -#endif - -/** - * @brief The POSIX C type "ssize_t" is available on Unix-like systems in - * unistd.h. For Windows Visual Studio based compilers without unistd.h, the - * following stanza allows use of ssize_t. - */ -#ifdef _MSC_VER -#include -#ifndef HAVE_SSIZE_T -typedef SSIZE_T ssize_t; -#endif -#else -#include -#endif - -/** - * @brief Expressions to test whether the attribute is recognized by the C++ - * compiler - */ -#ifndef INDI_HAS_CPP_ATTRIBUTE -#ifdef __has_cpp_attribute -#define INDI_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x) -#else -#define INDI_HAS_CPP_ATTRIBUTE(x) 0 -#endif -#endif - -/** - * @brief Expressions to test whether the attribute is recognized by the C - * compiler - */ -#ifndef INDI_HAS_ATTRIBUTE -#ifdef __has_attribute -#define INDI_HAS_ATTRIBUTE(x) __has_attribute(x) -#else -#define INDI_HAS_ATTRIBUTE(x) 0 -#endif -#endif - -/** - * @brief Allows attributes to be set on null statements - * - * The fallthrough attribute with a null statement serves as a fallthrough - * statement. It hints to the compiler that a statement that falls through to - * another case label, or user-defined label in a switch statement is - * intentional and thus the -Wimplicit-fallthrough warning must not trigger. The - * fallthrough attribute may appear at most once in each attribute list, and may - * not be mixed with other attributes. It can only be used in a switch statement - * (the compiler will issue an error otherwise), after a preceding statement and - * before a logically succeeding case label, or user-defined label. - * - * switch (cond) - * { - * case 1: - * bar (1); - * INDI_FALLTHROUGH; - * case 2: - * ... - * } - */ -#ifndef INDI_FALLTHROUGH -#if defined(__cplusplus) -#if INDI_HAS_CPP_ATTRIBUTE(clang::fallthrough) -#define INDI_FALLTHROUGH [[clang::fallthrough]] -#elif INDI_HAS_CPP_ATTRIBUTE(gnu::fallthrough) -#define INDI_FALLTHROUGH [[gnu::fallthrough]] -#elif INDI_HAS_CPP_ATTRIBUTE(fallthrough) -#define INDI_FALLTHROUGH [[fallthrough]] -#endif -#else -#if INDI_HAS_ATTRIBUTE(fallthrough) -#define INDI_FALLTHROUGH __attribute__((fallthrough)) -#else -#define INDI_FALLTHROUGH \ - do { \ - } while (0) -#endif -#endif -#endif - -/** - * @brief Opaque pointer - * - * The D_PTR macro is part of a design pattern called the d-pointer (also called - * the opaque pointer) where the implementation details of a library may be - * hidden from its users and changes to the implementation can be made to a - * library without breaking binary compatibility. - */ -#if defined(__cplusplus) - -#include - -template -static inline std::shared_ptr make_shared_weak(T *object) { - return std::shared_ptr(object, [](T *) {}); -} - -template -static inline T *getPtrHelper(T *ptr) { - return ptr; -} - -template -static inline typename Wrapper::element_type *getPtrHelper(const Wrapper &p) { - return p.get(); -} - -#define DECLARE_PRIVATE(Class) \ - inline Class##Private *d_func() { \ - return reinterpret_cast(getPtrHelper(this->d_ptr)); \ - } \ - inline const Class##Private *d_func() const { \ - return reinterpret_cast( \ - getPtrHelper(this->d_ptr)); \ - } \ - friend Class##Private; - -#define DECLARE_PRIVATE_D(Dptr, Class) \ - inline Class##Private *d_func() { \ - return reinterpret_cast(getPtrHelper(Dptr)); \ - } \ - inline const Class##Private *d_func() const { \ - return reinterpret_cast(getPtrHelper(Dptr)); \ - } \ - friend Class##Private; - -#define D_PTR(Class) Class##Private *const d = d_func() - -#endif - -// enable warnings for printf-style functions -#ifndef ATTRIBUTE_FORMAT_PRINTF -#if INDI_HAS_ATTRIBUTE(format) -#define ATTRIBUTE_FORMAT_PRINTF(A, B) __attribute__((format(printf, (A), (B)))) -#else -#define ATTRIBUTE_FORMAT_PRINTF(A, B) -#endif -#endif - -#ifdef SWIG -#define INDI_DEPRECATED(message) -#elif __cplusplus -#define INDI_DEPRECATED(message) [[deprecated(message)]] -#else -#define INDI_DEPRECATED(message) __attribute__((deprecated)) -#endif - -#endif diff --git a/src/atom/driver/config/number.cpp b/src/atom/driver/config/number.cpp deleted file mode 100644 index 6dd5fd48..00000000 --- a/src/atom/driver/config/number.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/* - Copyright (C) 2021 by Pawel Soja - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#include "indipropertynumber.h" -#include "indipropertynumber_p.h" - -namespace INDI -{ - -PropertyNumberPrivate::PropertyNumberPrivate(size_t count) - : PropertyBasicPrivateTemplate(count) -{ } - -PropertyNumberPrivate::~PropertyNumberPrivate() -{ } - -PropertyNumber::PropertyNumber(size_t count) - : PropertyBasic(*new PropertyNumberPrivate(count)) -{ } - -PropertyNumber::PropertyNumber(INDI::Property property) - : PropertyBasic(property_private_cast(property.d_ptr)) -{ } - -PropertyNumber::~PropertyNumber() -{ } - -bool PropertyNumber::update(const double values[], const char * const names[], int n) -{ - D_PTR(PropertyNumber); - return d->typedProperty.update(values, names, n) && (emitUpdate(), true); -} - -void PropertyNumber::fill( - const char *device, const char *name, const char *label, const char *group, - IPerm permission, double timeout, IPState state -) -{ - D_PTR(PropertyNumber); - d->typedProperty.setWidgets(d->widgets.data(), d->widgets.size()); - d->typedProperty.fill(device, name, label, group, permission, timeout, state); -} - -void PropertyNumber::updateMinMax() -{ - D_PTR(PropertyNumber); - d->typedProperty.updateMinMax(); -} - -} diff --git a/src/atom/driver/config/number.hpp b/src/atom/driver/config/number.hpp deleted file mode 100644 index c5685185..00000000 --- a/src/atom/driver/config/number.hpp +++ /dev/null @@ -1,45 +0,0 @@ -/* - Copyright (C) 2021 by Pawel Soja - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - USA -*/ - -#pragma once - -#include "indipropertybasic.h" - -namespace INDI { - -class PropertyNumberPrivate; -class PropertyNumber : public INDI::PropertyBasic { - DECLARE_PRIVATE(PropertyNumber) -public: - PropertyNumber(size_t count); - PropertyNumber(INDI::Property property); - ~PropertyNumber(); - -public: - bool update(const double values[], const char *const names[], int n); - - void fill(const char *device, const char *name, const char *label, - const char *group, IPerm permission, double timeout, - IPState state); - -public: - void updateMinMax(); -}; - -} // namespace INDI diff --git a/src/atom/driver/config/number_p.hpp b/src/atom/driver/config/number_p.hpp deleted file mode 100644 index d831ba83..00000000 --- a/src/atom/driver/config/number_p.hpp +++ /dev/null @@ -1,36 +0,0 @@ -/* - Copyright (C) 2021 by Pawel Soja - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - USA -*/ - -#pragma once - -#include "indipropertybasic_p.h" -#include "indipropertyview.h" - -namespace INDI { - -class PropertyNumberPrivate : public PropertyBasicPrivateTemplate { -public: - PropertyNumberPrivate(size_t count); - PropertyNumberPrivate(RawPropertyType *p) : BasicPropertyType(p) {} - virtual ~PropertyNumberPrivate(); - -public: -}; - -} // namespace INDI diff --git a/src/atom/driver/config/properties.cpp b/src/atom/driver/config/properties.cpp deleted file mode 100644 index fff09745..00000000 --- a/src/atom/driver/config/properties.cpp +++ /dev/null @@ -1,160 +0,0 @@ -/* - Copyright (C) 2021 by Pawel Soja - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -*/ -#include "indiproperties.h" -#include "indiproperties_p.h" - -namespace INDI -{ - -PropertiesPrivate::PropertiesPrivate() -{ } - -PropertiesPrivate::~PropertiesPrivate() -{ } - -Properties::Properties() - : d_ptr(new PropertiesPrivate) -{ } - -Properties::~Properties() -{ } - -Properties::Properties(std::shared_ptr dd) - : d_ptr(dd) -{ } - -void Properties::push_back(const INDI::Property &property) -{ - D_PTR(Properties); - d->properties.push_back(property); -} - -void Properties::push_back(INDI::Property &&property) -{ - D_PTR(Properties); - d->properties.push_back(std::move(property)); -} - -void Properties::clear() -{ - D_PTR(Properties); - d->properties.clear(); -} - -Properties::size_type Properties::size() const -{ - D_PTR(const Properties); - return d->properties.size(); -} - -Properties::reference Properties::at(size_type pos) -{ - D_PTR(Properties); - return d->properties.at(pos); -} - -Properties::const_reference Properties::at(size_type pos) const -{ - D_PTR(const Properties); - return d->properties.at(pos); -} - -Properties::reference Properties::operator[](Properties::size_type pos) -{ - D_PTR(Properties); - return d->properties.at(pos); -} - -Properties::const_reference Properties::operator[](Properties::size_type pos) const -{ - D_PTR(const Properties); - return d->properties.at(pos); -} - -Properties::reference Properties::front() -{ - D_PTR(Properties); - return d->properties.front(); -} - -Properties::const_reference Properties::front() const -{ - D_PTR(const Properties); - return d->properties.front(); -} - -Properties::reference Properties::back() -{ - D_PTR(Properties); - return d->properties.back(); -} - -Properties::const_reference Properties::back() const -{ - D_PTR(const Properties); - return d->properties.back(); -} - -Properties::iterator Properties::begin() -{ - D_PTR(Properties); - return d->properties.begin(); -} - -Properties::iterator Properties::end() -{ - D_PTR(Properties); - return d->properties.end(); -} - -Properties::const_iterator Properties::begin() const -{ - D_PTR(const Properties); - return d->properties.begin(); -} - -Properties::const_iterator Properties::end() const -{ - D_PTR(const Properties); - return d->properties.end(); -} - -Properties::iterator Properties::erase(iterator pos) -{ - D_PTR(Properties); - return d->properties.erase(pos); -} - -Properties::iterator Properties::erase(const_iterator pos) -{ - D_PTR(Properties); - return d->properties.erase(pos); -} - -Properties::iterator Properties::erase(iterator first, iterator last) -{ - D_PTR(Properties); - return d->properties.erase(first, last); -} - -Properties::iterator Properties::erase(const_iterator first, const_iterator last) -{ - D_PTR(Properties); - return d->properties.erase(first, last); -} -} diff --git a/src/atom/driver/config/properties.hpp b/src/atom/driver/config/properties.hpp deleted file mode 100644 index 7bd42075..00000000 --- a/src/atom/driver/config/properties.hpp +++ /dev/null @@ -1,95 +0,0 @@ -/* - Copyright (C) 2021 by Pawel Soja - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - USA -*/ -#pragma once - -#include -#include -#include -#include "indimacros.h" -#include "indiproperty.h" - - -namespace INDI { - -class PropertiesPrivate; -class Properties { - DECLARE_PRIVATE(Properties) - -public: - using iterator = std::deque::iterator; - using const_iterator = std::deque::const_iterator; - using reference = std::deque::reference; - using const_reference = std::deque::const_reference; - using size_type = std::deque::size_type; - -public: - Properties(); - ~Properties(); - -public: - void push_back(const INDI::Property &property); - void push_back(INDI::Property &&property); - void clear(); - -public: - bool empty() const; - -public: - size_type size() const; - -public: - reference at(size_type pos); - const_reference at(size_type pos) const; - - reference operator[](size_type pos); - const_reference operator[](size_type pos) const; - - reference front(); - const_reference front() const; - - reference back(); - const_reference back() const; - -public: - iterator begin(); - iterator end(); - - const_iterator begin() const; - const_iterator end() const; - -public: - iterator erase(iterator pos); - iterator erase(const_iterator pos); - iterator erase(iterator first, iterator last); - iterator erase(const_iterator first, const_iterator last); - - template - iterator erase_if(Predicate predicate); - -protected: - std::shared_ptr d_ptr; - Properties(std::shared_ptr dd); -}; - -template -inline Properties::iterator Properties::erase_if(Predicate predicate) { - return erase(std::remove_if(begin(), end(), predicate), end()); -} - -} // namespace INDI diff --git a/src/atom/driver/config/properties_p.hpp b/src/atom/driver/config/properties_p.hpp deleted file mode 100644 index e7bb3dc8..00000000 --- a/src/atom/driver/config/properties_p.hpp +++ /dev/null @@ -1,34 +0,0 @@ -/* - Copyright (C) 2021 by Pawel Soja - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - USA -*/ -#pragma once - -#include "indiproperties.h" - -namespace INDI { - -class PropertiesPrivate { -public: - PropertiesPrivate(); - virtual ~PropertiesPrivate(); - -public: - std::deque properties; -}; - -} // namespace INDI diff --git a/src/atom/driver/config/property.cpp b/src/atom/driver/config/property.cpp deleted file mode 100644 index ebd46461..00000000 --- a/src/atom/driver/config/property.cpp +++ /dev/null @@ -1,406 +0,0 @@ -/******************************************************************************* - Copyright(c) 2011 Jasem Mutlaq. All rights reserved. - 2022 Pawel Soja - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License version 2 as published by the Free Software Foundation. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*******************************************************************************/ - -#include "indiproperty.h" -#include "indiproperty_p.h" - -#include "basedevice.h" - -#include "indipropertyblob.h" -#include "indipropertylight.h" -#include "indipropertynumber.h" -#include "indipropertyswitch.h" -#include "indipropertytext.h" - - -#include "indipropertyblob_p.h" -#include "indipropertylight_p.h" -#include "indipropertynumber_p.h" -#include "indipropertyswitch_p.h" -#include "indipropertytext_p.h" - - -#include -#include - -namespace Atom::Driver { - -PropertyPrivate::PropertyPrivate(void *property, ATOM_PROPERTY_TYPE type) - : property(property), - type(property ? type : ATOM_UNKNOWN), - registered(property != nullptr) {} - -PropertyPrivate::PropertyPrivate(PropertyViewText *property) - : property(property), - type(property ? ATOM_TEXT : ATOM_UNKNOWN), - registered(property != nullptr) {} - -PropertyPrivate::PropertyPrivate(PropertyViewNumber *property) - : property(property), - type(property ? ATOM_NUMBER : ATOM_UNKNOWN), - registered(property != nullptr) {} - -PropertyPrivate::PropertyPrivate(PropertyViewSwitch *property) - : property(property), - type(property ? ATOM_SWITCH : ATOM_UNKNOWN), - registered(property != nullptr) {} - -PropertyPrivate::PropertyPrivate(PropertyViewLight *property) - : property(property), - type(property ? ATOM_LIGHT : ATOM_UNKNOWN), - registered(property != nullptr) {} - -PropertyPrivate::PropertyPrivate(PropertyViewBlob *property) - : property(property), - type(property ? ATOM_BLOB : ATOM_UNKNOWN), - registered(property != nullptr) {} - -Atom::Driver::Property *Property::self() { - D_PTR(Property); - return isValid() ? &d->self : nullptr; -} - -#define PROPERTY_CASE(CODE) \ - switch (d->property != nullptr ? d->type : ATOM_UNKNOWN) { \ - case ATOM_NUMBER: { \ - auto property = static_cast(d->property); \ - CODE \ - } break; \ - case ATOM_TEXT: { \ - auto property = static_cast(d->property); \ - CODE \ - } break; \ - case ATOM_SWITCH: { \ - auto property = static_cast(d->property); \ - CODE \ - } break; \ - case ATOM_LIGHT: { \ - auto property = static_cast(d->property); \ - CODE \ - } break; \ - case ATOM_BLOB: { \ - auto property = static_cast(d->property); \ - CODE \ - } break; \ - default:; \ - } - -PropertyPrivate::~PropertyPrivate() { - // Only delete properties if they were created dynamically via the - // buildSkeleton function. Other drivers are responsible for their own - // memory allocation. - if (property == nullptr || !dynamic) - return; - - auto d = this; - PROPERTY_CASE(delete property;) -} - -Property::Property() : d_ptr(new PropertyPrivate(nullptr, ATOM_UNKNOWN)) {} - -Property::Property(Atom::Driver::PropertyNumber property) : d_ptr(property.d_ptr) {} - -Property::Property(Atom::Driver::PropertyText property) : d_ptr(property.d_ptr) {} - -Property::Property(Atom::Driver::PropertySwitch property) : d_ptr(property.d_ptr) {} - -Property::Property(Atom::Driver::PropertyLight property) : d_ptr(property.d_ptr) {} - -Property::Property(Atom::Driver::PropertyBlob property) : d_ptr(property.d_ptr) {} - -Property::~Property() {} - -Property::Property(PropertyPrivate &dd) : d_ptr(&dd) {} - -Property::Property(const std::shared_ptr &dd) : d_ptr(dd) {} - -void Property::setProperty(void *p) { - D_PTR(Property); - d->type = p ? d->type : ATOM_UNKNOWN; - d->registered = p != nullptr; - d->property = p; -} - -void Property::setType(ATOM_PROPERTY_TYPE t) { - D_PTR(Property); - d->type = t; -} - -void Property::setRegistered(bool r) { - D_PTR(Property); - d->registered = r; -} - -void Property::setDynamic(bool dyn) { - D_PTR(Property); - d->dynamic = dyn; -} - -void Property::setBaseDevice(BaseDevice *idp) { - D_PTR(Property); - d->baseDevice = (idp == nullptr ? BaseDevice() : *idp); -} - -void Property::setBaseDevice(BaseDevice baseDevice) { - D_PTR(Property); - d->baseDevice = baseDevice; -} - -void *Property::getProperty() const { - D_PTR(const Property); - return d->property; -} - -ATOM_PROPERTY_TYPE Property::getType() const { - D_PTR(const Property); - return d->property != nullptr ? d->type : ATOM_UNKNOWN; -} - -std::string Property::getTypeAsString() const { - switch (getType()) { - case ATOM_NUMBER: - return "ATOM_NUMBER"; - case ATOM_SWITCH: - return "ATOM_SWITCH"; - case ATOM_TEXT: - return "ATOM_TEXT"; - case ATOM_LIGHT: - return "ATOM_LIGHT"; - case ATOM_BLOB: - return "ATOM_BLOB"; - case ATOM_UNKNOWN: - return "ATOM_UNKNOWN"; - } - return "ATOM_UNKNOWN"; -} - -bool Property::getRegistered() const { - D_PTR(const Property); - return d->registered; -} - -bool Property::isDynamic() const { - D_PTR(const Property); - return d->dynamic; -} - -BaseDevice Property::getBaseDevice() const { - D_PTR(const Property); - return d->baseDevice; -} - -void Property::setName(const std::string &name) { - D_PTR(Property); - PROPERTY_CASE(property->setName(name);) -} - -void Property::setLabel(const std::string &label) { - D_PTR(Property); - PROPERTY_CASE(property->setLabel(label);) -} - -void Property::setGroupName(const std::string &group) { - D_PTR(Property); - PROPERTY_CASE(property->setGroupName(group);) -} - -void Property::setDeviceName(const std::string &device) { - D_PTR(Property); - PROPERTY_CASE(property->setDeviceName(device);) -} - -void Property::setTimestamp(const std::string ×tamp) { - D_PTR(Property); - PROPERTY_CASE(property->setTimestamp(timestamp);) -} - -void Property::setState(IPState state) { - D_PTR(Property); - PROPERTY_CASE(property->setState(state);) -} - -void Property::setPermission(IPerm permission) { - D_PTR(Property); - PROPERTY_CASE(property->setPermission(permission);) -} - -void Property::setTimeout(double timeout) { - D_PTR(Property); - PROPERTY_CASE(property->setTimeout(timeout);) -} - -std::string Property::getName() const { - D_PTR(const Property); - PROPERTY_CASE(return property->getName();) - return nullptr; -} - -std::string Property::getLabel() const { - D_PTR(const Property); - PROPERTY_CASE(return property->getLabel();) - return nullptr; -} - -std::string Property::getGroupName() const { - D_PTR(const Property); - PROPERTY_CASE(return property->getGroupName();) - return nullptr; -} - -std::string Property::getDeviceName() const { - D_PTR(const Property); - PROPERTY_CASE(return property->getDeviceName();) - return nullptr; -} - -std::string Property::getTimestamp() const { - D_PTR(const Property); - PROPERTY_CASE(return property->getTimestamp();) - return nullptr; -} - -IPState Property::getState() const { - D_PTR(const Property); - PROPERTY_CASE(return property->getState();) - return IPS_ALERT; -} - -std::string Property::getStateAsString() const { return pstateStr(getState()); } - -IPerm Property::getPermission() const { - D_PTR(const Property); - PROPERTY_CASE(return property->getPermission();) - return IP_RO; -} - -bool Property::isEmpty() const { - D_PTR(const Property); - PROPERTY_CASE(return property->isEmpty();) - return true; -} - -bool Property::isValid() const { - D_PTR(const Property); - return d->type != ATOM_UNKNOWN; -} - -bool Property::isNameMatch(const std::string &otherName) const { - D_PTR(const Property); - PROPERTY_CASE(return property->isNameMatch(otherName);) - return false; -} - -bool Property::isLabelMatch(const std::string &otherLabel) const { - D_PTR(const Property); - PROPERTY_CASE(return property->isLabelMatch(otherLabel);) - return false; -} - -bool Property::isDeviceNameMatch(const std::string &otherDeviceName) const { - return getDeviceName() == otherDeviceName; -} - -bool Property::isTypeMatch(ATOM_PROPERTY_TYPE otherType) const { - return getType() == otherType; -} - -PropertyViewNumber *Property::getNumber() const { - D_PTR(const Property); - if (d->type == ATOM_NUMBER) - return static_cast(d->property); - - return nullptr; -} - -PropertyViewText *Property::getText() const { - D_PTR(const Property); - if (d->type == ATOM_TEXT) - return static_cast(d->property); - - return nullptr; -} - -PropertyViewLight *Property::getLight() const { - D_PTR(const Property); - if (d->type == ATOM_LIGHT) - return static_cast(d->property); - - return nullptr; -} - -PropertyViewSwitch *Property::getSwitch() const { - D_PTR(const Property); - if (d->type == ATOM_SWITCH) - return static_cast(d->property); - - return nullptr; -} - -PropertyViewBlob *Property::getBLOB() const { - D_PTR(const Property); - if (d->type == ATOM_BLOB) - return static_cast(d->property); - - return nullptr; -} - -bool Property::load() { - D_PTR(const Property); - PROPERTY_CASE(return property->load();) - return false; -} - -void Property::save(FILE *fp) const { - D_PTR(const Property); - PROPERTY_CASE(property->save(fp);) -} - -void Property::apply(const std::string &format, ...) const { - D_PTR(const Property); - va_list ap; - va_start(ap, format); - PROPERTY_CASE(property->vapply(format, ap);) - va_end(ap); -} - -void Property::define(const std::string &format, ...) const { - D_PTR(const Property); - va_list ap; - va_start(ap, format); - PROPERTY_CASE(property->vdefine(format, ap);) - va_end(ap); -} - -void Property::onUpdate(const std::function &callback) { - D_PTR(Property); - d->onUpdateCallback = callback; -} - -void Property::emitUpdate() { - D_PTR(Property); - if (d->onUpdateCallback) - d->onUpdateCallback(); -} - -bool Property::hasUpdateCallback() const { - D_PTR(const Property); - return d->onUpdateCallback != nullptr; -} - -} // namespace Atom::Driver diff --git a/src/atom/driver/config/property.hpp b/src/atom/driver/config/property.hpp deleted file mode 100644 index 3eef7f4d..00000000 --- a/src/atom/driver/config/property.hpp +++ /dev/null @@ -1,147 +0,0 @@ -/******************************************************************************* - Copyright(c) 2011 Jasem Mutlaq. All rights reserved. - 2022 Pawel Soja - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License version 2 as published by the Free Software Foundation. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*******************************************************************************/ - -#pragma once - -#include "indibase.h" -#include "indiutility.h" - -#include "indipropertyview.h" - -#include -#include -#include - -namespace Atom::Driver -{ -class BaseDevice; -class PropertyNumber; -class PropertyText; -class PropertySwitch; -class PropertyLight; -class PropertyBlob; -/** - * \class Atom::Driver::Property - \brief Provides generic container for Atom::Driver properties - -\author Jasem Mutlaq -*/ -class PropertyPrivate; -class Property -{ - DECLARE_PRIVATE(Property) - public: - Property(); - ~Property(); - - public: - Property(Atom::Driver::PropertyNumber property); - Property(Atom::Driver::PropertyText property); - Property(Atom::Driver::PropertySwitch property); - Property(Atom::Driver::PropertyLight property); - Property(Atom::Driver::PropertyBlob property); - - public: - void setProperty(void *); - void setType(ATOM_PROPERTY_TYPE t); - void setRegistered(bool r); - void setDynamic(bool d); - - void setBaseDevice(BaseDevice device); - - public: - void *getProperty() const; - ATOM_PROPERTY_TYPE getType() const; - std::string getTypeAsString() const; - bool getRegistered() const; - bool isDynamic() const; - BaseDevice getBaseDevice() const; - - public: // Convenience Functions - void setName(const std::string &name); - void setLabel(const std::string &label); - void setGroupName(const std::string &groupName); - void setDeviceName(const std::string &deviceName); - void setTimestamp(const std::string ×tamp); - void setState(IPState state); - void setPermission(IPerm permission); - void setTimeout(double timeout); - - public: // Convenience Functions - std::string getName() const; - std::string getLabel() const; - std::string getGroupName() const; - std::string getDeviceName() const; - std::string getTimestamp() const; - IPState getState() const; - std::string getStateAsString() const; - IPerm getPermission() const; - - public: - bool isEmpty() const; - bool isValid() const; - - bool isNameMatch(const std::string &otherName) const; - - bool isLabelMatch(const std::string &otherLabel) const; - - bool isDeviceNameMatch(const std::string &otherDeviceName) const; - - bool isTypeMatch(ATOM_PROPERTY_TYPE otherType) const; - - public: - void onUpdate(const std::function &callback); - - public: - void emitUpdate(); - bool hasUpdateCallback() const; - - public: - bool load(); - void save(FILE *fp) const; - - public: - void apply(const std::string &format, ...) const ATTRIBUTE_FORMAT_PRINTF(2, 3); - void define(const std::string &format, ...) const ATTRIBUTE_FORMAT_PRINTF(2, 3); - - void apply() const - { - apply(nullptr); - } - void define() const - { - define(nullptr); - } - - protected: - std::shared_ptr d_ptr; - Property(const std::shared_ptr &dd); - Property(PropertyPrivate &dd); - friend class PropertyNumber; - friend class PropertyText; - friend class PropertySwitch; - friend class PropertyLight; - friend class PropertyBlob; - - protected: - friend class BaseDevicePrivate; - Atom::Driver::Property *self(); -}; - -} // namespace Atom::Driver \ No newline at end of file diff --git a/src/atom/driver/config/property_p.hpp b/src/atom/driver/config/property_p.hpp deleted file mode 100644 index 4a31e6f5..00000000 --- a/src/atom/driver/config/property_p.hpp +++ /dev/null @@ -1,65 +0,0 @@ -/******************************************************************************* - Copyright(c) 2011 Jasem Mutlaq. All rights reserved. - 2022 Pawel Soja - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License version 2 as published by the Free Software Foundation. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*******************************************************************************/ - -#ifndef ATOM_DRIVER_CONFIG_PROPERTY_PROPERTY_P_HPP -#define ATOM_DRIVER_CONFIG_PROPERTY_PROPERTY_P_HPP - -#include -#include -#include "basedevice.h" -#include "indibase.h" -#include "indimacros.h" -#include "indiproperty.h" - -namespace Atom::Driver { - -template -static inline std::shared_ptr property_private_cast( - const std::shared_ptr &r) { - static struct Invalid : public T { - Invalid() : T(16) { this->type = ATOM_UNKNOWN; } - } invalid; - auto result = std::dynamic_pointer_cast(r); - return result != nullptr ? result : make_shared_weak(&invalid); -} - -class BaseDevice; -class PropertyPrivate { -public: - PropertyPrivate(void *property, ATOM_PROPERTY_TYPE type); - PropertyPrivate(PropertyViewText *property); - PropertyPrivate(PropertyViewNumber *property); - PropertyPrivate(PropertyViewSwitch *property); - PropertyPrivate(PropertyViewLight *property); - PropertyPrivate(PropertyViewBlob *property); - - virtual ~PropertyPrivate(); - - void *property = nullptr; - BaseDevice baseDevice; - ATOM_PROPERTY_TYPE type = ATOM_UNKNOWN; - bool registered = false; - bool dynamic = false; - - std::function onUpdateCallback; -}; - -} // namespace Atom::Driver - -#endif diff --git a/src/atom/driver/config/switch.cpp b/src/atom/driver/config/switch.cpp deleted file mode 100644 index f4e2a9c8..00000000 --- a/src/atom/driver/config/switch.cpp +++ /dev/null @@ -1,118 +0,0 @@ -/* - Copyright (C) 2021 by Pawel Soja - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#include "indipropertyswitch.h" -#include "indipropertyswitch_p.h" - -namespace INDI -{ - -PropertySwitchPrivate::PropertySwitchPrivate(size_t count) - : PropertyBasicPrivateTemplate(count) -{ } - -PropertySwitchPrivate::~PropertySwitchPrivate() -{ } - -PropertySwitch::PropertySwitch(size_t count) - : PropertyBasic(*new PropertySwitchPrivate(count)) -{ } - -PropertySwitch::PropertySwitch(INDI::Property property) - : PropertyBasic(property_private_cast(property.d_ptr)) -{ } - -PropertySwitch::~PropertySwitch() -{ } - -void PropertySwitch::reset() -{ - D_PTR(PropertySwitch); - d->typedProperty.reset(); -} - -int PropertySwitch::findOnSwitchIndex() const -{ - D_PTR(const PropertySwitch); - return d->typedProperty.findOnSwitchIndex(); -} - -INDI::WidgetViewSwitch *PropertySwitch::findOnSwitch() const -{ - D_PTR(const PropertySwitch); - return d->typedProperty.findOnSwitch(); -} - -bool PropertySwitch::update(const ISState states[], const char * const names[], int n) -{ - D_PTR(PropertySwitch); - if (d->onNewValuesCallback) - { - NewValues newValues; - for (int i=0; ionNewValuesCallback(newValues); - return true; - } - return d->typedProperty.update(states, names, n) && (emitUpdate(), true); -} - -bool PropertySwitch::hasUpdateCallback() const -{ - D_PTR(const PropertySwitch); - return d->onNewValuesCallback != nullptr || d->onUpdateCallback != nullptr; -} - -void PropertySwitch::fill( - const char *device, const char *name, const char *label, const char *group, - IPerm permission, ISRule rule, double timeout, IPState state -) -{ - D_PTR(PropertySwitch); - d->typedProperty.setWidgets(d->widgets.data(), d->widgets.size()); - d->typedProperty.fill(device, name, label, group, permission, rule, timeout, state); -} - -void PropertySwitch::setRule(ISRule rule) -{ - D_PTR(PropertySwitch); - d->typedProperty.setRule(rule); -} - -ISRule PropertySwitch::getRule() const -{ - D_PTR(const PropertySwitch); - return d->typedProperty.getRule(); -} - -const char * PropertySwitch::getRuleAsString() const -{ - D_PTR(const PropertySwitch); - return d->typedProperty.getRuleAsString(); -} - -void PropertySwitch::onNewValues(const std::function &callback) -{ - D_PTR(PropertySwitch); - d->onNewValuesCallback = callback; -} - -} diff --git a/src/atom/driver/config/switch.hpp b/src/atom/driver/config/switch.hpp deleted file mode 100644 index 7be4677a..00000000 --- a/src/atom/driver/config/switch.hpp +++ /dev/null @@ -1,68 +0,0 @@ -/* - Copyright (C) 2021 by Pawel Soja - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - USA -*/ - -#pragma once - -#include -#include "indipropertybasic.h" - - -namespace INDI { - -class PropertySwitchPrivate; -class PropertySwitch : public INDI::PropertyBasic { - DECLARE_PRIVATE(PropertySwitch) -public: - struct NewValues : public std::map { - bool contains(const std::string &key, const ISState &state) const { - auto it = this->find(key); - return it != this->cend() && it->second == state; - } - }; - -public: - PropertySwitch(size_t count); - PropertySwitch(INDI::Property property); - ~PropertySwitch(); - -public: - void onNewValues(const std::function &callback); - -public: - bool update(const ISState states[], const char *const names[], int n); - bool hasUpdateCallback() const; - - void fill(const char *device, const char *name, const char *label, - const char *group, IPerm permission, ISRule rule, double timeout, - IPState state); - -public: - void reset(); - int findOnSwitchIndex() const; - INDI::WidgetViewSwitch *findOnSwitch() const; - -public: - void setRule(ISRule rule); - -public: - ISRule getRule() const; - const char *getRuleAsString() const; -}; - -} // namespace INDI diff --git a/src/atom/driver/config/switch_p.hpp b/src/atom/driver/config/switch_p.hpp deleted file mode 100644 index 714f448e..00000000 --- a/src/atom/driver/config/switch_p.hpp +++ /dev/null @@ -1,44 +0,0 @@ -/* - Copyright (C) 2021 by Pawel Soja - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#pragma once - -#include "indipropertybasic_p.h" -#include "indipropertyview.h" -#include "indipropertyswitch.h" - -#include - -namespace INDI -{ - -class PropertySwitchPrivate: public PropertyBasicPrivateTemplate -{ - public: - PropertySwitchPrivate(size_t count); - PropertySwitchPrivate(RawPropertyType *p) - : BasicPropertyType(p) - { } - virtual ~PropertySwitchPrivate(); - - public: - std::function onNewValuesCallback; - -}; - -} diff --git a/src/atom/driver/config/text.cpp b/src/atom/driver/config/text.cpp deleted file mode 100644 index ca3770f7..00000000 --- a/src/atom/driver/config/text.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/* - Copyright (C) 2021 by Pawel Soja - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - USA -*/ - -#include "indipropertytext.h" -#include "indipropertytext_p.h" - -namespace INDI { - -PropertyTextPrivate::PropertyTextPrivate(size_t count) - : PropertyBasicPrivateTemplate(count) {} - -PropertyTextPrivate::~PropertyTextPrivate() {} - -PropertyText::PropertyText(size_t count) - : PropertyBasic(*new PropertyTextPrivate(count)) {} - -PropertyText::PropertyText(INDI::Property property) - : PropertyBasic( - property_private_cast(property.d_ptr)) {} - -PropertyText::~PropertyText() {} - -bool PropertyText::update(const char *const texts[], const char *const names[], - int n) { - D_PTR(PropertyText); - return d->typedProperty.update(texts, names, n) && (emitUpdate(), true); -} - -void PropertyText::fill(const char *device, const char *name, const char *label, - const char *group, IPerm permission, double timeout, - IPState state) { - D_PTR(PropertyText); - d->typedProperty.setWidgets(d->widgets.data(), d->widgets.size()); - d->typedProperty.fill(device, name, label, group, permission, timeout, - state); -} - -} // namespace INDI diff --git a/src/atom/driver/config/text.hpp b/src/atom/driver/config/text.hpp deleted file mode 100644 index 707c942a..00000000 --- a/src/atom/driver/config/text.hpp +++ /dev/null @@ -1,42 +0,0 @@ -/* - Copyright (C) 2021 by Pawel Soja - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - USA -*/ - -#pragma once - -#include "indipropertybasic.h" - -namespace INDI { - -class PropertyTextPrivate; -class PropertyText : public INDI::PropertyBasic { - DECLARE_PRIVATE(PropertyText) -public: - PropertyText(size_t count); - PropertyText(INDI::Property property); - ~PropertyText(); - -public: - bool update(const char *const texts[], const char *const names[], int n); - - void fill(const char *device, const char *name, const char *label, - const char *group, IPerm permission, double timeout, - IPState state); -}; - -} // namespace INDI diff --git a/src/atom/driver/config/text_p.hpp b/src/atom/driver/config/text_p.hpp deleted file mode 100644 index daf7a5b5..00000000 --- a/src/atom/driver/config/text_p.hpp +++ /dev/null @@ -1,36 +0,0 @@ -/* - Copyright (C) 2021 by Pawel Soja - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - USA -*/ - -#pragma once - -#include "indipropertybasic_p.h" -#include "indipropertyview.h" - -namespace INDI { - -class PropertyTextPrivate : public PropertyBasicPrivateTemplate { -public: - PropertyTextPrivate(size_t count); - PropertyTextPrivate(RawPropertyType *p) : BasicPropertyType(p) {} - virtual ~PropertyTextPrivate(); - -public: -}; - -} // namespace INDI diff --git a/src/atom/driver/config/traits.hpp b/src/atom/driver/config/traits.hpp deleted file mode 100644 index 7d330b57..00000000 --- a/src/atom/driver/config/traits.hpp +++ /dev/null @@ -1,79 +0,0 @@ -/* - Copyright (C) 2021 by Pawel Soja - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - USA -*/ - -#pragma once - -#include "indiapi.h" -#include "indiutility.h" - -namespace INDI { - -template -struct WidgetTraits; - -template <> -struct WidgetTraits { - using PropertyType = ITextVectorProperty; - struct UpdateArgs { - char **texts; - char **names; - int n; - }; -}; - -template <> -struct WidgetTraits { - using PropertyType = INumberVectorProperty; - struct UpdateArgs { - double *values; - char **names; - int n; - }; -}; - -template <> -struct WidgetTraits { - using PropertyType = ISwitchVectorProperty; - struct UpdateArgs { - ISState *states; - char **names; - int n; - }; -}; - -template <> -struct WidgetTraits { - using PropertyType = ILightVectorProperty; - struct UpdateArgs {}; -}; - -template <> -struct WidgetTraits { - using PropertyType = IBLOBVectorProperty; - struct UpdateArgs { - int *sizes; - int *blobsizes; - char **blobs; - char **formats; - char **names; - int n; - }; -}; - -} // namespace INDI diff --git a/src/atom/driver/config/view.cpp b/src/atom/driver/config/view.cpp deleted file mode 100644 index fb3f6f33..00000000 --- a/src/atom/driver/config/view.cpp +++ /dev/null @@ -1,294 +0,0 @@ -/* - Copyright (C) 2021 by Pawel Soja - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - USA -*/ - -#include "indipropertyview.h" - -void (*WeakIDSetTextVA)(const ITextVectorProperty *, const char *, - va_list) = nullptr; -void (*WeakIDDefTextVA)(const ITextVectorProperty *, const char *, - va_list) = nullptr; -void (*WeakIDSetNumberVA)(const INumberVectorProperty *, const char *, - va_list) = nullptr; -void (*WeakIDDefNumberVA)(const INumberVectorProperty *, const char *, - va_list) = nullptr; -void (*WeakIDSetSwitchVA)(const ISwitchVectorProperty *, const char *, - va_list) = nullptr; -void (*WeakIDDefSwitchVA)(const ISwitchVectorProperty *, const char *, - va_list) = nullptr; -void (*WeakIDSetLightVA)(const ILightVectorProperty *, const char *, - va_list) = nullptr; -void (*WeakIDDefLightVA)(const ILightVectorProperty *, const char *, - va_list) = nullptr; -void (*WeakIDSetBLOBVA)(const IBLOBVectorProperty *, const char *, - va_list) = nullptr; -void (*WeakIDDefBLOBVA)(const IBLOBVectorProperty *, const char *, - va_list) = nullptr; -int (*WeakIUUpdateText)(ITextVectorProperty *, char *[], char *[], - int) = nullptr; -int (*WeakIUUpdateNumber)(INumberVectorProperty *, double[], char *[], - int n) = nullptr; -int (*WeakIUUpdateSwitch)(ISwitchVectorProperty *, ISState *, char *[], - int n) = nullptr; -int (*WeakIUUpdateBLOB)(IBLOBVectorProperty *, int[], int[], char *[], char *[], - char *[], int n) = nullptr; -void (*WeakIUUpdateMinMax)(const INumberVectorProperty *) = nullptr; - -namespace INDI { - -static void errorUnavailable(const char *function) { - fprintf(stderr, "%s method available only on driver side\n", function); -} - -template <> -void PropertyView::vapply(const char *format, va_list arg) const { - if (WeakIDSetTextVA) - WeakIDSetTextVA(this, format, arg); - else - errorUnavailable(__FUNCTION__); -} - -template <> -void PropertyView::vdefine(const char *format, va_list arg) const { - if (WeakIDDefTextVA) - WeakIDDefTextVA(this, format, arg); - else - errorUnavailable(__FUNCTION__); -} - -template <> -void PropertyView::vapply(const char *format, va_list arg) const { - if (WeakIDSetNumberVA) - WeakIDSetNumberVA(this, format, arg); - else - errorUnavailable(__FUNCTION__); -} - -template <> -void PropertyView::vdefine(const char *format, va_list arg) const { - if (WeakIDDefNumberVA) - WeakIDDefNumberVA(this, format, arg); - else - errorUnavailable(__FUNCTION__); -} - -template <> -void PropertyView::vapply(const char *format, va_list arg) const { - if (WeakIDSetSwitchVA) - WeakIDSetSwitchVA(this, format, arg); - else - errorUnavailable(__FUNCTION__); -} - -template <> -void PropertyView::vdefine(const char *format, va_list arg) const { - if (WeakIDDefSwitchVA) - WeakIDDefSwitchVA(this, format, arg); - else - errorUnavailable(__FUNCTION__); -} - -template <> -void PropertyView::vapply(const char *format, va_list arg) const { - if (WeakIDSetLightVA) - WeakIDSetLightVA(this, format, arg); - else - errorUnavailable(__FUNCTION__); -} - -template <> -void PropertyView::vdefine(const char *format, va_list arg) const { - if (WeakIDDefLightVA) - WeakIDDefLightVA(this, format, arg); - else - errorUnavailable(__FUNCTION__); -} - -template <> -void PropertyView::vapply(const char *format, va_list arg) const { - if (WeakIDSetBLOBVA) - WeakIDSetBLOBVA(this, format, arg); - else - errorUnavailable(__FUNCTION__); -} - -template <> -void PropertyView::vdefine(const char *format, va_list arg) const { - if (WeakIDDefBLOBVA) - WeakIDDefBLOBVA(this, format, arg); - else - errorUnavailable(__FUNCTION__); -} - -template -void PropertyView::apply(const char *format, ...) const { - va_list ap; - va_start(ap, format); - this->vapply(format, ap); - va_end(ap); -} - -template -void PropertyView::define(const char *format, ...) const { - va_list ap; - va_start(ap, format); - this->vdefine(format, ap); - va_end(ap); -} - -template <> -template <> -void PropertyView::fill(const char *device, const char *name, - const char *label, const char *group, - IPerm permission, double timeout, - IPState state) { - IUFillTextVector(this, begin(), count(), device, name, label, group, - permission, timeout, state); -} - -template <> -template <> -void PropertyView::fill(const char *device, const char *name, - const char *label, const char *group, - IPerm permission, double timeout, - IPState state) { - IUFillNumberVector(this, begin(), count(), device, name, label, group, - permission, timeout, state); -} - -template <> -template <> -void PropertyView::fill(const char *device, const char *name, - const char *label, const char *group, - IPerm permission, ISRule rule, double timeout, - IPState state) { - IUFillSwitchVector(this, begin(), count(), device, name, label, group, - permission, rule, timeout, state); -} - -template <> -template <> -void PropertyView::fill(const char *device, const char *name, - const char *label, const char *group, - IPState state) { - IUFillLightVector(this, begin(), count(), device, name, label, group, - state); -} - -template <> -template <> -void PropertyView::fill(const char *device, const char *name, - const char *label, const char *group, - IPerm permission, double timeout, - IPState state) { - IUFillBLOBVector(this, begin(), count(), device, name, label, group, - permission, timeout, state); -} - -template <> -template <> -bool PropertyView::update(const char *const texts[], - const char *const names[], int n) { - if (WeakIUUpdateText) - return WeakIUUpdateText(this, const_cast(texts), - const_cast(names), n) == 0; - - errorUnavailable(__FUNCTION__); - return false; -} - -template <> -template <> -bool PropertyView::update(const double values[], - const char *const names[], int n) { - if (WeakIUUpdateNumber) - return WeakIUUpdateNumber(this, const_cast(values), - const_cast(names), n) == 0; - - errorUnavailable(__FUNCTION__); - return false; -} - -template <> -template <> -bool PropertyView::update(const ISState states[], - const char *const names[], int n) { - if (WeakIUUpdateSwitch) - return WeakIUUpdateSwitch(this, const_cast(states), - const_cast(names), n) == 0; - - errorUnavailable(__FUNCTION__); - return false; -} - -template <> -template <> -bool PropertyView::update(const int sizes[], const int blobsizes[], - const char *const blobs[], - const char *const formats[], - const char *const names[], int n) { - if (WeakIUUpdateBLOB) - return WeakIUUpdateBLOB( - this, const_cast(sizes), const_cast(blobsizes), - const_cast(blobs), const_cast(formats), - const_cast(names), n) == 0; - - errorUnavailable(__FUNCTION__); - return false; -} - -template <> -template <> -void PropertyView::updateMinMax() { - if (WeakIUUpdateMinMax) - WeakIUUpdateMinMax(this); -} - -void WidgetView::fill(const char *name, const char *label, - const char *initialText) { - IUFillText(this, name, label, initialText); -} - -void WidgetView::fill(const char *name, const char *label, - ISState state) { - IUFillSwitch(this, name, label, state); -} - -void WidgetView::fill(const char *name, const char *label, - IPState state) { - IUFillLight(this, name, label, state); -} - -void WidgetView::fill(const char *name, const char *label, - const char *format, double min, double max, - double step, double value) { - IUFillNumber(this, name, label, format, min, max, step, value); -} - -void WidgetView::fill(const char *name, const char *label, - const char *format) { - IUFillBLOB(this, name, label, format); -} - -template struct PropertyView; -template struct PropertyView; -template struct PropertyView; -template struct PropertyView; -template struct PropertyView; - -} // namespace INDI diff --git a/src/atom/driver/config/view.hpp b/src/atom/driver/config/view.hpp deleted file mode 100644 index a9d463c4..00000000 --- a/src/atom/driver/config/view.hpp +++ /dev/null @@ -1,1053 +0,0 @@ -/* - Copyright (C) 2021 by Pawel Soja - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - USA -*/ - -#pragma once - -#include "indiapi.h" -#include "indidevapi.h" -#include "indiwidgettraits.h" -#include "indiwidgetview.h" - -#include -#include -#include -#include -#include - - -namespace INDI { - -template -struct WidgetView; -template -struct PropertyView; - -typedef PropertyView PropertyViewText; -typedef PropertyView PropertyViewNumber; -typedef PropertyView PropertyViewSwitch; -typedef PropertyView PropertyViewLight; -typedef PropertyView PropertyViewBlob; - -typedef WidgetView WidgetViewText; -typedef WidgetView WidgetViewNumber; -typedef WidgetView WidgetViewSwitch; -typedef WidgetView WidgetViewLight; -typedef WidgetView WidgetViewBlob; - -#define PROPERTYVIEW_BASE_ACCESS public -// don't use direct access to low-level property -// #define PROPERTYVIEW_BASE_ACCESS protected // future - -/** - * \class INDI::PropertyView and INDI::WidgetView - * \brief Provides decorator for Low-Level IXXXVectorProperty/IXXX - * - * INDI::PropertyView - * - * A class that will allow a easy transition to the new widget handling - * interface (future). - * - Use PropertyViewText instead of ITextVectorProperty - * - Use PropertyViewNumber instead of INumberVectorProperty - * - Use PropertyViewSwitch instead of ISwitchVectorProperty - * - Use PropertyViewLight instead of ILightVectorProperty - * - Use PropertyViewBlob instead of IBLOBVectorProperty - * - * The PropertyView class is compatible with low-level IXXXVectorProperty - * structures. - * - * INDI::WidgetView - * - * A class that will allow a easy transition to the new widget handling - * interface (future). - * - Use WidgetViewText instead of IText - * - Use WidgetViewNumber instead of INumber - * - Use WidgetViewSwitch instead of ISwitch - * - Use WidgetViewLight instead of ILight - * - Use WidgetViewBlob instead of IBLOB - * - * The WidgetView class is compatible with low-level IXXX structures. - */ - -template -struct PropertyView : PROPERTYVIEW_BASE_ACCESS WidgetTraits::PropertyType { - using Type = T; - using PropertyType = typename WidgetTraits::PropertyType; - using WidgetType = WidgetView; - - friend class Property; - friend class PropertyPrivate; - friend class BaseDevice; - friend class DefaultDevice; - template - friend struct WidgetView; - - template - using enable_if_is_same_t = - typename std::enable_if::value, bool>::type; - -public: - PropertyView(); - - // #PS: do not delete items, they may be on the stack. - //~PropertyView() { for(auto &p: - //*this) {p.clear();} free(widget()); } - -public: - void setDeviceName(const char *name); /* outside implementation */ - void setDeviceName(const std::string &name); /* outside implementation */ - - void setName(const char *name); /* outside implementation */ - void setName(const std::string &name); /* outside implementation */ - - void setLabel(const char *label); /* outside implementation */ - void setLabel(const std::string &label); /* outside implementation */ - - void setGroupName(const char *name); /* outside implementation */ - void setGroupName(const std::string &name); /* outside implementation */ - - void setPermission(IPerm permission); /* outside implementation */ - void setTimeout(double timeout); /* outside implementation */ - void setState(IPState state); - - void setTimestamp(const char *timestamp); /* outside implementation */ - void setTimestamp( - const std::string ×tamp); /* outside implementation */ - - void setAux(void *user); /* outside implementation */ - void setWidgets(WidgetType *w, size_t count); /* outside implementation */ - - template - void setWidgets(WidgetType (&w)[N]); /* outside implementation */ - -public: // only for ISwitch - void setRule(ISRule rule); /* outside implementation */ - bool setRule(const std::string &rule); /* outside implementation */ - - template = true> - void reset() { - IUResetSwitch(this); - } - - template = true> - WidgetType *findOnSwitch() const { - return static_cast(IUFindOnSwitch(this)); - } - - template = true> - int findOnSwitchIndex() const { - return IUFindOnSwitchIndex(this); - } - -public: // only for INumber - template = true> - void updateMinMax(); /* outside implementation - only driver side, see - indipropertyview_driver.cpp */ - -public: // getters - const char *getDeviceName() const { return this->device; } - const char *getName() const { return this->name; } - const char *getLabel() const { return this->label; } - const char *getGroupName() const { return this->group; } - - IPerm getPermission() const; /* outside implementation */ - const char *getPermissionAsString() const { - return permStr(getPermission()); - } - - ISRule getRule() const; /* outside implementation */ - const char *getRuleAsString() const { return ruleStr(getRule()); } - - double getTimeout() const; /* outside implementation */ - IPState getState() const { return this->s; } - const char *getStateAsString() const { return pstateStr(getState()); } - - const char *getTimestamp() const { return this->timestamp; } - void *getAux() const { return this->aux; } - - int count() const; /* outside implementation */ - WidgetType *widget() const; /* outside implementation */ - - WidgetType *findWidgetByName( - const char *name) const; /* outside implementation */ - -public: // tests - bool isEmpty() const { return widget() == nullptr || count() == 0; } - - bool isNameMatch(const char *otherName) const { - return !strcmp(getName(), otherName); - } - bool isNameMatch(const std::string &otherName) const { - return getName() == otherName; - } - - bool isLabelMatch(const char *otherLabel) const { - return !strcmp(getLabel(), otherLabel); - } - bool isLabelMatch(const std::string &otherLabel) const { - return getLabel() == otherLabel; - } - -public: // only driver side - bool load(); - void save(FILE *f) const; /* outside implementation */ - - void vapply(const char *format, - va_list args) const; /* outside implementation - only driver - side, see indipropertyview_driver.cpp */ - void vdefine(const char *format, va_list args) - const; /* outside implementation - only driver side, see - indipropertyview_driver.cpp */ - - void apply(const char *format, ...) const - ATTRIBUTE_FORMAT_PRINTF(2, - 3); /* outside implementation - only driver - side, see indipropertyview_driver.cpp */ - void define(const char *format, ...) const - ATTRIBUTE_FORMAT_PRINTF(2, - 3); /* outside implementation - only driver - side, see indipropertyview_driver.cpp */ - - void apply() const { apply(nullptr); } - void define() const { define(nullptr); } - -public: - template = true> - void fill(const char *device, const char *name, const char *label, - const char *group, IPerm permission, double timeout, - IPState state); /* outside implementation - only driver side, see - indipropertyview_driver.cpp */ - - template = true> - void fill(const char *device, const char *name, const char *label, - const char *group, IPerm permission, double timeout, - IPState state); /* outside implementation - only driver side, see - indipropertyview_driver.cpp */ - - template = true> - void fill(const char *device, const char *name, const char *label, - const char *group, IPerm permission, ISRule rule, double timeout, - IPState state); /* outside implementation - only driver side, see - indipropertyview_driver.cpp */ - - template = true> - void fill(const char *device, const char *name, const char *label, - const char *group, - IPState state); /* outside implementation - only driver side, see - indipropertyview_driver.cpp */ - - template = true> - void fill(const char *device, const char *name, const char *label, - const char *group, IPerm permission, double timeout, - IPState state); /* outside implementation - only driver side, see - indipropertyview_driver.cpp */ - -public: - template = true> - bool update(const char *const texts[], const char *const names[], int n); - /* outside implementation - only driver side, see - * indipropertyview_driver.cpp */ - - template = true> - bool update(const double values[], const char *const names[], int n); - /* outside implementation - only driver side, see - * indipropertyview_driver.cpp */ - - template = true> - bool update(const ISState states[], const char *const names[], int n); - /* outside implementation - only driver side, see - * indipropertyview_driver.cpp */ - - /* - template = true> - bool update(..., const char * const names[], int n); - */ - - template = true> - bool update(const int sizes[], const int blobsizes[], - const char *const blobs[], const char *const formats[], - const char *const names[], - int n); /* outside implementation - only driver side, see - indipropertyview_driver.cpp */ - -public: - WidgetType *begin() const { return widget(); } - WidgetType *end() const { return widget() + count(); } - - WidgetType *at(size_t index) const { return widget() + index; } - -public: - void clear() { - for (auto &p : *this) { - p.clear(); - } - // free(widget()); // #PS: do not delete items, they may be on the - // stack. - memset(this, 0, sizeof(*this)); - } - -public: // internal use only - static PropertyView *cast(PropertyType *raw) { - return static_cast *>(raw); - } - PropertyType *cast() { return this; } -}; - -template -struct WidgetView; - -template <> -struct WidgetView : PROPERTYVIEW_BASE_ACCESS IText { - using Type = IText; - template - friend struct PropertyView; - -public: - WidgetView() { memset(this, 0, sizeof(*this)); } - WidgetView(const WidgetView &other) : Type(other) { - this->text = nullptr; - setText(other.text); - } - WidgetView(WidgetView &&other) : Type(other) { - memset(static_cast(&other), 0, sizeof(other)); - } - WidgetView &operator=(const WidgetView &other) { - return *this = WidgetView(other); - } - WidgetView &operator=(WidgetView &&other) { - std::swap(static_cast(other), static_cast(*this)); - return *this; - } - ~WidgetView() { free(this->text); } - void clear() { - free(this->text); - memset(this, 0, sizeof(*this)); - } - // bool isNull() const { return - // reinterpret_cast(this) == nullptr; } - -public: // setters - void setParent(ITextVectorProperty *parent) { this->tvp = parent; } - void setParent(PropertyView *parent) { - this->tvp = static_cast(parent); - } - - void setName(const char *name) { INDI::strlcpy(this->name, name); } - void setName(const std::string &name) { setName(name.data()); } - - void setLabel(const char *label) { INDI::strlcpy(this->label, label); } - void setLabel(const std::string &label) { setLabel(label.data()); } - - // void setText(const char *text) { - // free(this->text); this->text = strndup(text, strlen(text)); } - void setText(const char *text, size_t size) { - INDI::strlcpy( - this->text = static_cast(realloc(this->text, size + 1)), - text, size + 1); - } - void setText(const char *text) { setText(text, strlen(text)); } - void setText(const std::string &text) { setText(text.data(), text.size()); } - - void setAux(void *user) { this->aux0 = user; } - // don't use any other aux! - -public: // getters - const char *getName() const { return this->name; } - const char *getLabel() const { return this->label; } - const char *getText() const { return this->text ? this->text : ""; } - - void *getAux() const { return this->aux0; } - -public: // tests - bool isNameMatch(const char *otherName) const { - return !strcmp(getName(), otherName); - } - bool isNameMatch(const std::string &otherName) const { - return getName() == otherName; - } - - bool isLabelMatch(const char *otherLabel) const { - return !strcmp(getLabel(), otherLabel); - } - bool isLabelMatch(const std::string &otherLabel) const { - return getLabel() == otherLabel; - } - - bool isEmpty() const { return getText()[0] == '\0'; } - -public: - void fill( - const char *name, const char *label, - const char *initialText); /* outside implementation - only driver side, - see indipropertyview_driver.cpp */ - - void fill(const std::string &name, const std::string &label, - const std::string &initialText) { - fill(name.c_str(), label.c_str(), initialText.c_str()); - } -}; - -template <> -struct WidgetView : PROPERTYVIEW_BASE_ACCESS INumber { - using Type = INumber; - template - friend struct PropertyView; - -public: - WidgetView() { memset(this, 0, sizeof(*this)); } - WidgetView(const WidgetView &other) : Type(other) {} - WidgetView(WidgetView &&other) : Type(other) { - memset(static_cast(&other), 0, sizeof(other)); - } - WidgetView &operator=(const WidgetView &other) { - return *this = WidgetView(other); - } - WidgetView &operator=(WidgetView &&other) { - std::swap(static_cast(other), static_cast(*this)); - return *this; - } - ~WidgetView() {} - void clear() { memset(this, 0, sizeof(*this)); } - // bool isNull() const { return - // reinterpret_cast(this) == nullptr; } - -public: // setters - void setParent(INumberVectorProperty *parent) { this->nvp = parent; } - void setParent(PropertyView *parent) { - this->nvp = static_cast(parent); - } - - void setName(const char *name) { INDI::strlcpy(this->name, name); } - void setName(const std::string &name) { setName(name.data()); } - - void setLabel(const char *label) { INDI::strlcpy(this->label, label); } - void setLabel(const std::string &label) { setLabel(label.data()); } - - void setFormat(const char *format) { INDI::strlcpy(this->format, format); } - void setFormat(const std::string &format) { setLabel(format.data()); } - - void setMin(double min) { this->min = min; } - void setMax(double max) { this->max = max; } - void setMinMax(double min, double max) { - setMin(min); - setMax(max); - } - void setStep(double step) { this->step = step; } - void setValue(double value) { this->value = value; } - - void setAux(void *user) { this->aux0 = user; } - // don't use any other aux! - -public: // getters - const char *getName() const { return this->name; } - const char *getLabel() const { return this->label; } - const char *getFormat() const { return this->format; } - - double getMin() const { return this->min; } - double getMax() const { return this->max; } - double getStep() const { return this->step; } - double getValue() const { return this->value; } - - void *getAux() const { return this->aux0; } - -public: // tests - bool isNameMatch(const char *otherName) const { - return !strcmp(getName(), otherName); - } - bool isNameMatch(const std::string &otherName) const { - return getName() == otherName; - } - - bool isLabelMatch(const char *otherLabel) const { - return !strcmp(getLabel(), otherLabel); - } - bool isLabelMatch(const std::string &otherLabel) const { - return getLabel() == otherLabel; - } - -public: - void fill(const char *name, const char *label, const char *format, - double min, double max, double step, - double value); /* outside implementation - only driver side, see - indipropertyview_driver.cpp */ - - void fill(const std::string &name, const std::string &label, - const std::string &format, double min, double max, double step, - double value) { - fill(name.c_str(), label.c_str(), format.c_str(), min, max, step, - value); - } -}; - -template <> -struct WidgetView : PROPERTYVIEW_BASE_ACCESS ISwitch { - using Type = ISwitch; - template - friend struct PropertyView; - -public: - WidgetView() { memset(this, 0, sizeof(*this)); } - WidgetView(const WidgetView &other) : Type(other) {} - WidgetView(WidgetView &&other) : Type(other) { - memset(static_cast(&other), 0, sizeof(other)); - } - WidgetView &operator=(const WidgetView &other) { - return *this = WidgetView(other); - } - WidgetView &operator=(WidgetView &&other) { - std::swap(static_cast(other), static_cast(*this)); - return *this; - } - ~WidgetView() {} - void clear() { memset(this, 0, sizeof(*this)); } - // bool isNull() const { return - // reinterpret_cast(this) == nullptr; } - -public: // setters - void setParent(ISwitchVectorProperty *parent) { this->svp = parent; } - void setParent(PropertyView *parent) { - this->svp = static_cast(parent); - } - - void setName(const char *name) { INDI::strlcpy(this->name, name); } - void setName(const std::string &name) { setName(name.data()); } - - void setLabel(const char *label) { INDI::strlcpy(this->label, label); } - void setLabel(const std::string &label) { setLabel(label.data()); } - - void setState(const ISState &state) { this->s = state; } - bool setState(const std::string &state) { - return crackISState(state.data(), &this->s) == 0; - } - - void setAux(void *user) { this->aux = user; } - // don't use any other aux! - -public: // getters - const char *getName() const { return this->name; } - const char *getLabel() const { return this->label; } - - ISState getState() const { return this->s; } - const char *getStateAsString() const { return sstateStr(getState()); } - - void *getAux() const { return this->aux; } - -public: // tests - bool isNameMatch(const char *otherName) const { - return !strcmp(getName(), otherName); - } - bool isNameMatch(const std::string &otherName) const { - return getName() == otherName; - } - - bool isLabelMatch(const char *otherLabel) const { - return !strcmp(getLabel(), otherLabel); - } - bool isLabelMatch(const std::string &otherLabel) const { - return getLabel() == otherLabel; - } - -public: - void fill( - const char *name, const char *label, - ISState state = ISS_OFF); /* outside implementation - only driver side, - see indipropertyview_driver.cpp */ - - void fill(const std::string &name, const std::string &label, - ISState state = ISS_OFF) { - fill(name.c_str(), label.c_str(), state); - } -}; - -template <> -struct WidgetView : PROPERTYVIEW_BASE_ACCESS ILight { - using Type = ILight; - template - friend struct PropertyView; - -public: - WidgetView() { memset(this, 0, sizeof(*this)); } - WidgetView(const WidgetView &other) : Type(other) {} - WidgetView(WidgetView &&other) : Type(other) { - memset(static_cast(&other), 0, sizeof(other)); - } - WidgetView &operator=(const WidgetView &other) { - return *this = WidgetView(other); - } - WidgetView &operator=(WidgetView &&other) { - std::swap(static_cast(other), static_cast(*this)); - return *this; - } - ~WidgetView() {} - void clear() { memset(this, 0, sizeof(*this)); } - // bool isNull() const { return - // reinterpret_cast(this) == nullptr; } - -public: // setters - void setParent(ILightVectorProperty *parent) { this->lvp = parent; } - void setParent(PropertyView *parent) { - this->lvp = static_cast(parent); - } - - void setName(const char *name) { INDI::strlcpy(this->name, name); } - void setName(const std::string &name) { setName(name.data()); } - - void setLabel(const char *label) { INDI::strlcpy(this->label, label); } - void setLabel(const std::string &label) { setLabel(label.data()); } - - void setState(const IPState &state) { this->s = state; } - bool setState(const std::string &state) { - return crackIPState(state.data(), &this->s) == 0; - } - - void setAux(void *user) { this->aux = user; } - // don't use any other aux! - -public: // getters - const char *getName() const { return this->name; } - const char *getLabel() const { return this->label; } - - IPState getState() const { return this->s; } - const char *getStateAsString() const { return pstateStr(getState()); } - - void *getAux() const { return this->aux; } - -public: // tests - bool isNameMatch(const char *otherName) const { - return !strcmp(getName(), otherName); - } - bool isNameMatch(const std::string &otherName) const { - return getName() == otherName; - } - - bool isLabelMatch(const char *otherLabel) const { - return !strcmp(getLabel(), otherLabel); - } - bool isLabelMatch(const std::string &otherLabel) const { - return getLabel() == otherLabel; - } - -public: - void fill( - const char *name, const char *label, - IPState state = IPS_OK); /* outside implementation - only driver side, - see indipropertyview_driver.cpp */ - - void fill(const std::string &name, const std::string &&label, - IPState state = IPS_OK) { - fill(name.c_str(), label.c_str(), state); - } -}; - -template <> -struct WidgetView : PROPERTYVIEW_BASE_ACCESS IBLOB { - using Type = IBLOB; - template - friend struct PropertyView; - -public: - WidgetView() { memset(this, 0, sizeof(*this)); } - WidgetView(const WidgetView &other) : Type(other) {} - WidgetView(WidgetView &&other) : Type(other) { - memset(static_cast(&other), 0, sizeof(other)); - } - WidgetView &operator=(const WidgetView &other) { - return *this = WidgetView(other); - } - WidgetView &operator=(WidgetView &&other) { - std::swap(static_cast(other), static_cast(*this)); - return *this; - } - ~WidgetView() { /* free(this->blob); */ } - void clear() { /* free(this->blob); */ memset(this, 0, sizeof(*this)); } - // bool isNull() const { return - // reinterpret_cast(this) == nullptr; } - -public: // setters - void setParent(IBLOBVectorProperty *parent) { this->bvp = parent; } - void setParent(PropertyView *parent) { - this->bvp = static_cast(parent); - } - - void setName(const char *name) { INDI::strlcpy(this->name, name); } - void setName(const std::string &name) { setName(name.data()); } - - void setLabel(const char *label) { INDI::strlcpy(this->label, label); } - void setLabel(const std::string &label) { setLabel(label.data()); } - - void setFormat(const char *format) { INDI::strlcpy(this->format, format); } - void setFormat(const std::string &format) { setFormat(format.data()); } - - void setBlob(void *blob) { this->blob = blob; } - void setBlobLen(int size) { this->bloblen = size; } - void setSize(int size) { this->size = size; } - - void setAux(void *user) { this->aux0 = user; } - // don't use any other aux! - -public: // getters - const char *getName() const { return this->name; } - const char *getLabel() const { return this->label; } - const char *getFormat() const { return this->format; } - void *getBlob() { return this->blob; } - const void *getBlob() const { return this->blob; } - std::string getBlobAsString() const { - return std::string(static_cast(this->blob), - this->bloblen); - } - int getBlobLen() const { return this->bloblen; } - int getSize() const { return this->size; } - - void *getAux() const { return this->aux0; } - -public: // tests - bool isNameMatch(const char *otherName) const { - return !strcmp(getName(), otherName); - } - bool isNameMatch(const std::string &otherName) const { - return getName() == otherName; - } - - bool isLabelMatch(const char *otherLabel) const { - return !strcmp(getLabel(), otherLabel); - } - bool isLabelMatch(const std::string &otherLabel) const { - return getLabel() == otherLabel; - } - -public: - void fill(const char *name, const char *label, - const char *format); /* outside implementation - only driver side, - see indipropertyview_driver.cpp */ - - void fill(const std::string &name, const std::string &label, - const std::string &format) { - fill(name.c_str(), label.c_str(), format.c_str()); - } - -public: // internal use only - static WidgetView *cast(Type *blob) { - return static_cast *>(blob); - } - Type *cast() { return this; } -}; - -/* outside implementation */ -template -inline PropertyView::PropertyView() { - memset(this, 0, sizeof(*this)); -} - -template -inline void PropertyView::setDeviceName(const char *name) { - INDI::strlcpy(this->device, name); -} - -template -inline void PropertyView::setDeviceName(const std::string &name) { - setDeviceName(name.data()); -} - -template -inline void PropertyView::setName(const char *name) { - INDI::strlcpy(this->name, name); -} - -template -inline void PropertyView::setName(const std::string &name) { - setName(name.data()); -} - -template -inline void PropertyView::setLabel(const char *label) { - INDI::strlcpy(this->label, label); -} - -template -inline void PropertyView::setLabel(const std::string &label) { - setLabel(label.data()); -} - -template -inline void PropertyView::setGroupName(const char *name) { - INDI::strlcpy(this->group, name); -} - -template -inline void PropertyView::setGroupName(const std::string &name) { - setGroupName(name.data()); -} - -template -inline void PropertyView::setState(IPState state) { - this->s = state; -} - -template -inline void PropertyView::setTimestamp(const char *timestamp) { - INDI::strlcpy(this->timestamp, timestamp); -} - -template -inline void PropertyView::setTimestamp(const std::string ×tamp) { - setTimestamp(timestamp.data()); -} - -template -template -inline void PropertyView::setWidgets(WidgetType (&w)[N]) { - setWidgets(static_cast(w), N); -} - -template -inline void PropertyView::setAux(void *user) { - this->aux = user; -} - -template <> -inline bool PropertyView::load() { - return IULoadConfigNumber(this) == nnp; -} - -template <> -inline bool PropertyView::load() { - return IULoadConfigSwitch(this) == nsp; -} - -template <> -inline bool PropertyView::load() { - return false; -} - -template <> -inline bool PropertyView::load() { - return false; -} - -template <> -inline bool PropertyView::load() { - return IULoadConfigText(this) == ntp; -} - -template <> -inline void PropertyView::save(FILE *f) const { - IUSaveConfigNumber(f, this); -} - -template <> -inline void PropertyView::save(FILE *f) const { - IUSaveConfigText(f, this); -} - -template <> -inline void PropertyView::save(FILE *f) const { - IUSaveConfigSwitch(f, this); -} - -template <> -inline void PropertyView::save(FILE *f) const { - (void)f; /* IUSaveConfigLight(f, this); */ -} - -template <> -inline void PropertyView::save(FILE *f) const { - IUSaveConfigBLOB(f, this); -} - -template -inline void PropertyView::setTimeout(double timeout) { - this->timeout = timeout; -} - -template <> -inline void PropertyView::setTimeout(double) {} - -template -inline void PropertyView::setPermission(IPerm permission) { - this->p = permission; -} - -template <> -inline void PropertyView::setPermission(IPerm) {} - -template -inline void PropertyView::setRule(ISRule) {} - -template <> -inline void PropertyView::setRule(ISRule rule) { - this->r = rule; -} - -template -inline bool PropertyView::setRule(const std::string &) { - return false; -} - -template <> -inline bool PropertyView::setRule(const std::string &rule) { - return crackISRule(rule.data(), &this->r) == 0; -} - -template -inline WidgetView *PropertyView::findWidgetByName(const char *) const { - return nullptr; -} - -template <> -inline WidgetView *PropertyView::findWidgetByName( - const char *name) const { - return static_cast *>(IUFindText(this, name)); -} - -template <> -inline WidgetView *PropertyView::findWidgetByName( - const char *name) const { - return static_cast *>(IUFindNumber(this, name)); -} - -template <> -inline WidgetView *PropertyView::findWidgetByName( - const char *name) const { - return static_cast *>(IUFindSwitch(this, name)); -} - -template <> -inline WidgetView *PropertyView::findWidgetByName( - const char *name) const { - return static_cast *>(IUFindLight(this, name)); -} - -template <> -inline WidgetView *PropertyView::findWidgetByName( - const char *name) const { - return static_cast *>(IUFindBLOB(this, name)); -} - -template -inline IPerm PropertyView::getPermission() const { - return this->p; -} - -template <> -inline IPerm PropertyView::getPermission() const { - return IP_RO; -} - -template -inline ISRule PropertyView::getRule() const { - return ISR_NOFMANY; -} - -template <> -inline ISRule PropertyView::getRule() const { - return this->r; -} - -template -inline double PropertyView::getTimeout() const { - return this->timeout; -} - -template <> -inline double PropertyView::getTimeout() const { - return 0; -} - -template <> -inline void PropertyView::setWidgets(WidgetType *w, size_t size) { - this->tp = w; - this->ntp = int(size); -} - -template <> -inline void PropertyView::setWidgets(WidgetType *w, size_t size) { - this->np = w; - this->nnp = int(size); -} - -template <> -inline void PropertyView::setWidgets(WidgetType *w, size_t size) { - this->sp = w; - this->nsp = int(size); -} - -template <> -inline void PropertyView::setWidgets(WidgetType *w, size_t size) { - this->lp = w; - this->nlp = int(size); -} - -template <> -inline void PropertyView::setWidgets(WidgetType *w, size_t size) { - this->bp = w; - this->nbp = int(size); -} - -template <> -inline int PropertyView::count() const { - return this->ntp; -} - -template <> -inline int PropertyView::count() const { - return this->nnp; -} - -template <> -inline int PropertyView::count() const { - return this->nsp; -} - -template <> -inline int PropertyView::count() const { - return this->nlp; -} - -template <> -inline int PropertyView::count() const { - return this->nbp; -} - -template <> -inline PropertyView::WidgetType *PropertyView::widget() const { - return static_cast(this->tp); -} - -template <> -inline PropertyView::WidgetType *PropertyView::widget() - const { - return static_cast(this->np); -} - -template <> -inline PropertyView::WidgetType *PropertyView::widget() - const { - return static_cast(this->sp); -} - -template <> -inline PropertyView::WidgetType *PropertyView::widget() const { - return static_cast(this->lp); -} - -template <> -inline PropertyView::WidgetType *PropertyView::widget() const { - return static_cast(this->bp); -} - -} // namespace INDI diff --git a/src/atom/error/_script.hpp b/src/atom/error/_script.hpp index 87bd585f..19693e77 100644 --- a/src/atom/error/_script.hpp +++ b/src/atom/error/_script.hpp @@ -21,7 +21,7 @@ Description: Carbon binding for Atom-ERROR #include "error_stack.hpp" #include "exception.hpp" -using namespace Atom::Error; +using namespace atom::error; namespace Atom::_Script::Error { /** diff --git a/src/atom/error/error_stack.cpp b/src/atom/error/error_stack.cpp index 31594a83..a042873d 100644 --- a/src/atom/error/error_stack.cpp +++ b/src/atom/error/error_stack.cpp @@ -20,7 +20,7 @@ Description: Error Stack #include "atom/log/loguru.hpp" #include "atom/utils/time.hpp" -namespace Atom::Error { +namespace atom::error { std::ostream &operator<<(std::ostream &os, const ErrorInfo &error) { os << "{" << "\"errorMessage\": \"" << error.errorMessage << "\"," @@ -154,4 +154,4 @@ void ErrorStack::sortCompressedErrorStack() { }); } -} // namespace Atom::Error +} // namespace atom::error diff --git a/src/atom/error/error_stack.hpp b/src/atom/error/error_stack.hpp index 87e73952..1fb39578 100644 --- a/src/atom/error/error_stack.hpp +++ b/src/atom/error/error_stack.hpp @@ -18,10 +18,11 @@ Description: Error Stack #include #include #include +#include -#include "atom/experiment/string.hpp" +#include "atom//type/string.hpp" -namespace Atom::Error { +namespace atom::error { /** * @brief Error information structure. */ @@ -112,6 +113,6 @@ class ErrorStack { /// Sort the compressed error stack based on the timestamp of errors. void sortCompressedErrorStack(); }; -} // namespace Atom::Error +} // namespace atom::error #endif diff --git a/src/atom/error/exception.cpp b/src/atom/error/exception.cpp index 5f19b1f3..07b8b717 100644 --- a/src/atom/error/exception.cpp +++ b/src/atom/error/exception.cpp @@ -22,19 +22,19 @@ Description: Better Exception Library #include #include - #ifdef _WIN32 #include #include +#if !defined(__MINGW32__) && !defined(__MINGW64__) #pragma comment(lib, "dbghelp.lib") +#endif #elif defined(__APPLE__) || defined(__linux__) #include #include #include #endif -namespace Atom::Error -{ +namespace atom::error { const char* Exception::what() const noexcept { if (full_message_.empty()) { std::ostringstream oss; @@ -133,4 +133,4 @@ std::string Exception::getStackTrace() const { return oss.str(); } -} +} // namespace atom::error diff --git a/src/atom/error/exception.hpp b/src/atom/error/exception.hpp index a6e35245..d538379e 100644 --- a/src/atom/error/exception.hpp +++ b/src/atom/error/exception.hpp @@ -22,7 +22,7 @@ Description: Better Exception Library #include #include -namespace Atom::Error { +namespace atom::error { /** * @brief Custom exception class with detailed information about the error. @@ -107,7 +107,7 @@ class Exception : public std::exception { }; #define THROW_EXCEPTION(...) \ - throw Exception(__FILE__, __LINE__, __func__, __VA_ARGS__) + throw atom::error::Exception(__FILE__, __LINE__, __func__, __VA_ARGS__) class ObjectAlreadyExist : public std::logic_error { public: @@ -245,6 +245,6 @@ class FailToCallStaticFunction : public std::runtime_error { explicit FailToCallStaticFunction(const std::string &msg) : std::runtime_error(msg) {}; }; -} // namespace Atom::Error +} // namespace atom::error #endif diff --git a/src/atom/event/CMakeLists.txt b/src/atom/event/CMakeLists.txt deleted file mode 100644 index ea3b4654..00000000 --- a/src/atom/event/CMakeLists.txt +++ /dev/null @@ -1,158 +0,0 @@ -cmake_minimum_required(VERSION 3.20) -set(CMAKE_VERBOSE_MAKEFILE ON) - -project(atom-event C CXX) - -#set(CMAKE_DEBUG_POSTFIX "d") - -set(PROJ_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}) - -set(SIZEOF_VOIDP ${CMAKE_SIZEOF_VOID_P}) -if(CMAKE_SIZEOF_VOID_P EQUAL 8) - set(ARCH_64 TRUE) - set(PROCESSOR_ARCH "x64") -else() - set(ARCH_64 FALSE) - set(PROCESSOR_ARCH "x86") -endif() - -include_directories(${PROJ_ROOT_DIR}) -include_directories(${PROJ_ROOT_DIR}/utils) -include_directories(${PROJ_ROOT_DIR}/poll) - -file(GLOB SOURCE_FILES - ${PROJ_ROOT_DIR}/*.cpp - ${PROJ_ROOT_DIR}/utils/*.cpp - ${PROJ_ROOT_DIR}/poll/select_poll.cpp - ${PROJ_ROOT_DIR}/poll/vpoll.cpp - ${PROJ_ROOT_DIR}/poll/cvpoll.cpp - ${PROJ_ROOT_DIR}/poll/notifier.cpp) - -if (CMAKE_SYSTEM_NAME MATCHES "Windows") - file(GLOB WINDOWS_SOURCES ${PROJ_ROOT_DIR}/poll/iocp.cpp) - set(SOURCE_FILES ${SOURCE_FILES} ${WINDOWS_SOURCES}) -elseif (CMAKE_SYSTEM_NAME MATCHES "Darwin") - set(CMAKE_MACOSX_RPATH 1) - file(GLOB DARWIN_SOURCES ${PROJ_ROOT_DIR}/poll/kqueue.cpp - ${PROJ_ROOT_DIR}/poll/runloop.mm) - set(SOURCE_FILES ${SOURCE_FILES} ${DARWIN_SOURCES}) -elseif (CMAKE_SYSTEM_NAME MATCHES "Android") - file(GLOB ANDROID_SOURCES ${PROJ_ROOT_DIR}/poll/epoll.cpp) - set(SOURCE_FILES ${SOURCE_FILES} ${ANDROID_SOURCES}) -elseif (CMAKE_SYSTEM_NAME MATCHES "Linux") - file(GLOB LINUX_SOURCES ${PROJ_ROOT_DIR}/poll/epoll.cpp) - set(SOURCE_FILES ${SOURCE_FILES} ${LINUX_SOURCES}) -endif () - -if (CMAKE_SYSTEM_NAME MATCHES "Windows") - #add_definitions(-DATOM_EXPORTS) - add_definitions(-DNOMINMAX -DWIN32_LEAN_AND_MEAN) - add_definitions(-D_WINDOWS -D_LIB) - add_definitions(-D_UNICODE -DUNICODE) - if(CMAKE_SIZEOF_VOID_P EQUAL 8) - else() - add_definitions(-DWIN32) - endif() -elseif (CMAKE_SYSTEM_NAME MATCHES "Darwin") - add_definitions(-DATOM_HAS_RUNLOOP) -elseif (CMAKE_SYSTEM_NAME MATCHES "Android") - add_definitions(-DANDROID) -elseif (CMAKE_SYSTEM_NAME MATCHES "Linux") - add_definitions(-DLINUX) -endif () - -if (CMAKE_SYSTEM_NAME MATCHES "Windows") - option(WIN_USE_MD "Use DLL-specific version of multithread runtime library (/MD)" OFF) - #message(STATUS "++++++++ flags=${CMAKE_CXX_FLAGS_RELWITHDEBINFO}") - if (WIN_USE_MD) - message("Using DLL-specific version of multithread runtime library (/MD)") - else () - message("Using static version of multithread runtime library (/MT)") - endif () - #message(STATUS "++++++++ flags2=${CMAKE_CXX_FLAGS_RELWITHDEBINFO}") -elseif (CMAKE_SYSTEM_NAME MATCHES "Darwin") - set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fobjc-arc -std=c++14 -stdlib=libc++") - set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility-inlines-hidden -Wnon-virtual-dtor -Woverloaded-virtual -fPIC") - set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fobjc-arc") - if ((CMAKE_BUILD_TYPE STREQUAL "Debug") OR (CMAKE_BUILD_TYPE STREQUAL "debug")) - set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_DEBUG -g -O0") - set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_DEBUG -g -O0") - elseif (CMAKE_GENERATOR STREQUAL "Xcode") - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS} -D_DEBUG") - set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS} -D_DEBUG") - endif () - if ((CMAKE_OSX_ARCHITECTURES STREQUAL "armv7") OR (CMAKE_OSX_ARCHITECTURES STREQUAL "arm64")) - set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fembed-bitcode") - set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fembed-bitcode") - endif () -elseif (CMAKE_SYSTEM_NAME MATCHES "Android") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -fvisibility-inlines-hidden") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wnon-virtual-dtor -Woverloaded-virtual -fexceptions") -elseif (CMAKE_SYSTEM_NAME MATCHES "Linux") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -fPIC -m64 -march=x86-64") -endif () - -# ios target definition -if (CMAKE_SYSTEM_NAME MATCHES "Darwin") - if (CMAKE_GENERATOR STREQUAL "Xcode") - # Architectures - if(CMAKE_TARGET_SYSTEM STREQUAL "ios") - set(CMAKE_XCODE_ATTRIBUTE_SDKROOT iphoneos) - set(CMAKE_XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET 9.0) - set(CMAKE_XCODE_ATTRIBUTE_ARCHS "$(ARCHS_STANDARD)") - set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphonesimulator*] x86_64) - else () - set(CMAKE_XCODE_ATTRIBUTE_SDKROOT macosx) - set(CMAKE_XCODE_ATTRIBUTE_MACOSX_DEPLOYMENT_TARGET 10.9) - endif () - set(CMAKE_XCODE_ATTRIBUTE_ONLY_ACTIVE_ARCH NO) - elseif (CMAKE_TARGET_SYSTEM STREQUAL "ios") - set(IOS_DEPLOYMENT_TARGET "11.0") - set(XCODE_IOS_PLATFORM_VERSION_FLAG "-m${XCODE_IOS_PLATFORM}-version-min=${IOS_DEPLOYMENT_TARGET}") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${XCODE_IOS_PLATFORM_VERSION_FLAG}") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${XCODE_IOS_PLATFORM_VERSION_FLAG}") - elseif (CMAKE_TARGET_SYSTEM STREQUAL "mac") - set(CMAKE_OSX_DEPLOYMENT_TARGET "10.13") - endif () -endif () - - -if (ATOM_ENABLE_ASAN) - add_compile_options(-fsanitize=address,undefined -fsanitize-recover=all -fno-omit-frame-pointer - -fno-optimize-sibling-calls -fno-var-tracking -fno-stack-protector -O1 -g1) - message("Address Sanitizer enabled") -endif() - -add_library(atom-event STATIC ${SOURCE_FILES}) - -if (CMAKE_SYSTEM_NAME MATCHES "Windows") - if (ARCH_64) - set(LIBRARY_OUTPUT_PATH "${PROJ_ROOT_DIR}/lib/windows/${PROCESSOR_ARCH}/${CMAKE_BUILD_TYPE}") - else () - set(LIBRARY_OUTPUT_PATH "${PROJ_ROOT_DIR}/lib/windows/Win32/${CMAKE_BUILD_TYPE}") - endif () - -elseif (CMAKE_SYSTEM_NAME MATCHES "Darwin") - if (CMAKE_TARGET_SYSTEM STREQUAL "ios") - set(LIBRARY_OUTPUT_PATH "${PROJ_ROOT_DIR}/lib/ios/${CMAKE_BUILD_TYPE}-${XCODE_IOS_PLATFORM}") - elseif (CMAKE_TARGET_SYSTEM STREQUAL "mac") - set(LIBRARY_OUTPUT_PATH "${PROJ_ROOT_DIR}/lib/mac/${CMAKE_BUILD_TYPE}") - endif () - # xcode project attributes - if (CMAKE_GENERATOR STREQUAL "Xcode") - target_compile_options(atom-event PRIVATE $<$:-g -O0>) - target_compile_options(atom-event PRIVATE $<$:-g -Os>) - endif() -elseif (CMAKE_SYSTEM_NAME MATCHES "Linux") - if (NOT DEFINED CMAKE_SYSTEM_PROCESS OR CMAKE_SYSTEM_PROCESS STREQUAL "") - set(CMAKE_SYSTEM_PROCESS ${CMAKE_HOST_SYSTEM_PROCESSOR}) - endif () - if (CMAKE_SYSTEM_PROCESS STREQUAL "aarch64" ) - set(CMAKE_SYSTEM_PROCESS "arm64") - endif () - - message("CMAKE_SYSTEM_PROCESS=${CMAKE_SYSTEM_PROCESS}") - set(LIBRARY_OUTPUT_PATH "${PROJ_ROOT_DIR}/lib/linux/${CMAKE_SYSTEM_PROCESS}/${CMAKE_BUILD_TYPE}") -elseif (CMAKE_SYSTEM_NAME MATCHES "Android") - set(LIBRARY_OUTPUT_PATH "${PROJ_ROOT_DIR}/lib/android/${CMAKE_ANDROID_ARCH_ABI}") -endif () diff --git a/src/atom/event/LICENSE b/src/atom/event/LICENSE deleted file mode 100644 index 261eeb9e..00000000 --- a/src/atom/event/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/src/atom/event/README.md b/src/atom/event/README.md deleted file mode 100644 index aae86adc..00000000 --- a/src/atom/event/README.md +++ /dev/null @@ -1,122 +0,0 @@ -# Atom-Event Module - -## Description - -This module is transformed from the libkev (a cross-platform C++(C++14) event loop). It is a high performance event loop library. - -To enhance the performance of the Atom Driver Communication, we included this module and rewrote it. - -Another reason is that the libkev has a good performance cross different platforms, including windows/mac/iOS/linux/android - -## Usage - -A simple example from the libkev[README](README.md) - -```cpp -#include "kev.h" - -#include -#include - -using namespace Atom::Event; - -void foo() -{ - printf("foo called\n"); -} - -void foo2() -{ - printf("foo2 called\n"); -} - -int bar() -{ - printf("bar called\n"); - return 333; -} - -int main(int argc, const char * argv[]) -{ - EventLoop run_loop; - EventLoop::Token token = run_loop.createToken(); - - std::thread thr([&] { - if (run_loop.init()) { - run_loop.loop(); - } - }); - - Timer timer(&run_loop); - timer.schedule(3000, Timer::Mode::ONE_SHOT, [&] { - printf("onTimer\n"); - - run_loop.stop(); - }); - - auto delayed_token = run_loop.createToken(); - run_loop.postDelayed(1000,[] { - printf("postDelayed 1000\n"); - }, &delayed_token); - - run_loop.postDelayed(1500,[] { - printf("postDelayed 1500\n"); - }); - - run_loop.postDelayed(5000,[] { - printf("postDelayed 5000\n"); - }); - - delayed_token.reset(); - - run_loop.async([] { printf ("loop async\n"); }, &token); - printf("async called\n"); - - auto ret = run_loop.invoke([] { printf ("loop invoke\n"); return 88; }); - printf("ret=%d\n", ret); - - auto int_ptr = std::make_unique(123); - - ret = run_loop.invoke([p=std::move(int_ptr)] { - return *p; - }); - printf("move-only ret=%d\n", ret); - - int_ptr = std::make_unique(456); - run_loop.sync([p=std::move(int_ptr)] { - printf("sync: move-only, i=%d\n", *p); - }); - - int_ptr = std::make_unique(789); - run_loop.async([p=std::move(int_ptr)] { - printf("async: move-only, i=%d\n", *p); - }, &token); - - run_loop.post(foo); - int ddc = 81; - run_loop.post([=] { - printf("ddc=%d\n", ddc); - foo2(); - }, &token); - - //token.reset(); - - ret = run_loop.invoke(bar); - printf("ret=%d\n", ret); - - run_loop.invoke(foo); - - try { - if (thr.joinable()) { - thr.join(); - } - } catch(...) {} - - return 0; -} -``` - -## Requirements - -- A conforming C++14 compiler, however , after we rewrite the libkev, the c++20 is required. -- CMake v3.20 or newer diff --git a/src/atom/event/eventloop.cpp b/src/atom/event/eventloop.cpp deleted file mode 100644 index 6e392a8c..00000000 --- a/src/atom/event/eventloop.cpp +++ /dev/null @@ -1,546 +0,0 @@ -/* - * eventloop.cpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2024-2-10 - -Description: Main eventloop implementation - -**************************************************/ - -#include "eventloop.hpp" -#include "poll/iopoll.hpp" -#include "utils/kmqueue.hpp" -#include "utils/kmtrace.hpp" -#include "utils/skutils.hpp" - -#include -#include - - -ATOM_NS_BEGIN - -IOPoll *createIOPoll(PollType poll_type); - -EventLoop::Impl::Impl(PollType poll_type) - : poll_(createIOPoll(poll_type)), timer_mgr_(new TimerManager(this)) { - KM_SetObjKey("EventLoop"); -} - -EventLoop::Impl::~Impl() { - while (pending_objects_) { - auto obj = pending_objects_; - pending_objects_ = pending_objects_->next_; - obj->onLoopExit(); - } - ObserverCallback cb; - while (obs_queue_.dequeue(cb)) { - cb(LoopActivity::EXIT); - } - if (poll_) { - delete poll_; - poll_ = nullptr; - } -} - -bool EventLoop::Impl::init() { - if (!poll_->init()) { - return false; - } - stop_loop_ = false; - thread_id_ = std::this_thread::get_id(); - return true; -} - -PollType EventLoop::Impl::getPollType() const { - if (poll_) { - return poll_->getType(); - } - return PollType::DEFAULT; -} - -bool EventLoop::Impl::isPollLT() const { - if (poll_) { - return poll_->isLevelTriggered(); - } - return false; -} - -Result EventLoop::Impl::registerFd(SOCKET_FD fd, uint32_t events, - IOCallback cb) { - if (getPollType() == PollType::STLCV) { - return Result::NOT_SUPPORTED; - } - if (inSameThread()) { - return poll_->registerFd(fd, events, std::move(cb)); - } - return async([this, cb = std::move(cb), fd, events]() mutable { - auto ret = poll_->registerFd(fd, events, std::move(cb)); - if (ret != Result::OK) { - return; - } - }); -} - -Result EventLoop::Impl::updateFd(SOCKET_FD fd, uint32_t events) { - if (getPollType() == PollType::STLCV) { - return Result::NOT_SUPPORTED; - } - if (inSameThread()) { - return poll_->updateFd(fd, events); - } - return async([this, fd, events] { - auto ret = poll_->updateFd(fd, events); - if (ret != Result::OK) { - return; - } - }); -} - -Result EventLoop::Impl::unregisterFd(SOCKET_FD fd, bool close_fd) { - if (getPollType() == PollType::STLCV) { - return Result::NOT_SUPPORTED; - } - if (inSameThread()) { - auto ret = poll_->unregisterFd(fd); - if (close_fd) { - SKUtils::close(fd); - } - return ret; - } else { - auto ret = sync([this, fd, close_fd] { - poll_->unregisterFd(fd); - if (close_fd) { - SKUtils::close(fd); - } - }); - if (Result::OK != ret) { - return ret; - } - return Result::OK; - } -} - -Result EventLoop::Impl::appendObserver(ObserverCallback cb, - EventLoopToken *token) { - if (token && token->eventLoop().get() != this) { - return Result::INVALID_PARAM; - } - LockGuard g(obs_mutex_); - if (stop_loop_) { - return Result::INVALID_STATE; - } - auto obs_node = obs_queue_.enqueue(std::move(cb)); - if (token) { - token->obs_token_ = obs_node; - token->observed = true; - } - return Result::OK; -} - -Result EventLoop::Impl::removeObserver(EventLoopToken *token) { - if (token) { - if (token->eventLoop().get() != this) { - return Result::INVALID_STATE; - } - auto node = token->obs_token_.lock(); - if (node) { - LockGuard g(obs_mutex_); - obs_queue_.remove(node); - } - token->obs_token_.reset(); - token->observed = false; - } - return Result::OK; -} - -void EventLoop::Impl::appendPendingObject(PendingObject *obj) { - KM_ASSERT(inSameThread()); - if (pending_objects_) { - obj->next_ = pending_objects_; - pending_objects_->prev_ = obj; - } - pending_objects_ = obj; -} - -void EventLoop::Impl::removePendingObject(PendingObject *obj) { - KM_ASSERT(inSameThread()); - if (pending_objects_ == obj) { - pending_objects_ = obj->next_; - } - if (obj->prev_) { - obj->prev_->next_ = obj->next_; - } - if (obj->next_) { - obj->next_->prev_ = obj->prev_; - } -} - -void EventLoop::Impl::processTasks() { - TaskQueue tq; - { - std::unique_lock ul(task_mutex_); - task_queue_.swap(tq); - } - - for (auto &ts : tq) { - (*ts)(); - } -} - -void EventLoop::Impl::loopOnce(uint32_t max_wait_ms) { - processTasks(); - unsigned long wait_ms = max_wait_ms; - timer_mgr_->checkExpire(&wait_ms); - if (wait_ms > max_wait_ms) { - wait_ms = max_wait_ms; - } - if (!task_queue_.empty()) { - wait_ms = 0; - } - poll_->wait((uint32_t)wait_ms); -} - -void EventLoop::Impl::loop(uint32_t max_wait_ms) { - while (!stop_loop_) { - loopOnce(max_wait_ms); - } - processTasks(); - - while (pending_objects_) { - auto obj = pending_objects_; - pending_objects_ = pending_objects_->next_; - obj->onLoopExit(); - } - { - LockGuard g(obs_mutex_); - ObserverCallback cb; - while (obs_queue_.dequeue(cb)) { - cb(LoopActivity::EXIT); - } - } - KM_INFOXTRACE("loop, stopped"); -} - -void EventLoop::Impl::stop() { - // KM_INFOXTRACE("stop"); - stop_loop_ = true; - wakeup(); -} - -Result EventLoop::Impl::appendTask(Task task, EventLoopToken *token, - const char *debugStr) { - if (token && token->eventLoop().get() != this) { - return Result::INVALID_PARAM; - } - if (stop_loop_) { - return Result::INVALID_STATE; - } - std::string dstr{debugStr ? debugStr : ""}; - TaskSlotPtr ptr; - if (token) { - auto p = - std::make_shared(std::move(task), std::move(dstr)); - token->appendTaskNode(p); - ptr = std::move(p); - } else { - ptr = std::make_shared(std::move(task), std::move(dstr)); - } - bool need_wakeup; - { - LockGuard g(task_mutex_); - need_wakeup = task_queue_.empty(); - task_queue_.emplace_back(std::move(ptr)); - } - if (need_wakeup) { - wakeup(); - } - return Result::OK; -} - -Result EventLoop::Impl::appendDelayedTask(uint32_t delay_ms, Task task, - EventLoopToken *token, - const char *debugStr) { - if (token && token->eventLoop().get() != this) { - return Result::INVALID_PARAM; - } - if (stop_loop_) { - return Result::INVALID_STATE; - } - std::string dstr{debugStr ? debugStr : ""}; - auto ptr = std::make_shared(this, std::move(task), - std::move(dstr)); - if (token) { - token->appendDelayedTaskNode(ptr); - } - // NOTE: ptr is stored in TimerCallback, so no queue is needed for - // DelayedTaskSlot. ptr will be released after timer cancelled or executed, - // or TimerManager destructed - ptr->timer.schedule(delay_ms, Timer::Mode::ONE_SHOT, [ptr]() mutable { - // this closure will be released when user reset the token - (*std::exchange(ptr, nullptr))(); - }); - return Result::OK; -} - -template -class auto_clean { -public: - auto_clean(Callable &&c) : c_(std::move(c)) {} - auto_clean(auto_clean &&other) - : c_(std::move(other.c_)), cleared_(other.cleared_) { - other.cleared_ = true; - } - auto_clean(const auto_clean &other) - : auto_clean(std::move(const_cast(other))) {} - ~auto_clean() { - if (!cleared_) - c_(); - } - -private: - Callable c_; - bool cleared_ = false; -}; -Result EventLoop::Impl::sync(Task task, EventLoopToken *token, - const char *debugStr) { - if (inSameThread()) { - task(); - return Result::OK; - } else { - std::mutex m; - std::condition_variable cv; - bool ready = false; - bool executed = false; - auto clean = [&] { - std::lock_guard g(m); - ready = true; - cv.notify_one(); // the waiting thread may block again since m is - // not released - }; - auto_clean sc(std::move(clean)); - auto task_sync = [&, sc{std::move(sc)}] { - task(); - executed = true; - }; - auto ret = post(task_sync, token, debugStr); - if (ret != Result::OK) { - return ret; - } - std::unique_lock lk(m); - cv.wait(lk, [&ready] { return ready; }); - return executed ? Result::OK : Result::ABORTED; - } -} - -Result EventLoop::Impl::async(Task task, EventLoopToken *token, - const char *debugStr) { - if (inSameThread()) { - task(); - return Result::OK; - } else { - return post(std::move(task), token, debugStr); - } -} - -Result EventLoop::Impl::post(Task task, EventLoopToken *token, - const char *debugStr) { - return appendTask(std::move(task), token, debugStr); -} - -Result EventLoop::Impl::postDelayed(uint32_t delay_ms, Task task, - EventLoopToken *token, - const char *debugStr) { - return appendDelayedTask(delay_ms, std::move(task), token, debugStr); -} - -void EventLoop::Impl::wakeup() { poll_->notify(); } - -///////////////////////////////////////////////////////////////// -// DelayedTaskSlot -DelayedTaskSlot::DelayedTaskSlot(EventLoop::Impl *loop, EventLoop::Task &&t, - std::string debugStr) - : TaskSlot(std::move(t), std::move(debugStr)), timer(loop->getTimerMgr()) {} - -///////////////////////////////////////////////////////////////// -// EventLoop::Token::Impl -EventLoop::Token::Impl::Impl() {} - -EventLoop::Token::Impl::~Impl() { reset(); } - -void EventLoop::Token::Impl::eventLoop(const EventLoopPtr &loop) { - loop_ = loop; -} - -EventLoopPtr EventLoop::Token::Impl::eventLoop() { return loop_.lock(); } - -void EventLoop::Token::Impl::appendTaskNode(TokenTaskSlotPtr &node) { - LockGuard g(mutex_); - clearInactiveTasks(); - ttask_nodes_.emplace_back(node); -} - -void EventLoop::Token::Impl::clearInactiveTasks() { - for (auto it = ttask_nodes_.begin(); it != ttask_nodes_.end();) { - if (!(*it)->isActive()) { - it = ttask_nodes_.erase(it); - } else { - break; - } - } -} - -void EventLoop::Token::Impl::appendDelayedTaskNode(DelayedTaskSlotPtr &node) { - LockGuard g(mutex_); - clearInactiveDelayedTasks(); - dtask_nodes_.emplace_back(node); -} - -void EventLoop::Token::Impl::clearInactiveDelayedTasks() { - for (auto it = dtask_nodes_.begin(); it != dtask_nodes_.end(); ++it) { - if (!(*it)->isActive()) { - //(*it)->cancel(); - it = dtask_nodes_.erase(it); - } else { - break; - } - } -} - -void EventLoop::Token::Impl::clearAllTasks() { - auto loop = loop_.lock(); - - std::unique_lock ul(mutex_); - pending_ttask_nodes_.splice(pending_ttask_nodes_.end(), - std::move(ttask_nodes_)); - pending_dtask_nodes_.splice(pending_dtask_nodes_.end(), - std::move(dtask_nodes_)); - - while (!pending_ttask_nodes_.empty()) { - bool pop_task = true; - auto ts = pending_ttask_nodes_.front(); - if (ts->isActive()) { - ul.unlock(); - ts->cancel(loop && loop->inSameThread()); - ul.lock(); - pop_task = !pending_ttask_nodes_.empty() && - ts == pending_ttask_nodes_.front(); - } - if (pop_task) { - pending_ttask_nodes_.pop_front(); - } - } - - while (!pending_dtask_nodes_.empty()) { - bool pop_task = true; - auto ds = pending_dtask_nodes_.front(); - if (ds->isActive()) { - ul.unlock(); - ds->cancel(); - ul.lock(); - pop_task = !pending_dtask_nodes_.empty() && - ds == pending_dtask_nodes_.front(); - } - if (pop_task) { - pending_dtask_nodes_.pop_front(); - } - } -} - -bool EventLoop::Token::Impl::expired() { - return loop_.expired() || (observed && obs_token_.expired()); -} - -void EventLoop::Token::Impl::reset() { - auto loop = loop_.lock(); - if (loop) { - if (!obs_token_.expired()) { - loop->removeObserver(this); - obs_token_.reset(); - } - } - clearAllTasks(); -} - -ATOM_NS_END - -///////////////////////////////////////////////////////////////// -// - -#ifdef ATOM_OS_WIN -#include -#endif - -ATOM_NS_BEGIN - -#ifdef ATOM_OS_WIN -extern LPFN_CONNECTEX connect_ex; -extern LPFN_ACCEPTEX accept_ex; -#endif - -IOPoll *createEPoll(); -IOPoll *createVPoll(); -IOPoll *createKQueue(); -IOPoll *createSelectPoll(); -IOPoll *createIocpPoll(); -IOPoll *createRunLoop(); -IOPoll *createCVPoll(); - -IOPoll *createDefaultIOPoll() { -#ifdef ATOM_OS_WIN - if (connect_ex && accept_ex) { - return createIocpPoll(); - } - return createSelectPoll(); -#elif defined(ATOM_OS_LINUX) - return createEPoll(); -#elif defined(ATOM_OS_MAC) - return createKQueue(); - // return createVPoll(); -#else - return createSelectPoll(); -#endif -} - -IOPoll *createIOPoll(PollType poll_type) { - switch (poll_type) { - case PollType::POLL: - return createVPoll(); - case PollType::SELECT: - return createSelectPoll(); - case PollType::KQUEUE: -#ifdef ATOM_OS_MAC - return createKQueue(); -#else - return createDefaultIOPoll(); -#endif - case PollType::EPOLL: -#ifdef ATOM_OS_LINUX - return createEPoll(); -#else - return createDefaultIOPoll(); -#endif - case PollType::IOCP: -#ifdef ATOM_OS_WIN - return createIocpPoll(); -#else - return createDefaultIOPoll(); -#endif - case PollType::RUNLOOP: -#if defined(ATOM_OS_MAC) && defined(ATOM_HAS_RUNLOOP) - return createRunLoop(); -#else - return createDefaultIOPoll(); -#endif - case PollType::STLCV: - return createCVPoll(); - default: - return createDefaultIOPoll(); - } -} - -ATOM_NS_END diff --git a/src/atom/event/eventloop.hpp b/src/atom/event/eventloop.hpp deleted file mode 100644 index cd91120d..00000000 --- a/src/atom/event/eventloop.hpp +++ /dev/null @@ -1,311 +0,0 @@ -/* - * eventloop.hpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2024-2-10 - -Description: Main eventloop implementation - -**************************************************/ - -#ifndef ATOM_EVENT_EVENTLOOP_HPP -#define ATOM_EVENT_EVENTLOOP_HPP - -#include "kev.hpp" -#include "kevdefs.hpp" -#include "timer.hpp" -#include "utils/kmobject.hpp" -#include "utils/kmqueue.hpp" - - -#ifdef _WIN32 -#include -#endif -#include -#include -#include -#include -#include - - -ATOM_NS_BEGIN - -class IOPoll; -using EventLoopToken = EventLoop::Token::Impl; -using EventLoopPtr = EventLoop::ImplPtr; -using EventLoopWeakPtr = std::weak_ptr; - -class TaskSlot { -public: - TaskSlot(EventLoop::Task &&t, std::string debugStr) - : task(std::move(t)), debugStr(std::move(debugStr)) {} - virtual ~TaskSlot() {} - virtual void operator()() { - if (task) { - task(); - clearTask(); - } - } - void clearTask() { std::exchange(task, nullptr); } - bool isActive() const { return bool(task); } - EventLoop::Task task; - std::string debugStr; -}; -using TaskSlotPtr = std::shared_ptr; -using TaskQueue = std::list; - -class TokenTaskSlot final : public TaskSlot { -public: - TokenTaskSlot(EventLoop::Task &&t, std::string debugStr) - : TaskSlot(std::move(t), std::move(debugStr)) {} - void operator()() override { - auto expected = State::ACTIVE; - std::lock_guard g(mlock); - if (state_.compare_exchange_strong(expected, State::RUNNING)) { - TaskSlot::operator()(); - state_.exchange(State::INACTIVE); - } - } - void cancel(bool inLoopThread) { - auto expected = State::ACTIVE; - if (state_.compare_exchange_strong(expected, State::INACTIVE)) { - clearTask(); - } else if (expected == State::RUNNING) { - if (!inLoopThread) { - // wait for running complete - mlock.lock(); - mlock.unlock(); - } - } - } - - enum class State { ACTIVE, RUNNING, INACTIVE }; - - std::atomic state_{State::ACTIVE}; - mutable std::mutex mlock; -}; -using TokenTaskSlotPtr = std::shared_ptr; -using TokenTaskQueue = std::list; - -class DelayedTaskSlot final : public TaskSlot { -public: - DelayedTaskSlot(EventLoop::Impl *loop, EventLoop::Task &&t, - std::string debugStr); - void cancel() { - timer.cancel(); - clearTask(); - } - -public: - Timer::Impl timer; -}; -using DelayedTaskSlotPtr = std::shared_ptr; -using DelayedTaskQueue = std::list; - -enum class LoopActivity { - EXIT, -}; -using ObserverCallback = std::function; -using ObserverToken = std::weak_ptr::DLNode>; - -/** - * PendingObject is used to cache the IOCP context when destroying IocpSocket - * that has pending operations. It will be removed after all pending operatios - * are completed, or the loop exited - */ -class PendingObject { -public: - virtual ~PendingObject() {} - virtual bool isPending() const = 0; - virtual void onLoopExit() = 0; - -public: - PendingObject *next_ = nullptr; - PendingObject *prev_ = nullptr; -}; - -class EventLoop::Impl : public KMObject { -public: - Impl(PollType poll_type); - Impl(const Impl &other) = delete; - Impl(Impl &&other) = delete; - ~Impl(); - - Impl &operator=(const Impl &other) = delete; - Impl &operator=(Impl &&other) = delete; - -public: - bool init(); - Result registerFd(SOCKET_FD fd, uint32_t events, IOCallback cb); - Result updateFd(SOCKET_FD fd, uint32_t events); - Result unregisterFd(SOCKET_FD fd, bool close_fd); - TimerManager::Ptr getTimerMgr() { return timer_mgr_; } - - PollType getPollType() const; - bool isPollLT() const; // level trigger - - Result appendObserver(ObserverCallback cb, EventLoopToken *token); - Result removeObserver(EventLoopToken *token); - -public: - bool inSameThread() const { - return std::this_thread::get_id() == thread_id_; - } - std::thread::id threadId() const { return thread_id_; } - Result appendTask(Task task, EventLoopToken *token, const char *debugStr); - Result appendDelayedTask(uint32_t delay_ms, Task task, - EventLoopToken *token, const char *debugStr); - - template - auto invoke(F &&f, EventLoopToken *token = nullptr, - const char *debugStr = nullptr) { - Result err; - return invoke(std::forward(f), err, token, debugStr); - } - - template ()())>{}, - int> = 0> - auto invoke(F &&f, Result &err, EventLoopToken *token = nullptr, - const char *debugStr = nullptr) { - static_assert(!std::is_same{}, "is void"); - if (inSameThread()) { - return f(); - } - using ReturnType = decltype(f()); - ReturnType retval; - auto task_sync = [&] { retval = f(); }; - err = sync(std::move(task_sync), token, debugStr); - return retval; - } - - template ()())>{}, - int> = 0> - void invoke(F &&f, Result &err, EventLoopToken *token = nullptr, - const char *debugStr = nullptr) { - static_assert(std::is_same{}, "not void"); - if (inSameThread()) { - return f(); - } - err = sync(std::forward(f), token, debugStr); - } - - template {}, int> = 0> - Result sync(F &&f, EventLoopToken *token = nullptr, - const char *debugStr = nullptr) { - lambda_wrapper wf{std::forward(f)}; - return sync(Task(std::move(wf)), token, debugStr); - } - Result sync(Task task, EventLoopToken *token = nullptr, - const char *debugStr = nullptr); - - template {}, int> = 0> - Result async(F &&f, EventLoopToken *token = nullptr, - const char *debugStr = nullptr) { - lambda_wrapper wf{std::forward(f)}; - return async(Task(std::move(wf)), token, debugStr); - } - Result async(Task task, EventLoopToken *token = nullptr, - const char *debugStr = nullptr); - - template {}, int> = 0> - Result post(F &&f, EventLoopToken *token = nullptr, - const char *debugStr = nullptr) { - lambda_wrapper wf{std::forward(f)}; - return post(Task(std::move(wf)), token, debugStr); - } - Result post(Task task, EventLoopToken *token = nullptr, - const char *debugStr = nullptr); - - template {}, int> = 0> - Result postDelayed(uint32_t delay_ms, F &&f, - EventLoopToken *token = nullptr, - const char *debugStr = nullptr) { - lambda_wrapper wf{std::forward(f)}; - return postDelayed(delay_ms, Task(std::move(wf)), token, debugStr); - } - Result postDelayed(uint32_t delay_ms, Task task, - EventLoopToken *token = nullptr, - const char *debugStr = nullptr); - - void wakeup(); - - void loopOnce(uint32_t max_wait_ms); - void loop(uint32_t max_wait_ms = -1); - void stop(); - bool stopped() const { return stop_loop_; } - void reset() { stop_loop_ = false; } - - void appendPendingObject(PendingObject *obj); - void removePendingObject(PendingObject *obj); - -protected: - void processTasks(); - -protected: - using ObserverQueue = DLQueue; - using LockType = std::mutex; - using LockGuard = std::lock_guard; - - IOPoll *poll_; - std::atomic stop_loop_{false}; - std::thread::id thread_id_; - - TaskQueue task_queue_; - LockType task_mutex_; - - ObserverQueue obs_queue_; - LockType obs_mutex_; - - TimerManager::Ptr timer_mgr_; - - PendingObject *pending_objects_ = nullptr; -}; - -class EventLoop::Token::Impl { -public: - Impl(); - ~Impl(); - - void eventLoop(const EventLoopPtr &loop); - EventLoopPtr eventLoop(); - - void appendTaskNode(TokenTaskSlotPtr &node); - void clearInactiveTasks(); - void appendDelayedTaskNode(DelayedTaskSlotPtr &node); - void clearInactiveDelayedTasks(); - void clearAllTasks(); - - bool expired(); - void reset(); - -protected: - using LockType = std::mutex; - using LockGuard = std::lock_guard; - friend class EventLoop::Impl; - EventLoopWeakPtr loop_; - - TokenTaskQueue ttask_nodes_; - DelayedTaskQueue dtask_nodes_; - LockType mutex_; - // when reset() is called from multiple different threads, - // all of them need wait for completion of all pending tasks - TokenTaskQueue pending_ttask_nodes_; - DelayedTaskQueue pending_dtask_nodes_; - - bool observed = false; - ObserverToken obs_token_; -}; - -ATOM_NS_END - -#endif diff --git a/src/atom/event/kev.cpp b/src/atom/event/kev.cpp deleted file mode 100644 index bee56c8a..00000000 --- a/src/atom/event/kev.cpp +++ /dev/null @@ -1,170 +0,0 @@ -/* - * kev.cpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2024-2-10 - -Description: Main - -**************************************************/ - -#include "kev.hpp" -#include "eventloop.hpp" -#include "utils/kmtrace.hpp" - -ATOM_NS_BEGIN - -/////////////////////////////////////////////////////////////////////////////////////////////////////////// -// class EventLoop -EventLoop::EventLoop() : EventLoop(PollType::DEFAULT) {} - -EventLoop::EventLoop(PollType poll_type) - : pimpl_(std::make_shared(poll_type)) {} - -EventLoop::EventLoop(EventLoop &&other) - : pimpl_(std::exchange(other.pimpl_, nullptr)) {} - -EventLoop::~EventLoop() {} - -EventLoop &EventLoop::operator=(EventLoop &&other) { - if (this != &other) { - pimpl_ = std::exchange(other.pimpl_, nullptr); - } - - return *this; -} - -bool EventLoop::init() { return pimpl_->init(); } - -EventLoop::Token EventLoop::createToken() { - Token t; - if (!t.pimpl_) { // lazy initialize token pimpl - t.pimpl_ = new Token::Impl(); - } - t.pimpl()->eventLoop(pimpl()); - return t; -} - -PollType EventLoop::getPollType() const { return pimpl_->getPollType(); } - -bool EventLoop::isPollLT() const { return pimpl_->isPollLT(); } - -Result EventLoop::registerFd(SOCKET_FD fd, uint32_t events, IOCallback cb) { - return pimpl_->registerFd(fd, events, std::move(cb)); -} - -Result EventLoop::updateFd(SOCKET_FD fd, uint32_t events) { - return pimpl_->updateFd(fd, events); -} - -Result EventLoop::unregisterFd(SOCKET_FD fd, bool close_fd) { - return pimpl_->unregisterFd(fd, close_fd); -} - -void EventLoop::loopOnce(uint32_t max_wait_ms) { - pimpl_->loopOnce(max_wait_ms); -} - -void EventLoop::loop(uint32_t max_wait_ms) { pimpl_->loop(max_wait_ms); } - -void EventLoop::stop() { pimpl_->stop(); } - -bool EventLoop::stopped() const { return pimpl_->stopped(); } - -void EventLoop::reset() { pimpl_->reset(); } - -EventLoop::ImplPtr EventLoop::pimpl() { return pimpl_; } - -bool EventLoop::inSameThread() const { return pimpl_->inSameThread(); } - -Result EventLoop::sync(Task task, Token *token, const char *debugStr) { - return pimpl_->sync(std::move(task), token ? token->pimpl() : nullptr, - debugStr); -} - -Result EventLoop::async(Task task, Token *token, const char *debugStr) { - return pimpl_->async(std::move(task), token ? token->pimpl() : nullptr, - debugStr); -} - -Result EventLoop::post(Task task, Token *token, const char *debugStr) { - return pimpl_->post(std::move(task), token ? token->pimpl() : nullptr, - debugStr); -} - -Result EventLoop::postDelayed(uint32_t delay_ms, Task task, Token *token, - const char *debugStr) { - return pimpl_->postDelayed(delay_ms, std::move(task), - token ? token->pimpl() : nullptr, debugStr); -} - -void EventLoop::wakeup() { pimpl_->wakeup(); } - -void EventLoop::cancel(Token *token) { - if (token) { - token->pimpl()->clearAllTasks(); - } -} - -EventLoop::Token::Token() - : pimpl_(nullptr) // lazy initialize pimpl_ -{} - -EventLoop::Token::Token(Token &&other) - : pimpl_(std::exchange(other.pimpl_, nullptr)) {} - -EventLoop::Token::~Token() { delete pimpl_; } - -EventLoop::Token &EventLoop::Token::operator=(Token &&other) { - if (this != &other) { - if (pimpl_) { - delete pimpl_; - } - pimpl_ = std::exchange(other.pimpl_, nullptr); - } - return *this; -} - -void EventLoop::Token::reset() { - if (pimpl_) { - pimpl_->reset(); - } -} - -EventLoop::Token::Impl *EventLoop::Token::pimpl() { return pimpl_; } - -/////////////////////////////////////////////////////////////////////////////////////////////////////////// - -Timer::Timer(EventLoop *loop) - : pimpl_(new Impl(loop->pimpl()->getTimerMgr())) {} - -Timer::Timer(Timer &&other) : pimpl_(std::exchange(other.pimpl_, nullptr)) {} - -Timer::~Timer() { delete pimpl_; } - -Timer &Timer::operator=(Timer &&other) { - if (this != &other) { - if (pimpl_) { - delete pimpl_; - } - pimpl_ = std::exchange(other.pimpl_, nullptr); - } - - return *this; -} - -bool Timer::schedule(uint32_t delay_ms, Mode mode, TimerCallback cb) { - return pimpl_->schedule(delay_ms, mode, std::move(cb)); -} - -void Timer::cancel() { pimpl_->cancel(); } - -Timer::Impl *Timer::pimpl() { return pimpl_; } - -void setLogCallback(LogCallback cb) { setTraceFunc(cb); } - -ATOM_NS_END diff --git a/src/atom/event/kev.hpp b/src/atom/event/kev.hpp deleted file mode 100644 index 3d808bc0..00000000 --- a/src/atom/event/kev.hpp +++ /dev/null @@ -1,287 +0,0 @@ -/* - * kev.cpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2024-2-10 - -Description: Main - -**************************************************/ - -#ifndef __KEVAPI_HPP -#define __KEVAPI_HPP - -#include "kevdefs.hpp" -#include "kmtypes.hpp" - -#include -#include -#include - -ATOM_NS_BEGIN - -class EventLoop { -public: - using Task = std::function; - - class Token { - public: - Token(); - Token(Token &&other); - Token(const Token &other) = delete; - ~Token(); - - Token &operator=(Token &&other); - Token &operator=(const Token &other) = delete; - - /* clear all tasks that are scheduled to this token. you cannot cancel - * the task that is in running, but will wait untill the task completion - */ - void reset(); - - class Impl; - Impl *pimpl(); - - private: - Impl *pimpl_; - - friend class EventLoop; - }; - -public: - EventLoop(); - EventLoop(PollType poll_type); - EventLoop(const EventLoop &) = delete; - EventLoop(EventLoop &&other); - ~EventLoop(); - - EventLoop &operator=(const EventLoop &) = delete; - EventLoop &operator=(EventLoop &&other); - -public: - bool init(); - - /* NOTE: cb must be valid untill unregisterFd called - * this API is thread-safe - */ - Result registerFd(SOCKET_FD fd, uint32_t events, IOCallback cb); - /* - * this API is thread-safe - */ - Result updateFd(SOCKET_FD fd, uint32_t events); - /* - * this API is thread-safe - */ - Result unregisterFd(SOCKET_FD fd, bool close_fd); - - PollType getPollType() const; - bool isPollLT() const; // level trigger - -public: - bool inSameThread() const; - - /* create a token, it can be used to cancel the tasks that are scheduled - * with it if caller can guarantee the resources used by tasks are valid - * when task running, then token is no need, otherwise the caller should - * cancel the tasks queued in loop before the resources are unavailable - */ - Token createToken(); - - /* run the task in loop thread and wait untill task is executed. - * the task will be executed at once if called on loop thread - * token is always unnecessary for sync task - * - * @param f the task to be executed. it will always be executed when call - * success - * - * @return return the result of f() - */ - template - auto invoke(F &&f, Token *token = nullptr, const char *debugStr = nullptr) { - Result err; - return invoke(std::forward(f), err, token, debugStr); - } - - /* run the task in loop thread and wait untill task is executed. - * the task will be executed at once if called on loop thread - * token is always unnecessary for sync task - * - * @param f the task to be executed. it will always be executed when call - * success - * @param err when f is executed, err is Result::OK, otherwise is Result - * - * @return return the result of f() - */ - template ()())>{}, - int> = 0> - auto invoke(F &&f, Result &err, Token *token = nullptr, - const char *debugStr = nullptr) { - static_assert(!std::is_void{}, "is void"); - if (inSameThread()) { - return f(); - } - using ReturnType = decltype(f()); - ReturnType retval; - auto task_sync = [&] { retval = f(); }; - err = sync(std::move(task_sync), token, debugStr); - return retval; - } - - template ()())>{}, - int> = 0> - void invoke(F &&f, Result &err, Token *token = nullptr, - const char *debugStr = nullptr) { - static_assert(std::is_void{}, "not void"); - if (inSameThread()) { - return f(); - } - err = sync(std::forward(f), token, debugStr); - } - - /* run the task in loop thread and wait untill task is executed. - * the task will be executed at once if called on loop thread - * token is always unnecessary for sync task - * - * @param task the task to be executed. it will always be executed when call - * success - */ - template {}, int> = 0> - Result sync(F &&f, Token *token = nullptr, const char *debugStr = nullptr) { - lambda_wrapper wf{std::forward(f)}; - return sync(Task(std::move(wf)), token, debugStr); - } - Result sync(Task task, Token *token = nullptr, - const char *debugStr = nullptr); - - /* run the task in loop thread. - * the task will be executed at once if called on loop thread - * - * @param task the task to be executed. it will always be executed when call - * success - * @param token to be used to cancel the task. If token is null, the caller - * should make sure the resources referenced by task are valid when task - * running - * @param debugStr debug message of the f, e.g. file name and line where f - * is generated - */ - template {}, int> = 0> - Result async(F &&f, Token *token = nullptr, - const char *debugStr = nullptr) { - lambda_wrapper wf{std::forward(f)}; - return async(Task(std::move(wf)), token, debugStr); - } - Result async(Task task, Token *token = nullptr, - const char *debugStr = nullptr); - - /* run the task in loop thread at next time. - * - * @param task the task to be executed. it will always be executed when call - * success - * @param token to be used to cancel the task. If token is null, the caller - * should make sure the resources referenced by task are valid when task - * running - */ - template {}, int> = 0> - Result post(F &&f, Token *token = nullptr, const char *debugStr = nullptr) { - lambda_wrapper wf{std::forward(f)}; - return post(Task(std::move(wf)), token, debugStr); - } - Result post(Task task, Token *token = nullptr, - const char *debugStr = nullptr); - - template {}, int> = 0> - Result postDelayed(uint32_t delay_ms, F &&f, Token *token = nullptr, - const char *debugStr = nullptr) { - lambda_wrapper wf{std::forward(f)}; - return postDelayed(delay_ms, Task(std::move(wf)), token, debugStr); - } - Result postDelayed(uint32_t delay_ms, Task task, Token *token = nullptr, - const char *debugStr = nullptr); - - void wakeup(); - - /* cancel the tasks that are scheduled with token. you cannot cancel the - * task that is in running, but will wait untill the task completion - * - * @param token token of the tasks - * this API is thread-safe - */ - void cancel(Token *token); - - void loopOnce(uint32_t max_wait_ms); - void loop(uint32_t max_wait_ms = -1); - - /* stop the loop, no more Task can be posted to loop on stopped state - * reset() can be used to reset the stopped falg - */ - void stop(); - bool stopped() const; - - /* reset the loop state, Task can be posted again to the loop after reset - */ - void reset(); - - class Impl; - using ImplPtr = std::shared_ptr; - ImplPtr pimpl(); - -private: - ImplPtr pimpl_; -}; - -class Timer { -public: - using TimerCallback = std::function; - enum class Mode { ONE_SHOT, REPEATING }; - - Timer(EventLoop *loop); - Timer(const Timer &) = delete; - Timer(Timer &&other); - ~Timer(); - - Timer &operator=(const Timer &) = delete; - Timer &operator=(Timer &&other); - - /** - * Schedule the timer. This API is thread-safe - */ - template {}, int> = 0> - bool schedule(uint32_t delay_ms, Mode mode, F &&f) { - lambda_wrapper wf{std::forward(f)}; - return schedule(delay_ms, mode, TimerCallback(std::move(wf))); - } - // TimerCallback will be reset when: - // 1. timer is cancelled - // 2. timer is executed and Timer::Mode is ONE_SHOT - // 3. the TimerManager in EventLoop is destroyed and timer is still in queue - bool schedule(uint32_t delay_ms, Mode mode, TimerCallback cb); - - /** - * Cancel the scheduled timer. This API is thread-safe - */ - void cancel(); - - class Impl; - Impl *pimpl(); - -private: - Impl *pimpl_; -}; - -using LogCallback = std::function; -void setLogCallback(LogCallback cb); - -ATOM_NS_END - -#endif diff --git a/src/atom/event/kevdefs.hpp b/src/atom/event/kevdefs.hpp deleted file mode 100644 index 79db5e64..00000000 --- a/src/atom/event/kevdefs.hpp +++ /dev/null @@ -1,94 +0,0 @@ -/* - * kevdefs.hpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2024-2-10 - -Description: Some defines for kev - -**************************************************/ - -#ifndef __KEVDEFS_HPP -#define __KEVDEFS_HPP - -#include "kmconf.hpp" - -#include -#include -#include - - -#define ATOM_NS_BEGIN namespace Atom::Event { -#define ATOM_NS_END } -#define ATOM_NS_USING using namespace Atom::Event; - -ATOM_NS_BEGIN - -#ifdef ATOM_OS_WIN -using SOCKET_FD = uintptr_t; -const SOCKET_FD INVALID_FD = (SOCKET_FD)~0; -#else -using SOCKET_FD = int; -const SOCKET_FD INVALID_FD = ((SOCKET_FD)-1); -#endif - -using KMEvent = uint32_t; -using IOCallback = std::function; - -const uint32_t kEventRead = 1; -const uint32_t kEventWrite = (1 << 1); -const uint32_t kEventError = (1 << 2); -const uint32_t kEventNetwork = (kEventRead | kEventWrite | kEventError); - -enum class Result : int { - OK = 0, - FAILED = -1, - FATAL = -2, - REJECTED = -3, - CLOSED = -4, - AGAIN = -5, - ABORTED = -6, - TIMEOUT = -7, - INVALID_STATE = -8, - INVALID_PARAM = -9, - INVALID_PROTO = -10, - ALREADY_EXIST = -11, - NOT_EXIST = -12, - SOCK_ERROR = -13, - POLL_ERROR = -14, - PROTO_ERROR = -15, - SSL_ERROR = -16, - BUFFER_TOO_SMALL = -17, - BUFFER_TOO_LONG = -18, - NOT_SUPPORTED = -19, - NOT_IMPLEMENTED = -20, - NOT_AUTHORIZED = -21, - - DESTROYED = -699 -}; - -enum class PollType { - DEFAULT, - SELECT, - POLL, - EPOLL, - KQUEUE, - IOCP, - RUNLOOP, - STLCV, // none IO event loop -}; - -#ifdef ATOM_OS_WIN -struct iovec { - unsigned long iov_len; - char *iov_base; -}; -#endif - -ATOM_NS_END - -#endif diff --git a/src/atom/event/kmconf.hpp b/src/atom/event/kmconf.hpp deleted file mode 100644 index 31f9e73c..00000000 --- a/src/atom/event/kmconf.hpp +++ /dev/null @@ -1,52 +0,0 @@ -/* - * kevconf.hpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2024-2-10 - -Description: Configuration - -**************************************************/ - -#ifndef ATOM_EVENT_CONF_HPP -#define ATOM_EVENT_CONF_HPP - -#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || \ - defined(_WIN64) || defined(__CYGWIN__) -#define ATOM_OS_WIN -#elif defined(linux) || defined(__linux) || defined(__linux__) -#define ATOM_OS_LINUX -#if defined(__ANDROID__) -#define ATOM_OS_ANDROID -#endif -#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) -#define ATOM_OS_MAC -#include -#if TARGET_OS_IPHONE == 1 -#define ATOM_OS_IOS -#endif -#else -#error "Unknown OS, I don't know what to do" -#endif - -#ifdef ATOM_OS_WIN -#if defined(_WIN64) -#define ATOM_ENV64 -#else -#define ATOM_ENV32 -#endif -#endif - -#if defined(__GNUC__) || defined(__clang__) -#if defined(__x86_64__) || defined(__ppc64__) -#define ATOM_ENV64 -#else -#define ATOM_ENV32 -#endif -#endif - -#endif diff --git a/src/atom/event/kmtypes.hpp b/src/atom/event/kmtypes.hpp deleted file mode 100644 index 222f844c..00000000 --- a/src/atom/event/kmtypes.hpp +++ /dev/null @@ -1,58 +0,0 @@ -/* - * kmtypes.hpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2024-2-10 - -Description: Lambda wrapper - -**************************************************/ - -#ifndef __KEVTYPES_HPP -#define __KEVTYPES_HPP - -#include - -namespace Atom::Event { - -template -struct lambda_wrapper; - -template -struct lambda_wrapper{}>> { - Fn fn; - - template - auto operator()(Args &&...args) { - return fn(std::forward(args)...); - } -}; - -template -struct lambda_wrapper{} && - std::is_move_constructible{}>> { - Fn fn; - - lambda_wrapper(Fn &&fn) : fn(std::forward(fn)) {} - - lambda_wrapper(lambda_wrapper &&) = default; - lambda_wrapper &operator=(lambda_wrapper &&) = default; - - lambda_wrapper(const lambda_wrapper &rhs) : fn(const_cast(rhs.fn)) { - throw 0; - } - lambda_wrapper &operator=(const lambda_wrapper &) { throw 0; } - - template - auto operator()(Args &&...args) { - return fn(std::forward(args)...); - } -}; - -} // namespace Atom::Event - -#endif // __KEVTYPES_HPP diff --git a/src/atom/event/poll/CVPoll.cpp b/src/atom/event/poll/CVPoll.cpp deleted file mode 100644 index 2ed0de5b..00000000 --- a/src/atom/event/poll/CVPoll.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/* - * cvpoll.cpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2024-2-10 - -Description: cvpoll - -**************************************************/ - -#include "iopoll.hpp" - -#include -#include - -using namespace std::chrono; - -ATOM_NS_BEGIN - -class CVPoll : public IOPoll { -public: - bool init() override; - Result registerFd(SOCKET_FD fd, KMEvent events, IOCallback cb) override { - return Result::NOT_SUPPORTED; - } - Result unregisterFd(SOCKET_FD fd) override { return Result::NOT_SUPPORTED; } - Result updateFd(SOCKET_FD fd, KMEvent events) override { - return Result::NOT_SUPPORTED; - } - Result wait(uint32_t wait_ms) override; - void notify() override; - PollType getType() const override { return PollType::STLCV; } - bool isLevelTriggered() const override { return false; } - -private: - bool ready_{false}; - std::mutex mutex_; - std::condition_variable cv_; -}; - -bool CVPoll::init() { - { - std::lock_guard g(mutex_); - ready_ = false; - } - return true; -} - -Result CVPoll::wait(uint32_t wait_ms) { - auto ms = milliseconds(wait_ms); - { - std::unique_lock lk(mutex_); - // bool ret = timeBeginPeriod(1) == TIMERR_NOERROR; - if (cv_.wait_for(lk, ms, [this] { return ready_; })) { - ready_ = false; - } - // if (ret) timeEndPeriod(1); - } - return Result::OK; -} - -void CVPoll::notify() { - { - std::lock_guard g(mutex_); - ready_ = true; - } - cv_.notify_one(); -} - -IOPoll *createCVPoll() { return new CVPoll(); } - -ATOM_NS_END diff --git a/src/atom/event/poll/EPoll.cpp b/src/atom/event/poll/EPoll.cpp deleted file mode 100644 index dd3cd8e5..00000000 --- a/src/atom/event/poll/EPoll.cpp +++ /dev/null @@ -1,197 +0,0 @@ -/* - * epoll.cpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2024-2-10 - -Description: Epoll Wrapper for Linux. - -**************************************************/ - -#include "iopoll.hpp" -#include "notifier.hpp" -#include "utils/kmtrace.hpp" - -#include - -ATOM_NS_BEGIN - -#define MAX_EPOLL_FDS 5000 -#define MAX_EVENT_NUM 500 - -class EPoll : public IOPoll { -public: - EPoll(); - ~EPoll(); - - bool init(); - Result registerFd(SOCKET_FD fd, KMEvent events, IOCallback cb); - Result unregisterFd(SOCKET_FD fd); - Result updateFd(SOCKET_FD fd, KMEvent events); - Result wait(uint32_t wait_time_ms); - void notify(); - PollType getType() const { return PollType::EPOLL; } - bool isLevelTriggered() const { return false; } - -private: - uint32_t get_events(KMEvent kuma_events); - KMEvent get_kuma_events(uint32_t events); - -private: - int epoll_fd_; - NotifierPtr notifier_{std::move(Notifier::createNotifier())}; -}; - -EPoll::EPoll() : epoll_fd_(INVALID_FD) {} - -EPoll::~EPoll() { - if (INVALID_FD != epoll_fd_) { - close(epoll_fd_); - epoll_fd_ = INVALID_FD; - } -} - -bool EPoll::init() { - if (INVALID_FD != epoll_fd_) { - return true; - } - epoll_fd_ = epoll_create(MAX_EPOLL_FDS); - if (INVALID_FD == epoll_fd_) { - return false; - } - if (!notifier_->ready()) { - if (!notifier_->init()) { - close(epoll_fd_); - epoll_fd_ = INVALID_FD; - return false; - } - IOCallback cb([this](SOCKET_FD, KMEvent ev, void *, size_t) { - notifier_->onEvent(ev); - }); - registerFd(notifier_->getReadFD(), kEventRead | kEventError, - std::move(cb)); - } - return true; -} - -uint32_t EPoll::get_events(KMEvent kuma_events) { - uint32_t ev = - EPOLLET; // EPOLLIN | EPOLLOUT | EPOLLERR | EPOLLHUP | EPOLLET; - if (kuma_events & kEventRead) { - ev |= EPOLLIN; - } - if (kuma_events & kEventWrite) { - ev |= EPOLLOUT; - } - if (kuma_events & kEventError) { - ev |= EPOLLERR | EPOLLHUP; - } - return ev; -} - -KMEvent EPoll::get_kuma_events(uint32_t events) { - KMEvent ev = 0; - if (events & EPOLLIN) { - ev |= kEventRead; - } - if (events & EPOLLOUT) { - ev |= kEventWrite; - } - if (events & (EPOLLERR | EPOLLHUP)) { - ev |= kEventError; - } - return ev; -} - -Result EPoll::registerFd(SOCKET_FD fd, KMEvent events, IOCallback cb) { - if (fd < 0) { - return Result::INVALID_PARAM; - } - resizePollItems(fd); - int epoll_op = EPOLL_CTL_ADD; - if (INVALID_FD != poll_items_[fd].fd) { - epoll_op = EPOLL_CTL_MOD; - } - poll_items_[fd].fd = fd; - poll_items_[fd].events = events; - poll_items_[fd].cb = std::move(cb); - struct epoll_event evt = {0}; - evt.data.ptr = (void *)(long)fd; - evt.events = get_events( - events); // EPOLLIN | EPOLLOUT | EPOLLERR | EPOLLHUP | EPOLLET; - if (epoll_ctl(epoll_fd_, epoll_op, fd, &evt) < 0) { - KM_ERRTRACE("EPoll::registerFd error, fd=" - << fd << ", ev=" << evt.events << ", errno=" << errno); - return Result::FAILED; - } - KM_INFOTRACE("EPoll::registerFd, fd=" << fd << ", ev=" << evt.events); - - return Result::OK; -} - -Result EPoll::unregisterFd(SOCKET_FD fd) { - int max_fd = int(poll_items_.size() - 1); - KM_INFOTRACE("EPoll::unregisterFd, fd=" << fd << ", max_fd=" << max_fd); - if (fd < 0 || fd > max_fd) { - KM_WARNTRACE("EPoll::unregisterFd, failed, max_fd=" << max_fd); - return Result::INVALID_PARAM; - } - epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, fd, NULL); - if (fd < max_fd) { - poll_items_[fd].reset(); - } else if (fd == max_fd) { - poll_items_.pop_back(); - } - return Result::OK; -} - -Result EPoll::updateFd(SOCKET_FD fd, KMEvent events) { - if (fd < 0 || fd >= poll_items_.size() || - INVALID_FD == poll_items_[fd].fd) { - return Result::FAILED; - } - struct epoll_event evt = {0}; - evt.data.ptr = (void *)(long)fd; - evt.events = get_events(events); - if (epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, fd, &evt) < 0) { - KM_ERRTRACE("EPoll::updateFd error, fd=" << fd << ", errno=" << errno); - return Result::FAILED; - } - poll_items_[fd].events = events; - return Result::OK; -} - -Result EPoll::wait(uint32_t wait_ms) { - struct epoll_event events[MAX_EVENT_NUM]; - int nfds = epoll_wait(epoll_fd_, events, MAX_EVENT_NUM, wait_ms); - if (nfds < 0) { - if (errno != EINTR) { - KM_ERRTRACE("EPoll::wait, errno=" << errno); - } - KM_INFOTRACE("EPoll::wait, nfds=" << nfds << ", errno=" << errno); - } else { - for (int i = 0; i < nfds; ++i) { - SOCKET_FD fd = (SOCKET_FD)(long)events[i].data.ptr; - if (fd < poll_items_.size()) { - auto revents = get_kuma_events(events[i].events); - revents &= poll_items_[fd].events; - if (revents) { - auto &cb = poll_items_[fd].cb; - if (cb) - cb(fd, revents, nullptr, 0); - } - } - } - } - return Result::OK; -} - -void EPoll::notify() { notifier_->notify(); } - -IOPoll *createEPoll() { return new EPoll(); } - -ATOM_NS_END diff --git a/src/atom/event/poll/KQueue.cpp b/src/atom/event/poll/KQueue.cpp deleted file mode 100644 index 18226bef..00000000 --- a/src/atom/event/poll/KQueue.cpp +++ /dev/null @@ -1,259 +0,0 @@ -/* - * kqueue.cpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2024-2-10 - -Description: kqueue poller - -**************************************************/ - -#include "iopoll.hpp" -#include "notifier.hpp" -#include "utils/kmtrace.hpp" - -#include -#include -#include - - -ATOM_NS_BEGIN - -#define MAX_EVENT_NUM 256 - -class KQueue : public IOPoll { -public: - KQueue(); - ~KQueue(); - - bool init() override; - Result registerFd(SOCKET_FD fd, KMEvent events, IOCallback cb) override; - Result unregisterFd(SOCKET_FD fd) override; - Result updateFd(SOCKET_FD fd, KMEvent events) override; - Result wait(uint32_t wait_time_ms) override; - void notify() override; - PollType getType() const override { return PollType::KQUEUE; } - - // can be false on ET mode, but return true to removing the write event - // and thus reduce the kqueue eventlist size - bool isLevelTriggered() const override { return true; } - -private: - int kqueue_fd_{-1}; - NotifierPtr notifier_; - - // on ET mode (EV_CLEAR is set), it seems EVFILT_READ won't be triggered - // if EVFILT_READ is set after data arrived - bool work_on_et_mode_{false}; -}; - -KQueue::KQueue() {} - -KQueue::~KQueue() { - if (INVALID_FD != kqueue_fd_) { - ::close(kqueue_fd_); - kqueue_fd_ = INVALID_FD; - } -} - -bool KQueue::init() { - if (INVALID_FD != kqueue_fd_) { - return true; - } - kqueue_fd_ = ::kqueue(); - if (INVALID_FD == kqueue_fd_) { - return false; - } -#if defined(EVFILT_USER) && defined(NOTE_TRIGGER) - struct kevent ev; - EV_SET(&ev, 0, EVFILT_USER, EV_ADD | EV_CLEAR, 0, 0, 0); - if (::kevent(kqueue_fd_, &ev, 1, 0, 0, 0) != -1) { - notifier_.reset(); - } else -#endif - { - notifier_ = Notifier::createNotifier(); - } - if (notifier_ && !notifier_->ready()) { - if (!notifier_->init()) { - ::close(kqueue_fd_); - kqueue_fd_ = INVALID_FD; - return false; - } - IOCallback cb([this](SOCKET_FD, KMEvent ev, void *, size_t) { - notifier_->onEvent(ev); - }); - registerFd(notifier_->getReadFD(), kEventRead | kEventError, - std::move(cb)); - } - return true; -} - -Result KQueue::registerFd(SOCKET_FD fd, KMEvent events, IOCallback cb) { - if (fd < 0) { - return Result::INVALID_PARAM; - } - resizePollItems(fd); - poll_items_[fd].fd = fd; - poll_items_[fd].cb = std::move(cb); - auto ret = updateFd(fd, events); - if (ret != Result::OK) { - poll_items_[fd].reset(); - } - KM_INFOTRACE("KQueue::registerFd, fd=" << fd << ", ev=" << events - << ", ret=" << (int)ret); - return ret; -} - -Result KQueue::unregisterFd(SOCKET_FD fd) { - int max_fd = int(poll_items_.size() - 1); - KM_INFOTRACE("KQueue::unregisterFd, fd=" << fd << ", max_fd=" << max_fd); - if (fd < 0 || fd > max_fd) { - KM_WARNTRACE("KQueue::unregisterFd, failed, max_fd=" << max_fd); - return Result::INVALID_PARAM; - } - struct kevent kevents[2]; - int nchanges = 0; - if (poll_items_[fd].events & kEventRead) { - EV_SET(&kevents[nchanges++], fd, EVFILT_READ, EV_DELETE, 0, 0, 0); - } - if (poll_items_[fd].events & kEventWrite) { - EV_SET(&kevents[nchanges++], fd, EVFILT_WRITE, EV_DELETE, 0, 0, 0); - } - ::kevent(kqueue_fd_, kevents, nchanges, 0, 0, 0); - if (fd < max_fd) { - poll_items_[fd].reset(); - } else if (fd == max_fd) { - poll_items_.pop_back(); - } - return Result::OK; -} - -Result KQueue::updateFd(SOCKET_FD fd, KMEvent events) { - if (fd < 0 || fd >= poll_items_.size() || - INVALID_FD == poll_items_[fd].fd) { - return Result::INVALID_PARAM; - } - - struct kevent kevents[2]; - int nchanges = 0; - if (!!(poll_items_[fd].events & kEventRead) && !(events & kEventRead)) { - EV_SET(&kevents[nchanges++], fd, EVFILT_READ, EV_DELETE, 0, 0, 0); - poll_items_[fd].events &= ~kEventRead; - } - if (!!(poll_items_[fd].events & kEventWrite) && !(events & kEventWrite)) { - EV_SET(&kevents[nchanges++], fd, EVFILT_WRITE, EV_DELETE, 0, 0, 0); - poll_items_[fd].events &= ~kEventWrite; - } - if (nchanges) { // remove events - ::kevent(kqueue_fd_, kevents, nchanges, 0, 0, 0); - } - if (poll_items_[fd].events == events) { - return Result::OK; - } - nchanges = 0; - unsigned short op = EV_ADD; - if (work_on_et_mode_) { - op |= EV_CLEAR; - } - if (events & kEventRead) { - EV_SET(&kevents[nchanges++], fd, EVFILT_READ, op, 0, 0, 0); - } - if (events & kEventWrite) { - EV_SET(&kevents[nchanges++], fd, EVFILT_WRITE, op, 0, 0, 0); - } - if (nchanges && ::kevent(kqueue_fd_, kevents, nchanges, 0, 0, 0) == -1) { - KM_ERRTRACE("KQueue::updateFd error, fd=" << fd << ", errno=" << errno); - return Result::FAILED; - } - poll_items_[fd].events = events; - // KM_INFOTRACE("KQueue::updateFd, fd="< -#include -#elif defined(ATOM_OS_LINUX) -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#elif defined(ATOM_OS_MAC) -#include -#include -#include - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#else -#error "UNSUPPORTED OS" -#endif - -#ifdef ATOM_OS_LINUX -#include "event_notifier.hpp" -#elif !defined(ATOM_OS_WIN) -#include "pipe_notifier.hpp" -#else -#include "socket_notifier.hpp" -#endif - -ATOM_NS_USING - -NotifierPtr Notifier::createNotifier() { -#ifdef ATOM_OS_LINUX - return NotifierPtr(new EventNotifier()); -#elif !defined(ATOM_OS_WIN) - return NotifierPtr(new PipeNotifier()); -#else - return NotifierPtr(new SocketNotifier()); -#endif -} diff --git a/src/atom/event/poll/RunLoop.mm b/src/atom/event/poll/RunLoop.mm deleted file mode 100644 index bb70a9df..00000000 --- a/src/atom/event/poll/RunLoop.mm +++ /dev/null @@ -1,309 +0,0 @@ -/* - * runloop.mm - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2024-2-10 - -Description: RunLoop for Mac - -*************************************************/ - -#ifdef ATOM_HAS_RUNLOOP - -#include "IOPoll.h" -#include "utils/kmtrace.h" - -#include - -ATOM_NS_BEGIN - -static void KevSocketCallBack(CFSocketRef s, - CFSocketCallBackType type, - CFDataRef address, - const void *data, - void *info); - -class RunLoopMac : public IOPoll -{ -public: - ~RunLoopMac(); - bool init() override; - Result registerFd(SOCKET_FD fd, KMEvent events, IOCallback cb) override; - Result unregisterFd(SOCKET_FD fd) override; - Result updateFd(SOCKET_FD fd, KMEvent events) override; - Result wait(uint32_t wait_ms) override; - void notify() override; - PollType getType() const override { return PollType::RUNLOOP; } - bool isLevelTriggered() const override { return true; } - - void onSocketCallBack(CFSocketRef s, CFSocketCallBackType type); - -private: - CFSocketCallBackType get_events(KMEvent kuma_events); - KMEvent get_kuma_events(CFSocketCallBackType events); - void resizeSockItems(SOCKET_FD fd) { - auto count = sock_items_.size(); - if (fd >= count) { - if(fd > count + 1024) { - sock_items_.resize(fd+1); - } else { - sock_items_.resize(count + 1024); - } - } - } - -private: - CFRunLoopRef loopref_ = nil; - CFRunLoopSourceRef notifier_ = nil; - //CFRunLoopObserverRef observer_ = nil; - - struct SockItem - { - void reset() { - fd = INVALID_FD; - sock = nil; - source = nil; - events = 0; - revents = 0; - cb = nullptr; - } - SOCKET_FD fd { INVALID_FD }; - CFSocketRef sock {nil}; - CFRunLoopSourceRef source {nil}; - KMEvent events { 0 }; // kuma events registered - KMEvent revents { 0 }; // kuma events received - IOCallback cb; - }; - std::vector sock_items_; -}; - -RunLoopMac::~RunLoopMac() -{ - if (notifier_) { - if (loopref_) { - CFRunLoopRemoveSource(loopref_, notifier_, kCFRunLoopDefaultMode); - } - CFRelease(notifier_); - notifier_ = nil; - } - if (loopref_) { - CFRunLoopWakeUp(loopref_); - CFRunLoopStop(loopref_); - CFRelease(loopref_); - loopref_ = nil; - } -} - -bool RunLoopMac::init() -{ - auto loopref = CFRunLoopGetCurrent(); - if (loopref == loopref_) { - return true; - } - std::swap(loopref, loopref_); - CFRetain(loopref_); - if (loopref) { - if (notifier_) { - CFRunLoopRemoveSource(loopref, notifier_, kCFRunLoopDefaultMode); - } - CFRelease(loopref); - } - - if (!notifier_) { - CFRunLoopSourceContext context; - bzero(&context, sizeof(context)); - notifier_ = CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &context); - if (notifier_ == nil) { - CFRelease(loopref_); - loopref_ = nil; - return false; - } - } - CFRunLoopAddSource(loopref_, notifier_, kCFRunLoopDefaultMode); - - return true; -} - -CFSocketCallBackType RunLoopMac::get_events(KMEvent kuma_events) -{ - CFSocketCallBackType ev = kCFSocketNoCallBack; - if(kuma_events & kEventRead) { - ev |= kCFSocketReadCallBack; - } - if(kuma_events & kEventWrite) { - ev |= kCFSocketWriteCallBack; - } - if(kuma_events & kEventError) { - ev |= kCFSocketReadCallBack; - } - return ev; -} - -KMEvent RunLoopMac::get_kuma_events(CFSocketCallBackType events) -{ - KMEvent ev = 0; - if(events & kCFSocketReadCallBack) { - ev |= kEventRead; - } - if(events & kCFSocketWriteCallBack) { - ev |= kEventWrite; - } - return ev; -} - -Result RunLoopMac::registerFd(SOCKET_FD fd, KMEvent events, IOCallback cb) -{ - if (fd < 0) { - return Result::INVALID_PARAM; - } - resizeSockItems(fd); - sock_items_[fd].fd = fd; - sock_items_[fd].events = events; - sock_items_[fd].cb = std::move(cb); - - auto cb_types = kCFSocketReadCallBack | kCFSocketWriteCallBack; - CFSocketContext context = {0, this, nil, nil, nil}; - auto sock = CFSocketCreateWithNative(nil, fd, cb_types, - KevSocketCallBack, &context); - if (sock == nil) { - KM_ERRTRACE("RunLoop::registerFd error, fd=" << fd << ", ev=" << events); - return Result::FAILED; - } - auto flags = CFSocketGetSocketFlags (sock); - flags |= kCFSocketAutomaticallyReenableReadCallBack; - flags &= ~kCFSocketCloseOnInvalidate; - CFSocketSetSocketFlags(sock, flags); - CFSocketCallBackType disabled_types = kCFSocketNoCallBack; - if (!(events & kEventRead)) { - disabled_types |= kCFSocketReadCallBack; - } - if (!(events & kEventWrite)) { - disabled_types |= kCFSocketWriteCallBack; - } - CFSocketDisableCallBacks(sock, disabled_types); - auto sockSource = CFSocketCreateRunLoopSource(NULL, sock, 0); - sock_items_[fd].sock = sock; - sock_items_[fd].source = sockSource; - CFRunLoopAddSource(loopref_, sockSource, kCFRunLoopDefaultMode); - - KM_INFOTRACE("RunLoop::registerFd, fd=" << fd << ", ev=" << events); - - return Result::OK; -} - -Result RunLoopMac::unregisterFd(SOCKET_FD fd) -{ - int max_fd = int(sock_items_.size() - 1); - KM_INFOTRACE("RunLoop::unregisterFd, fd="< - -ATOM_NS_BEGIN - -class SelectPoll : public IOPoll { -public: - SelectPoll(); - ~SelectPoll(); - - bool init() override; - Result registerFd(SOCKET_FD fd, KMEvent events, IOCallback cb) override; - Result unregisterFd(SOCKET_FD fd) override; - Result updateFd(SOCKET_FD fd, KMEvent events) override; - Result wait(uint32_t wait_time_ms) override; - void notify() override; - PollType getType() const override { return PollType::SELECT; } - bool isLevelTriggered() const override { return true; } - -private: - struct PollFD { - SOCKET_FD fd = INVALID_FD; - KMEvent events = 0; - }; - -private: - using PollFdVector = std::vector; - NotifierPtr notifier_{Notifier::createNotifier()}; - PollFdVector poll_fds_; - - fd_set read_fds_; - fd_set write_fds_; - fd_set except_fds_; - SOCKET_FD max_fd_; - -private: - void updateFdSet(SOCKET_FD fd, KMEvent events); -}; - -SelectPoll::SelectPoll() : max_fd_(0) { - FD_ZERO(&read_fds_); - FD_ZERO(&write_fds_); - FD_ZERO(&except_fds_); -} - -SelectPoll::~SelectPoll() { poll_fds_.clear(); } - -bool SelectPoll::init() { - if (!notifier_->ready()) { - if (!notifier_->init()) { - return false; - } - IOCallback cb([this](SOCKET_FD, KMEvent ev, void *, size_t) { - notifier_->onEvent(ev); - }); - registerFd(notifier_->getReadFD(), kEventRead | kEventError, - std::move(cb)); - } - return true; -} - -Result SelectPoll::registerFd(SOCKET_FD fd, KMEvent events, IOCallback cb) { - if (fd < 0) { - return Result::INVALID_PARAM; - } - KM_INFOTRACE("SelectPoll::registerFd, fd=" << fd); - resizePollItems(fd); - if (INVALID_FD == poll_items_[fd].fd || -1 == poll_items_[fd].idx) { - PollFD pfd; - pfd.fd = fd; - pfd.events = events; - poll_fds_.push_back(pfd); - poll_items_[fd].idx = int(poll_fds_.size() - 1); - } - poll_items_[fd].fd = fd; - poll_items_[fd].events = events; - poll_items_[fd].cb = std::move(cb); - updateFdSet(fd, events); - return Result::OK; -} - -Result SelectPoll::unregisterFd(SOCKET_FD fd) { - auto max_fd = SOCKET_FD(poll_items_.size() - 1); - KM_INFOTRACE("SelectPoll::unregisterFd, fd=" << fd - << ", max_fd=" << max_fd); - if (fd < 0 || fd > max_fd) { - KM_WARNTRACE("SelectPoll::unregisterFd, failed, max_fd=" << max_fd); - return Result::INVALID_PARAM; - } - updateFdSet(fd, 0); - int idx = poll_items_[fd].idx; - if (fd < max_fd) { - poll_items_[fd].reset(); - } else if (fd == max_fd) { - poll_items_.pop_back(); - } - int last_idx = int(poll_fds_.size() - 1); - if (idx > last_idx || -1 == idx) { - return Result::OK; - } - if (idx != last_idx) { - std::iter_swap(poll_fds_.begin() + idx, poll_fds_.end() - 1); - poll_items_[poll_fds_[idx].fd].idx = idx; - } - poll_fds_.pop_back(); - return Result::OK; -} - -Result SelectPoll::updateFd(SOCKET_FD fd, KMEvent events) { - auto max_fd = SOCKET_FD(poll_items_.size() - 1); - if (fd < 0 || -1 == max_fd || fd > max_fd) { - KM_WARNTRACE( - "SelectPoll::updateFd, failed, fd=" << fd << ", max_fd=" << max_fd); - return Result::INVALID_PARAM; - } - if (poll_items_[fd].fd != fd) { - KM_WARNTRACE("SelectPoll::updateFd, failed, fd=" << fd << ", item_fd=" - << poll_items_[fd].fd); - return Result::INVALID_PARAM; - } - int idx = poll_items_[fd].idx; - if (idx < 0 || idx >= (int)poll_fds_.size()) { - KM_WARNTRACE("SelectPoll::updateFd, failed, index=" << idx); - return Result::INVALID_STATE; - } - if (poll_fds_[idx].fd != fd) { - KM_WARNTRACE("SelectPoll::updateFd, failed, fd=" << fd << ", pfds_fd=" - << poll_fds_[idx].fd); - return Result::INVALID_PARAM; - } - poll_fds_[idx].events = events; - poll_items_[fd].events = events; - updateFdSet(fd, events); - return Result::OK; -} - -void SelectPoll::updateFdSet(SOCKET_FD fd, KMEvent events) { - if (events != 0) { - if (events & kEventRead) { - FD_SET(fd, &read_fds_); - } else { - FD_CLR(fd, &read_fds_); - } - if (events & kEventWrite) { - FD_SET(fd, &write_fds_); - } else { - FD_CLR(fd, &write_fds_); - } - if (events & kEventError) { - FD_SET(fd, &except_fds_); - } - if (fd > max_fd_) { - max_fd_ = fd; - } - } else { - FD_CLR(fd, &read_fds_); - FD_CLR(fd, &write_fds_); - FD_CLR(fd, &except_fds_); - if (max_fd_ == fd) { - auto it = std::max_element( - poll_fds_.begin(), poll_fds_.end(), - [](PollFD &pf1, PollFD &pf2) { return pf1.fd < pf2.fd; }); - max_fd_ = it != poll_fds_.end() ? (*it).fd : 0; - } - } -} - -Result SelectPoll::wait(uint32_t wait_ms) { - fd_set readfds, writefds, exceptfds; - memcpy(&readfds, &read_fds_, sizeof(read_fds_)); - memcpy(&writefds, &write_fds_, sizeof(write_fds_)); - memcpy(&exceptfds, &except_fds_, sizeof(except_fds_)); - struct timeval tval { - 0, 0 - }; - if (wait_ms != -1) { - tval.tv_sec = wait_ms / 1000; - tval.tv_usec = (wait_ms - tval.tv_sec * 1000) * 1000; - } - int nready = ::select(static_cast(max_fd_ + 1), &readfds, &writefds, - &exceptfds, wait_ms == -1 ? nullptr : &tval); - if (nready <= 0) { - return Result::OK; - } - // copy poll fds since event handler may unregister fd - PollFdVector poll_fds = poll_fds_; - int fds_count = int(poll_fds.size()); - for (int i = 0; i < fds_count && nready > 0; ++i) { - KMEvent revents = 0; - SOCKET_FD fd = poll_fds[i].fd; - if (FD_ISSET(fd, &readfds)) { - revents |= kEventRead; - --nready; - } - if (nready > 0 && FD_ISSET(fd, &writefds)) { - revents |= kEventWrite; - --nready; - } - if (nready > 0 && FD_ISSET(fd, &exceptfds)) { - revents |= kEventError; - --nready; - } - if (fd < poll_items_.size()) { - revents &= poll_items_[fd].events; - if (revents) { - auto &cb = poll_items_[fd].cb; - if (cb) - cb(fd, revents, nullptr, 0); - } - } - } - return Result::OK; -} - -void SelectPoll::notify() { notifier_->notify(); } - -IOPoll *createSelectPoll() { return new SelectPoll(); } - -ATOM_NS_END diff --git a/src/atom/event/poll/VPoll.cpp b/src/atom/event/poll/VPoll.cpp deleted file mode 100644 index ea5a2016..00000000 --- a/src/atom/event/poll/VPoll.cpp +++ /dev/null @@ -1,229 +0,0 @@ -/* - * vpoll.cpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2024-2-10 - -Description: VPoll Notifier (Windows) - -*************************************************/ - -#include "iopoll.hpp" -#include "notifier.hpp" -#include "utils/kmtrace.hpp" -#include "utils/skutils.hpp" - -#include - -#ifdef ATOM_OS_WIN -#include -#else -#include -#endif - -ATOM_NS_BEGIN - -class VPoll : public IOPoll { -public: - VPoll(); - ~VPoll(); - - bool init() override; - Result registerFd(SOCKET_FD fd, KMEvent events, IOCallback cb) override; - Result unregisterFd(SOCKET_FD fd) override; - Result updateFd(SOCKET_FD fd, KMEvent events) override; - Result wait(uint32_t wait_ms) override; - void notify() override; - PollType getType() const override { return PollType::POLL; } - bool isLevelTriggered() const override { return true; } - -private: - uint32_t get_events(KMEvent kuma_events); - KMEvent get_kuma_events(uint32_t events); - -private: - typedef std::vector PollFdVector; - NotifierPtr notifier_{Notifier::createNotifier()}; - PollFdVector poll_fds_; -}; - -VPoll::VPoll() {} - -VPoll::~VPoll() { - poll_fds_.clear(); - poll_items_.clear(); -} - -bool VPoll::init() { - if (!notifier_->ready()) { - if (!notifier_->init()) { - return false; - } - IOCallback cb([this](SOCKET_FD, KMEvent ev, void *, size_t) { - notifier_->onEvent(ev); - }); - registerFd(notifier_->getReadFD(), kEventRead | kEventError, - std::move(cb)); - } - return true; -} - -uint32_t VPoll::get_events(KMEvent kuma_events) { - uint32_t ev = 0; - if (kuma_events & kEventRead) { - ev |= POLLIN; -#ifndef ATOM_OS_WIN - ev |= POLLPRI; -#endif - } - if (kuma_events & kEventWrite) { - ev |= POLLOUT; -#ifndef ATOM_OS_WIN - ev |= POLLWRBAND; -#endif - } - if (kuma_events & kEventError) { -#ifndef ATOM_OS_WIN - ev |= POLLERR | POLLHUP | POLLNVAL; -#endif - } - return ev; -} - -KMEvent VPoll::get_kuma_events(uint32_t events) { - KMEvent ev = 0; - if (events & (POLLIN | POLLPRI)) { - ev |= kEventRead; - } - if (events & (POLLOUT | POLLWRBAND)) { - ev |= kEventWrite; - } - if (events & (POLLERR | POLLHUP | POLLNVAL)) { - ev |= kEventError; - } - return ev; -} - -Result VPoll::registerFd(SOCKET_FD fd, KMEvent events, IOCallback cb) { - if (fd < 0) { - return Result::INVALID_PARAM; - } - resizePollItems(fd); - int idx = -1; - if (INVALID_FD == poll_items_[fd].fd || -1 == poll_items_[fd].idx) { // new - pollfd pfd; - pfd.fd = fd; - pfd.events = get_events(events); - poll_fds_.push_back(pfd); - idx = int(poll_fds_.size() - 1); - poll_items_[fd].idx = idx; - } - poll_items_[fd].fd = fd; - poll_items_[fd].events = events; - poll_items_[fd].cb = std::move(cb); - KM_INFOTRACE("VPoll::registerFd, fd=" << fd << ", events=" << events - << ", index=" << idx); - - return Result::OK; -} - -Result VPoll::unregisterFd(SOCKET_FD fd) { - auto max_fd = SOCKET_FD(poll_items_.size() - 1); - KM_INFOTRACE("VPoll::unregisterFd, fd=" << fd << ", max_fd=" << max_fd); - if (fd < 0 || -1 == max_fd || fd > max_fd) { - KM_WARNTRACE("VPoll::unregisterFd, failed, max_fd=" << max_fd); - return Result::INVALID_PARAM; - } - int idx = poll_items_[fd].idx; - if (fd < max_fd) { - poll_items_[fd].reset(); - } else if (fd == max_fd) { - poll_items_.pop_back(); - } - - int last_idx = int(poll_fds_.size() - 1); - if (idx > last_idx || -1 == idx) { - return Result::OK; - } - if (idx != last_idx) { - std::iter_swap(poll_fds_.begin() + idx, poll_fds_.end() - 1); - poll_items_[poll_fds_[idx].fd].idx = idx; - } - poll_fds_.pop_back(); - return Result::OK; -} - -Result VPoll::updateFd(SOCKET_FD fd, KMEvent events) { - auto max_fd = SOCKET_FD(poll_items_.size() - 1); - if (fd < 0 || -1 == max_fd || fd > max_fd) { - KM_WARNTRACE("VPoll::updateFd, failed, fd=" << fd - << ", max_fd=" << max_fd); - return Result::INVALID_PARAM; - } - if (poll_items_[fd].fd != fd) { - KM_WARNTRACE("VPoll::updateFd, failed, fd=" << fd << ", item_fd=" - << poll_items_[fd].fd); - return Result::INVALID_PARAM; - } - int idx = poll_items_[fd].idx; - if (idx < 0 || idx >= (int)poll_fds_.size()) { - KM_WARNTRACE("VPoll::updateFd, failed, index=" << idx); - return Result::INVALID_STATE; - } - if (poll_fds_[idx].fd != fd) { - KM_WARNTRACE("VPoll::updateFd, failed, fd=" << fd << ", pfds_fd=" - << poll_fds_[idx].fd); - return Result::INVALID_PARAM; - } - poll_fds_[idx].events = get_events(events); - poll_items_[fd].events = events; - return Result::OK; -} - -Result VPoll::wait(uint32_t wait_ms) { -#ifdef ATOM_OS_WIN - int num_revts = - WSAPoll(&poll_fds_[0], static_cast(poll_fds_.size()), wait_ms); -#else - int num_revts = poll(&poll_fds_[0], (nfds_t)poll_fds_.size(), wait_ms); -#endif - if (-1 == num_revts) { - if (EINTR == errno) { - errno = 0; - } else { - KM_ERRTRACE("VPoll::wait, err=" << SKUtils::getLastError()); - } - return Result::INVALID_STATE; - } - - // copy poll fds since event handler may unregister fd - PollFdVector poll_fds = poll_fds_; - - int idx = 0; - int last_idx = int(poll_fds.size() - 1); - while (num_revts > 0 && idx <= last_idx) { - if (poll_fds[idx].revents) { - --num_revts; - if (poll_fds[idx].fd < poll_items_.size()) { - auto &item = poll_items_[poll_fds[idx].fd]; - auto revents = get_kuma_events(poll_fds[idx].revents); - revents &= item.events; - if (revents && item.cb) { - item.cb(poll_fds[idx].fd, revents, nullptr, 0); - } - } - } - ++idx; - } - return Result::OK; -} - -void VPoll::notify() { notifier_->notify(); } - -IOPoll *createVPoll() { return new VPoll(); } - -ATOM_NS_END diff --git a/src/atom/event/poll/WinPoll.cpp b/src/atom/event/poll/WinPoll.cpp deleted file mode 100644 index 7a18292f..00000000 --- a/src/atom/event/poll/WinPoll.cpp +++ /dev/null @@ -1,223 +0,0 @@ -/* - * winpoll.cpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2024-2-10 - -Description: WinPoll Notifier (Windows) - -*************************************************/ - -#include "IOPoll.h" -#include "utils/kmtrace.h" - -ATOM_NS_BEGIN - -#define WM_SOCKET_NOTIFY 0x0373 - -#define WM_POLLER_NOTIFY WM_USER + 101 - -#define KM_WIN_CLASS_NAME "kev_win_class_name" - -class WinPoll : public IOPoll { -public: - WinPoll(); - ~WinPoll(); - - bool init(); - Result registerFd(SOCKET_FD fd, uint32_t events, IOCallback cb); - Result unregisterFd(SOCKET_FD fd); - Result updateFd(SOCKET_FD fd, uint32_t events); - Result wait(uint32_t wait_ms); - void notify(); - PollType getType() const { return PollType::WIN; } - bool isLevelTriggered() const { return false; } - -public: - void on_socket_notify(SOCKET_FD fd, uint32_t events); - - void on_poller_notify(); - -private: - uint32_t get_events(uint32_t kuma_events); - uint32_t get_kuma_events(uint32_t events); - void resizePollItems(SOCKET_FD fd); - -private: - HWND hwnd_; - PollItemVector poll_items_; -}; - -WinPoll::WinPoll() : hwnd_(NULL) {} - -WinPoll::~WinPoll() { - if (hwnd_) { - if (::IsWindow(hwnd_)) { - DestroyWindow(hwnd_); - } - hwnd_ = NULL; - } -} - -bool WinPoll::init() { - hwnd_ = ::CreateWindow(KM_WIN_CLASS_NAME, NULL, WS_OVERLAPPED, 0, 0, 0, 0, - NULL, NULL, NULL, 0); - if (NULL == hwnd_) { - return false; - } - SetWindowLong(hwnd_, 0, (LONG)this); - return true; -} - -uint32_t WinPoll::get_events(uint32_t kuma_events) { - uint32_t ev = 0; - if (kuma_events & kEventRead) { - ev |= FD_READ; - } - if (kuma_events & kEventWrite) { - ev |= FD_WRITE; - } - if (kuma_events & kEventError) { - ev |= FD_CLOSE; - } - return ev; -} - -uint32_t WinPoll::get_kuma_events(uint32_t events) { - uint32_t ev = 0; - if (events & FD_CONNECT) { // writeable - ev |= kEventWrite; - } - if (events & FD_ACCEPT) { // writeable - ev |= kEventRead; - } - if (events & FD_READ) { - ev |= kEventRead; - } - if (events & FD_WRITE) { - ev |= kEventWrite; - } - if (events & FD_CLOSE) { - ev |= kEventError; - } - return ev; -} - -void WinPoll::resizePollItems(SOCKET_FD fd) { - if (fd >= poll_items_.size()) { - poll_items_.resize(fd + 1); - } -} - -Result WinPoll::registerFd(SOCKET_FD fd, uint32_t events, IOCallback cb) { - KM_INFOTRACE("WinPoll::registerFd, fd=" << fd << ", events=" << events); - resizePollItems(fd); - poll_items_[fd].fd = fd; - poll_items_[fd].cb = std::move(cb); - WSAAsyncSelect(fd, hwnd_, WM_SOCKET_NOTIFY, - get_events(events) | FD_CONNECT); - return Result::OK; -} - -Result WinPoll::unregisterFd(SOCKET_FD fd) { - KM_INFOTRACE("WinPoll::unregisterFd, fd=" << fd); - SOCKET_FD max_fd = poll_items_.size() - 1; - if (fd < 0 || -1 == max_fd || fd > max_fd) { - KM_WARNTRACE("WinPoll::unregisterFd, failed, max_fd=" << max_fd); - return Result::INVALID_PARAM; - } - if (fd == max_fd) { - poll_items_.pop_back(); - } else { - poll_items_[fd].cb = nullptr; - poll_items_[fd].fd = INVALID_FD; - } - WSAAsyncSelect(fd, hwnd_, 0, 0); - return Result::OK; -} - -Result WinPoll::updateFd(SOCKET_FD fd, uint32_t events) { - SOCKET_FD max_fd = poll_items_.size() - 1; - if (fd < 0 || -1 == max_fd || fd > max_fd) { - KM_WARNTRACE("WinPoll::updateFd, failed, fd=" << fd - << ", max_fd=" << max_fd); - return Result::INVALID_PARAM; - } - if (poll_items_[fd].fd != fd) { - KM_WARNTRACE("WinPoll::updateFd, failed, fd=" << fd << ", fd1=" - << poll_items_[fd].fd); - return Result::INVALID_PARAM; - } - return Result::OK; -} - -Result WinPoll::wait(uint32_t wait_ms) { - MSG msg; - if (GetMessage(&msg, NULL, 0, 0)) { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - return Result::OK; -} - -void WinPoll::notify() { - if (hwnd_) { - ::PostMessage(hwnd_, WM_POLLER_NOTIFY, 0, 0); - } -} - -void WinPoll::on_socket_notify(SOCKET_FD fd, uint32_t events) { - int err = WSAGETSELECTERROR(events); - int evt = WSAGETSELECTEVENT(events); -} - -void WinPoll::on_poller_notify() {} - -IOPoll *createWinPoll() { return new WinPoll(); } - -////////////////////////////////////////////////////////////////////////// -// -LRESULT CALLBACK km_notify_wnd_proc(HWND hwnd, UINT uMsg, WPARAM wParam, - LPARAM lParam) { - switch (uMsg) { - case WM_SOCKET_NOTIFY: { - WinPoll *poll = (WinPoll *)GetWindowLong(hwnd, 0); - if (poll) - poll->on_socket_notify(wParam, lParam); - return 0L; - } - - case WM_POLLER_NOTIFY: { - WinPoll *poll = (WinPoll *)GetWindowLong(hwnd, 0); - if (poll) - poll->on_poller_notify(); - return 0L; - } - } - return DefWindowProc(hwnd, uMsg, wParam, lParam); -} - -static void initWinClass() { - WNDCLASS wc = {0}; - wc.style = 0; - wc.lpfnWndProc = (WNDPROC)km_notify_wnd_proc; - wc.cbClsExtra = 0; - wc.cbWndExtra = sizeof(void *); - wc.hInstance = NULL; - wc.hIcon = 0; - wc.hCursor = 0; - wc.hbrBackground = 0; - wc.lpszMenuName = NULL; - wc.lpszClassName = KM_WIN_CLASS_NAME; - RegisterClass(&wc); -} - -static void uninitWinClass() { UnregisterClass(KM_WIN_CLASS_NAME, NULL); } - -// WBX_Init_Object g_init_obj(poller_load, poller_unload); - -ATOM_NS_END diff --git a/src/atom/event/poll/event_notifier.hpp b/src/atom/event/poll/event_notifier.hpp deleted file mode 100644 index 767ceb0d..00000000 --- a/src/atom/event/poll/event_notifier.hpp +++ /dev/null @@ -1,73 +0,0 @@ -/* - * event_notifier.hpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2024-2-10 - -Description: EventNotifier - -**************************************************/ - -#ifndef __EventNotifier_HPP -#define __EventNotifier_HPP - -#include "notifier.hpp" -#include "utils/utils.hpp" - - -#include -#include - -ATOM_NS_BEGIN - -class EventNotifier : public Notifier { -public: - ~EventNotifier() { cleanup(); } - bool init() override { - cleanup(); - efd_ = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK); - return efd_ >= 0; - } - bool ready() override { return efd_ >= 0; } - void notify() override { - if (efd_ >= 0) { - // eventfd_write(efd_, 1); - ssize_t ret = 0; - do { - uint64_t count = 1; - ret = write(efd_, &count, sizeof(count)); - } while (ret < 0 && errno == EINTR); - } - } - - SOCKET_FD getReadFD() override { return efd_; } - - Result onEvent(KMEvent ev) override { - uint64_t count = 0; - ssize_t ret = 0; - do { - // eventfd_t val; - // eventfd_read(efd_, &val); - ret = read(efd_, &count, sizeof(count)); - } while (ret < 0 && errno == EINTR); - return Result::OK; - } - -private: - void cleanup() { - if (efd_ != -1) { - close(efd_); - efd_ = -1; - } - } - - int efd_{-1}; -}; - -ATOM_NS_END - -#endif diff --git a/src/atom/event/poll/iocp.cpp b/src/atom/event/poll/iocp.cpp deleted file mode 100644 index 6c49fddb..00000000 --- a/src/atom/event/poll/iocp.cpp +++ /dev/null @@ -1,159 +0,0 @@ -/* - * iocp.cpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2024-2-10 - -Description: IOCP poller for Windows - -**************************************************/ - -#include "iopoll.hpp" -#include "utils/kmtrace.hpp" -#include "utils/utils.hpp" - -ATOM_NS_BEGIN - -class IocpPoll : public IOPoll { -public: - IocpPoll(); - ~IocpPoll(); - - bool init(); - Result registerFd(SOCKET_FD fd, KMEvent events, IOCallback cb); - Result unregisterFd(SOCKET_FD fd); - Result updateFd(SOCKET_FD fd, KMEvent events); - Result wait(uint32_t wait_ms); - void notify(); - PollType getType() const { return PollType::IOCP; } - bool isLevelTriggered() const { return false; } - -protected: - HANDLE hCompPort_ = nullptr; -}; - -IocpPoll::IocpPoll() {} - -IocpPoll::~IocpPoll() { - if (hCompPort_) { - CloseHandle(hCompPort_); - hCompPort_ = nullptr; - } -} - -bool IocpPoll::init() { - if (hCompPort_) { - return true; - } - hCompPort_ = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 1); - if (!hCompPort_) { - KM_ERRTRACE("IocpPoll::init, CreateIoCompletionPort failed, err=" - << GetLastError()); - return false; - } - return true; -} - -Result IocpPoll::registerFd(SOCKET_FD fd, KMEvent events, IOCallback cb) { - KM_INFOTRACE("IocpPoll::registerFd, fd=" << fd << ", events=" << events); - if (CreateIoCompletionPort((HANDLE)fd, hCompPort_, (ULONG_PTR)fd, 0) == - NULL) { - return Result::POLL_ERROR; - } - resizePollItems(fd); - poll_items_[fd].fd = fd; - poll_items_[fd].cb = std::move(cb); - return Result::OK; -} - -Result IocpPoll::unregisterFd(SOCKET_FD fd) { - KM_INFOTRACE("IocpPoll::unregisterFd, fd=" << fd); - SOCKET_FD max_fd = poll_items_.size() - 1; - if (fd < 0 || -1 == max_fd || fd > max_fd) { - KM_WARNTRACE("IocpPoll::unregisterFd, failed, max_fd=" << max_fd); - return Result::INVALID_PARAM; - } - if (fd == max_fd) { - poll_items_.pop_back(); - } else { - poll_items_[fd].cb = nullptr; - poll_items_[fd].fd = INVALID_FD; - } - - return Result::OK; -} - -Result IocpPoll::updateFd(SOCKET_FD fd, KMEvent events) { - return Result::NOT_SUPPORTED; -} - -#if 1 -Result IocpPoll::wait(uint32_t wait_ms) { - OVERLAPPED_ENTRY entries[128]; - ULONG count = 0; - auto success = GetQueuedCompletionStatusEx( - hCompPort_, entries, ARRAY_SIZE(entries), &count, wait_ms, FALSE); - if (success) { - for (ULONG i = 0; i < count; ++i) { - if (entries[i].lpOverlapped) { - SOCKET_FD fd = (SOCKET_FD)entries[i].lpCompletionKey; - if (fd < poll_items_.size()) { - IOCallback &cb = poll_items_[fd].cb; - size_t io_size = entries[i].dwNumberOfBytesTransferred; - if (cb) - cb(fd, 0, entries[i].lpOverlapped, io_size); - } - } - } - } else { - auto err = ::GetLastError(); - if (err != WAIT_TIMEOUT) { - KM_ERRTRACE("IocpPoll::wait, err=" << err); - } - } - return Result::OK; -} -#else -Result IocpPoll::wait(uint32_t wait_ms) { - DWORD bytes; - ULONG_PTR key; - OVERLAPPED *pOverlapped = NULL; - auto success = GetQueuedCompletionStatus(hCompPort_, &bytes, &key, - &pOverlapped, wait_ms); - if (success) { - SOCKET_FD fd = (SOCKET_FD)key; - if (fd < poll_items_.size()) { - IOCallback &cb = poll_items_[fd].cb; - size_t io_size = bytes; - if (cb) - cb(fd, 0, pOverlapped, io_size); - } - } else { - auto err = ::GetLastError(); - if (NULL == pOverlapped) { // GetQueuedCompletionStatus() failed - if (err != WAIT_TIMEOUT) { - KM_ERRTRACE("IocpPoll::wait, err=" << err); - } - } else { // async IO failed - if (key) { - SOCKET_FD fd = (SOCKET_FD)key; - } - } - } - return Result::OK; -} -#endif - -void IocpPoll::notify() { - if (hCompPort_ != nullptr) { - PostQueuedCompletionStatus(hCompPort_, 0, 0, NULL); - } -} - -IOPoll *createIocpPoll() { return new IocpPoll(); } - -ATOM_NS_END diff --git a/src/atom/event/poll/iopoll.hpp b/src/atom/event/poll/iopoll.hpp deleted file mode 100644 index e1551e34..00000000 --- a/src/atom/event/poll/iopoll.hpp +++ /dev/null @@ -1,123 +0,0 @@ -/* - * iopoll.hpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2024-2-10 - -Description: IOPoll implementation - -**************************************************/ - -#ifndef __IOPoll_HPP -#define __IOPoll_HPP - -#include "kevdefs.hpp" - -#ifdef ATOM_OS_WIN -#include -#include -#include - -#elif defined(ATOM_OS_LINUX) -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#elif defined(ATOM_OS_MAC) -#include -#include -#include - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#else -#error "UNSUPPORTED OS" -#endif - -#include -#include -#include -#include -#include - - -#include -#include -#include - - -ATOM_NS_BEGIN - -struct PollItem { - void reset() { - fd = INVALID_FD; - idx = -1; - events = 0; - revents = 0; - cb = nullptr; - } - SOCKET_FD fd{INVALID_FD}; - int idx{-1}; - KMEvent events{0}; // kuma events registered - KMEvent revents{0}; // kuma events received - IOCallback cb; -}; -typedef std::vector PollItemVector; - -class IOPoll { -public: - virtual ~IOPoll() {} - - virtual bool init() = 0; - virtual Result registerFd(SOCKET_FD fd, KMEvent events, IOCallback cb) = 0; - virtual Result unregisterFd(SOCKET_FD fd) = 0; - virtual Result updateFd(SOCKET_FD fd, KMEvent events) = 0; - virtual Result wait(uint32_t wait_time_ms) = 0; - virtual void notify() = 0; - virtual PollType getType() const = 0; - virtual bool isLevelTriggered() const = 0; - -protected: - void resizePollItems(SOCKET_FD fd) { - auto count = poll_items_.size(); - if (fd >= count) { - if (fd > count + 1024) { - poll_items_.resize(fd + 1); - } else { - poll_items_.resize(count + 1024); - } - } - } - PollItemVector poll_items_; -}; - -ATOM_NS_END - -#endif diff --git a/src/atom/event/poll/notifier.hpp b/src/atom/event/poll/notifier.hpp deleted file mode 100644 index ae0d5d74..00000000 --- a/src/atom/event/poll/notifier.hpp +++ /dev/null @@ -1,40 +0,0 @@ -/* - * notifier.hpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2024-2-10 - -Description: Notifier - -**************************************************/ - -#ifndef __Notifier_HPP -#define __Notifier_HPP - -#include "kevdefs.hpp" - -#include - -ATOM_NS_BEGIN - -class Notifier { -public: - virtual ~Notifier() {} - virtual bool init() = 0; - virtual bool ready() = 0; - virtual void notify() = 0; - virtual SOCKET_FD getReadFD() = 0; - virtual Result onEvent(KMEvent ev) = 0; - - static std::unique_ptr createNotifier(); -}; - -using NotifierPtr = std::unique_ptr; - -ATOM_NS_END - -#endif diff --git a/src/atom/event/poll/pipe_notifier.hpp b/src/atom/event/poll/pipe_notifier.hpp deleted file mode 100644 index 3dfe23aa..00000000 --- a/src/atom/event/poll/pipe_notifier.hpp +++ /dev/null @@ -1,86 +0,0 @@ -/* - * pipe_notifier.hpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2024-2-10 - -Description: PipeNotifier for poll - -**************************************************/ - -#ifndef __PipeNotifier_HPP -#define __PipeNotifier_HPP - -#include "Notifier.h" -#include "utils/utils.h" - - -ATOM_NS_BEGIN - -class PipeNotifier : public Notifier { -public: - enum { READ_FD = 0, WRITE_FD }; - ~PipeNotifier() { cleanup(); } - bool init() override { - cleanup(); - if (::pipe(fds_) != 0) { - cleanup(); - return false; - } else { - ::fcntl(fds_[READ_FD], F_SETFL, O_RDONLY | O_NONBLOCK); - ::fcntl(fds_[WRITE_FD], F_SETFL, O_WRONLY | O_NONBLOCK); -#ifdef FD_CLOEXEC - ::fcntl(fds_[READ_FD], F_SETFD, - ::fcntl(fds_[READ_FD], F_GETFD) | FD_CLOEXEC); - ::fcntl(fds_[WRITE_FD], F_SETFD, - ::fcntl(fds_[WRITE_FD], F_GETFD) | FD_CLOEXEC); -#endif - return true; - } - } - bool ready() override { - return fds_[READ_FD] != INVALID_FD && fds_[WRITE_FD] != INVALID_FD; - } - void notify() override { - if (fds_[WRITE_FD] != INVALID_FD) { - ssize_t ret = 0; - do { - char c = 1; - ret = ::write(fds_[WRITE_FD], &c, sizeof(c)); - } while (ret < 0 && errno == EINTR); - } - } - - SOCKET_FD getReadFD() override { return fds_[READ_FD]; } - - Result onEvent(KMEvent ev) override { - char buf[1024]; - ssize_t ret = 0; - do { - ret = ::read(fds_[READ_FD], buf, sizeof(buf)); - } while (ret == sizeof(buf) || (ret < 0 && errno == EINTR)); - return Result::OK; - } - -private: - void cleanup() { - if (fds_[READ_FD] != INVALID_FD) { - ::close(fds_[READ_FD]); - fds_[READ_FD] = INVALID_FD; - } - if (fds_[WRITE_FD] != INVALID_FD) { - ::close(fds_[WRITE_FD]); - fds_[WRITE_FD] = INVALID_FD; - } - } - - SOCKET_FD fds_[2]{INVALID_FD, INVALID_FD}; -}; - -ATOM_NS_END - -#endif diff --git a/src/atom/event/poll/socket_notifier.hpp b/src/atom/event/poll/socket_notifier.hpp deleted file mode 100644 index bdd023ac..00000000 --- a/src/atom/event/poll/socket_notifier.hpp +++ /dev/null @@ -1,118 +0,0 @@ -/* - * socket_notifier.hpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2024-2-10 - -Description: Socket Notifier - -*************************************************/ - -#ifndef ATOM_EVENT_SOCKET_NOTIFIER_HPP -#define ATOM_EVENT_SOCKET_NOTIFIER_HPP - -#include "notifier.hpp" -#include "utils/defer.hpp" -#include "utils/skutils.hpp" -#include "utils/utils.hpp" - - -ATOM_NS_BEGIN - -class SocketNotifier : public Notifier { -public: - enum { READ_FD = 0, WRITE_FD }; - ~SocketNotifier() { cleanup(); } - bool init() override { - cleanup(); - - sockaddr_storage ss_addr{0}; - struct addrinfo hints = {0}; - hints.ai_family = AF_INET; - hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = AI_NUMERICHOST | AI_ADDRCONFIG; - if (km_set_sock_addr("127.0.0.1", 0, &hints, - (struct sockaddr *)&ss_addr, - sizeof(ss_addr)) != 0) { - return false; - } - auto lfd = ::socket(AF_INET, SOCK_STREAM, 0); - DEFER(SKUtils::close(lfd)); - if (::bind(lfd, (const sockaddr *)&ss_addr, sizeof(sockaddr_in)) != 0) { - return false; - } - socklen_t addr_len = sizeof(ss_addr); - if (::getsockname(lfd, (struct sockaddr *)&ss_addr, &addr_len) != 0) { - return false; - } - char ip[128] = {0}; - uint16_t port = 0; - km_get_sock_addr((struct sockaddr *)&ss_addr, addr_len, ip, sizeof(ip), - &port); - if (km_set_sock_addr("127.0.0.1", port, &hints, - (struct sockaddr *)&ss_addr, - sizeof(ss_addr)) != 0) { - return false; - } - if (::listen(lfd, 1) != 0) { - return false; - } - - fds_[WRITE_FD] = ::socket(AF_INET, SOCK_STREAM, 0); - if (::connect(fds_[WRITE_FD], (const sockaddr *)&ss_addr, - sizeof(sockaddr_in)) != 0) { - cleanup(); - return false; - } - fds_[READ_FD] = ::accept(lfd, NULL, NULL); - if (INVALID_FD == fds_[READ_FD]) { - cleanup(); - return false; - } - set_nonblocking(fds_[READ_FD]); - set_nonblocking(fds_[WRITE_FD]); - set_tcpnodelay(fds_[READ_FD]); - set_tcpnodelay(fds_[WRITE_FD]); - return true; - } - bool ready() override { - return fds_[READ_FD] != INVALID_FD && fds_[WRITE_FD] != INVALID_FD; - } - void notify() { - char c = 1; - SKUtils::send(fds_[WRITE_FD], &c, sizeof(c), 0); - } - - SOCKET_FD getReadFD() override { return fds_[READ_FD]; } - - Result onEvent(KMEvent ev) override { - char buf[1024]; - ssize_t ret = 0; - do { - ret = SKUtils::recv(fds_[READ_FD], buf, sizeof(buf), 0); - } while (ret == sizeof(buf)); - return Result::OK; - } - -private: - void cleanup() { - if (fds_[READ_FD] != INVALID_FD) { - SKUtils::close(fds_[READ_FD]); - fds_[READ_FD] = INVALID_FD; - } - if (fds_[WRITE_FD] != INVALID_FD) { - SKUtils::close(fds_[WRITE_FD]); - fds_[WRITE_FD] = INVALID_FD; - } - } - - SOCKET_FD fds_[2]{INVALID_FD, INVALID_FD}; -}; - -ATOM_NS_END - -#endif diff --git a/src/atom/event/timer.cpp b/src/atom/event/timer.cpp deleted file mode 100644 index 233ef3fa..00000000 --- a/src/atom/event/timer.cpp +++ /dev/null @@ -1,430 +0,0 @@ -/* - * timer.cpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2024-2-11 - -Description: Timer manager. - -**************************************************/ - -#include "timer.hpp" -#include "eventloop.hpp" - -#include -#include - -ATOM_NS_USING - -ATOM_NS_BEGIN - -int find_first_set(unsigned int b); -TICK_COUNT_TYPE get_tick_count_ms(); -TICK_COUNT_TYPE calc_time_elapse_delta_ms(TICK_COUNT_TYPE now_tick, - TICK_COUNT_TYPE &start_tick); - -ATOM_NS_END - -////////////////////////////////////////////////////////////////////////// -// Timer::Impl -Timer::Impl::Impl(TimerManager::Ptr mgr) : timer_mgr_(mgr) {} - -Timer::Impl::~Impl() { cancel(); } - -bool Timer::Impl::schedule(uint32_t delay_ms, Mode mode, TimerCallback cb) { - auto mgr = timer_mgr_.lock(); - if (mgr) { - return mgr->scheduleTimer(&timer_node_, delay_ms, mode, std::move(cb)); - } - return false; -} - -void Timer::Impl::cancel() { - auto mgr = timer_mgr_.lock(); - if (mgr) { - mgr->cancelTimer(&timer_node_); - } -} - -////////////////////////////////////////////////////////////////////////// -// TimerManager -TimerManager::TimerManager(EventLoop::Impl *loop) : loop_(loop) { - memset(&tv0_bitmap_, 0, sizeof(tv0_bitmap_)); - for (int i = 0; i < TV_COUNT; ++i) { - for (int j = 0; j < TIMER_VECTOR_SIZE; ++j) { - list_init_head(&tv_[i][j]); - } - } -} - -TimerManager::~TimerManager() { - std::vector timer_cbs; // hold timer cb temporarily - std::lock_guard g(mutex_); - for (int i = 0; i < TV_COUNT && timer_count_ > 0; ++i) { - for (int j = 0; j < TIMER_VECTOR_SIZE && timer_count_ > 0; ++j) { - while (!list_empty(&tv_[i][j])) { - auto *timer_node = tv_[i][j].next_; - list_remove_node(timer_node); - timer_cbs.emplace_back(timer_node->cancel()); - --timer_count_; - } - } - } -} - -bool TimerManager::scheduleTimer(TimerNode *timer_node, uint32_t delay_ms, - Timer::Mode mode, TimerCallback cb) { - if (isTimerPending(timer_node) && delay_ms == timer_node->delay_ms_) { - return true; - } - TICK_COUNT_TYPE now_tick = get_tick_count_ms(); - bool need_notify = false; - bool ret = false; - { - std::unique_lock ul(mutex_); - timer_node->cancelled_ = false; - /*if (timer_node == running_node_ && !loop_->inSameThread()) { - // timer is running, user may reschedule the timer in callback - if(reschedule_node_ == timer_node) { - reschedule_node_ = nullptr; - } - ul.unlock(); - running_mutex_.lock(); - if(running_node_ == timer_node) { - running_node_ = nullptr; - } - running_mutex_.unlock(); - ul.lock(); - if (timer_node->cancelled_) { - // timer is cancelled in callback - return false; - } - }*/ - if (isTimerPending(timer_node)) { - removeTimer(timer_node); - } - if (reschedule_node_ == timer_node) { - reschedule_node_ = nullptr; - } - timer_node->start_tick_ = now_tick; - timer_node->delay_ms_ = delay_ms; - timer_node->repeating_ = mode == Timer::Mode::REPEATING; - timer_node->cb_ = std::move(cb); - - ret = addTimer(timer_node, FROM_SCHEDULE); - long diff = long(now_tick - last_tick_); - if (last_remain_ms_ == -1 || - (diff >= 0 && delay_ms < last_remain_ms_ - diff)) { - // need update poll wait time - need_notify = !loop_->inSameThread(); - } - } - if (need_notify) { - loop_->wakeup(); - } - return ret; -} - -void TimerManager::cancelTimer(TimerNode *timer_node) { - if (timer_node->cancelled_) { - return; - } - timer_node->cancelled_ = true; - - TimerCallback timer_cb; // hold timer cb temporarily - { - std::unique_lock ul(mutex_); - if (running_node_ == timer_node && !loop_->inSameThread()) { - if (reschedule_node_ == timer_node) { - reschedule_node_ = nullptr; - } - ul.unlock(); - running_mutex_.lock(); - if (running_node_ == timer_node) { - running_node_ = nullptr; - } - running_mutex_.unlock(); - ul.lock(); - } - if (isTimerPending(timer_node)) { - removeTimer(timer_node); - } - if (reschedule_node_ == timer_node) { - reschedule_node_ = nullptr; - } - timer_cb = timer_node->cancel(); - } -} - -void TimerManager::list_init_head(TimerNode *head) { - head->next_ = head; - head->prev_ = head; -} - -void TimerManager::list_add_node(TimerNode *head, TimerNode *timer_node) { - head->prev_->next_ = timer_node; - timer_node->prev_ = head->prev_; - timer_node->next_ = head; - head->prev_ = timer_node; -} - -void TimerManager::list_remove_node(TimerNode *timer_node) { - timer_node->prev_->next_ = timer_node->next_; - timer_node->next_->prev_ = timer_node->prev_; - timer_node->resetNode(); -} - -void TimerManager::list_replace(TimerNode *old_head, TimerNode *new_head) { - new_head->next_ = old_head->next_; - new_head->next_->prev_ = new_head; - new_head->prev_ = old_head->prev_; - new_head->prev_->next_ = new_head; - list_init_head(old_head); -} - -void TimerManager::list_combine(TimerNode *from_head, TimerNode *to_head) { - if (from_head->next_ == from_head) { - return; - } - to_head->prev_->next_ = from_head->next_; - from_head->next_->prev_ = to_head->prev_; - from_head->prev_->next_ = to_head; - to_head->prev_ = from_head->prev_; - list_init_head(from_head); -} - -bool TimerManager::list_empty(TimerNode *head) { return head->next_ == head; } - -void TimerManager::set_tv0_bitmap(int idx) { - unsigned char a = (unsigned char)(idx / (sizeof(tv0_bitmap_[0]) * 8)); - unsigned char b = (unsigned char)(idx % (sizeof(tv0_bitmap_[0]) * 8)); - tv0_bitmap_[a] |= 1 << b; -} - -void TimerManager::clear_tv0_bitmap(int idx) { - unsigned char a = (unsigned char)(idx / (sizeof(tv0_bitmap_[0]) * 8)); - unsigned char b = (unsigned char)(idx % (sizeof(tv0_bitmap_[0]) * 8)); - tv0_bitmap_[a] &= ~(1 << b); -} - -int TimerManager::find_first_set_in_bitmap(int idx) { - unsigned char a = (unsigned char)(idx / (sizeof(tv0_bitmap_[0]) * 8)); - unsigned char b = (unsigned char)(idx % (sizeof(tv0_bitmap_[0]) * 8)); - int pos = -1; - pos = find_first_set(tv0_bitmap_[a] >> b); - if (-1 == pos) { - int i = a + 1; - for (i &= 7; i != a; ++i, i &= 7) { - pos = find_first_set(tv0_bitmap_[i]); - if (-1 == pos) { - continue; - } - if (i < a) { - i += 8; - } - pos += (i - a - 1) * 32; - pos += 32 - b; - break; - } - } - if (-1 == pos && b > 0) { - unsigned int bits = (tv0_bitmap_[a] << (32 - b)) >> (32 - b); - pos = find_first_set(bits); - if (pos >= 0) { - pos += 256 - b; - } - } - return pos; -} - -bool TimerManager::addTimer(TimerNode *timer_node, FROM from) { - if (0 == timer_count_ && FROM_SCHEDULE == from) { - last_tick_ = timer_node->start_tick_; - } - TICK_COUNT_TYPE fire_tick = timer_node->delay_ms_ + timer_node->start_tick_; - if (fire_tick - last_tick_ > (((TICK_COUNT_TYPE)-1) >> 1)) // time backward - { // fire it right now - fire_tick = last_tick_; - } - if (fire_tick == last_tick_) { - ++fire_tick; // = next_jiffies - } - TICK_COUNT_TYPE elapse_jiffies = fire_tick - last_tick_; - TICK_COUNT_TYPE fire_jiffies = fire_tick; - TimerNode *head; - if (elapse_jiffies < TIMER_VECTOR_SIZE) { - int i = fire_jiffies & TIMER_VECTOR_MASK; - head = &tv_[0][i]; - set_tv0_bitmap(i); - timer_node->tv_index_ = 0; - timer_node->tl_index_ = i; - } else if (elapse_jiffies < 1 << (2 * TIMER_VECTOR_BITS)) { - int i = (fire_jiffies >> TIMER_VECTOR_BITS) & TIMER_VECTOR_MASK; - head = &tv_[1][i]; - timer_node->tv_index_ = 1; - timer_node->tl_index_ = i; - } else if (elapse_jiffies < 1 << (3 * TIMER_VECTOR_BITS)) { - int i = (fire_jiffies >> (2 * TIMER_VECTOR_BITS)) & TIMER_VECTOR_MASK; - head = &tv_[2][i]; - timer_node->tv_index_ = 2; - timer_node->tl_index_ = i; - } else if (elapse_jiffies <= 0xFFFFFFFF) { - int i = (fire_jiffies >> (3 * TIMER_VECTOR_BITS)) & TIMER_VECTOR_MASK; - head = &tv_[3][i]; - timer_node->tv_index_ = 3; - timer_node->tl_index_ = i; - } else { // don't support elapse larger than 0xffffffff - // printf("add_timer, failed, elapse=%lu, start_tick=%lu, - // last_tick=%lu\n", timer_node->elapse, timer_node->start_tick, - // last_tick_); - return false; - } - list_add_node(head, timer_node); - if (FROM_SCHEDULE == from || FROM_RESCHEDULE == from) { - ++timer_count_; - } - return true; -} - -void TimerManager::removeTimer(TimerNode *timer_node) { - if (0 == timer_node->tv_index_ && timer_node->next_ != timer_node && - timer_node->next_ == timer_node->prev_ && - timer_node->next_ == &tv_[0][timer_node->tl_index_]) { - clear_tv0_bitmap(timer_node->tl_index_); - } - list_remove_node(timer_node); - if (--timer_count_ == 0) { - last_remain_ms_ = -1; - } -} - -int TimerManager::cascadeTimer(int tv_idx, int tl_idx) { - TimerNode tmp_head; - list_init_head(&tmp_head); - list_replace(&tv_[tv_idx][tl_idx], &tmp_head); - TimerNode *next_node = tmp_head.next_; - TimerNode *tmp_node = nullptr; - while (next_node != &tmp_head) { - tmp_node = next_node; - next_node = next_node->next_; - addTimer(tmp_node, FROM_CASCADE); - } - - return tl_idx; -} - -#define JIFFIES_COMPARE(j1, j2) std::make_signed::type(j1 - j2) -#define INDEX(N) \ - ((next_jiffies >> ((N + 1) * TIMER_VECTOR_BITS)) & TIMER_VECTOR_MASK) -int TimerManager::checkExpire(unsigned long *remain_ms) { - if (0 == timer_count_) { - last_remain_ms_ = -1; - *remain_ms = last_remain_ms_; - return 0; - } - TICK_COUNT_TYPE now_tick = get_tick_count_ms(); - TICK_COUNT_TYPE delta_tick = - calc_time_elapse_delta_ms(now_tick, last_tick_); - if (0 == delta_tick) { - if (remain_ms) { - if (last_remain_ms_ != -1 && last_remain_ms_ != 0) { - *remain_ms = last_remain_ms_; - } else { - // calc remain time in ms - mutex_.lock(); - int pos = - find_first_set_in_bitmap(now_tick & TIMER_VECTOR_MASK); - mutex_.unlock(); - *remain_ms = -1 == pos ? 256 : pos; - last_remain_ms_ = *remain_ms; - } - } - return 0; - } - TICK_COUNT_TYPE cur_jiffies = now_tick; - TICK_COUNT_TYPE next_jiffies = last_tick_ + 1; - last_tick_ = now_tick; - TICK_COUNT_TYPE last_tick = now_tick; - TimerNode tmp_head; - list_init_head(&tmp_head); - std::vector timer_cbs; // hold timer cb temporarily - mutex_.lock(); - while (JIFFIES_COMPARE(cur_jiffies, next_jiffies) >= 0) { - int idx = next_jiffies & TIMER_VECTOR_MASK; -#if 1 - int delta = 0; - if (0 != idx && (delta = find_first_set_in_bitmap(idx)) != 0) { - if (-1 == delta || - ((idx + delta) & TIMER_VECTOR_MASK) < idx) { // run over 0 - delta = - TIMER_VECTOR_SIZE - idx; // need cascade timer when index 0 - } - idx += delta; - idx &= TIMER_VECTOR_MASK; - next_jiffies += delta; - if (JIFFIES_COMPARE(next_jiffies, cur_jiffies) > 0) { - next_jiffies = cur_jiffies + 1; - break; - } - } -#endif - ++next_jiffies; - if (!idx && (!cascadeTimer(1, INDEX(0))) && - (!cascadeTimer(2, INDEX(1)))) { - cascadeTimer(3, INDEX(2)); - } - list_combine(&tv_[0][idx], &tmp_head); - clear_tv0_bitmap(idx); - } - - int count = 0; - while (!list_empty(&tmp_head)) { - reschedule_node_ = tmp_head.next_; - running_node_ = reschedule_node_; - list_remove_node(reschedule_node_); - --timer_count_; - mutex_.unlock(); // sync nodes in tmp_list with cancel_timer. - - running_mutex_.lock(); - if (running_node_) { - (*running_node_)(); - running_node_ = nullptr; - ++count; - } - running_mutex_.unlock(); - - mutex_.lock(); - if (reschedule_node_) { - if (reschedule_node_->repeating_ && !reschedule_node_->cancelled_) { - reschedule_node_->start_tick_ = now_tick; - addTimer(reschedule_node_, FROM_RESCHEDULE); - } else { - timer_cbs.emplace_back(reschedule_node_->cancel()); - } - reschedule_node_ = nullptr; - } - } - - if (remain_ms) { - // calc remain time in ms - int pos = find_first_set_in_bitmap(cur_jiffies & TIMER_VECTOR_MASK); - *remain_ms = -1 == pos ? 256 : pos; - } - - mutex_.unlock(); - if (remain_ms) { // revise the remain time - now_tick = get_tick_count_ms(); - delta_tick = calc_time_elapse_delta_ms(now_tick, last_tick); - if (*remain_ms <= delta_tick) { - *remain_ms = 0; - } else { - *remain_ms -= (unsigned long)delta_tick; - } - last_remain_ms_ = *remain_ms; - } - return count; -} diff --git a/src/atom/event/timer.hpp b/src/atom/event/timer.hpp deleted file mode 100644 index 88e047f1..00000000 --- a/src/atom/event/timer.hpp +++ /dev/null @@ -1,163 +0,0 @@ -/* - * timer.hpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2024-2-11 - -Description: Timer manager. - -**************************************************/ - -#ifndef ATOM_EVENT_TIMER_HPP -#define ATOM_EVENT_TIMER_HPP - -#include "kev.hpp" -#include "kevdefs.hpp" - - -#include -#include -#include -#include - - -#ifndef TICK_COUNT_TYPE -#define TICK_COUNT_TYPE uint64_t -#endif - -ATOM_NS_BEGIN - -#define TIMER_VECTOR_BITS 8 -#define TIMER_VECTOR_SIZE (1 << TIMER_VECTOR_BITS) -#define TIMER_VECTOR_MASK (TIMER_VECTOR_SIZE - 1) -#define TV_COUNT 4 - -class TimerManager { -public: - using Ptr = std::shared_ptr; - using TimerCallback = std::function; - class TimerNode; - - TimerManager(EventLoop::Impl *loop); - ~TimerManager(); - - bool scheduleTimer(TimerNode *timer, uint32_t delay_ms, Timer::Mode mode, - TimerCallback cb); - void cancelTimer(TimerNode *timer); - - int checkExpire(unsigned long *remain_ms = nullptr); - -public: - class TimerNode { - public: - TimerNode() = default; - TimerNode(const TimerNode &) = delete; - TimerNode(TimerNode &&other) = delete; - TimerNode &operator=(const TimerNode &other) = delete; - TimerNode &operator=(TimerNode &&other) = delete; - void operator()() { - if (!cancelled_ && cb_) { - cb_(); - } - } - void resetNode() { - tv_index_ = -1; - tl_index_ = -1; - prev_ = nullptr; - next_ = nullptr; - } - auto cancel() { - cancelled_ = true; - // NOTE: this TimerNode object may be destroyed when cb_ is reset - return std::exchange(cb_, nullptr); - } - - std::atomic cancelled_{true}; - bool repeating_{false}; - uint32_t delay_ms_{0}; - TICK_COUNT_TYPE start_tick_{0}; - // NOTE: timer callback will be reset after timer cancelled or executed, - // or when TimerManager destructed - // NOTE: the TimerNode may be destroyed when TimerCallback is reset, - // for example, the DealyedTaskSlotPtr is stored in TimerCallback - // and will be destroyed when TimerCallback is reset - // NOTE: must not destruct the cb_ under lock of TimerManager::mutex_, - // since its destruction may result to another timer to be - // cancelled - TimerCallback cb_; - - protected: - friend class TimerManager; - int tv_index_{-1}; - int tl_index_{-1}; - TimerNode *prev_{nullptr}; - TimerNode *next_{nullptr}; - }; - -private: - typedef enum { FROM_SCHEDULE, FROM_CASCADE, FROM_RESCHEDULE } FROM; - bool addTimer(TimerNode *timer_node, FROM from); - void removeTimer(TimerNode *timer_node); - int cascadeTimer(int tv_idx, int tl_idx); - bool isTimerPending(TimerNode *timer_node) { - return timer_node->next_ != nullptr; - } - - void list_init_head(TimerNode *head); - void list_add_node(TimerNode *head, TimerNode *timer_node); - void list_remove_node(TimerNode *timer_node); - void list_replace(TimerNode *old_head, TimerNode *new_head); - void list_combine(TimerNode *from_head, TimerNode *to_head); - bool list_empty(TimerNode *head); - - void set_tv0_bitmap(int idx); - void clear_tv0_bitmap(int idx); - int find_first_set_in_bitmap(int idx); - -private: - EventLoop::Impl *loop_; - std::mutex mutex_; - std::mutex running_mutex_; - TimerNode *running_node_{nullptr}; - TimerNode *reschedule_node_{nullptr}; - unsigned long last_remain_ms_ = -1; - TICK_COUNT_TYPE last_tick_{0}; - uint32_t timer_count_{0}; - uint32_t tv0_bitmap_[8]; // 1 -- have timer in this slot - TimerNode tv_[TV_COUNT][TIMER_VECTOR_SIZE]; // timer vectors -}; - -class Timer::Impl { -public: - using TimerCallback = Timer::TimerCallback; - - Impl(TimerManager::Ptr mgr); - Impl(const Impl &other) = delete; - Impl(Impl &&other) = delete; - ~Impl(); - - Impl &operator=(const Impl &other) = delete; - Impl &operator=(Impl &&other) = delete; - - template {}, int> = 0> - bool schedule(uint32_t delay_ms, Mode mode, F &&f) { - lambda_wrapper wf{std::forward(f)}; - return schedule(delay_ms, mode, TimerCallback(std::move(wf))); - } - bool schedule(uint32_t delay_ms, Mode mode, TimerCallback cb); - void cancel(); - -private: - friend class TimerManager; - std::weak_ptr timer_mgr_; - TimerManager::TimerNode timer_node_; // intrusive list node -}; - -ATOM_NS_END - -#endif diff --git a/src/atom/event/utils/defer.hpp b/src/atom/event/utils/defer.hpp deleted file mode 100644 index cfc34f39..00000000 --- a/src/atom/event/utils/defer.hpp +++ /dev/null @@ -1,54 +0,0 @@ -/* - * defer.hpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2024-2-10 - -Description: Defer Exec - -*************************************************/ - -#pragma once - -#include -#include - -namespace Atom::Event { -template -class DeferExec final { -public: - DeferExec(Callable c) : c_(std::move(c)), canceled_(false) {} - DeferExec(DeferExec &&other) noexcept - : c_(std::move(other.c_)), canceled_(other.canceled_) { - other.canceled_ = true; - } - ~DeferExec() { - if (!canceled_) { - c_(); - } - } - - DeferExec(const DeferExec &) = delete; - DeferExec &operator=(const DeferExec &) = delete; - - void cancel() { canceled_ = true; } - -private: - Callable c_; - bool canceled_; -}; - -template -DeferExec make_defer(Callable c) { - return {std::move(c)}; -} -} // namespace Atom::Event - -#define CONCAT_XY(x, y) x##y -#define MAKE_DEFER(r, l) \ - auto CONCAT_XY(defer_exec_, l) = Atom::Event::make_defer([&]() { r; }) -#define DEFER(r) MAKE_DEFER(r, __LINE__) diff --git a/src/atom/event/utils/destroy_detector.hpp b/src/atom/event/utils/destroy_detector.hpp deleted file mode 100644 index 27174559..00000000 --- a/src/atom/event/utils/destroy_detector.hpp +++ /dev/null @@ -1,72 +0,0 @@ -/* - * destroy_detector.hpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2024-2-10 - -Description: Destroy Detector - -*************************************************/ - -#ifndef ATOM_EVENT_DESTRORY_DETECTOR_HPP -#define ATOM_EVENT_DESTRORY_DETECTOR_HPP - -#include -#include -#include - -namespace Atom::Event { -class DestroyDetector { -public: - virtual ~DestroyDetector() { - for (auto &c : checkers_) { - c->destroyed_ = true; - } - } - - class Checker final { - public: - Checker() = default; - Checker(DestroyDetector *dd) { - auto it = - std::find(dd->checkers_.begin(), dd->checkers_.end(), this); - if (it == dd->checkers_.end()) { - dd->checkers_.push_back(this); - } - } - ~Checker() { - auto it = - std::find(dd_->checkers_.begin(), dd_->checkers_.end(), this); - if (it != dd_->checkers_.end()) { - dd_->checkers_.erase(it); - } - } - bool isDestroyed() const { return destroyed_; } - - private: - friend class DestroyDetector; - - DestroyDetector *dd_ = nullptr; - bool destroyed_ = false; - }; - -protected: - std::vector checkers_; -}; - -#define DESTROY_DETECTOR_SETUP() \ - Atom::Event::DestroyDetector::Checker __dd_check(this); - -#define DESTROY_DETECTOR_CHECK(ret) \ - if (__dd_check.isDestroyed()) \ - return ret; - -#define DESTROY_DETECTOR_CHECK_VOID() DESTROY_DETECTOR_CHECK((void())) - -} // namespace Atom::Event - -#endif /* ATOM_EVENT_DESTRORY_DETECTOR */ diff --git a/src/atom/event/utils/kmobject.hpp b/src/atom/event/utils/kmobject.hpp deleted file mode 100644 index 70185857..00000000 --- a/src/atom/event/utils/kmobject.hpp +++ /dev/null @@ -1,48 +0,0 @@ -/* - * kmobject.hpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2024-2-10 - -Description: KMObject - -*************************************************/ - -#ifndef ATOM_EVENT_OBJECT_HPP -#define ATOM_EVENT_OBJECT_HPP - -#include -#include -#include - -namespace Atom::Event { -class KMObject { -public: - KMObject() { - static std::atomic s_objIdSeed{0}; - objId_ = ++s_objIdSeed; - } - - const std::string &getObjKey() const { return objKey_; } - - long getObjId() const { return objId_; } - -protected: - std::string objKey_; - long objId_ = 0; -}; - -#define KM_SetObjKey(x) \ - do { \ - std::stringstream ss; \ - ss << x << "_" << objId_; \ - objKey_ = ss.str(); \ - } while (0) - -} // namespace Atom::Event - -#endif /* ATOM_EVENT_OBJECT_HPP */ diff --git a/src/atom/event/utils/kmqueue.hpp b/src/atom/event/utils/kmqueue.hpp deleted file mode 100644 index a4eae837..00000000 --- a/src/atom/event/utils/kmqueue.hpp +++ /dev/null @@ -1,223 +0,0 @@ -/* - * kmqueue.hpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2024-2-10 - -Description: Memory Queue - -*************************************************/ - -#pragma once - -#include -#include - -namespace Atom::Event { - -const size_t kPaddingSize = 128; -/// -// enqueue on a thread and dequene on another thread -/// -template -class KMQueue { -public: - KMQueue() { - head_ = new TLNode(); - tail_ = head_; - } - ~KMQueue() { - TLNode *node = nullptr; - while (head_) { - node = head_; - head_ = head_->next_.load(std::memory_order_relaxed); - delete node; - } - } - - template - void enqueue(Args &&...args) { - TLNode *node = new TLNode(std::forward(args)...); - tail_->next_.store(node, std::memory_order_release); - tail_ = node; - ++count_; - } - - bool dequeue(E &element) { - auto *node = head_->next_.load(std::memory_order_acquire); - if (node == nullptr) { - return false; - } - --count_; - element = std::move(node->element_); - delete head_; - head_ = node; - return true; - } - - E &front() { - auto *node = head_->next_.load(std::memory_order_acquire); - if (node == nullptr) { - static E E_empty{}; - return E_empty; - } - return node->element_; - } - - void pop_front() { - auto *node = head_->next_.load(std::memory_order_acquire); - if (node != nullptr) { - --count_; - delete head_; - head_ = node; - } - } - - bool empty() { return size() == 0; } - - size_t size() { return count_.load(std::memory_order_relaxed); } - -protected: - class TLNode { - public: - template - TLNode(Args &&...args) : element_{std::forward(args)...} {} - - E element_; - std::atomic next_{nullptr}; - }; - - TLNode *head_{nullptr}; - char __pad0__[kPaddingSize - sizeof(TLNode *)]; - TLNode *tail_{nullptr}; - char __pad1__[kPaddingSize - sizeof(TLNode *)]; - std::atomic count_{0}; -}; - -// double linked list -template -class DLQueue final { -public: - class DLNode { - public: - using Ptr = std::shared_ptr; - - template - DLNode(Args &&...args) : element_{std::forward(args)...} {} - E &element() { return element_; } - bool isLinked() const { return linked_; } - - private: - friend class DLQueue; - E element_; - bool linked_{false}; - Ptr prev_; - Ptr next_; - }; - using NodePtr = typename DLNode::Ptr; - -public: - ~DLQueue() { - while (head_) { - head_->linked_ = false; - head_ = head_->next_; - } - } - - template - NodePtr enqueue(Args &&...args) { - auto node = std::make_shared(std::forward(args)...); - return enqueue(node); - } - - NodePtr enqueue(NodePtr &node) { - if (empty()) { - head_ = node; - } else { - tail_->next_ = node; - node->prev_ = tail_; - } - tail_ = node; - node->linked_ = true; - ++count_; - return node; - } - - bool dequeue(E &element) { - if (empty()) { - return false; - } - element = std::move(head_->element_); - pop_front(); - return true; - } - - E &front() { - if (empty()) { - static E E_empty{}; - return E_empty; - } - return head_->element_; - } - - NodePtr &front_node() { return head_; } - - void pop_front() { - if (!empty()) { - head_->linked_ = false; - if (head_->next_) { - head_ = head_->next_; - head_->prev_->next_.reset(); - head_->prev_.reset(); - } else { - head_.reset(); - tail_.reset(); - } - --count_; - } - } - - bool remove(const NodePtr &node) { // make sure the node is in this queue - if (!node || (!node->prev_ && !node->next_ && node != head_)) { - return false; - } - if (node->next_) { - node->next_->prev_ = node->prev_; - } else if (tail_ == node) { - tail_ = node->prev_; - } - if (node->prev_) { - node->prev_->next_ = node->next_; - } else if (head_ == node) { - head_ = node->next_; - } - node->next_.reset(); - node->prev_.reset(); - node->linked_ = false; - --count_; - return true; - } - - bool empty() { return !head_; } - - size_t size() { return count_.load(std::memory_order_relaxed); } - - void swap(DLQueue &other) { - head_.swap(other.head_); - tail_.swap(other.tail_); - auto c = count_.exchange(other.count_.load(std::memory_order_relaxed), - std::memory_order_relaxed); - other.count_.exchange(c, std::memory_order_relaxed); - } - -protected: - NodePtr head_; - NodePtr tail_; - std::atomic count_{0}; -}; - -} // namespace Atom::Event diff --git a/src/atom/event/utils/kmtrace.cpp b/src/atom/event/utils/kmtrace.cpp deleted file mode 100644 index b139d269..00000000 --- a/src/atom/event/utils/kmtrace.cpp +++ /dev/null @@ -1,165 +0,0 @@ -/* - * kmtrace.cpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2024-2-10 - -Description: Trace Destroy Detector - -*************************************************/ - -#include "kmtrace.hpp" - -#include -#include -#include -#include -#include -#include -#include - -#ifdef ATOM_OS_WIN -#include -#elif defined(ATOM_OS_LINUX) -#include -#include -#if !defined(ATOM_OS_ANDROID) -#include -#endif -#endif - -#ifdef ATOM_OS_WIN -#define getCurrentThreadId() GetCurrentThreadId() -#define vsnprintf(d, dl, fmt, ...) \ - _vsnprintf_s(d, dl, _TRUNCATE, fmt, ##__VA_ARGS__) -#elif defined(ATOM_OS_MAC) -#define getCurrentThreadId() pthread_mach_thread_np(pthread_self()) -#elif defined(ATOM_OS_ANDROID) -#define getCurrentThreadId() gettid() -#elif defined(ATOM_OS_LINUX) -#define getCurrentThreadId() syscall(__NR_gettid) -#else -#define getCurrentThreadId() pthread_self() -#endif - -#ifdef ATOM_OS_ANDROID -#include -#endif - -#define ATOM_TRACE_TAG "KEV" - -namespace { -std::string getDateTimeString(bool utc) { - auto now = std::chrono::system_clock::now(); - auto msecs = std::chrono::duration_cast( - now.time_since_epoch()) - .count() % - 1000; - auto itt = std::chrono::system_clock::to_time_t(now); - struct tm res; -#ifdef ATOM_OS_WIN - utc ? gmtime_s(&res, &itt) : localtime_s(&res, &itt); // windows and C11 -#else - utc ? gmtime_r(&itt, &res) : localtime_r(&itt, &res); -#endif - std::ostringstream ss; - ss << std::put_time(&res, "%FT%T.") << std::setfill('0') << std::setw(3) - << msecs; - if (utc) { - ss << 'Z'; - } else { - ss << std::put_time(&res, "%z"); - } - return ss.str(); -} -} // namespace - -namespace Atom::Event { - -static TraceFunc s_traceFunc = nullptr; -static int s_traceLevel = TRACE_LEVEL_INFO; - -const char *kTraceStrings[] = {"NONE", "ERROR", "WARN", - "INFO", "DEBUG", "VERBOS"}; - -#ifdef ATOM_OS_ANDROID -const int kAndroidLogLevels[] = {ANDROID_LOG_INFO, ANDROID_LOG_ERROR, - ANDROID_LOG_WARN, ANDROID_LOG_INFO, - ANDROID_LOG_DEBUG, ANDROID_LOG_VERBOSE}; -#endif - -void tracePrint(int level, const char *szMessage, ...) { - va_list VAList; - char szMsgBuf[2048] = {0}; - va_start(VAList, szMessage); - vsnprintf(szMsgBuf, sizeof(szMsgBuf) - 1, szMessage, VAList); - - if (level > TRACE_LEVEL_MAX) { - level = TRACE_LEVEL_MAX; - } else if (level < TRACE_LEVEL_ERROR) { - level = TRACE_LEVEL_ERROR; - } - -#if defined(ATOM_OS_ANDROID) - int android_level = kAndroidLogLevels[level]; - __android_log_print(android_level, ATOM_TRACE_TAG, "%s", szMsgBuf); -#else - std::stringstream ss; - ss << kTraceStrings[level]; - ss << " [" << getCurrentThreadId() << "] " << szMsgBuf << '\n'; -#if defined(ATOM_OS_WIN) - OutputDebugStringA(ss.str().c_str()); -#else - printf("%s, %s", getDateTimeString(false).c_str(), ss.str().c_str()); -#endif -#endif -} - -void printTrace(int level, const std::string &msg) { - if (level > TRACE_LEVEL_MAX) { - level = TRACE_LEVEL_MAX; - } else if (level < TRACE_LEVEL_ERROR) { - level = TRACE_LEVEL_ERROR; - } -#if defined(ATOM_OS_ANDROID) - int android_level = kAndroidLogLevels[level]; - __android_log_print(android_level, ATOM_TRACE_TAG, "%s", msg.c_str()); -#else - std::stringstream ss; - ss << kTraceStrings[level]; - ss << " [" << getCurrentThreadId() << "] " << msg << '\n'; -#if defined(ATOM_OS_WIN) - OutputDebugStringA(ss.str().c_str()); -#else - printf("%s %s", getDateTimeString(false).c_str(), ss.str().c_str()); -#endif -#endif -} - -void traceWrite(int level, const std::string &msg) { - if (s_traceFunc) { - s_traceFunc(level, std::string(msg)); - } else { - printTrace(level, msg); - } -} - -void traceWrite(int level, std::string &&msg) { - if (s_traceFunc) { - s_traceFunc(level, std::move(msg)); - } else { - printTrace(level, msg); - } -} - -void setTraceFunc(TraceFunc func) { s_traceFunc = std::move(func); } - -void setTraceLevel(int level) { s_traceLevel = level; } - -int getTraceLevel() { return s_traceLevel; } - -} // namespace Atom::Event diff --git a/src/atom/event/utils/kmtrace.hpp b/src/atom/event/utils/kmtrace.hpp deleted file mode 100644 index d89ab4e9..00000000 --- a/src/atom/event/utils/kmtrace.hpp +++ /dev/null @@ -1,79 +0,0 @@ -/* - * kmtrace.hpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2024-2-10 - -Description: Trace Destroy Detector - -*************************************************/ - -#pragma once - -#include "../kmconf.hpp" - -#include -#include -#include - -namespace Atom::Event { - -#define KM_TRACE(l, x) \ - do { \ - if (l <= Atom::Event::getTraceLevel()) { \ - std::ostringstream __kev_oss_42__; \ - __kev_oss_42__ << x; \ - Atom::Event::traceWrite(l, __kev_oss_42__.str()); \ - } \ - } while (0) - -#define KM_XTRACE(l, x) \ - do { \ - if (l <= Atom::Event::getTraceLevel()) { \ - std::ostringstream __kev_oss_42__; \ - __kev_oss_42__ << getObjKey() << ":: " << x; \ - Atom::Event::traceWrite(l, __kev_oss_42__.str()); \ - } \ - } while (0) - -#define KM_INFOXTRACE(x) KM_XTRACE(Atom::Event::TRACE_LEVEL_INFO, x) -#define KM_WARNXTRACE(x) KM_XTRACE(Atom::Event::TRACE_LEVEL_WARN, x) -#define KM_ERRXTRACE(x) KM_XTRACE(Atom::Event::TRACE_LEVEL_ERROR, x) -#define KM_DBGXTRACE(x) KM_XTRACE(Atom::Event::TRACE_LEVEL_DEBUG, x) - -#define KM_INFOTRACE(x) KM_TRACE(Atom::Event::TRACE_LEVEL_INFO, x) -#define KM_WARNTRACE(x) KM_TRACE(Atom::Event::TRACE_LEVEL_WARN, x) -#define KM_ERRTRACE(x) KM_TRACE(Atom::Event::TRACE_LEVEL_ERROR, x) -#define KM_DBGTRACE(x) KM_TRACE(Atom::Event::TRACE_LEVEL_DEBUG, x) - -#define KM_INFOTRACE_THIS(x) \ - KM_TRACE(Atom::Event::TRACE_LEVEL_INFO, x << ", this=" << this) -#define KM_WARNTRACE_THIS(x) \ - KM_TRACE(Atom::Event::TRACE_LEVEL_WARN, x << ", this=" << this) -#define KM_ERRTRACE_THIS(x) \ - KM_TRACE(Atom::Event::TRACE_LEVEL_ERROR, x << ", this=" << this) -#define KM_DBGTRACE_THIS(x) \ - KM_TRACE(Atom::Event::TRACE_LEVEL_DEBUG, x << ", this=" << this) - -#define KM_ASSERT(x) assert(x) - -const int TRACE_LEVEL_ERROR = 1; -const int TRACE_LEVEL_WARN = 2; -const int TRACE_LEVEL_INFO = 3; -const int TRACE_LEVEL_DEBUG = 4; -const int TRACE_LEVEL_VERBOS = 5; -const int TRACE_LEVEL_MAX = TRACE_LEVEL_VERBOS; - -void traceWrite(int level, const std::string &msg); -void traceWrite(int level, std::string &&msg); - -using TraceFunc = std::function; -void setTraceFunc(TraceFunc func); -void setTraceLevel(int level); -int getTraceLevel(); - -} // namespace Atom::Event diff --git a/src/atom/event/utils/skutils.hpp b/src/atom/event/utils/skutils.hpp deleted file mode 100644 index 97d13f23..00000000 --- a/src/atom/event/utils/skutils.hpp +++ /dev/null @@ -1,217 +0,0 @@ -/* - * skutils.hpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2024-2-10 - -Description: SskUtils - -*************************************************/ - -#pragma once - -#include "../kevdefs.hpp" - -#ifdef ATOM_OS_WIN -#include -#else // ATOM_OS_WIN -#include -#include -#include -#include -#include -#endif - -ATOM_NS_BEGIN - -#ifdef ATOM_OS_WIN -#define SK_CONST_BUF_LEN static_cast(buf), static_cast(len) -#define SK_BUF_LEN static_cast(buf), static_cast(len) -using ssize_t = std::make_signed_t; -#else -#define SK_CONST_BUF_LEN buf, len -#define SK_BUF_LEN buf, len -using ssize_t = ssize_t; -#endif - -class SKUtils { -public: - static ssize_t send(SOCKET_FD fd, const void *buf, size_t len, int flags) { - ssize_t ret = 0; - do { - ret = ::send(fd, SK_CONST_BUF_LEN, flags); - } while (ret < 0 && getLastError() == EINTR); - return ret; - } - - static ssize_t recv(SOCKET_FD fd, void *buf, size_t len, int flags) { - ssize_t ret = 0; - do { - ret = ::recv(fd, SK_BUF_LEN, flags); - } while (ret < 0 && getLastError() == EINTR); - return ret; - } - - static ssize_t send(SOCKET_FD fd, const iovec *iovs, int count) { - ssize_t ret = 0; -#ifdef ATOM_OS_WIN - DWORD bytes_sent = 0; - ret = ::WSASend(fd, (LPWSABUF)iovs, count, &bytes_sent, 0, NULL, NULL); - if (0 == ret) - ret = bytes_sent; -#else - do { - ret = ::writev(fd, iovs, count); - } while (ret < 0 && getLastError() == EINTR); -#endif - return ret; - } - - static ssize_t recv(SOCKET_FD fd, const iovec *iovs, int count) { - ssize_t ret = 0; -#ifdef ATOM_OS_WIN - DWORD bytes_recv = 0; - ret = ::WSARecv(fd, (LPWSABUF)iovs, count, &bytes_recv, 0, NULL, NULL); - if (0 == ret) - ret = (ssize_t)bytes_recv; -#else - do { - ret = ::readv(fd, iovs, count); - } while (ret < 0 && getLastError() == EINTR); -#endif - return ret; - } - - static ssize_t sendto(SOCKET_FD fd, const void *buf, size_t len, int flags, - const sockaddr *addr, socklen_t addr_len) { - ssize_t ret = 0; - do { - ret = ::sendto(fd, SK_CONST_BUF_LEN, 0, addr, addr_len); - } while (ret < 0 && getLastError() == EINTR); - return ret; - } - - static ssize_t recvfrom(SOCKET_FD fd, void *buf, size_t len, int flags, - struct sockaddr *addr, socklen_t *addr_len) { - ssize_t ret = 0; - do { - ret = ::recvfrom(fd, SK_BUF_LEN, 0, addr, addr_len); - } while (ret < 0 && getLastError() == EINTR); - return ret; - } - - static ssize_t sendto(SOCKET_FD fd, const iovec *iovs, int count, int flags, - const sockaddr *addr, socklen_t addr_len) { - ssize_t ret = 0; -#ifdef ATOM_OS_WIN - DWORD bytes_sent = 0; - ret = ::WSASendTo(fd, (LPWSABUF)iovs, count, &bytes_sent, 0, addr, - addr_len, NULL, NULL); - if (0 == ret) - ret = (ssize_t)bytes_sent; -#else // ATOM_OS_WIN - msghdr send_msg; - send_msg.msg_iov = const_cast(iovs); - send_msg.msg_iovlen = count; - send_msg.msg_name = const_cast(addr); - send_msg.msg_namelen = addr_len; - send_msg.msg_control = 0; - send_msg.msg_controllen = 0; - send_msg.msg_flags = 0; - do { - ret = ::sendmsg(fd, &send_msg, 0); - } while (ret < 0 && getLastError() == EINTR); -#endif // ATOM_OS_WIN - return ret; - } - - static ssize_t recvfrom(SOCKET_FD fd, const iovec *iovs, int count, - int flags, struct sockaddr *addr, - socklen_t *addr_len) { - ssize_t ret = 0; -#ifdef ATOM_OS_WIN - DWORD bytes_recv = 0; - int alen = *addr_len; - ret = ::WSARecvFrom(fd, (LPWSABUF)iovs, count, &bytes_recv, 0, addr, - &alen, NULL, NULL); - *addr_len = alen; - if (0 == ret) - ret = (ssize_t)bytes_recv; -#else // ATOM_OS_WIN - uint8_t msg_ctrl[1024]; - msghdr recv_msg; - recv_msg.msg_iov = const_cast(iovs); - recv_msg.msg_iovlen = count; - recv_msg.msg_name = addr; - recv_msg.msg_namelen = *addr_len; - recv_msg.msg_control = msg_ctrl; - recv_msg.msg_controllen = sizeof(msg_ctrl); - recv_msg.msg_flags = 0; - do { - ret = ::recvmsg(fd, &recv_msg, 0); - } while (ret < 0 && getLastError() == EINTR); -#endif // ATOM_OS_WIN - return ret; - } - - static int close(SOCKET_FD fd) { -#ifdef ATOM_OS_WIN - return ::closesocket(fd); -#else - return ::close(fd); -#endif - } - - static std::string getSockName(SOCKET_FD fd) { - if (fd == INVALID_FD) { - return std::string(); - } - - sockaddr_storage ss_addr; - socklen_t addr_len = sizeof(ss_addr); - if (::getsockname(fd, (sockaddr *)&ss_addr, &addr_len) != 0) { - return std::string(); - } - char ip[128] = {0}; - if (::getnameinfo((struct sockaddr *)&ss_addr, addr_len, ip, sizeof(ip), - NULL, 0, NI_NUMERICHOST | NI_NUMERICSERV) != 0) { - return std::string(); - } - return ip; - } - - static std::string getPeerName(SOCKET_FD fd) { - if (fd == INVALID_FD) { - return std::string(); - } - - sockaddr_storage ss_addr; - socklen_t addr_len = sizeof(ss_addr); - if (::getpeername(fd, (sockaddr *)&ss_addr, &addr_len) != 0) { - return std::string(); - } - char ip[128] = {0}; - if (::getnameinfo((struct sockaddr *)&ss_addr, addr_len, ip, sizeof(ip), - NULL, 0, NI_NUMERICHOST | NI_NUMERICSERV) != 0) { - return std::string(); - } - return ip; - } - - static int getLastError() { -#ifdef ATOM_OS_WIN - return ::WSAGetLastError(); -#else - return errno; -#endif - } -}; - -ATOM_NS_END - -#undef SK_BUF_LEN -#undef SK_CONST_BUF_LEN diff --git a/src/atom/event/utils/utils.cpp b/src/atom/event/utils/utils.cpp deleted file mode 100644 index f76313e0..00000000 --- a/src/atom/event/utils/utils.cpp +++ /dev/null @@ -1,894 +0,0 @@ -/* - * utils.cpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2024-2-10 - -Description: Utils - -*************************************************/ - -#include "utils.hpp" - -#include -#include -#include - -#ifdef ATOM_OS_WIN -#include -#include -#include -#else -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if defined(ATOM_OS_LINUX) || defined(ATOM_OS_ANDROID) -#include -#endif -#if defined(ATOM_OS_MAC) || defined(ATOM_OS_IOS) -#include -#include -#include "CoreFoundation/CoreFoundation.h" -#ifndef ATOM_OS_IOS -#include -#endif -#endif -#endif - -#include -#include -#include -#include -#include -#include -#include - -#include "kmtrace.hpp" - -using namespace std::chrono; - -ATOM_NS_BEGIN - -enum { KM_RESOLVE_IPV0 = 0, KM_RESOLVE_IPV4 = 1, KM_RESOLVE_IPV6 = 2 }; - -#if 0 -int km_resolve_2_ip_v4(const char *host_name, char *ip_buf, size_t ip_buf_len) -{ - const char* ptr = host_name; - bool is_digit = true; - while(*ptr) { - if(*ptr != ' ' && *ptr != '\t') { - if(*ptr != '.' && !(*ptr >= '0' && *ptr <= '9')) { - is_digit = false; - break; - } - } - ++ptr; - } - - if (is_digit) { - strncpy_s(ip_buf, ip_buf_len, host_name, strlen(host_name)); - return 0; - } - - struct hostent* he = nullptr; -#ifdef ATOM_OS_LINUX - int nError = 0; - char szBuffer[1024] = {0}; - struct hostent *pheResultBuf = reinterpret_cast(szBuffer); - - if (::gethostbyname_r( - host_name, - pheResultBuf, - szBuffer + sizeof(struct hostent), - sizeof(szBuffer) - sizeof(struct hostent), - &pheResultBuf, - &nError) == 0) - { - he = pheResultBuf; - } -#else - he = gethostbyname(host_name); -#endif - - if(he && he->h_addr_list && he->h_addr_list[0]) - { -#ifndef ATOM_OS_WIN - inet_ntop(AF_INET, he->h_addr_list[0], ip_buf, ip_buf_len); - return 0; -#else - char* tmp = (char*)inet_ntoa((in_addr&)(*he->h_addr_list[0])); - if(tmp) { - strncpy_s(ip_buf, ip_buf_len, tmp, strlen(tmp)); - return 0; - } -#endif - } - - ip_buf[0] = 0; - return -1; -} -#endif - -int km_resolve_2_ip(const char *host_name, char *ip_buf, size_t ip_buf_len, - int ipv) { - if (!host_name || !ip_buf) { - return -1; - } - - ip_buf[0] = '\0'; - - addrinfo *ai = nullptr; - struct addrinfo hints = {0}; - if (KM_RESOLVE_IPV6 == ipv) { - hints.ai_family = AF_INET6; - } else if (KM_RESOLVE_IPV4 == ipv) { - hints.ai_family = AF_INET; - } else { - hints.ai_family = AF_UNSPEC; - } - hints.ai_flags = AI_ADDRCONFIG; // will block 10 seconds in some case if - // not set AI_ADDRCONFIG - if (getaddrinfo(host_name, nullptr, &hints, &ai) != 0 || !ai) { - return -1; - } -#ifdef ATOM_OS_WIN - auto ip_buf_size = static_cast(ip_buf_len); -#else - auto ip_buf_size = ip_buf_len; -#endif - for (addrinfo *aii = ai; aii; aii = aii->ai_next) { - if (AF_INET6 == aii->ai_family && - (KM_RESOLVE_IPV6 == ipv || KM_RESOLVE_IPV0 == ipv)) { - sockaddr_in6 *sa6 = (sockaddr_in6 *)aii->ai_addr; - if (IN6_IS_ADDR_LINKLOCAL(&(sa6->sin6_addr))) - continue; - if (IN6_IS_ADDR_SITELOCAL(&(sa6->sin6_addr))) - continue; - if (getnameinfo(aii->ai_addr, - static_cast(aii->ai_addrlen), ip_buf, - ip_buf_size, NULL, 0, - NI_NUMERICHOST | NI_NUMERICSERV) != 0) - continue; - else - break; // found a ipv6 address - } else if (AF_INET == aii->ai_family && - (KM_RESOLVE_IPV4 == ipv || KM_RESOLVE_IPV0 == ipv)) { - if (getnameinfo(aii->ai_addr, - static_cast(aii->ai_addrlen), ip_buf, - ip_buf_size, NULL, 0, - NI_NUMERICHOST | NI_NUMERICSERV) != 0) - continue; - else - break; // found a ipv4 address - } - } - if ('\0' == ip_buf[0] && KM_RESOLVE_IPV0 == ipv && - getnameinfo(ai->ai_addr, static_cast(ai->ai_addrlen), ip_buf, - ip_buf_size, NULL, 0, - NI_NUMERICHOST | NI_NUMERICSERV) != 0) { - freeaddrinfo(ai); - return -1; - } - freeaddrinfo(ai); - return 0; -} - -int km_set_sock_addr(const char *addr, unsigned short port, addrinfo *hints, - sockaddr *sk_addr, size_t sk_addr_len) { - char service[128] = {0}; - struct addrinfo *ai = nullptr; - if (!addr && hints) { - hints->ai_flags |= AI_PASSIVE; - } - snprintf(service, sizeof(service) - 1, "%d", port); - auto ret = getaddrinfo(addr, service, hints, &ai); - if (ret != 0 || !ai) { - if (ai) - freeaddrinfo(ai); - return ret; - } - if (ai->ai_addrlen > sk_addr_len) { - if (ai) - freeaddrinfo(ai); - return -1; - } - if (sk_addr) { - memcpy(sk_addr, ai->ai_addr, ai->ai_addrlen); - } - freeaddrinfo(ai); - return 0; -} - -int km_get_sock_addr(const sockaddr *sk_addr, size_t sk_addr_len, char *addr, - size_t addr_len, unsigned short *port) { -#ifdef ATOM_OS_WIN - auto addr_size = static_cast(addr_len); -#else - auto addr_size = addr_len; -#endif - char service[16] = {0}; - if (getnameinfo(sk_addr, static_cast(sk_addr_len), addr, - addr_size, service, sizeof(service), - NI_NUMERICHOST | NI_NUMERICSERV) != 0) - return -1; - if (port) - *port = atoi(service); - return 0; -} - -int km_get_sock_addr(const sockaddr *addr, size_t addr_len, std::string &ip, - uint16_t *port) { - char ip_buf[128] = {0}; - if (km_get_sock_addr(addr, addr_len, ip_buf, sizeof(ip_buf), port) != 0) { - return -1; - } - ip = ip_buf; - return 0; -} - -int km_get_sock_addr(const sockaddr_storage &addr, std::string &ip, - uint16_t *port) { - char ip_buf[128] = {0}; - auto addr_len = km_get_addr_length(addr); - if (km_get_sock_addr((const sockaddr *)&addr, addr_len, ip_buf, - sizeof(ip_buf), port) != 0) { - return -1; - } - ip = ip_buf; - return 0; -} - -int km_set_addr_port(uint16_t port, sockaddr_storage &addr) { - if (AF_INET == addr.ss_family) { - sockaddr_in *p = (sockaddr_in *)&addr; - p->sin_port = htons(port); - } else if (AF_INET6 == addr.ss_family) { - sockaddr_in6 *p = (sockaddr_in6 *)&addr; - p->sin6_port = htons(port); - } else { - return -1; - } - return 0; -} - -size_t km_get_addr_length(const sockaddr_storage &addr) { - size_t addr_len = sizeof(addr); - if (AF_INET == addr.ss_family) { - addr_len = sizeof(sockaddr_in); - } else if (AF_INET6 == addr.ss_family) { - addr_len = sizeof(sockaddr_in6); - } - return addr_len; -} - -bool km_is_ipv6_address(const char *addr) { - sockaddr_storage ss_addr = {0}; - struct addrinfo hints = {0}; - hints.ai_family = AF_UNSPEC; - hints.ai_flags = AI_NUMERICHOST; - if (km_set_sock_addr(addr, 0, &hints, (struct sockaddr *)&ss_addr, - sizeof(ss_addr)) != 0) { - return false; - } - return AF_INET6 == ss_addr.ss_family; -} - -bool km_is_ip_address(const char *addr) { - sockaddr_storage ss_addr = {0}; - struct addrinfo hints = {0}; - hints.ai_family = AF_UNSPEC; - hints.ai_flags = AI_NUMERICHOST; - return km_set_sock_addr(addr, 0, &hints, (struct sockaddr *)&ss_addr, - sizeof(ss_addr)) == 0; -} - -bool km_is_mcast_address(const char *addr) { - sockaddr_storage ss_addr = {0}; - struct addrinfo hints = {0}; - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_DGRAM; - hints.ai_flags = - AI_NUMERICHOST | AI_ADDRCONFIG; // will block 10 seconds in some case - // if not set AI_ADDRCONFIG - km_set_sock_addr(addr, 0, &hints, (struct sockaddr *)&ss_addr, - sizeof(ss_addr)); - switch (ss_addr.ss_family) { - case AF_INET: { - struct sockaddr_in *sa_in4 = (struct sockaddr_in *)&ss_addr; - return IN_MULTICAST(ntohl(sa_in4->sin_addr.s_addr)); - } - case AF_INET6: { - struct sockaddr_in6 *sa_in6 = (struct sockaddr_in6 *)&ss_addr; - return IN6_IS_ADDR_MULTICAST(&sa_in6->sin6_addr) ? true : false; - } - } - return false; -} - -int km_parse_address(const char *addr, char *proto, size_t proto_len, - char *host, size_t host_len, unsigned short *port) { - if (!addr || !host) - return -1; - - const char *tmp = strstr(addr, "://"); - if (tmp) { - if (proto) { - auto tmp_len = - (std::min)(proto_len - 1, static_cast(tmp - addr)); - memcpy(proto, addr, tmp_len); - proto[tmp_len] = '\0'; - } - tmp += 3; - } else { - if (proto) - proto[0] = '\0'; - tmp = addr; - } - const char *end = strchr(tmp, '/'); - if (!end) { - end = addr + strlen(addr); - } - - const char *tmp1 = strchr(tmp, '['); - if (tmp1) { // ipv6 address - tmp = tmp1 + 1; - tmp1 = strchr(tmp, ']'); - if (!tmp1) - return -1; - auto tmp_len = - (std::min)(host_len - 1, static_cast(tmp1 - tmp)); - memcpy(host, tmp, tmp_len); - host[tmp_len] = '\0'; - tmp = tmp1 + 1; - tmp1 = strchr(tmp, ':'); - if (tmp1 && tmp1 <= end) - tmp = tmp1 + 1; - else - tmp = nullptr; - } else { // ipv4 address - tmp1 = strchr(tmp, ':'); - if (tmp1 && tmp1 <= end) { - auto tmp_len = - (std::min)(host_len - 1, static_cast(tmp1 - tmp)); - memcpy(host, tmp, tmp_len); - host[tmp_len] = '\0'; - tmp = tmp1 + 1; - } else { - auto tmp_len = - (std::min)(host_len - 1, static_cast(end - tmp)); - memcpy(host, tmp, tmp_len); - host[tmp_len] = '\0'; - tmp = nullptr; - } - } - - if (port) { - *port = tmp ? atoi(tmp) : 0; - } - - return 0; -} - -int set_nonblocking(SOCKET_FD fd) { -#ifdef ATOM_OS_WIN - int mode = 1; - ::ioctlsocket(fd, FIONBIO, (ULONG *)&mode); -#else - int flag = ::fcntl(fd, F_GETFL, 0); - ::fcntl(fd, F_SETFL, flag | O_NONBLOCK | O_ASYNC); -#endif - return 0; -} - -int set_tcpnodelay(SOCKET_FD fd) { - int opt_val = 1; - return ::setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&opt_val, - sizeof(int)); -} - -int find_first_set(uint32_t b) { - if (0 == b) { - return -1; - } - int n = 0; - if (!(0xffff & b)) - n += 16; - if (!((0xff << n) & b)) - n += 8; - if (!((0xf << n) & b)) - n += 4; - if (!((0x3 << n) & b)) - n += 2; - if (!((0x1 << n) & b)) - n += 1; - return n; -} - -int find_first_set(uint64_t b) { - if (0 == b) { - return -1; - } - int n = 0; - if (!(0xffffffff & b)) - n += 32; - if (!((0xffffLL << n) & b)) - n += 16; - if (!((0xffLL << n) & b)) - n += 8; - if (!((0xfLL << n) & b)) - n += 4; - if (!((0x3LL << n) & b)) - n += 2; - if (!((0x1LL << n) & b)) - n += 1; - return n; -} - -TICK_COUNT_TYPE get_tick_count_ms() { - using namespace std::chrono; - steady_clock::time_point _now = steady_clock::now(); - milliseconds _now_ms = duration_cast(_now.time_since_epoch()); - return (TICK_COUNT_TYPE)_now_ms.count(); -} - -TICK_COUNT_TYPE calc_time_elapse_delta_ms(TICK_COUNT_TYPE now_tick, - TICK_COUNT_TYPE &start_tick) { - if (now_tick - start_tick > (((TICK_COUNT_TYPE)-1) >> 1)) { - start_tick = now_tick; - return 0; - } - return now_tick - start_tick; -} - -#if 0 -// need c++ 14 -bool is_equal(const std::string &s1, const std::string &s2) -{ - return std::equal(s1.begin(), s1.end(), s2.begin(), s2.end(), - [] (const char &ch1, const char &ch2) { - return std::toupper(ch1) == std::toupper(ch2); - }); -} -#endif - -bool is_equal(const char *str1, const char *str2) { - return strcasecmp(str1, str2) == 0; -} - -bool is_equal(const std::string &str1, const std::string &str2) { - return str1.length() == str2.length() && - strcasecmp(str1.c_str(), str2.c_str()) == 0; -} - -bool is_equal(const char *str1, const std::string &str2) { - return strcasecmp(str1, str2.c_str()) == 0; -} - -bool is_equal(const std::string &str1, const char *str2) { - return strcasecmp(str1.c_str(), str2) == 0; -} - -bool is_equal(const char *str1, const char *str2, int n) { - return strncasecmp(str1, str2, n) == 0; -} - -bool is_equal(const std::string &str1, const std::string &str2, int n) { - return strncasecmp(str1.c_str(), str2.c_str(), n) == 0; -} - -bool is_equal(const char *str1, const std::string &str2, int n) { - return strncasecmp(str1, str2.c_str(), n) == 0; -} - -bool is_equal(const std::string &str1, const char *str2, int n) { - return strncasecmp(str1.c_str(), str2, n) == 0; -} - -char *trim_left(char *str, char c) { - while (*str && *str++ == c) { - ; - } - - return str; -} - -char *trim_right(char *str, char c) { - return trim_right(str, str + strlen(str), c); -} - -char *trim_right(char *str, char *str_end, char c) { - while (--str_end >= str && *str_end == c) { - ; - } - *(++str_end) = 0; - - return str; -} - -std::string &trim_left(std::string &str, char c) { - str.erase(0, str.find_first_not_of(c)); - return str; -} - -std::string &trim_right(std::string &str, char c) { - auto pos = str.find_last_not_of(c); - if (pos != std::string::npos) { - str.erase(pos + 1); - } - return str; -} - -bool contains_token(const std::string &str, const std::string &token, - char delim) { - bool found = false; - for_each_token(str, delim, [&found, &token](std::string &t) { - if (is_equal(t, token)) { - found = true; - return false; - } - return true; - }); - - return found; -} - -bool remove_token(std::string &tokens, const std::string &token, char delim) { - bool removed = false; - std::string str; - for_each_token(tokens, delim, [&removed, &token, &str](std::string &t) { - if (is_equal(t, token)) { - removed = true; - } else { - if (!str.empty()) { - str += ", "; - } - str += t; - } - return true; - }); - tokens = std::move(str); - - return removed; -} - -size_t random_bytes(void *buf, size_t len) { - using rand_type = unsigned int; - using bytes_randomizer = - std::independent_bits_engine; - - auto sl = len / sizeof(rand_type); - auto rl = len - sl * sizeof(rand_type); - auto *p = static_cast(buf); - bytes_randomizer br(std::random_device{}()); - if (sl > 0) { - std::generate(p, p + sl, std::ref(br)); - } - if (rl > 0) { - rand_type r = br(); - memcpy(static_cast(buf) + len - rl, &r, rl); - } - return len; -} - -std::string getExecutablePath() { - std::string str_path; -#ifdef ATOM_OS_WIN - char c_path[MAX_PATH] = {0}; - GetModuleFileNameA(NULL, c_path, sizeof(c_path)); - str_path = c_path; -#elif defined(ATOM_OS_MAC) -#ifndef ATOM_OS_IOS - char c_path[PROC_PIDPATHINFO_MAXSIZE]; - if (proc_pidpath(getpid(), c_path, sizeof(c_path)) <= 0) { - return "./"; - } - str_path = c_path; -#else - char c_path[PATH_MAX] = {0}; - uint32_t size = sizeof(c_path); - CFBundleRef cf_bundle = CFBundleGetMainBundle(); - if (cf_bundle) { - CFURLRef cf_url = CFBundleCopyBundleURL(cf_bundle); - if (CFURLGetFileSystemRepresentation(cf_url, TRUE, (UInt8 *)c_path, - PATH_MAX)) { - CFStringRef cf_str = - CFURLCopyFileSystemPath(cf_url, kCFURLPOSIXPathStyle); - CFStringGetCString(cf_str, c_path, PATH_MAX, - kCFStringEncodingASCII); - CFRelease(cf_str); - } - CFRelease(cf_url); - str_path = c_path; - if (str_path.at(str_path.length() - 1) != PATH_SEPARATOR) { - str_path += PATH_SEPARATOR; - } - return str_path; - } else { - _NSGetExecutablePath(c_path, &size); - } - str_path = c_path; -#endif -#elif defined(ATOM_OS_LINUX) - char c_path[1024] = {0}; - if (readlink("/proc/self/exe", c_path, sizeof(c_path)) < 0) { - return "./"; - } - str_path = c_path; -#else - return "./"; -#endif - if (str_path.empty()) { - return "./"; - } - auto pos = str_path.rfind(PATH_SEPARATOR, str_path.size()); - if (pos != std::string::npos) { - str_path.resize(pos); - } - str_path.append(1, PATH_SEPARATOR); - return str_path; -} - -std::string getModuleFullPath(const void *addr_in_module) { - if (!addr_in_module) { - return ""; - } - std::string str_path; -#ifdef ATOM_OS_WIN - HMODULE hmodule = 0; - auto flags = GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | - GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT; - auto ret = ::GetModuleHandleEx(flags, (LPCTSTR)addr_in_module, &hmodule); - if (!ret) { - return ""; - } - char file_name[2048] = {0}; - auto count = ::GetModuleFileNameA(hmodule, file_name, ARRAYSIZE(file_name)); - if (count == 0) { - return ""; - } - str_path = file_name; -#elif defined(ATOM_OS_MAC) || defined(ATOM_OS_LINUX) - Dl_info dl_info; - dladdr((void *)addr_in_module, &dl_info); - - str_path = dl_info.dli_fname; -#else - return ""; -#endif - -#ifdef ATOM_OS_MAC - auto pos1 = str_path.rfind(PATH_SEPARATOR); - auto pos2 = pos1; - int count = 4; -#ifdef ATOM_OS_IOS - count = 2; -#endif - while (pos2 != std::string::npos && pos2 > 0 && --count > 0) { - pos1 = pos2; - pos2 = str_path.rfind(PATH_SEPARATOR, pos1 - 1); - } - if (pos2 != std::string::npos) { - auto name = str_path.substr(pos2 + 1, pos1 - pos2 - 1); - auto pos3 = name.rfind('.'); - if (pos3 != std::string::npos) { - auto ext = name.substr(pos3 + 1); - if (ext == "framework" || ext == "bundle" || ext == "app") { - str_path.erase(pos1); - } - } - } -#endif - - return str_path; -} - -std::string getCurrentModulePath() { - std::string str_path = getModuleFullPath((void *)getCurrentModulePath); - auto pos = str_path.rfind(PATH_SEPARATOR, str_path.size()); - str_path.resize(pos); - return str_path; -} - -std::string toString(const system_clock::time_point &time, bool utc) { - auto msecs = - duration_cast(time.time_since_epoch()).count() % 1000; - auto itt = system_clock::to_time_t(time); - struct tm res; -#ifdef ATOM_OS_WIN - utc ? gmtime_s(&res, &itt) : localtime_s(&res, &itt); // windows and C11 -#else - utc ? gmtime_r(&itt, &res) : localtime_r(&itt, &res); -#endif - std::ostringstream ss; - ss << std::put_time(&res, "%FT%T.") << std::setfill('0') << std::setw(3) - << msecs; - if (utc) { - ss << 'Z'; - } else { - ss << std::put_time(&res, "%z"); - } - return ss.str(); -} - -std::string getDateTimeString(bool utc) { - auto now = system_clock::now(); - return toString(now, utc); -} - -#if defined(ATOM_OS_WIN) -std::string utf8_encode(const wchar_t *wstr, int len) { - if (!wstr || !len) - return std::string(); - auto utf8_len = - WideCharToMultiByte(CP_UTF8, 0, wstr, len, NULL, 0, NULL, NULL); - if (utf8_len <= 0) { - return ""; - } - std::string utf8_str(utf8_len, 0); - utf8_len = WideCharToMultiByte(CP_UTF8, 0, wstr, len, &utf8_str[0], - utf8_len, NULL, NULL); - if (utf8_len < 0) { - return ""; - } - return utf8_str; -} - -std::string utf8_encode(const wchar_t *wstr) { - auto utf8_len = - WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL); - if (utf8_len <= 1) { // include the terminating null character - return ""; - } - std::string utf8_str(utf8_len, 0); - utf8_len = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, &utf8_str[0], utf8_len, - NULL, NULL); - --utf8_len; // exclude the terminating null character - if (utf8_len < 0) { - return ""; - } - utf8_str.resize(utf8_len); - return utf8_str; -} -// Convert a wide Unicode string to an UTF8 string -std::string utf8_encode(const std::wstring &wstr) { - if (wstr.empty()) - return std::string(); - int size_needed = WideCharToMultiByte( - CP_UTF8, 0, &wstr[0], (int)wstr.size(), NULL, 0, NULL, NULL); - std::string strTo(size_needed, 0); - WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), &strTo[0], - size_needed, NULL, NULL); - return strTo; -} - -// Convert an UTF8 string to a wide Unicode String -std::wstring utf8_decode(const std::string &str) { - if (str.empty()) - return std::wstring(); - int size_needed = - MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0); - std::wstring wstrTo(size_needed, 0); - MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), &wstrTo[0], - size_needed); - return wstrTo; -} - -void setCurrentThreadNameX(const char *name) { - struct { - DWORD dwType; - LPCSTR szName; - DWORD dwThreadID; - DWORD dwFlags; - } threadname_info = {0x1000, name, static_cast(-1), 0}; - - try { - ::RaiseException(0x406D1388, 0, sizeof(threadname_info) / sizeof(DWORD), - reinterpret_cast(&threadname_info)); - } catch (...) { - } -} -#endif // ATOM_OS_WIN - -void setCurrentThreadName(const char *name) { -#if defined(ATOM_OS_WIN) -#ifndef __WINRT__ - using PFN_SetThreadDescription = HRESULT(WINAPI *)(HANDLE, PCWSTR); - static PFN_SetThreadDescription pfn_SetThreadDescription = nullptr; - static HMODULE kernel32 = nullptr; - - if (!kernel32) { - kernel32 = LoadLibraryW(L"kernel32.dll"); - if (kernel32) { - pfn_SetThreadDescription = (PFN_SetThreadDescription)GetProcAddress( - kernel32, "SetThreadDescription"); - } - } - - if (pfn_SetThreadDescription != nullptr) { - auto wstr = utf8_decode(name); - if (!wstr.empty()) { - auto hr = - pfn_SetThreadDescription(::GetCurrentThread(), wstr.c_str()); - if (SUCCEEDED(hr)) { - return; - } - } - } -#endif - - setCurrentThreadNameX(name); -#elif defined(ATOM_OS_LINUX) || defined(ATOM_OS_ANDROID) - prctl(PR_SET_NAME, reinterpret_cast(name)); -#elif defined(ATOM_OS_MAC) || defined(ATOM_OS_IOS) - pthread_setname_np(name); -#endif -} - -ATOM_NS_END - -#ifdef ATOM_OS_WIN -ATOM_NS_BEGIN -LPFN_CONNECTEX connect_ex = nullptr; -LPFN_ACCEPTEX accept_ex = nullptr; -LPFN_CANCELIOEX cancel_io_ex = nullptr; -ATOM_NS_END - -ATOM_NS_USING - -void kev_init() { - WSADATA wsaData; - WORD wVersionRequested = MAKEWORD(1, 1); - int nResult = WSAStartup(wVersionRequested, &wsaData); - if (nResult != 0) { - return; - } - - auto sock = socket(AF_INET, SOCK_STREAM, 0); - GUID guid = WSAID_CONNECTEX; - DWORD bytes = 0; - if (::WSAIoctl(sock, SIO_GET_EXTENSION_FUNCTION_POINTER, &guid, - sizeof(guid), &connect_ex, sizeof(connect_ex), &bytes, 0, - 0) != 0) { - connect_ex = nullptr; - } - - guid = WSAID_ACCEPTEX; - bytes = 0; - if (::WSAIoctl(sock, SIO_GET_EXTENSION_FUNCTION_POINTER, &guid, - sizeof(guid), &accept_ex, sizeof(accept_ex), &bytes, 0, - 0) != 0) { - accept_ex = nullptr; - } - closesocket(sock); - cancel_io_ex = (LPFN_CANCELIOEX)GetProcAddress(GetModuleHandle(L"KERNEL32"), - "CancelIoEx"); -} - -void kev_fini() { WSACleanup(); } - -class KMInitializer { - static KMInitializer s_singleton; - - KMInitializer() { kev_init(); } - -public: - ~KMInitializer() { kev_fini(); } -}; -KMInitializer KMInitializer::s_singleton; - -#pragma comment(lib, "ws2_32.lib") - -#endif // ATOM_OS_WIN diff --git a/src/atom/event/utils/utils.hpp b/src/atom/event/utils/utils.hpp deleted file mode 100644 index 1d24f27f..00000000 --- a/src/atom/event/utils/utils.hpp +++ /dev/null @@ -1,168 +0,0 @@ -/* - * utils.cpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2024-2-10 - -Description: Utils - -*************************************************/ - -#ifndef ATOM_EVENT_UITLS_HPP -#define ATOM_EVENT_UITLS_HPP - -#include "../kevdefs.hpp" - -#ifdef ATOM_OS_WIN -#include -#else // ATOM_OS_WIN -#include -#include -#include -#if defined(ATOM_OS_LINUX) && !defined(ATOM_OS_ANDROID) -#include -#endif -#endif // ATOM_OS_WIN - -#include -#include -#include -#include -#include - -struct addrinfo; -struct sockaddr; -struct sockaddr_storage; - -ATOM_NS_BEGIN - -#ifdef ATOM_OS_WIN -#define snprintf(d, dl, fmt, ...) \ - _snprintf_s(d, dl, _TRUNCATE, fmt, ##__VA_ARGS__) -#define vsnprintf(d, dl, fmt, ...) \ - _vsnprintf_s(d, dl, _TRUNCATE, fmt, ##__VA_ARGS__) -#define strcasecmp _stricmp -#define strncasecmp _strnicmp -#define getCurrentThreadId() GetCurrentThreadId() -using LPFN_CANCELIOEX = BOOL(WINAPI *)(HANDLE, LPOVERLAPPED); -#elif defined(ATOM_OS_MAC) -#define getCurrentThreadId() pthread_mach_thread_np(pthread_self()) -#elif defined(ATOM_OS_ANDROID) -#define getCurrentThreadId() gettid() -#elif defined(ATOM_OS_LINUX) -#define getCurrentThreadId() syscall(__NR_gettid) -#else -#define getCurrentThreadId() pthread_self() -#endif - -#ifdef ATOM_OS_WIN -#define PATH_SEPARATOR '\\' -#else -#define PATH_SEPARATOR '/' -#define strncpy_s(d, dl, s, c) \ - do { \ - if (0 == dl) \ - break; \ - size_t sz = (dl - 1) > c ? c : (dl - 1); \ - strncpy(d, s, sz); \ - d[sz] = '\0'; \ - } while (0) -#endif - -#ifndef TICK_COUNT_TYPE -#define TICK_COUNT_TYPE uint64_t -#endif - -#define UNUSED(x) (void)(x) - -#if __cplusplus > 201402L -// c++17 -#define FALLTHROUGH [[fallthrough]]; -#else -#define FALLTHROUGH -#endif - -template -char (&ArraySizeHelper(const T (&array)[N]))[N]; -#define ARRAY_SIZE(array) (sizeof(Atom::Event::ArraySizeHelper(array))) - -int set_nonblocking(SOCKET_FD fd); -int set_tcpnodelay(SOCKET_FD fd); -int find_first_set(uint32_t b); -int find_first_set(uint64_t b); -TICK_COUNT_TYPE get_tick_count_ms(); -TICK_COUNT_TYPE calc_time_elapse_delta_ms(TICK_COUNT_TYPE now_tick, - TICK_COUNT_TYPE &start_tick); - -bool is_equal(const char *str1, const char *str2); -bool is_equal(const std::string &str1, const std::string &str2); -bool is_equal(const char *str1, const std::string &str2); -bool is_equal(const std::string &str1, const char *str2); -bool is_equal(const char *str1, const char *str2, int n); -bool is_equal(const std::string &str1, const std::string &str2, int n); -bool is_equal(const char *str1, const std::string &str2, int n); -bool is_equal(const std::string &str1, const char *str2, int n); -char *trim_left(char *str, char c); -char *trim_right(char *str, char c); -char *trim_right(char *str, char *str_end, char c); -std::string &trim_left(std::string &str, char c); -std::string &trim_right(std::string &str, char c); - -std::string getExecutablePath(); -std::string getModuleFullPath(const void *addr_in_module); -std::string getCurrentModulePath(); - -template // (std::string &token) -> bool -void for_each_token(const std::string &tokens, char delim, LAMBDA &&func) { - std::stringstream ss; - ss.str(tokens); - std::string token; - while (std::getline(ss, token, delim)) { - trim_left(token, ' '); - trim_right(token, ' '); - if (!func(token)) { - break; - } - } -} -bool contains_token(const std::string &tokens, const std::string &token, - char delim); -bool remove_token(std::string &tokens, const std::string &token, char delim); - -size_t random_bytes(void *buf, size_t len); - -int km_resolve_2_ip(const char *host_name, char *ip_buf, size_t ip_buf_len, - int ipv = 0); -int km_parse_address(const char *addr, char *proto, size_t proto_len, - char *host, size_t host_len, unsigned short *port); -int km_set_sock_addr(const char *addr, unsigned short port, addrinfo *hints, - sockaddr *sk_addr, size_t sk_addr_len); -int km_get_sock_addr(const sockaddr *sk_addr, size_t sk_addr_len, char *addr, - size_t addr_len, unsigned short *port); -bool km_is_ipv6_address(const char *addr); -bool km_is_ip_address(const char *addr); -bool km_is_mcast_address(const char *addr); - -int km_get_sock_addr(const sockaddr *addr, size_t addr_len, std::string &ip, - uint16_t *port); -int km_get_sock_addr(const sockaddr_storage &addr, std::string &ip, - uint16_t *port); -int km_set_addr_port(uint16_t port, sockaddr_storage &addr); -size_t km_get_addr_length(const sockaddr_storage &addr); - -inline bool km_is_fatal_error(Result err) { - return err != Result::OK && err != Result::AGAIN; -} - -std::string toString(const std::chrono::system_clock::time_point &time, - bool utc); -std::string getDateTimeString(bool utc); -void setCurrentThreadName(const char *name); - -ATOM_NS_END - -#endif // ATOM_EVENT_UITLS_HPP diff --git a/src/atom/experiment/CMakeLists.txt b/src/atom/experiment/CMakeLists.txt deleted file mode 100644 index adc20f41..00000000 --- a/src/atom/experiment/CMakeLists.txt +++ /dev/null @@ -1,70 +0,0 @@ -# CMakeLists.txt for Atom-Experiment -# This project is licensed under the terms of the GPL3 license. -# -# Project Name: Atom-Experiment -# Description: A collection of experiments for the Atom project -# Author: Max Qian -# License: GPL3 - -cmake_minimum_required(VERSION 3.20) -project(atom-experiment C CXX) - -# Sources -list(APPEND ${PROJECT_NAME}_SOURCES - platform.cpp - string.cpp -) - -# Headers -list(APPEND ${PROJECT_NAME}_HEADERS - any.hpp - anyutils.hpp - bind_first.hpp - callable.hpp - decorate.hpp - flatmap.hpp - func_traits.hpp - invoke.hpp - list.hpp - memory.hpp - noncopyable.hpp - object.hpp - optional.hpp - platform.hpp - ranges.hpp - short_alloc.hpp - stack_vector.hpp - static_vector.hpp - string.hpp - to_string.hpp - type_info.hpp -) - -# Build Object Library -add_library(${PROJECT_NAME}_OBJECT OBJECT) -set_property(TARGET ${PROJECT_NAME}_OBJECT PROPERTY POSITION_INDEPENDENT_CODE 1) - -target_sources(${PROJECT_NAME}_OBJECT - PUBLIC - ${${PROJECT_NAME}_HEADERS} - PRIVATE - ${${PROJECT_NAME}_SOURCES} -) - -target_link_libraries(${PROJECT_NAME}_OBJECT ${${PROJECT_NAME}_LIBS}) - -add_library(${PROJECT_NAME} STATIC) - -target_link_libraries(${PROJECT_NAME} ${PROJECT_NAME}_OBJECT ${${PROJECT_NAME}_LIBS}) -target_link_libraries(${PROJECT_NAME} ${CMAKE_THREAD_LIBS_INIT}) -target_include_directories(${PROJECT_NAME} PUBLIC .) - -set_target_properties(${PROJECT_NAME} PROPERTIES - VERSION ${CMAKE_HYDROGEN_VERSION_STRING} - SOVERSION ${HYDROGEN_SOVERSION} - OUTPUT_NAME ${PROJECT_NAME} -) - -install(TARGETS ${PROJECT_NAME} - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} -) \ No newline at end of file diff --git a/src/atom/experiment/meson.build b/src/atom/experiment/meson.build deleted file mode 100644 index ccb5965f..00000000 --- a/src/atom/experiment/meson.build +++ /dev/null @@ -1,50 +0,0 @@ -project('Atom-Experiment', 'cpp') - -# Define sources and headers -sources = [ - 'platform.cpp', - 'string.cpp' -] -headers = [ - 'any.hpp', - 'anyutils.hpp', - 'bind_first.hpp', - 'callable.hpp', - 'decorate.hpp', - 'flatmap.hpp', - 'func_traits.hpp', - 'invoke.hpp', - 'list.hpp', - 'memory.hpp', - 'noncopyable.hpp', - 'object.hpp', - 'optional.hpp', - 'platform.hpp', - 'ranges.hpp', - 'short_alloc.hpp', - 'stack_vector.hpp', - 'static_vector.hpp', - 'string.hpp', - 'to_string.hpp', - 'type_info.hpp' -] - -# Create object library -atom_experiment_obj = library('atom_experiment', - sources + headers, - cpp_std: c_std -) - -# Create static library -atom_experiment_static = static_library('atom_experiment_static', atom_experiment_obj) - -# Set version properties -version = '1.0.0' # You should define your version here -soversion = '1' - -atom_experiment_static.version = version -atom_experiment_static.soversion = soversion -atom_experiment_static.basename = 'Atom-Experiment' - -# Install target -install_targets(atom_experiment_static) diff --git a/src/atom/experiment/xmake.lua b/src/atom/experiment/xmake.lua deleted file mode 100644 index 0930b4f7..00000000 --- a/src/atom/experiment/xmake.lua +++ /dev/null @@ -1,65 +0,0 @@ --- xmake.lua for Atom-Experiment --- This project is licensed under the terms of the GPL3 license. --- --- Project Name: Atom-Experiment --- Description: A collection of experiments for the Atom project --- Author: Max Qian --- License: GPL3 - -add_rules("mode.debug", "mode.release") - -set_project("atom-experiment") -set_version("1.0.0") -set_license("GPL3") - --- Sources -local sources = { - "platform.cpp", - "string.cpp" -} - --- Headers -local headers = { - "any.hpp", - "anyutils.hpp", - "bind_first.hpp", - "callable.hpp", - "decorate.hpp", - "flatmap.hpp", - "func_traits.hpp", - "invoke.hpp", - "list.hpp", - "memory.hpp", - "noncopyable.hpp", - "object.hpp", - "optional.hpp", - "platform.hpp", - "ranges.hpp", - "short_alloc.hpp", - "stack_vector.hpp", - "static_vector.hpp", - "string.hpp", - "to_string.hpp", - "type_info.hpp" -} - --- Build Object Library -target("atom-experiment-object") - set_kind("object") - add_headerfiles(headers, {public = true}) - add_files(sources, {public = false}) - --- Build Static Library -target("atom-experiment") - set_kind("static") - add_deps("atom-experiment-object") - add_packages("threads") - add_includedirs(".", {public = true}) - - set_targetdir("$(buildir)/lib") - set_objectdir("$(buildir)/obj") - - after_build(function (target) - os.cp("$(buildir)/lib", "$(projectdir)/lib") - os.cp("$(projectdir)/*.hpp", "$(projectdir)/include") - end) \ No newline at end of file diff --git a/src/atom/type/abi.hpp b/src/atom/function/abi.hpp similarity index 100% rename from src/atom/type/abi.hpp rename to src/atom/function/abi.hpp diff --git a/src/atom/experiment/bind_first.hpp b/src/atom/function/bind_first.hpp similarity index 100% rename from src/atom/experiment/bind_first.hpp rename to src/atom/function/bind_first.hpp diff --git a/src/atom/experiment/callable.hpp b/src/atom/function/callable.hpp similarity index 100% rename from src/atom/experiment/callable.hpp rename to src/atom/function/callable.hpp diff --git a/src/atom/experiment/decorate.hpp b/src/atom/function/decorate.hpp similarity index 100% rename from src/atom/experiment/decorate.hpp rename to src/atom/function/decorate.hpp diff --git a/src/atom/experiment/func_traits.hpp b/src/atom/function/func_traits.hpp similarity index 100% rename from src/atom/experiment/func_traits.hpp rename to src/atom/function/func_traits.hpp diff --git a/src/atom/experiment/invoke.hpp b/src/atom/function/invoke.hpp similarity index 100% rename from src/atom/experiment/invoke.hpp rename to src/atom/function/invoke.hpp diff --git a/src/atom/experiment/type_info.hpp b/src/atom/function/type_info.hpp similarity index 100% rename from src/atom/experiment/type_info.hpp rename to src/atom/function/type_info.hpp diff --git a/src/atom/experiment/memory.hpp b/src/atom/memory/memory.hpp similarity index 99% rename from src/atom/experiment/memory.hpp rename to src/atom/memory/memory.hpp index 90458107..e41e28cb 100644 --- a/src/atom/experiment/memory.hpp +++ b/src/atom/memory/memory.hpp @@ -62,7 +62,7 @@ class MemoryPool : public std::pmr::memory_resource, NonCopyable { size_t size; size_t used; std::unique_ptr> memory; - Chunk(size_t s) + explicit Chunk(size_t s) : size(s), used(0), memory(static_cast(::operator new(s)), [](uint8_t *p) { ::operator delete(p); }) {} }; diff --git a/src/atom/experiment/object.hpp b/src/atom/memory/object.hpp similarity index 100% rename from src/atom/experiment/object.hpp rename to src/atom/memory/object.hpp diff --git a/src/atom/experiment/short_alloc.hpp b/src/atom/memory/short_alloc.hpp similarity index 100% rename from src/atom/experiment/short_alloc.hpp rename to src/atom/memory/short_alloc.hpp diff --git a/src/atom/server/commander.hpp b/src/atom/server/commander.hpp index b8d7c3b2..81fbe067 100644 --- a/src/atom/server/commander.hpp +++ b/src/atom/server/commander.hpp @@ -28,7 +28,7 @@ Description: Commander #endif #include "atom/experiment/decorate.hpp" -#include "atom/experiment/noncopyable.hpp" +#include "atom/type/noncopyable.hpp" /** * @brief Generic command dispatcher class for handling and dispatching diff --git a/src/atom/server/daemon.cpp b/src/atom/server/daemon.cpp index 650fa1d9..9921f8a8 100644 --- a/src/atom/server/daemon.cpp +++ b/src/atom/server/daemon.cpp @@ -36,7 +36,7 @@ std::string g_pidFilePath = "lithium-daemon"; // 定义 g_isDaemon 变量 bool g_isDaemon = false; -namespace Atom::Async { +namespace atom::async { std::string DaemonGuard::ToString() const { std::stringstream ss; ss << "[DaemonGuard parentId=" << m_parentId << " mainId=" << m_mainId @@ -205,4 +205,4 @@ bool CheckPidFile() { return true; #endif } -} // namespace Atom::Async \ No newline at end of file +} // namespace atom::async \ No newline at end of file diff --git a/src/atom/server/daemon.hpp b/src/atom/server/daemon.hpp index 5cd2d3eb..8c0b0937 100644 --- a/src/atom/server/daemon.hpp +++ b/src/atom/server/daemon.hpp @@ -32,7 +32,7 @@ Description: Daemon process implementation #include #endif -namespace Atom::Async { +namespace atom::async { // Class for managing process information class DaemonGuard { public: @@ -118,6 +118,6 @@ void WritePidFile(); */ bool CheckPidFile(); -} // namespace Atom::Async +} // namespace atom::async #endif diff --git a/src/atom/server/global_ptr.hpp b/src/atom/server/global_ptr.hpp index 15dad4e6..2d7f1914 100644 --- a/src/atom/server/global_ptr.hpp +++ b/src/atom/server/global_ptr.hpp @@ -29,7 +29,7 @@ Description: Global shared pointer manager #include #endif -#include "atom/experiment/noncopyable.hpp" +#include "atom/type/noncopyable.hpp" #define GetPtr GlobalSharedPtrManager::getInstance().getSharedPtr #define GetWeakPtr GlobalSharedPtrManager::getInstance().getWeakPtrFromSharedPtr diff --git a/src/atom/server/variables.hpp b/src/atom/server/variables.hpp index 4be6fab5..52dfb6f7 100644 --- a/src/atom/server/variables.hpp +++ b/src/atom/server/variables.hpp @@ -29,7 +29,7 @@ Description: Variable Registry 类,用于注册、获取和观察变量值。 #include #endif -#include "atom/experiment/noncopyable.hpp" +#include "atom/type/noncopyable.hpp" #include "atom/experiment/string.hpp" #include "atom/error/error_stack.hpp" diff --git a/src/atom/experiment/platform.cpp b/src/atom/system/platform.cpp similarity index 100% rename from src/atom/experiment/platform.cpp rename to src/atom/system/platform.cpp diff --git a/src/atom/experiment/platform.hpp b/src/atom/system/platform.hpp similarity index 100% rename from src/atom/experiment/platform.hpp rename to src/atom/system/platform.hpp diff --git a/src/atom/experiment/any.hpp b/src/atom/type/any.hpp similarity index 100% rename from src/atom/experiment/any.hpp rename to src/atom/type/any.hpp diff --git a/src/atom/experiment/flatmap.hpp b/src/atom/type/flatmap.hpp similarity index 100% rename from src/atom/experiment/flatmap.hpp rename to src/atom/type/flatmap.hpp diff --git a/src/atom/type/flatset.hpp b/src/atom/type/flatset.hpp index 232c63db..dbb77206 100644 --- a/src/atom/type/flatset.hpp +++ b/src/atom/type/flatset.hpp @@ -23,6 +23,7 @@ Description: A FlatSet #include #include +namespace atom::type { template > class FlatSet { public: @@ -265,5 +266,6 @@ void swap(FlatSet& lhs, FlatSet& rhs) noexcept(noexcept(lhs.swap(rhs))) { lhs.swap(rhs); } +} // namespace atom::type #endif // ATOM_TYPE_FLAT_SET_HPP \ No newline at end of file diff --git a/src/atom/type/ini.cpp b/src/atom/type/ini.cpp index 4bf644d3..1753eb1a 100644 --- a/src/atom/type/ini.cpp +++ b/src/atom/type/ini.cpp @@ -19,6 +19,7 @@ Description: INI File Read/Write Library #include "atom/error/exception.hpp" +namespace atom::type { bool INIFile::has(const std::string §ion, const std::string &key) const { std::shared_lock lock(m_sharedMutex); auto it = data.find(section); @@ -42,7 +43,7 @@ void INIFile::load(const std::string &filename) { std::unique_lock lock(m_sharedMutex); std::ifstream file(filename); if (!file.is_open()) { - throw Atom::Error::FileNotReadable("Failed to open file: " + filename); + THROW_EXCEPTION("Failed to open file: " + filename); } std::string line; @@ -58,7 +59,7 @@ void INIFile::save(const std::string &filename) { std::unique_lock lock(m_sharedMutex); std::ofstream file(filename); if (!file.is_open()) { - throw Atom::Error::FileNotWritable("Failed to create file: " + + throw atom::error::FileNotWritable("Failed to create file: " + filename); } @@ -84,7 +85,7 @@ void INIFile::save(const std::string &filename) { file << entry.first << "=" << std::any_cast(entry.second) << "\n"; } else { - throw Atom::Error::InvalidArgument("Unsupported type"); + throw atom::error::InvalidArgument("Unsupported type"); } } file << "\n"; @@ -150,7 +151,7 @@ std::string INIFile::toJson() const { << "\": " << std::any_cast(entry.second) << ", "; } } catch (const std::bad_any_cast &e) { - throw Atom::Error::InvalidArgument("Unsupported type"); + throw atom::error::InvalidArgument("Unsupported type"); } } } @@ -194,7 +195,7 @@ std::string INIFile::toXml() const { << std::any_cast(entry.second) << "\n"; } } catch (const std::bad_any_cast &e) { - throw Atom::Error::InvalidArgument("Unsupported type"); + throw atom::error::InvalidArgument("Unsupported type"); } } oss << " \n"; @@ -202,42 +203,4 @@ std::string INIFile::toXml() const { oss << "\n"; return oss.str(); } - -/* -int main() -{ - INIFile ini; - try - { - ini.load("config.ini"); - - // 获取配置项 - std::optional usernameOpt = ini.get("User", -"Username"); std::optional passwordOpt = -ini.get("User", "Password"); - - if (usernameOpt.has_value() && passwordOpt.has_value()) - { - std::cout << "Username: " << usernameOpt.value() << std::endl; - std::cout << "Password: " << passwordOpt.value() << std::endl; - } - else - { - std::cout << "Username or Password not found" << std::endl; - } - - // 修改配置项 - ini.set("User", "Password", std::string("new_pas")); - - // 存储到文件 - ini.save("config_modified.ini"); - } - catch (const std::exception &e) - { - std::cerr << "Error: " << e.what() << std::endl; - } - - return 0; -} - -*/ \ No newline at end of file +} // namespace atom::type diff --git a/src/atom/type/ini.hpp b/src/atom/type/ini.hpp index 6ca870cd..805880e4 100644 --- a/src/atom/type/ini.hpp +++ b/src/atom/type/ini.hpp @@ -26,6 +26,8 @@ Description: INI File Read/Write Library #include #endif +namespace atom::type +{ class INIFile { public: /** @@ -86,10 +88,17 @@ class INIFile { * @param section 部分名 * @return 部分内容 */ +#if ENABLE_FASTHASH + emhash8::HashMap operator[]( + const std::string §ion) { + return data[section]; + } +#else std::unordered_map operator[]( const std::string §ion) { return data[section]; } +#endif /** * @brief 将INI文件中的数据转换为JSON字符串 @@ -126,7 +135,9 @@ class INIFile { */ std::string trim(const std::string &str); }; +} + -#include "ini_impl.hpp" +#include "ini.inl" #endif diff --git a/src/atom/type/ini_impl.hpp b/src/atom/type/ini.inl similarity index 90% rename from src/atom/type/ini_impl.hpp rename to src/atom/type/ini.inl index 77eeb5e3..7e16c5eb 100644 --- a/src/atom/type/ini_impl.hpp +++ b/src/atom/type/ini.inl @@ -1,5 +1,5 @@ /* - * ini_impl.hpp + * ini.inl * * Copyright (C) 2023-2024 Max Qian */ @@ -12,8 +12,13 @@ Description: INI File Read/Write Library **************************************************/ -#ifndef ATOM_TYPE_INI_IMPL_HPP -#define ATOM_TYPE_INI_IMPL_HPP +#ifndef ATOM_TYPE_INI_INL +#define ATOM_TYPE_INI_INL + +#include "ini.hpp" + +namespace atom::type +{ template void INIFile::set(const std::string §ion, const std::string &key, @@ -40,4 +45,6 @@ std::optional INIFile::get(const std::string §ion, return std::nullopt; } +} + #endif \ No newline at end of file diff --git a/src/atom/experiment/iter.hpp b/src/atom/type/iter.hpp similarity index 100% rename from src/atom/experiment/iter.hpp rename to src/atom/type/iter.hpp diff --git a/src/atom/experiment/list.hpp b/src/atom/type/list.hpp similarity index 100% rename from src/atom/experiment/list.hpp rename to src/atom/type/list.hpp diff --git a/src/atom/experiment/noncopyable.hpp b/src/atom/type/noncopyable.hpp similarity index 100% rename from src/atom/experiment/noncopyable.hpp rename to src/atom/type/noncopyable.hpp diff --git a/src/atom/experiment/optional.hpp b/src/atom/type/optional.hpp similarity index 100% rename from src/atom/experiment/optional.hpp rename to src/atom/type/optional.hpp diff --git a/src/atom/experiment/short_string.cpp b/src/atom/type/short_string.cpp similarity index 100% rename from src/atom/experiment/short_string.cpp rename to src/atom/type/short_string.cpp diff --git a/src/atom/experiment/short_string.hpp b/src/atom/type/short_string.hpp similarity index 100% rename from src/atom/experiment/short_string.hpp rename to src/atom/type/short_string.hpp diff --git a/src/atom/experiment/stack_vector.hpp b/src/atom/type/stack_vector.hpp similarity index 100% rename from src/atom/experiment/stack_vector.hpp rename to src/atom/type/stack_vector.hpp diff --git a/src/atom/experiment/sstring.hpp b/src/atom/type/static_string.hpp similarity index 100% rename from src/atom/experiment/sstring.hpp rename to src/atom/type/static_string.hpp diff --git a/src/atom/experiment/static_vector.hpp b/src/atom/type/static_vector.hpp similarity index 100% rename from src/atom/experiment/static_vector.hpp rename to src/atom/type/static_vector.hpp diff --git a/src/atom/experiment/string.cpp b/src/atom/type/string.cpp similarity index 100% rename from src/atom/experiment/string.cpp rename to src/atom/type/string.cpp diff --git a/src/atom/experiment/string.hpp b/src/atom/type/string.hpp similarity index 100% rename from src/atom/experiment/string.hpp rename to src/atom/type/string.hpp diff --git a/src/atom/experiment/anyutils.hpp b/src/atom/utils/anyutils.hpp similarity index 97% rename from src/atom/experiment/anyutils.hpp rename to src/atom/utils/anyutils.hpp index 1028967d..87f8d356 100644 --- a/src/atom/experiment/anyutils.hpp +++ b/src/atom/utils/anyutils.hpp @@ -218,19 +218,19 @@ template template [[nodiscard]] std::string toXml(const T &value, const std::string &tagName) { if constexpr (std::is_same_v || - std::is_same_v || std::is_same_v) - [[likely]] { + std::is_same_v || + std::is_same_v) { return "<" + tagName + ">" + value + ""; - } else if constexpr (std::is_arithmetic_v) [[likely]] { + } else if constexpr (std::is_arithmetic_v) { return "<" + tagName + ">" + std::to_string(value) + ""; - } else if constexpr (std::is_pointer_v) [[unlikely]] { + } else if constexpr (std::is_pointer_v) { if (value == nullptr) [[unlikely]] { return "<" + tagName + "null" + "/>"; } else [[likely]] { return toXml(*value, tagName); } - } else [[unlikely]] { + } else { return "<" + tagName + ">"; // Default to empty element for unknown type } diff --git a/src/atom/experiment/ranges.hpp b/src/atom/utils/ranges.hpp similarity index 100% rename from src/atom/experiment/ranges.hpp rename to src/atom/utils/ranges.hpp diff --git a/src/atom/utils/switch.hpp b/src/atom/utils/switch.hpp index f3e9ae43..a4783441 100644 --- a/src/atom/utils/switch.hpp +++ b/src/atom/utils/switch.hpp @@ -27,7 +27,7 @@ Description: Smart Switch just like javascript #endif #include "atom/error/exception.hpp" -#include "atom/experiment/noncopyable.hpp" +#include "atom/type/noncopyable.hpp" namespace Atom::Utils { /** diff --git a/src/atom/experiment/to_string.hpp b/src/atom/utils/to_string.hpp similarity index 100% rename from src/atom/experiment/to_string.hpp rename to src/atom/utils/to_string.hpp From 1c34612fb864e0d8054b361a67814ff88af2b3d3 Mon Sep 17 00:00:00 2001 From: Max Qian Date: Sun, 28 Apr 2024 20:03:00 +0800 Subject: [PATCH 2/4] update not finished -- rewrite component -- just move to codespace, my computer is so slow --- .../client/atom-hydrogen/hydrogencamera.cpp | 6 +- .../client/atom-hydrogen/hydrogencamera.hpp | 6 +- .../atom-hydrogen/hydrogenfilterwheel.cpp | 6 +- .../atom-hydrogen/hydrogenfilterwheel.hpp | 6 +- .../client/atom-hydrogen/hydrogenfocuser.cpp | 6 +- .../client/atom-hydrogen/hydrogenfocuser.hpp | 6 +- .../atom-hydrogen/hydrogentelescope.cpp | 6 +- .../atom-hydrogen/hydrogentelescope.hpp | 6 +- driver/solver/atom-astap/astap.cpp | 2 +- src/LithiumApp.cpp | 2 +- src/addon/manager.cpp | 6 +- src/addon/manager.hpp | 2 +- src/atom/CMakeLists.txt | 4 - src/atom/components/CMakeLists.txt | 21 +-- src/atom/components/abilities.hpp | 32 ++++ src/atom/components/base/main.cpp | 21 +-- src/atom/components/component.cpp | 110 ----------- src/atom/components/component.hpp | 51 ++++-- src/atom/components/component.inl | 171 +++++++++++++++++- src/atom/components/configor.hpp | 2 +- src/atom/components/dispatch.inl | 2 +- src/atom/components/ffi.hpp | 101 ----------- .../components/templates/exe_component.cpp | 8 +- src/atom/components/templates/shared.hpp | 3 +- .../templates/{shared.cpp => shared.inl} | 33 +++- src/atom/driver/device.cpp | 2 +- src/atom/error/_pybind.cpp | 95 ++++++++++ src/atom/error/error_stack.cpp | 4 +- src/atom/function/callable.hpp | 57 +++++- src/atom/function/ffi.hpp | 140 ++++++++++++++ src/atom/function/invoke.hpp | 14 ++ src/atom/io/_pybind.cpp | 106 +++++++++++ src/atom/io/_script.hpp | 2 +- src/atom/io/compress.cpp | 4 +- src/atom/io/compress.hpp | 4 +- src/atom/io/file.cpp | 4 +- src/atom/io/file.hpp | 4 +- src/atom/io/idirectory.cpp | 4 +- src/atom/io/idirectory.hpp | 4 +- src/atom/io/ifile.cpp | 4 +- src/atom/io/ifile.hpp | 4 +- src/atom/io/io.cpp | 6 +- src/atom/io/io.hpp | 4 +- src/atom/server/daemon.cpp | 4 +- src/atom/system/os.cpp | 2 +- src/atom/type/CMakeLists.txt | 3 +- src/atom/type/message.cpp | 9 +- src/atom/type/message.hpp | 7 +- src/atom/type/pointer.hpp | 34 +++- src/atom/utils/_script.hpp | 2 +- src/atom/utils/aes.cpp | 6 +- src/atom/utils/aes.hpp | 4 +- src/atom/utils/argsview.cpp | 4 +- src/atom/utils/argsview.hpp | 4 +- src/atom/utils/convert.cpp | 4 +- src/atom/utils/convert.hpp | 4 +- src/atom/utils/env.cpp | 4 +- src/atom/utils/env.hpp | 4 +- src/atom/utils/random.cpp | 4 +- src/atom/utils/random.hpp | 4 +- src/atom/utils/stopwatcher.cpp | 4 +- src/atom/utils/stopwatcher.hpp | 4 +- src/atom/utils/string.cpp | 4 +- src/atom/utils/string.hpp | 4 +- src/atom/utils/switch.hpp | 4 +- src/atom/utils/time.cpp | 4 +- src/atom/utils/time.hpp | 4 +- src/atom/utils/utf.cpp | 4 +- src/atom/utils/utf.hpp | 4 +- src/atom/utils/uuid.cpp | 4 +- src/atom/utils/uuid.hpp | 4 +- src/atom/utils/validate_aligned_storage.hpp | 4 +- src/atom/utils/xml.cpp | 4 +- src/atom/utils/xml.hpp | 4 +- src/preload.cpp | 6 +- .../websocket/template/error_message.hpp | 6 +- src/task/manager.hpp | 2 +- src/task/tick.cpp | 2 +- src/task/tick.hpp | 4 +- tests/atom/algorithm/md5.cpp | 4 +- 80 files changed, 835 insertions(+), 429 deletions(-) create mode 100644 src/atom/components/abilities.hpp delete mode 100644 src/atom/components/component.cpp delete mode 100644 src/atom/components/ffi.hpp rename src/atom/components/templates/{shared.cpp => shared.inl} (78%) create mode 100644 src/atom/error/_pybind.cpp create mode 100644 src/atom/function/ffi.hpp create mode 100644 src/atom/io/_pybind.cpp diff --git a/driver/client/atom-hydrogen/hydrogencamera.cpp b/driver/client/atom-hydrogen/hydrogencamera.cpp index 00f5be27..a4603572 100644 --- a/driver/client/atom-hydrogen/hydrogencamera.cpp +++ b/driver/client/atom-hydrogen/hydrogencamera.cpp @@ -21,11 +21,11 @@ Description: Hydorgen Camera HydrogenCamera::HydrogenCamera(const std::string &name) : Camera(name) { DLOG_F(INFO, "Hydorgen camera {} init successfully", name); m_number_switch = std::make_unique< - Atom::Utils::StringSwitch>(); + atom::utils::StringSwitch>(); m_switch_switch = std::make_unique< - Atom::Utils::StringSwitch>(); + atom::utils::StringSwitch>(); m_text_switch = std::make_unique< - Atom::Utils::StringSwitch>(); + atom::utils::StringSwitch>(); registerFunc("connect", &HydrogenCamera::connect, this); registerFunc("disconnect", &HydrogenCamera::disconnect, this); diff --git a/driver/client/atom-hydrogen/hydrogencamera.hpp b/driver/client/atom-hydrogen/hydrogencamera.hpp index c03ff6d6..01c6e306 100644 --- a/driver/client/atom-hydrogen/hydrogencamera.hpp +++ b/driver/client/atom-hydrogen/hydrogencamera.hpp @@ -381,11 +381,11 @@ class HydrogenCamera : public Camera, public HYDROGEN::BaseClient { std::atomic polling_period; - std::unique_ptr> + std::unique_ptr> m_number_switch; - std::unique_ptr> + std::unique_ptr> m_switch_switch; - std::unique_ptr> + std::unique_ptr> m_text_switch; private: diff --git a/driver/client/atom-hydrogen/hydrogenfilterwheel.cpp b/driver/client/atom-hydrogen/hydrogenfilterwheel.cpp index 0a348e66..8f1d7d69 100644 --- a/driver/client/atom-hydrogen/hydrogenfilterwheel.cpp +++ b/driver/client/atom-hydrogen/hydrogenfilterwheel.cpp @@ -23,11 +23,11 @@ HydrogenFilterwheel::HydrogenFilterwheel(const std::string &name) DLOG_F(INFO, "Hydrogen filterwheel {} init successfully", name); m_number_switch = std::make_unique< - Atom::Utils::StringSwitch>(); + atom::utils::StringSwitch>(); m_switch_switch = std::make_unique< - Atom::Utils::StringSwitch>(); + atom::utils::StringSwitch>(); m_text_switch = std::make_unique< - Atom::Utils::StringSwitch>(); + atom::utils::StringSwitch>(); m_switch_switch->registerCase( "CONNECTION", [this](HYDROGEN::PropertyViewSwitch *svp) { diff --git a/driver/client/atom-hydrogen/hydrogenfilterwheel.hpp b/driver/client/atom-hydrogen/hydrogenfilterwheel.hpp index 17d414fe..f3f3c838 100644 --- a/driver/client/atom-hydrogen/hydrogenfilterwheel.hpp +++ b/driver/client/atom-hydrogen/hydrogenfilterwheel.hpp @@ -76,11 +76,11 @@ class HydrogenFilterwheel : public Filterwheel, public HYDROGEN::BaseClient { std::string hydrogen_filter_version = ""; std::string hydrogen_filter_interface = ""; - std::unique_ptr> + std::unique_ptr> m_number_switch; - std::unique_ptr> + std::unique_ptr> m_switch_switch; - std::unique_ptr> + std::unique_ptr> m_text_switch; }; diff --git a/driver/client/atom-hydrogen/hydrogenfocuser.cpp b/driver/client/atom-hydrogen/hydrogenfocuser.cpp index 1bc94fb7..b6521ee3 100644 --- a/driver/client/atom-hydrogen/hydrogenfocuser.cpp +++ b/driver/client/atom-hydrogen/hydrogenfocuser.cpp @@ -22,11 +22,11 @@ HydrogenFocuser::HydrogenFocuser(const std::string &name) : Focuser(name) { DLOG_F(INFO, "Hydrogen Focuser {} init successfully", name); m_number_switch = std::make_unique< - Atom::Utils::StringSwitch>(); + atom::utils::StringSwitch>(); m_switch_switch = std::make_unique< - Atom::Utils::StringSwitch>(); + atom::utils::StringSwitch>(); m_text_switch = std::make_unique< - Atom::Utils::StringSwitch>(); + atom::utils::StringSwitch>(); m_switch_switch->registerCase( "CONNECTION", [this](HYDROGEN::PropertyViewSwitch *svp) { diff --git a/driver/client/atom-hydrogen/hydrogenfocuser.hpp b/driver/client/atom-hydrogen/hydrogenfocuser.hpp index da1a9f4f..45babc2a 100644 --- a/driver/client/atom-hydrogen/hydrogenfocuser.hpp +++ b/driver/client/atom-hydrogen/hydrogenfocuser.hpp @@ -225,11 +225,11 @@ class HydrogenFocuser : public Focuser, public HYDROGEN::BaseClient { std::string hydrogen_focuser_version = ""; // Hydrogen 设备固件版本 std::string hydrogen_focuser_interface = ""; // Hydrogen 接口版本 - std::unique_ptr> + std::unique_ptr> m_number_switch; - std::unique_ptr> + std::unique_ptr> m_switch_switch; - std::unique_ptr> + std::unique_ptr> m_text_switch; }; diff --git a/driver/client/atom-hydrogen/hydrogentelescope.cpp b/driver/client/atom-hydrogen/hydrogentelescope.cpp index 45130070..52b310b0 100644 --- a/driver/client/atom-hydrogen/hydrogentelescope.cpp +++ b/driver/client/atom-hydrogen/hydrogentelescope.cpp @@ -23,11 +23,11 @@ HydrogenTelescope::HydrogenTelescope(const std::string &name) DLOG_F(INFO, "Hydrogen telescope {} init successfully", name); m_number_switch = std::make_unique< - Atom::Utils::StringSwitch>(); + atom::utils::StringSwitch>(); m_switch_switch = std::make_unique< - Atom::Utils::StringSwitch>(); + atom::utils::StringSwitch>(); m_text_switch = std::make_unique< - Atom::Utils::StringSwitch>(); + atom::utils::StringSwitch>(); m_switch_switch->registerCase( "CONNECTION", [this](HYDROGEN::PropertyViewSwitch *svp) { diff --git a/driver/client/atom-hydrogen/hydrogentelescope.hpp b/driver/client/atom-hydrogen/hydrogentelescope.hpp index 39d52911..6d6723f2 100644 --- a/driver/client/atom-hydrogen/hydrogentelescope.hpp +++ b/driver/client/atom-hydrogen/hydrogentelescope.hpp @@ -217,10 +217,10 @@ class HydrogenTelescope : public Telescope, public HYDROGEN::BaseClient { std::string hydrogen_telescope_version = ""; // Hydrogen 设备固件版本 std::string hydrogen_telescope_interface = ""; // Hydrogen 接口版本 - std::unique_ptr> + std::unique_ptr> m_number_switch; - std::unique_ptr> + std::unique_ptr> m_switch_switch; - std::unique_ptr> + std::unique_ptr> m_text_switch; }; \ No newline at end of file diff --git a/driver/solver/atom-astap/astap.cpp b/driver/solver/atom-astap/astap.cpp index eb8b1363..7a06abc4 100644 --- a/driver/solver/atom-astap/astap.cpp +++ b/driver/solver/atom-astap/astap.cpp @@ -73,7 +73,7 @@ bool AstapSolver::solveImage(const std::string &image, const int &timeout, auto ret = Atom::Async::asyncRetry( [](const std::string &cmd) -> std::string { - return Atom::Utils::executeCommand(cmd, false); + return atom::utils::executeCommand(cmd, false); }, 3, std::chrono::seconds(5), cmd); diff --git a/src/LithiumApp.cpp b/src/LithiumApp.cpp index 4206c490..58e78a71 100644 --- a/src/LithiumApp.cpp +++ b/src/LithiumApp.cpp @@ -175,7 +175,7 @@ void InitLithiumApp(int argc, char **argv) { AddPtr("lithium.cmd.global", CommandDispatcher::createShared()); - AddPtr("lithium.utils.env", Atom::Utils::Env::createShared(argc, argv)); + AddPtr("lithium.utils.env", atom::utils::Env::createShared(argc, argv)); // TODO: Addons path need to be configurable AddPtr("lithium.addon.loader", ModuleLoader::createShared("./modules")); diff --git a/src/addon/manager.cpp b/src/addon/manager.cpp index d9af5ec9..bdd93191 100644 --- a/src/addon/manager.cpp +++ b/src/addon/manager.cpp @@ -47,7 +47,7 @@ ComponentManager::ComponentManager() : m_Sandbox(nullptr), m_Compiler(nullptr) { GetWeakPtr(constants::LITHIUM_MODULE_LOADER); CHECK_WEAK_PTR_EXPIRED(m_ModuleLoader, "load module loader from gpm: lithium.addon.loader"); - m_Env = GetWeakPtr(constants::LITHIUM_UTILS_ENV); + m_Env = GetWeakPtr(constants::LITHIUM_UTILS_ENV); CHECK_WEAK_PTR_EXPIRED(m_Env, "load env from gpm: lithium.utils.env"); m_AddonManager = GetWeakPtr(constants::LITHIUM_ADDON_MANAGER); @@ -140,10 +140,10 @@ bool ComponentManager::Initialize() { #ifdef _WIN32 // This is to pass file name check auto module_path_str = - Atom::Utils::replaceString(module_path.string(), "/", "\\"); + atom::utils::replaceString(module_path.string(), "/", "\\"); #else auto module_path_str = - Atom::Utils::replaceString(module_path.string(), "\\", "/"); + atom::utils::replaceString(module_path.string(), "\\", "/"); #endif // This step is to load the dynamic library diff --git a/src/addon/manager.hpp b/src/addon/manager.hpp index 57e18eca..39640e5d 100644 --- a/src/addon/manager.hpp +++ b/src/addon/manager.hpp @@ -272,7 +272,7 @@ class ComponentManager { private: std::weak_ptr m_ModuleLoader; - std::weak_ptr m_Env; + std::weak_ptr m_Env; // The finder used to find the components // std::unique_ptr m_ComponentFinder; diff --git a/src/atom/CMakeLists.txt b/src/atom/CMakeLists.txt index d2a23517..2565bfc4 100644 --- a/src/atom/CMakeLists.txt +++ b/src/atom/CMakeLists.txt @@ -31,8 +31,6 @@ add_subdirectory(async) add_subdirectory(components) add_subdirectory(connection) add_subdirectory(driver) -add_subdirectory(event) -add_subdirectory(experiment) add_subdirectory(io) add_subdirectory(log) add_subdirectory(server) @@ -81,8 +79,6 @@ list(APPEND ${PROJECT_NAME}_LIBS atom-task atom-io atom-driver - atom-event - atom-experiment atom-component atom-type atom-utils diff --git a/src/atom/components/CMakeLists.txt b/src/atom/components/CMakeLists.txt index 92ac89dc..b1d2cd00 100644 --- a/src/atom/components/CMakeLists.txt +++ b/src/atom/components/CMakeLists.txt @@ -3,34 +3,17 @@ project(atom-component C CXX) list(APPEND ${PROJECT_NAME}_SOURCES - component.cpp - + configor.cpp + dispatch.cpp types.cpp - - templates/alone_component.cpp - templates/exe_component.cpp - templates/script_component.cpp - templates/shared_component.cpp - templates/task_component.cpp ) # Headers list(APPEND ${PROJECT_NAME}_HEADERS - component.hpp - macro.hpp - - types.hpp - - templates/alone_component.hpp - templates/exe_component.hpp - templates/script_component.hpp - templates/shared_component.hpp - templates/task_component.hpp ) list(APPEND ${PROJECT_NAME}_LIBS loguru - atom-experiment atom-type atom-utils atom-server diff --git a/src/atom/components/abilities.hpp b/src/atom/components/abilities.hpp new file mode 100644 index 00000000..d686c303 --- /dev/null +++ b/src/atom/components/abilities.hpp @@ -0,0 +1,32 @@ +#ifndef ATOM_COMPONENTS_ABILITIES_HPP +#define ATOM_COMPONENTS_ABILITIES_HPP + +#include + +template +struct has_getValue { + template + static constexpr auto check(int) -> decltype(std::declval().getValue(), + std::true_type{}); + + template + static constexpr std::false_type check(...); + + static constexpr bool value = decltype(check(0))::value; +}; + +template +struct has_setValue { + template + static constexpr auto check(int) -> decltype(std::declval().setValue( + std::declval(), + std::declval()), + std::true_type{}); + + template + static constexpr std::false_type check(...); + + static constexpr bool value = decltype(check(0))::value; +}; + +#endif diff --git a/src/atom/components/base/main.cpp b/src/atom/components/base/main.cpp index 5217f034..c10a3d42 100644 --- a/src/atom/components/base/main.cpp +++ b/src/atom/components/base/main.cpp @@ -1,8 +1,8 @@ -#include "atom/components/templates/shared_component.hpp" +#include "atom/components/templates/shared.hpp" #include -class MySharedComponent : public SharedComponent { +class MySharedComponent : public SharedComponent { public: explicit MySharedComponent(const std::string &name); virtual ~MySharedComponent(); @@ -20,9 +20,8 @@ MySharedComponent::MySharedComponent(const std::string &name) initialize(); - registerFunc("helloWorld", &MySharedComponent::helloWorld, this); - - registerVariable("var_x", 0, "a test var"); + registerCommand("helloWorld", + [this](const json ¶ms) { return helloWorld(params); }); } MySharedComponent::~MySharedComponent() {} @@ -45,16 +44,6 @@ json MySharedComponent::helloWorld(const json ¶ms) { int main() { std::shared_ptr mycomponent = std::make_shared("mycomponent"); - mycomponent->runFunc("helloWorld", {{"aaa", "aaaa"}}); - auto myvar = mycomponent->getVariable("var_x"); - std::cout << (myvar.has_value() ? myvar.value() : -1) << std::endl; - mycomponent->setVariable("var_x", 1); - myvar = mycomponent->getVariable("var_x"); - std::cout << (myvar.has_value() ? myvar.value() : -1) << std::endl; - - mycomponent->runFunc( - "registerVariable", - {{"name", "status"}, {"value", "ok"}, {"description", "a test value"}}); - std::cout << mycomponent->getVariableInfo("status") << std::endl; + mycomponent->dispatch("helloWorld", json::object({"message", "hello"})); return 0; } \ No newline at end of file diff --git a/src/atom/components/component.cpp b/src/atom/components/component.cpp deleted file mode 100644 index 3eb15494..00000000 --- a/src/atom/components/component.cpp +++ /dev/null @@ -1,110 +0,0 @@ -/* - * component.cpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2023-8-6 - -Description: Basic Component Definition - -**************************************************/ - -#include "component.hpp" - -#include -#include -namespace fs = std::filesystem; - -#include "atom/error/exception.hpp" -#include "atom/log/loguru.hpp" -#include "atom/utils/string.hpp" - -#if __cplusplus >= 202002L -#include -#else -#include -#endif - -Component::Component(const std::string& name) - : m_name(name), - m_ConfigManager(std::make_unique()), - m_CommandDispatcher(std::make_unique()), - m_VariableManager(std::make_unique()), - m_typeInfo(user_type()) { - // Empty -} - -Component::~Component() { - // Empty -} - -bool Component::initialize() { return true; } - -bool Component::destroy() { return true; } - -std::string Component::getName() const { return m_name; } - -std::optional Component::getValue(const std::string& key_path) const { - return m_ConfigManager->getValue(key_path); -} - -bool Component::setValue(const std::string& key_path, const json& value) { - return m_ConfigManager->setValue(key_path, value); -} - -bool Component::hasValue(const std::string& key_path) const { - return getValue(key_path).has_value(); -} - -bool Component::loadFromFile(const fs::path& path) { - return m_ConfigManager->loadFromFile(path); -} - -bool Component::saveToFile(const fs::path& file_path) const { - return m_ConfigManager->saveToFile(file_path); -} - -void Component::addAlias(const std::string& name, const std::string& alias) { - m_CommandDispatcher->addAlias(name, alias); -} - -void Component::addGroup(const std::string& name, const std::string& group) { - m_CommandDispatcher->addGroup(name, group); -} - -void Component::setTimeout(const std::string& name, - std::chrono::milliseconds timeout) { - m_CommandDispatcher->setTimeout(name, timeout); -} - -void Component::clearCache() { m_CommandDispatcher->clearCache(); } - -void Component::removeCommand(const std::string& name) { - m_CommandDispatcher->removeCommand(name); -} - -std::vector Component::getCommandsInGroup( - const std::string& group) const { - return m_CommandDispatcher->getCommandsInGroup(group); -} - -std::string Component::getCommandDescription(const std::string& name) const - -{ - return m_CommandDispatcher->getCommandDescription(name); -} - -#if ENABLE_FASTHASH -emhash::HashSet Component::getCommandAliases( - const std::string& name) const -#else -std::unordered_set Component::getCommandAliases( - const std::string& name) const -#endif - -{ - return m_CommandDispatcher->getCommandAliases(name); -} \ No newline at end of file diff --git a/src/atom/components/component.hpp b/src/atom/components/component.hpp index 65e6737b..110fd0de 100644 --- a/src/atom/components/component.hpp +++ b/src/atom/components/component.hpp @@ -16,8 +16,8 @@ Description: Basic Component Definition #define ATOM_COMPONENT_HPP #include -#include #include +#include #include "types.hpp" @@ -26,10 +26,12 @@ Description: Basic Component Definition #include "configor.hpp" +#include "atom/function/type_info.hpp" #include "atom/type/noncopyable.hpp" -#include "atom/experiment/type_info.hpp" -class Component : public std::enable_shared_from_this, public NonCopyable { +template +class Component : public std::enable_shared_from_this, + public NonCopyable { public: /** * @brief Constructs a new Component object. @@ -65,6 +67,10 @@ class Component : public std::enable_shared_from_this, public NonCopy */ virtual bool destroy(); + std::unordered_map getComponentAbilities() const; + + bool hasAbility(const std::string& ability) const; + /** * @brief Gets the name of the plugin. * @@ -72,6 +78,8 @@ class Component : public std::enable_shared_from_this, public NonCopy */ std::string getName() const; + Type_Info getTypeInfo() const; + // ------------------------------------------------------------------- // Component Configuration methods // ------------------------------------------------------------------- @@ -103,7 +111,7 @@ class Component : public std::enable_shared_from_this, public NonCopy [[nodiscard("status of the value should not be ignored")]] bool hasValue( const std::string& key_path) const; - /** + /** * @brief 从指定文件中加载JSON配置,并与原有配置进行合并 * * Load JSON configuration from the specified file and merge with the @@ -176,8 +184,7 @@ class Component : public std::enable_shared_from_this, public NonCopy const std::string& name, const std::string& group, const std::string& description, std::function func, std::optional> precondition = std::nullopt, - std::optional> postcondition = std::nullopt) - { + std::optional> postcondition = std::nullopt) { m_CommandDispatcher->registerCommand(name, group, description, func, precondition, postcondition); } @@ -241,8 +248,7 @@ class Component : public std::enable_shared_from_this, public NonCopy void setTimeout(const std::string& name, std::chrono::milliseconds timeout); template - std::any dispatch(const std::string& name, Args&&... args) - { + std::any dispatch(const std::string& name, Args&&... args) { return m_CommandDispatcher->dispatch(name, std::forward(args)...); } @@ -262,6 +268,28 @@ class Component : public std::enable_shared_from_this, public NonCopy const std::string& name) const; #endif + // ------------------------------------------------------------------- + // Other Components methods + // ------------------------------------------------------------------- + /** + * @note This method is not thread-safe. And we must make sure the pointer + * is valid. The PointerSentinel will help you to avoid this problem. We + * will directly get the std::weak_ptr from the pointer. + */ + + /** + * @return The names of the components that are needed by this component. + * @note This will be called when the component is initialized. + */ + std::vector getNeededComponents() const; + + void addOtherComponent(const std::string& name, + const PointerSentinel& component); + + void removeOtherComponent(const std::string& name); + + void clearOtherComponents(); + private: std::string m_name; std::string m_configPath; @@ -272,9 +300,10 @@ class Component : public std::enable_shared_from_this, public NonCopy m_CommandDispatcher; ///< The command dispatcher for managing commands. std::unique_ptr m_VariableManager; ///< The variable registry for managing variables. - std::unique_ptr - m_ConfigManager; - + std::unique_ptr m_ConfigManager; + + std::unordered_map> m_OtherComponents; + std::mutex m_mutex; }; diff --git a/src/atom/components/component.inl b/src/atom/components/component.inl index 1edf9772..fb2c2831 100644 --- a/src/atom/components/component.inl +++ b/src/atom/components/component.inl @@ -1,18 +1,169 @@ #ifndef ATOM_COMPONENT_INL #define ATOM_COMPONENT_INL -#include +#include "abilities.hpp" +#include "component.hpp" -template -struct has_getValue { - template - static constexpr auto check(int) -> decltype(std::declval().getValue(), - std::true_type{}); +#include +#include +namespace fs = std::filesystem; - template - static constexpr std::false_type check(...); +#include "atom/error/exception.hpp" +#include "atom/log/loguru.hpp" +#include "atom/utils/string.hpp" - static constexpr bool value = decltype(check(0))::value; -}; +#if __cplusplus >= 202002L +#include +#else +#include +#endif + +template +Component::Component(const std::string& name) + : m_name(name), + m_ConfigManager(std::make_unique()), + m_CommandDispatcher(std::make_unique()), + m_VariableManager(std::make_unique()), + m_typeInfo(user_type()) { + // Empty +} + +template +Component::~Component() { + // Empty +} +template +bool Component::initialize() { + return static_cast(this)->initialize(); +} + +template +bool Component::destroy() { + LOG_F(INFO, "Destroying component: {}", m_name); + return static_cast(this)->destroy(); +} + +template +std::string Component::getName() const { + return m_name; +} + +template +Type_Info Component::getTypeInfo() const { + return m_typeInfo; +} + +template +std::unordered_map +Component::getComponentAbilities() const { + std::unordered_map abilities; + bool has_getValue_ = has_getValue::value; + bool has_setValue_ = has_setValue::value; + return abilities; +} + +template +bool Component::hasAbility(const std::string& ability) const { + return getComponentAbilities().contains(ability); +} + +template +std::optional Component::getValue( + const std::string& key_path) const { + return m_ConfigManager->getValue(key_path); +} + +template +bool Component::setValue(const std::string& key_path, + const json& value) { + return m_ConfigManager->setValue(key_path, value); +} + +template +bool Component::hasValue(const std::string& key_path) const { + return getValue(key_path).has_value(); +} + +template +bool Component::loadFromFile(const fs::path& path) { + return m_ConfigManager->loadFromFile(path); +} + +template +bool Component::saveToFile(const fs::path& file_path) const { + return m_ConfigManager->saveToFile(file_path); +} + +template +void Component::addAlias(const std::string& name, + const std::string& alias) { + m_CommandDispatcher->addAlias(name, alias); +} + +template +void Component::addGroup(const std::string& name, + const std::string& group) { + m_CommandDispatcher->addGroup(name, group); +} + +template +void Component::setTimeout(const std::string& name, + std::chrono::milliseconds timeout) { + m_CommandDispatcher->setTimeout(name, timeout); +} + +template +void Component::clearCache() { + m_CommandDispatcher->clearCache(); +} + +template +void Component::removeCommand(const std::string& name) { + m_CommandDispatcher->removeCommand(name); +} + +template +std::vector Component::getCommandsInGroup( + const std::string& group) const { + return m_CommandDispatcher->getCommandsInGroup(group); +} + +template +std::string Component::getCommandDescription( + const std::string& name) const { + return m_CommandDispatcher->getCommandDescription(name); +} + +template +#if ENABLE_FASTHASH +emhash::HashSet Component::getCommandAliases( + const std::string& name) const +#else +std::unordered_set Component::getCommandAliases( + const std::string& name) const +#endif +{ + return m_CommandDispatcher->getCommandAliases(name); +} +template +std::vector Component::getNeededComponents() const { + return static_cast(this)->getNeededComponents(); +} + +template +void Component::addOtherComponent( + const std::string& name, const PointerSentinel& component) { + m_OtherComponents[name] = std::move(component); +} + +template +void Component::removeOtherComponent(const std::string& name) { + m_OtherComponents.erase(name); +} + +template +void Component::clearOtherComponents() { + m_OtherComponents.clear(); +} #endif diff --git a/src/atom/components/configor.hpp b/src/atom/components/configor.hpp index 3f95a574..e6798802 100644 --- a/src/atom/components/configor.hpp +++ b/src/atom/components/configor.hpp @@ -20,7 +20,7 @@ Description: Configor #include namespace fs = std::filesystem; -#include "error/error_code.hpp" +#include "atom/error/error_code.hpp" #include "atom/type/json.hpp" using json = nlohmann::json; diff --git a/src/atom/components/dispatch.inl b/src/atom/components/dispatch.inl index 7c82f308..93203d1a 100644 --- a/src/atom/components/dispatch.inl +++ b/src/atom/components/dispatch.inl @@ -4,7 +4,7 @@ #include "dispatch.hpp" #include "atom/error/exception.hpp" -#include "atom/type/abi.hpp" +#include "atom/function/abi.hpp" template void CommandDispatcher::registerCommand( diff --git a/src/atom/components/ffi.hpp b/src/atom/components/ffi.hpp deleted file mode 100644 index dbff964f..00000000 --- a/src/atom/components/ffi.hpp +++ /dev/null @@ -1,101 +0,0 @@ -#ifndef ATOM_COMPONENT_FFI_HPP -#define ATOM_COMPONENT_FFI_HPP - -#include -#include -#include -#include -#include -#include - -// Exception class for FFI errors -class FFIException : public std::exception { -public: - explicit FFIException(const std::string &message) : message_(message) {} - const char *what() const noexcept override { return message_.c_str(); } - -private: - std::string message_; -}; - -template -class FFIWrapper { -public: - FFIWrapper(ffi_type **argTypes, int numArgs, ffi_type *returnType) - : argTypes_(argTypes), numArgs_(numArgs), returnType_(returnType) { - cif_ = new ffi_cif; - ffi_prep_cif(cif_, FFI_DEFAULT_ABI, numArgs_, returnType_, argTypes_); - } - - template - ReturnType call(void *funcPtr, CallArgs... args) { - if constexpr (sizeof...(CallArgs) != sizeof...(Args)) { - throw FFIException("Incorrect number of arguments provided."); - } - - void *argsArray[] = {&args...}; - ReturnType result; - ffi_call(cif_, FFI_FN(funcPtr), &result, argsArray); - return result; - } - - ~FFIWrapper() { delete cif_; } - -private: - ffi_cif *cif_; - ffi_type **argTypes_; - int numArgs_; - ffi_type *returnType_; -}; - -class DynamicLibrary { -public: - explicit DynamicLibrary(const std::string &libraryPath) : handle_(nullptr) { - handle_ = dlopen(libraryPath.c_str(), RTLD_LAZY); - if (!handle_) { - throw FFIException("Failed to load dynamic library."); - } - } - - ~DynamicLibrary() { - if (handle_) { - dlclose(handle_); - } - } - - template - void addFunction(const std::string &functionName) { - void *funcPtr = dlsym(handle_, functionName.c_str()); - if (!funcPtr) { - throw FFIException("Failed to find symbol."); - } - functionMap_[functionName] = funcPtr; - } - - template - ReturnType callFunction(const std::string &functionName, Args... args) { - auto it = functionMap_.find(functionName); - if (it == functionMap_.end()) { - throw FFIException("Function not found in the library."); - } - - void *funcPtr = it->second; - - ffi_type **argTypes = new ffi_type *[sizeof...(Args)]; - for (size_t i = 0; i < sizeof...(Args); ++i) { - argTypes[i] = &ffi_type_pointer; - } - - ffi_type *returnType = &ffi_type_pointer; - - FFIWrapper ffiWrapper(argTypes, sizeof...(Args), - returnType); - return ffiWrapper.call(funcPtr, args...); - } - -private: - void *handle_; - std::unordered_map functionMap_; -}; - -#endif diff --git a/src/atom/components/templates/exe_component.cpp b/src/atom/components/templates/exe_component.cpp index 2d5597f7..8f477d52 100644 --- a/src/atom/components/templates/exe_component.cpp +++ b/src/atom/components/templates/exe_component.cpp @@ -39,7 +39,7 @@ json ExecutableComponent::RunSystemCommand(const json ¶ms) DLOG_F(INFO, "Running command: {}", command); if (m_ProcessManager) { - if (!m_ProcessManager->createProcess(command, identifier.empty() ? Atom::Utils::generateRandomString(10) : identifier)) + if (!m_ProcessManager->createProcess(command, identifier.empty() ? atom::utils::generateRandomString(10) : identifier)) { LOG_F(ERROR, "Failed to run executable plugin : {}", command); return createErrorResponse(__func__, json(), std::format("Failed to run executable plugin : {}", command)); @@ -63,7 +63,7 @@ json ExecutableComponent::RunSystemCommandOutput(const json ¶ms) if (m_ProcessManager) { DLOG_F(INFO, "Running command: {}", command); - if (m_ProcessManager->createProcess(command, identifier.empty() ? Atom::Utils::generateRandomString(10) : identifier)) + if (m_ProcessManager->createProcess(command, identifier.empty() ? atom::utils::generateRandomString(10) : identifier)) { LOG_F(ERROR, "Started {} successfully", command); return createSuccessResponse(__func__, json()); @@ -87,7 +87,7 @@ json ExecutableComponent::RunScript(const json ¶ms) if (m_ProcessManager) { DLOG_F(INFO, "Running script: {}", script); - if (m_ProcessManager->createProcess(script, identifier.empty() ? Atom::Utils::generateRandomString(10) : identifier)) + if (m_ProcessManager->createProcess(script, identifier.empty() ? atom::utils::generateRandomString(10) : identifier)) { LOG_F(ERROR, "Started {} successfully", script); return createSuccessResponse(__func__, json()); @@ -111,7 +111,7 @@ json ExecutableComponent::RunScriptOutput(const json ¶ms) if (m_ProcessManager) { DLOG_F(INFO, "Running script: {}", script); - if (m_ProcessManager->createProcess(script, identifier.empty() ? Atom::Utils::generateRandomString(10) : identifier)) + if (m_ProcessManager->createProcess(script, identifier.empty() ? atom::utils::generateRandomString(10) : identifier)) { LOG_F(ERROR, "Started {} successfully", script); return createSuccessResponse(__func__, json()); diff --git a/src/atom/components/templates/shared.hpp b/src/atom/components/templates/shared.hpp index ba51cb50..76b6f32f 100644 --- a/src/atom/components/templates/shared.hpp +++ b/src/atom/components/templates/shared.hpp @@ -5,7 +5,8 @@ #include "atom/type/message.hpp" -class SharedComponent : public Component { +template +class SharedComponent : public Component { explicit SharedComponent(const std::string &name); virtual ~SharedComponent() override; diff --git a/src/atom/components/templates/shared.cpp b/src/atom/components/templates/shared.inl similarity index 78% rename from src/atom/components/templates/shared.cpp rename to src/atom/components/templates/shared.inl index b8c9863e..22adaba1 100644 --- a/src/atom/components/templates/shared.cpp +++ b/src/atom/components/templates/shared.inl @@ -1,3 +1,6 @@ +#ifndef ATOM_COMPONENT_SHARED_INL +#define ATOM_COMPONENT_SHARED_INL + #include "shared.hpp" #include "atom/error/exception.hpp" @@ -8,7 +11,8 @@ using namespace atom::error; -SharedComponent::SharedComponent(const std::string &name) : Component(name) { +template +SharedComponent::SharedComponent(const std::string &name) : Component(name) { m_handleFunction = [shared_this = shared_from_this()](const std::any &message) { LOG_F(INFO, "SharedComponent::handleFunction"); @@ -54,19 +58,23 @@ SharedComponent::SharedComponent(const std::string &name) : Component(name) { registerCommand("handleVoid", handleVoidMessage); } -SharedComponent::~SharedComponent() {} +template +SharedComponent::~SharedComponent() {} -bool SharedComponent::initialize() { return true; } +template +bool SharedComponent::initialize() { return true; } -bool SharedComponent::destroy() { return true; } +template +bool SharedComponent::destroy() { return true; } -void SharedComponent::handleVoidMessage( +template +void SharedComponent::handleVoidMessage( const std::shared_ptr &message) { LOG_F(INFO, "SharedComponent::handleVoid"); auto name = message->name(); try { - + dispatch(name); } catch(const std::exception& e) { @@ -75,17 +83,22 @@ void SharedComponent::handleVoidMessage( } -void SharedComponent::handleTextMessage( +template +void SharedComponent::handleTextMessage( const std::shared_ptr &message) { LOG_F(INFO, "SharedComponent::handleText"); } -void SharedComponent::handleBooleanMessage( +template +void SharedComponent::handleBooleanMessage( const std::shared_ptr &message) { LOG_F(INFO, "SharedComponent::handleBoolean"); } -void SharedComponent::handleNumberMessage( +template +void SharedComponent::handleNumberMessage( const std::shared_ptr &message) { LOG_F(INFO, "SharedComponent::handleNumber"); -} \ No newline at end of file +} + +#endif diff --git a/src/atom/driver/device.cpp b/src/atom/driver/device.cpp index a92e9eb2..810a9779 100644 --- a/src/atom/driver/device.cpp +++ b/src/atom/driver/device.cpp @@ -32,7 +32,7 @@ AtomDriver::~AtomDriver() {} bool AtomDriver::initialize() { SharedComponent::initialize(); - Atom::Utils::UUIDGenerator generator; + atom::utils::UUIDGenerator generator; m_uuid = generator.generateUUID(); registerVariable("DEVICE_NAME", m_name); diff --git a/src/atom/error/_pybind.cpp b/src/atom/error/_pybind.cpp new file mode 100644 index 00000000..f574a5f7 --- /dev/null +++ b/src/atom/error/_pybind.cpp @@ -0,0 +1,95 @@ +#include + +#include "error_code.hpp" +#include "error_stack.hpp" +#include "exception.hpp" + +namespace py = pybind11; + +using namespace atom::error; + +PYBIND11_MODULE(atom_error, m) { + py::enum_(m, "LIError") + .value("None", LIError::None) + .value("NotFound", LIError::NotFound) + .value("OpenError", LIError::OpenError) + .value("AccessDenied", LIError::AccessDenied) + .value("ReadError", LIError::ReadError) + .value("WriteError", LIError::WriteError) + .value("PermissionDenied", LIError::PermissionDenied) + .value("ParseError", LIError::ParseError) + .value("InvalidPath", LIError::InvalidPath) + .value("FileExists", LIError::FileExists) + .value("DirectoryNotEmpty", LIError::DirectoryNotEmpty) + .value("TooManyOpenFiles", LIError::TooManyOpenFiles) + .value("DiskFull", LIError::DiskFull) + .value("LoadError", LIError::LoadError) + .value("UnLoadError", LIError::UnLoadError); + + py::enum_(m, "DeviceError") + .value("None", DeviceError::None) + .value("NotSpecific", DeviceError::NotSpecific) + .value("NotFound", DeviceError::NotFound) + .value("NotSupported", DeviceError::NotSupported) + .value("NotConnected", DeviceError::NotConnected) + .value("MissingValue", DeviceError::MissingValue) + .value("InvalidValue", DeviceError::InvalidValue) + .value("Busy", DeviceError::Busy) + .value("ExposureError", DeviceError::ExposureError) + .value("GainError", DeviceError::GainError) + .value("OffsetError", DeviceError::OffsetError) + .value("ISOError", DeviceError::ISOError) + .value("CoolingError", DeviceError::CoolingError) + .value("GotoError", DeviceError::GotoError) + .value("ParkError", DeviceError::ParkError) + .value("UnParkError", DeviceError::UnParkError) + .value("ParkedError", DeviceError::ParkedError) + .value("HomeError", DeviceError::HomeError); + + py::enum_(m, "DeviceWarning") + .value("ExposureWarning", DeviceWarning::ExposureWarning) + .value("GainWarning", DeviceWarning::GainWarning) + .value("OffsetWarning", DeviceWarning::OffsetWarning) + .value("ISOWarning", DeviceWarning::ISOWarning) + .value("CoolingWarning", DeviceWarning::CoolingWarning) + .value("GotoWarning", DeviceWarning::GotoWarning) + .value("ParkWarning", DeviceWarning::ParkWarning) + .value("UnParkWarning", DeviceWarning::UnParkWarning) + .value("ParkedWarning", DeviceWarning::ParkedWarning) + .value("HomeWarning", DeviceWarning::HomeWarning); + + py::enum_(m, "ServerError") + .value("None", ServerError::None) + .value("InvalidParameters", ServerError::InvalidParameters) + .value("InvalidFormat", ServerError::InvalidFormat) + .value("MissingParameters", ServerError::MissingParameters) + .value("RunFailed", ServerError::RunFailed) + .value("UnknownError", ServerError::UnknownError) + .value("UnknownCommand", ServerError::UnknownCommand) + .value("UnknownDevice", ServerError::UnknownDevice) + .value("UnknownDeviceType", ServerError::UnknownDeviceType) + .value("UnknownDeviceName", ServerError::UnknownDeviceName) + .value("UnknownDeviceID", ServerError::UnknownDeviceID); + + py::class_(m, "ErrorInfo") + .def(py::init<>()) + .def_readwrite("errorMessage", &ErrorInfo::errorMessage) + .def_readwrite("moduleName", &ErrorInfo::moduleName) + .def_readwrite("functionName", &ErrorInfo::functionName) + .def_readwrite("line", &ErrorInfo::line) + .def_readwrite("fileName", &ErrorInfo::fileName) + .def_readwrite("timestamp", &ErrorInfo::timestamp) + .def_readwrite("uuid", &ErrorInfo::uuid); + + py::class_(m, "ErrorStack") + .def(py::init<>()) + .def("createShared", &ErrorStack::createShared) + .def("createUnique", &ErrorStack::createUnique) + .def("insertError", &ErrorStack::insertError) + .def("setFilteredModules", &ErrorStack::setFilteredModules) + .def("clearFilteredModules", &ErrorStack::clearFilteredModules) + .def("printFilteredErrorStack", &ErrorStack::printFilteredErrorStack) + .def("getFilteredErrorsByModule", + &ErrorStack::getFilteredErrorsByModule) + .def("getCompressedErrors", &ErrorStack::getCompressedErrors); +} diff --git a/src/atom/error/error_stack.cpp b/src/atom/error/error_stack.cpp index a042873d..d24755a3 100644 --- a/src/atom/error/error_stack.cpp +++ b/src/atom/error/error_stack.cpp @@ -29,7 +29,7 @@ std::ostream &operator<<(std::ostream &os, const ErrorInfo &error) { << "\"line\": " << error.line << "," << "\"fileName\": \"" << error.fileName << "\"," << "\"timestamp\": \"" - << Atom::Utils::timeStampToString(error.timestamp) << "\"," + << atom::utils::timeStampToString(error.timestamp) << "\"," << "\"uuid\": \"" << error.uuid << "\"" << "}"; @@ -45,7 +45,7 @@ std::string operator<<(const std::string &str, const ErrorInfo &error) { << "\"line\": " << error.line << "," << "\"fileName\": \"" << error.fileName << "\"," << "\"timestamp\": \"" - << Atom::Utils::timeStampToString(error.timestamp) << "\"," + << atom::utils::timeStampToString(error.timestamp) << "\"," << "\"uuid\": \"" << error.uuid << "\"" << "}"; diff --git a/src/atom/function/callable.hpp b/src/atom/function/callable.hpp index f67c5519..d14920b6 100644 --- a/src/atom/function/callable.hpp +++ b/src/atom/function/callable.hpp @@ -12,8 +12,8 @@ Description: make a callabel object **************************************************/ -#ifndef ATOM_EXPERIMENT_CALLABLE_HPP -#define ATOM_EXPERIMENT_CALLABLE_HPP +#ifndef ATOM_FUNCTION_CALLABLE_HPP +#define ATOM_FUNCTION_CALLABLE_HPP #include #include @@ -23,7 +23,7 @@ Description: make a callabel object template struct Constructor { template - auto operator()(Inner &&...inner) const -> std::shared_ptr { + auto operator()(Inner&&... inner) const -> std::shared_ptr { return std::make_shared(std::forward(inner)...); } }; @@ -35,7 +35,7 @@ struct Const_Caller { : m_func(t_func) {} template - constexpr auto operator()(const Class &o, Inner &&...inner) const + constexpr auto operator()(const Class& o, Inner&&... inner) const noexcept(noexcept((o.*m_func)(std::forward(inner)...))) -> Ret { return (o.*m_func)(std::forward(inner)...); } @@ -49,7 +49,7 @@ struct Fun_Caller { : m_func(t_func) {} template - constexpr auto operator()(Inner &&...inner) const + constexpr auto operator()(Inner&&... inner) const noexcept(noexcept(m_func(std::forward(inner)...))) -> Ret { return m_func(std::forward(inner)...); } @@ -63,7 +63,7 @@ struct Caller { : m_func(t_func) {} template - constexpr auto operator()(Class &o, Inner &&...inner) const + constexpr auto operator()(Class& o, Inner&&... inner) const noexcept(noexcept((o.*m_func)(std::forward(inner)...))) -> Ret { return (o.*m_func)(std::forward(inner)...); } @@ -72,8 +72,8 @@ struct Caller { }; template -struct Arity : std::integral_constant>::value> {}; +struct Arity + : std::integral_constant>> {}; template struct Function_Signature; @@ -98,4 +98,43 @@ struct Callable_Traits { decltype(&std::remove_reference_t::operator())>::Return_Type; }; -#endif // ATOM_EXPERIMENT_CALLABLE_HPP \ No newline at end of file +template +struct Fun_Caller_Noexcept { + explicit constexpr Fun_Caller_Noexcept(Ret (*t_func)(Param...) noexcept) + : m_func(t_func) {} + + template + constexpr auto operator()(Inner&&... inner) const noexcept -> Ret { + return m_func(std::forward(inner)...); + } + Ret (*m_func)(Param...) noexcept; +}; + +template +struct Caller_Noexcept { + explicit constexpr Caller_Noexcept(Ret (Class::*t_func)(Param...) noexcept) + : m_func(t_func) {} + + template + constexpr auto operator()(Class& o, + Inner&&... inner) const noexcept -> Ret { + return (o.*m_func)(std::forward(inner)...); + } + + Ret (Class::*m_func)(Param...) noexcept; +}; + +template +struct Is_Noexcept_Callable : std::false_type {}; + +template +struct Is_Noexcept_Callable : std::true_type {}; + +template +struct Is_Noexcept_Callable + : std::true_type {}; + +template +constexpr bool Is_Noexcept_Callable_v = Is_Noexcept_Callable::value; + +#endif // ATOM_FUNCTION_CALLABLE_HPP \ No newline at end of file diff --git a/src/atom/function/ffi.hpp b/src/atom/function/ffi.hpp new file mode 100644 index 00000000..1a6812de --- /dev/null +++ b/src/atom/function/ffi.hpp @@ -0,0 +1,140 @@ +/* + * ffi.hpp + * + * Copyright (C) 2023-2024 Max Qian + */ + +/************************************************* + +Date: 2023-3-29 + +Description: FFI Function + +**************************************************/ + +#ifndef ATOM_FUNCTION_FFI_HPP +#define ATOM_FUNCTION_FFI_HPP + +#ifdef _MSC_VER +#include +#else +#include +#endif +#include +#include +#include +#include +#include +#include +#include + +#include "atom/error/exception.hpp" +#include "atom/type/noncopyable.hpp" + +class FFIException : public std::exception { +public: + explicit FFIException(const std::string &message) : message_(message) {} + const char *what() const noexcept override { return message_.c_str(); } + +private: + std::string message_; +}; + +template +constexpr ffi_type *getFFIType() { + if constexpr (std::is_same_v) { + return &ffi_type_sint; + } else if constexpr (std::is_same_v) { + return &ffi_type_float; + } else if constexpr (std::is_same_v) { + return &ffi_type_double; + } else if constexpr (std::is_same_v) { + return &ffi_type_pointer; + } else { + return &ffi_type_pointer; + } +} + +template +class FFIWrapper { +public: + FFIWrapper() { + argTypes_ = {getFFIType()...}; + returnType_ = getFFIType(); + + if (ffi_prep_cif(&cif_, FFI_DEFAULT_ABI, sizeof...(Args), returnType_, + argTypes_.data()) != FFI_OK) { + throw FFIException("Failed to prepare FFI call interface."); + } + } + + ReturnType call(void *funcPtr, Args... args) { + void *argsArray[] = {&args...}; + ReturnType result; + + ffi_call(&cif_, FFI_FN(funcPtr), &result, argsArray); + return result; + } + +private: + ffi_cif cif_; + std::vector argTypes_; + ffi_type *returnType_; +}; + +class DynamicLibrary : public NonCopyable { +public: + explicit DynamicLibrary(const std::string &libraryPath) : handle_(nullptr) { +#ifdef _MSC_VER + handle_ = LoadLibrary(libraryPath.c_str()); +#else + handle_ = dlopen(libraryPath.c_str(), RTLD_LAZY); +#endif + if (!handle_) { + throw FFIException("Failed to load dynamic library."); + } + } + + ~DynamicLibrary() { + if (handle_) { +#ifdef _MSC_VER + FreeLibrary((HMODULE)handle_); +#else + dlclose(handle_); +#endif + } + } + + template + void addFunction(const std::string &functionName) { +#ifdef _MSC_VER + void *funcPtr = + (void *)GetProcAddress((HMODULE)handle_, functionName.c_str()); +#else + void *funcPtr = dlsym(handle_, functionName.c_str()); +#endif + if (!funcPtr) { + throw FFIException("Failed to find symbol."); + } + functionMap_[functionName] = funcPtr; + } + + template + ReturnType callFunction(const std::string &functionName, Args... args) { + auto it = functionMap_.find(functionName); + if (it == functionMap_.end()) { + throw FFIException("Function not found in the library."); + } + + void *funcPtr = it->second; + FFIWrapper ffiWrapper; + + return ffiWrapper.call(funcPtr, args...); + } + +private: + void *handle_; + std::unordered_map functionMap_; +}; + +#endif diff --git a/src/atom/function/invoke.hpp b/src/atom/function/invoke.hpp index 83a938f0..cbf68932 100644 --- a/src/atom/function/invoke.hpp +++ b/src/atom/function/invoke.hpp @@ -38,6 +38,20 @@ auto delay_invoke(F &&f, Args &&...args) { }; } +template +auto delay_mem_invoke(R (T::*f)(Args...), T *obj) { + return [f, obj](Args... args) { + return (obj->*f)(std::forward(args)...); + }; +} + +template +auto delay_cmem_invoke(R (T::*f)(Args...) const, const T *obj) { + return [f, obj](Args... args) { + return (obj->*f)(std::forward(args)...); + }; +} + template requires Invocable auto safe_call(Func &&func, Args &&...args) { diff --git a/src/atom/io/_pybind.cpp b/src/atom/io/_pybind.cpp new file mode 100644 index 00000000..88594531 --- /dev/null +++ b/src/atom/io/_pybind.cpp @@ -0,0 +1,106 @@ +#include + +#include "compress.hpp" +#include "file.hpp" +#include "glob.hpp" +#include "idirectory.hpp" +#include "ifile.hpp" +#include "io.hpp" + +namespace py = pybind11; + +using namespace atom::io; + +PYBIND11_MODULE(atom_io, m) { + m.doc() = "atom_io module"; + + m.def("compress_file", &compress_file, "Compress a file"); + m.def("decompress_file", &decompress_file, "Decompress a file"); + m.def("compress_folder", &compress_folder, "Compress a folder"); + m.def("extract_zip", &extract_zip, "Extract a zip file"); + m.def("create_zip", &create_zip, "Create a zip file"); + + py::class_(m, "FileManager") + .def("create_file", &FileManager::createFile, "Create a file") + .def("open_file", &FileManager::openFile, "Open a file") + .def("read_file", &FileManager::readFile, "Read a file") + .def("write_file", &FileManager::writeFile, "Write a file") + .def("move_file", &FileManager::moveFile, "Move a file") + .def("delete_file", &FileManager::deleteFile, "Delete a file") + .def("get_file_size", &FileManager::getFileSize, + "Get the size of a file") + .def("get_file_directory", &FileManager::getFileDirectory, + "Get the directory of a file"); + + m.def("translate", &glob::translate, "Translate a pattern"); + m.def("expand_tilde", &glob::expand_tilde, "Expand a tilde"); + m.def("has_magic", &glob::has_magic, "Check if a pattern has magic"); + m.def("is_hidden", &glob::is_hidden, "Check if a file is hidden"); + m.def("string_replace", &glob::string_replace, "Replace a string"); + m.def("is_recursive", &glob::is_recursive, + "Check if a pattern is recursive"); + m.def("filter", &glob::filter, "Filter a list of files"); + m.def("glob0", &glob::glob0, "Glob0"); + m.def("compile_pattern", &glob::compile_pattern, "Compile a pattern"); + m.def("glob1", &glob::glob1, "Glob1"); + m.def("glob2", &glob::glob2, "Glob2"); + m.def("iter_directory", &glob::iter_directory, "Iterate over a directory"); + m.def("rlistdir", &glob::rlistdir, "List a directory recursively"); + + py::class_(m, "DirectoryWrapper") + .def("get_path", &DirectoryWrapper::get_path, + "Get the path of a " + "directory") + .def("get_size", &DirectoryWrapper::get_size, + "Get the size of a " + "directory") + .def("get_size_string", &DirectoryWrapper::get_size_string, + "Get the size of a directory as a string") + .def("list_files", &DirectoryWrapper::list_files, + "List the files of a " + "directory") + .def("list_directories", &DirectoryWrapper::list_directories, + "List the directories of a directory") + .def("create_directory", &DirectoryWrapper::create_directory, + "Create a directory"); + + py::class_(m, "FileWrapper") + .def("get_path", &FileWrapper::get_path, "Get the path of a file") + .def("get_size", &FileWrapper::get_size, "Get the size of a file") + .def("get_size_string", &FileWrapper::get_size_string, + "Get the size of a file as a string") + .def("get_parent_path", &FileWrapper::get_parent_path, + "Get the parent path of a file") + .def("get_extension", &FileWrapper::get_extension, + "Get the extension of a file") + .def("get_stem", &FileWrapper::get_stem, "Get the stem of a file") + .def("get_last_write_time", &FileWrapper::get_last_write_time, + "Get the last write time of a file") + .def("get_hard_link_count", &FileWrapper::get_hard_link_count, + "Get the hard link count of a file") + .def("is_directory", &FileWrapper::is_directory, + "Check if a file is a directory") + .def("is_regular_file", &FileWrapper::is_regular_file, + "Check if a file is a regular file") + .def("is_binary_file", &FileWrapper::is_binary_file, + "Check if a file is a binary file") + .def("is_symlink", &FileWrapper::is_symlink, + "Check if a file is a symlink") + .def("exists", &FileWrapper::exists, "Check if a file exists") + .def("rename", &FileWrapper::rename, "Rename a file"); + + m.def("is_folder_exists", + py::overload_cast(&isFolderExists), + "Check if a folder exists"); + m.def("is_folder_name_valid", &isFolderNameValid, + "Check if a folder name is valid"); + m.def("is_file_exists", + py::overload_cast(&isFileExists), + "Check if a file exists"); + m.def("is_file_name_valid", &isFileNameValid, + "Check if a file name is valid"); + m.def("is_absolute_path", &isAbsolutePath, "Check if a path is absolute"); + m.def("is_executable_file", &isExecutableFile, + "Check if a file is executable"); + m.def("is_folder_empty", &isFolderEmpty, "Check if a folder is empty"); +} diff --git a/src/atom/io/_script.hpp b/src/atom/io/_script.hpp index 9fd62d6b..ba81912a 100644 --- a/src/atom/io/_script.hpp +++ b/src/atom/io/_script.hpp @@ -24,7 +24,7 @@ Description: Carbon binding for Atom-IO #include "ifile.hpp" #include "io.hpp" -using namespace Atom::IO; +using namespace atom::io; namespace Atom::_Script::IO { /** diff --git a/src/atom/io/compress.cpp b/src/atom/io/compress.cpp index 2dcd4c38..c0ad41ce 100644 --- a/src/atom/io/compress.cpp +++ b/src/atom/io/compress.cpp @@ -60,7 +60,7 @@ class ProgressListener : public ZipProgressListener { } }; -namespace Atom::IO { +namespace atom::io { bool compress_file(const std::string &file_name, const std::string &output_folder) { fs::path input_path(file_name); @@ -307,4 +307,4 @@ bool create_zip(const std::string &source_folder, const std::string &zip_file) { return false; } } -} // namespace Atom::IO +} // namespace atom::io diff --git a/src/atom/io/compress.hpp b/src/atom/io/compress.hpp index 1bd9c81e..852387c5 100644 --- a/src/atom/io/compress.hpp +++ b/src/atom/io/compress.hpp @@ -17,7 +17,7 @@ Description: Compressor using ZLib #include -namespace Atom::IO { +namespace atom::io { /** * @brief 对单个文件进行压缩 * @param file_name 待压缩的文件名(包含路径) @@ -99,6 +99,6 @@ bool create_zip(const std::string &source_folder, const std::string &zip_file); */ bool extract_zip(const std::string &zip_file, const std::string &destination_folder); -} // namespace Atom::IO +} // namespace atom::io #endif diff --git a/src/atom/io/file.cpp b/src/atom/io/file.cpp index 313bc514..0404c375 100644 --- a/src/atom/io/file.cpp +++ b/src/atom/io/file.cpp @@ -27,7 +27,7 @@ Description: File Manager namespace fs = std::filesystem; -namespace Atom::IO { +namespace atom::io { bool FileManager::createFile(const std::string &filename) { if (fs::exists(filename)) { @@ -141,4 +141,4 @@ std::string FileManager::getFileDirectory(const std::string &filename) { } } -} // namespace Atom::IO \ No newline at end of file +} // namespace atom::io \ No newline at end of file diff --git a/src/atom/io/file.hpp b/src/atom/io/file.hpp index 59ebe6bc..192b7ee1 100644 --- a/src/atom/io/file.hpp +++ b/src/atom/io/file.hpp @@ -18,7 +18,7 @@ Description: File Manager #include #include -namespace Atom::IO { +namespace atom::io { /** * @class FileManager * @brief 文件管理器类,提供文件的创建、打开、读取、写入、移动、删除等功能。 @@ -87,6 +87,6 @@ class FileManager { std::string m_filename; ///< 当前打开的文件名 }; -} // namespace Atom::IO +} // namespace atom::io #endif diff --git a/src/atom/io/idirectory.cpp b/src/atom/io/idirectory.cpp index f591bd65..70984644 100644 --- a/src/atom/io/idirectory.cpp +++ b/src/atom/io/idirectory.cpp @@ -17,7 +17,7 @@ Description: Directory Wrapper #include #include -namespace Atom::IO { +namespace atom::io { DirectoryWrapper::DirectoryWrapper(const fs::path& dir_path) : dir_path_(dir_path) {} @@ -82,4 +82,4 @@ std::vector DirectoryWrapper::list_directories() const { void DirectoryWrapper::create_directory(const std::string& name) const { fs::create_directory(dir_path_ / name); } -} // namespace Atom::IO +} // namespace atom::io diff --git a/src/atom/io/idirectory.hpp b/src/atom/io/idirectory.hpp index 13f6c469..a964ec27 100644 --- a/src/atom/io/idirectory.hpp +++ b/src/atom/io/idirectory.hpp @@ -21,7 +21,7 @@ Description: Directory Wrapper namespace fs = std::filesystem; -namespace Atom::IO { +namespace atom::io { /** * @brief A wrapper class for interacting with directories. */ @@ -92,6 +92,6 @@ class DirectoryWrapper { fs::path dir_path_; ///< The path to the directory. }; -} // namespace Atom::IO +} // namespace atom::io #endif diff --git a/src/atom/io/ifile.cpp b/src/atom/io/ifile.cpp index c5de7f77..35e888e8 100644 --- a/src/atom/io/ifile.cpp +++ b/src/atom/io/ifile.cpp @@ -17,7 +17,7 @@ Description: File Wrapper #include #include -namespace Atom::IO { +namespace atom::io { FileWrapper::FileWrapper(const fs::path& file_path) : file_path_(file_path) {} void FileWrapper::write(const std::string& content) { write_file(content); } @@ -203,4 +203,4 @@ fs::perms FileWrapper::permissions() const { return fs::status(file_path_).permissions(); } -} // namespace Atom::IO +} // namespace atom::io diff --git a/src/atom/io/ifile.hpp b/src/atom/io/ifile.hpp index 1bc60098..4a299884 100644 --- a/src/atom/io/ifile.hpp +++ b/src/atom/io/ifile.hpp @@ -21,7 +21,7 @@ Description: File Wrapper namespace fs = std::filesystem; -namespace Atom::IO { +namespace atom::io { class FileWrapper { public: @@ -247,4 +247,4 @@ class FileWrapper { return T(std::istreambuf_iterator(file), {}); } }; -} // namespace Atom::IO +} // namespace atom::io diff --git a/src/atom/io/io.cpp b/src/atom/io/io.cpp index 2fd7b502..7393a199 100644 --- a/src/atom/io/io.cpp +++ b/src/atom/io/io.cpp @@ -57,7 +57,7 @@ namespace fs = std::filesystem; return ""; \ } -namespace Atom::IO { +namespace atom::io { bool createDirectory(const std::string &path) { ATOM_IO_CHECK_ARGUMENT(path); @@ -82,7 +82,7 @@ void createDirectory(const std::string &date, const std::string &rootDir) { return; } - auto tokens = Atom::Utils::splitString(date, '/'); + auto tokens = atom::utils::splitString(date, '/'); // Create directories fs::path currentDir = rootDir; @@ -562,4 +562,4 @@ bool isExecutableFile(const std::string &fileName, const std::string &fileExt) { DLOG_F(INFO, "The file '{}' exists and is executable.", filePath.string()); return true; } -} // namespace Atom::IO +} // namespace atom::io diff --git a/src/atom/io/io.hpp b/src/atom/io/io.hpp index 51005e81..91d908e9 100644 --- a/src/atom/io/io.hpp +++ b/src/atom/io/io.hpp @@ -22,7 +22,7 @@ Description: IO #include namespace fs = std::filesystem; -namespace Atom::IO { +namespace atom::io { /** * @brief Creates a directory with the specified path. * @@ -394,6 +394,6 @@ enum class FileOption { Path, Name }; * 如果文件不存在或发生错误,则返回 false */ bool isExecutableFile(const std::string &fileName, const std::string &fileExt); -} // namespace Atom::IO +} // namespace atom::io #endif diff --git a/src/atom/server/daemon.cpp b/src/atom/server/daemon.cpp index 9921f8a8..f964f9df 100644 --- a/src/atom/server/daemon.cpp +++ b/src/atom/server/daemon.cpp @@ -40,8 +40,8 @@ namespace atom::async { std::string DaemonGuard::ToString() const { std::stringstream ss; ss << "[DaemonGuard parentId=" << m_parentId << " mainId=" << m_mainId - << " parentStartTime=" << Utils::timeStampToString(m_parentStartTime) - << " mainStartTime=" << Utils::timeStampToString(m_mainStartTime) + << " parentStartTime=" << utils::timeStampToString(m_parentStartTime) + << " mainStartTime=" << utils::timeStampToString(m_mainStartTime) << " restartCount=" << m_restartCount.load() << "]"; return ss.str(); } diff --git a/src/atom/system/os.cpp b/src/atom/system/os.cpp index 94dfe5c8..4fe2fa71 100644 --- a/src/atom/system/os.cpp +++ b/src/atom/system/os.cpp @@ -46,7 +46,7 @@ void walk(const fs::path &root) { std::string jwalk(const std::string &root) { DLOG_F(INFO, "Walking: {}", root.generic_string()); - if (!Atom::IO::isFolderExists(root)) + if (!atom::io::isFolderExists(root)) { LOG_F(ERROR, "Directory not exists: {}", root); return ""; diff --git a/src/atom/type/CMakeLists.txt b/src/atom/type/CMakeLists.txt index 1eb8126a..30f63d30 100644 --- a/src/atom/type/CMakeLists.txt +++ b/src/atom/type/CMakeLists.txt @@ -17,12 +17,11 @@ set(${PROJECT_NAME}_SOURCES # Headers set(${PROJECT_NAME}_HEADERS - abi.hpp args.hpp enum_flag.hpp enum_flag.inl flatset.hpp - ini_impl.hpp + ini.inl ini.hpp json.hpp message.hpp diff --git a/src/atom/type/message.cpp b/src/atom/type/message.cpp index bf66f31f..d1eac52c 100644 --- a/src/atom/type/message.cpp +++ b/src/atom/type/message.cpp @@ -24,8 +24,8 @@ using namespace std; Message::Message(Type t, const string &name, const string &target, const string &origin) : type_(t), name_(name), target_(target), origin_(origin) { - timestamp_ = Atom::Utils::getChinaTimestampString(); - Atom::Utils::UUIDGenerator generator; + timestamp_ = atom::utils::getChinaTimestampString(); + atom::utils::UUIDGenerator generator; uuid_ = generator.generateUUID(); } @@ -65,9 +65,10 @@ double Message::api_version() const { return api_version_; } // Void Message VoidMessage::VoidMessage(const string &name, const string &target, - const string &origin) - : Message(Type::kVoid, name, target, origin) {} + const string &origin, bool has_return) + : Message(Type::kVoid, name, target, origin), has_return(has_return) {} +bool VoidMessage::hasReturn() const { return has_return; } // TextMessage TextMessage::TextMessage(const string &name, const string &text, const string &target, const string &origin) diff --git a/src/atom/type/message.hpp b/src/atom/type/message.hpp index cf8a953b..2d61673f 100644 --- a/src/atom/type/message.hpp +++ b/src/atom/type/message.hpp @@ -67,7 +67,12 @@ class Message { class VoidMessage : public Message { public: explicit VoidMessage(const std::string &name, const std::string &target, - const std::string &origin); + const std::string &origin, bool has_return); + + bool hasReturn() const; + +private: + bool has_return; }; // TextMessage class diff --git a/src/atom/type/pointer.hpp b/src/atom/type/pointer.hpp index 7c1aa05a..b6b11490 100644 --- a/src/atom/type/pointer.hpp +++ b/src/atom/type/pointer.hpp @@ -31,7 +31,8 @@ template concept PointerType = std::is_pointer_v || std::is_same_v::type>> || - std::is_same_v::type>>; + std::is_same_v::type>> || + std::is_same_v::type>>; /** * @brief A class template to hold different types of pointers using @@ -43,7 +44,7 @@ template class PointerSentinel { public: // Using std::variant to store different types of pointers - std::variant, std::unique_ptr, T*> ptr; + std::variant, std::unique_ptr, std::weak_ptr, T*> ptr; /** * @brief Construct a new Pointer Sentinel object from a shared pointer. @@ -59,6 +60,13 @@ class PointerSentinel { */ explicit PointerSentinel(std::unique_ptr&& p) : ptr(std::move(p)) {} + /** + * @brief Construct a new Pointer Sentinel object from a weak pointer. + * + * @param p The weak pointer. + */ + explicit PointerSentinel(std::weak_ptr p) : ptr(p) {} + /** * @brief Construct a new Pointer Sentinel object from a raw pointer. * @@ -74,13 +82,17 @@ class PointerSentinel { PointerSentinel(const PointerSentinel& other) : ptr(std::visit( [](const auto& p) - -> std::variant, std::unique_ptr, T*> { + -> std::variant, std::unique_ptr, + std::weak_ptr, T*> { if constexpr (std::is_same_v, std::shared_ptr>) { return p; } else if constexpr (std::is_same_v, std::unique_ptr>) { return std::make_unique(*p); + } else if constexpr (std::is_same_v, + std::weak_ptr>) { + return p; } else { return new T(*p); } @@ -97,9 +109,12 @@ class PointerSentinel { [](auto&& arg) -> T* { using U = std::decay_t; if constexpr (std::is_pointer_v) { - return arg; // 原始指针 + return arg; + } else if constexpr (std::is_same_v>) { + auto spt = arg.lock(); // Try to lock the weak_ptr + return spt ? spt.get() : nullptr; } else { - return arg.get(); // 智能指针 + return arg.get(); } }, ptr); @@ -123,6 +138,15 @@ class PointerSentinel { using U = std::decay_t; if constexpr (std::is_pointer_v) { return ((*arg).*func)(std::forward(args)...); + } else if constexpr (std::is_same_v>) { + auto spt = arg.lock(); + if (spt) { + return ((*spt.get()).* + func)(std::forward(args)...); + } else { + // Handle the case where weak_ptr is expired + throw std::runtime_error("weak_ptr is expired"); + } } else { return ((*arg.get()).*func)(std::forward(args)...); } diff --git a/src/atom/utils/_script.hpp b/src/atom/utils/_script.hpp index b47e36c4..ebb90165 100644 --- a/src/atom/utils/_script.hpp +++ b/src/atom/utils/_script.hpp @@ -28,7 +28,7 @@ Description: Carbon binding for Atom-Utils #include "uuid.hpp" #include "xml.hpp" -using namespace Atom::Utils; +using namespace atom::utils; namespace Atom::_Script::Utils { /** diff --git a/src/atom/utils/aes.cpp b/src/atom/utils/aes.cpp index 274adea6..100f486d 100644 --- a/src/atom/utils/aes.cpp +++ b/src/atom/utils/aes.cpp @@ -27,7 +27,7 @@ Description: Simple implementation of AES encryption const int AES_BLOCK_SIZE = 16; -namespace Atom::Utils { +namespace atom::utils { std::string encryptAES(std::string_view plaintext, std::string_view key) { EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); EVP_EncryptInit_ex(ctx, EVP_aes_128_ecb(), nullptr, @@ -142,7 +142,7 @@ std::string decompress(std::string_view data) { } std::string calculateSha256(std::string_view filename) { - if (!Atom::IO::isFileExists(std::string(filename))) { + if (!atom::io::isFileExists(std::string(filename))) { LOG_F(ERROR, "File not exist: {}", filename); return ""; } @@ -178,4 +178,4 @@ std::string calculateSha256(std::string_view filename) { return sha256_val; } -} // namespace Atom::Utils +} // namespace atom::utils diff --git a/src/atom/utils/aes.hpp b/src/atom/utils/aes.hpp index ef8d7013..c9254d6a 100644 --- a/src/atom/utils/aes.hpp +++ b/src/atom/utils/aes.hpp @@ -17,7 +17,7 @@ Description: Simple implementation of AES encryption #include -namespace Atom::Utils { +namespace atom::utils { /** * @brief 使用AES算法对输入的明文进行加密。 * @@ -61,6 +61,6 @@ namespace Atom::Utils { * @return 文件的SHA-256哈希值 */ [[nodiscard]] std::string calculateSha256(std::string_view filename); -} // namespace Atom::Utils +} // namespace atom::utils #endif diff --git a/src/atom/utils/argsview.cpp b/src/atom/utils/argsview.cpp index f2410a27..4bb50e0d 100644 --- a/src/atom/utils/argsview.cpp +++ b/src/atom/utils/argsview.cpp @@ -14,7 +14,7 @@ Description: ArgsView Class for C++ #include "argsview.hpp" -namespace Atom::Utils { +namespace atom::utils { ArgsView::ArgsView(int argc, char** argv) : m_argc(argc), m_argv(argv) { for (int i = 1; i < m_argc; ++i) { std::string_view arg(m_argv[i]); @@ -67,4 +67,4 @@ void ArgsView::addRule(std::string_view prefix, m_rules.emplace_back(prefix, handler); } -} // namespace Atom::Utils +} // namespace atom::utils diff --git a/src/atom/utils/argsview.hpp b/src/atom/utils/argsview.hpp index ea890d66..fe4c6235 100644 --- a/src/atom/utils/argsview.hpp +++ b/src/atom/utils/argsview.hpp @@ -24,7 +24,7 @@ Description: ArgsView Class for C++ #include #include -namespace Atom::Utils { +namespace atom::utils { /** * @brief Represents a view of command-line arguments. */ @@ -108,6 +108,6 @@ class ArgsView { m_rules; }; -} // namespace Atom::Utils +} // namespace atom::utils #endif \ No newline at end of file diff --git a/src/atom/utils/convert.cpp b/src/atom/utils/convert.cpp index f0754900..bd98ac99 100644 --- a/src/atom/utils/convert.cpp +++ b/src/atom/utils/convert.cpp @@ -19,7 +19,7 @@ Description: Convert Utils for Windows #include #include -namespace Atom::Utils { +namespace atom::utils { LPWSTR CharToLPWSTR(std::string_view charString) { const int size = MultiByteToWideChar(CP_ACP, 0, charString.data(), @@ -64,6 +64,6 @@ std::wstring LPWSTRToWString(LPWSTR lpwstr) { return std::wstring(lpwstr); } std::wstring LPCWSTRToWString(LPCWSTR lpcwstr) { return std::wstring(lpcwstr); } -} // namespace Atom::Utils +} // namespace atom::utils #endif \ No newline at end of file diff --git a/src/atom/utils/convert.hpp b/src/atom/utils/convert.hpp index b884e2df..8a2f3276 100644 --- a/src/atom/utils/convert.hpp +++ b/src/atom/utils/convert.hpp @@ -21,7 +21,7 @@ Description: Convert Utils for Windows #include #include -namespace Atom::Utils { +namespace atom::utils { /** * @brief Converts a string_view containing char characters to LPWSTR (wide * character string). @@ -75,7 +75,7 @@ namespace Atom::Utils { */ [[nodiscard]] std::wstring LPCWSTRToWString(LPCWSTR lpcwstr); -} // namespace Atom::Utils +} // namespace atom::utils #endif diff --git a/src/atom/utils/env.cpp b/src/atom/utils/env.cpp index f1be20ef..49baa27c 100644 --- a/src/atom/utils/env.cpp +++ b/src/atom/utils/env.cpp @@ -24,7 +24,7 @@ Description: Environment variable management #include "atom/log/loguru.hpp" -namespace Atom::Utils { +namespace atom::utils { Env::Env(int argc, char **argv) { std::filesystem::path exe_path; @@ -207,7 +207,7 @@ std::string Env::getAbsoluteWorkPath(const std::string &path) const { } std::string Env::getConfigPath() { return getAbsolutePath(get("c", "config")); } -} // namespace Atom::Utils +} // namespace atom::utils /* int main(int argc, char **argv) diff --git a/src/atom/utils/env.hpp b/src/atom/utils/env.hpp index 5d5a3c1f..a408e961 100644 --- a/src/atom/utils/env.hpp +++ b/src/atom/utils/env.hpp @@ -21,7 +21,7 @@ Description: Environment variable management #include #include -namespace Atom::Utils { +namespace atom::utils { /** * @brief 环境变量类,用于获取和设置程序的环境变量、命令行参数等信息。 */ @@ -144,6 +144,6 @@ class Env { mutable std::mutex m_mutex; ///< 互斥锁,用于保护成员变量。 }; -} // namespace Atom::Utils +} // namespace atom::utils #endif diff --git a/src/atom/utils/random.cpp b/src/atom/utils/random.cpp index 81b71f30..8419643c 100644 --- a/src/atom/utils/random.cpp +++ b/src/atom/utils/random.cpp @@ -14,7 +14,7 @@ Description: Simple random number generator #include "random.hpp" -namespace Atom::Utils { +namespace atom::utils { std::mt19937 createRandomGenerator() { std::random_device rd; std::seed_seq seed{rd(), rd(), rd(), rd()}; @@ -37,4 +37,4 @@ std::string generateRandomString(int length) { return randomString; } -} // namespace Atom::Utils \ No newline at end of file +} // namespace atom::utils \ No newline at end of file diff --git a/src/atom/utils/random.hpp b/src/atom/utils/random.hpp index c5460481..eb0a9927 100644 --- a/src/atom/utils/random.hpp +++ b/src/atom/utils/random.hpp @@ -18,7 +18,7 @@ Description: Simple random number generator #include #include -namespace Atom::Utils { +namespace atom::utils { template > class random : public Distribution { @@ -46,6 +46,6 @@ class random : public Distribution { }; [[nodiscard]] std::string generateRandomString(int length); -} // namespace Atom::Utils +} // namespace atom::utils #endif diff --git a/src/atom/utils/stopwatcher.cpp b/src/atom/utils/stopwatcher.cpp index 951203c4..dc36f1ad 100644 --- a/src/atom/utils/stopwatcher.cpp +++ b/src/atom/utils/stopwatcher.cpp @@ -20,7 +20,7 @@ Description: Simple implementation of a stopwatch #include -namespace Atom::Utils { +namespace atom::utils { StopWatcher::StopWatcher() : m_running(false), m_paused(false) {} void StopWatcher::start() { @@ -110,4 +110,4 @@ void StopWatcher::checkCallbacks( } } } -} // namespace Atom::Utils +} // namespace atom::utils diff --git a/src/atom/utils/stopwatcher.hpp b/src/atom/utils/stopwatcher.hpp index 04d9ed4f..46e76729 100644 --- a/src/atom/utils/stopwatcher.hpp +++ b/src/atom/utils/stopwatcher.hpp @@ -20,7 +20,7 @@ Description: Simple implementation of a stopwatch #include #include -namespace Atom::Utils { +namespace atom::utils { /** * @brief 用于计时的类。 * @@ -127,6 +127,6 @@ class StopWatcher { const std::chrono::time_point ¤tTime); }; -} // namespace Atom::Utils +} // namespace atom::utils #endif \ No newline at end of file diff --git a/src/atom/utils/string.cpp b/src/atom/utils/string.cpp index d534777d..7edbde81 100644 --- a/src/atom/utils/string.cpp +++ b/src/atom/utils/string.cpp @@ -21,7 +21,7 @@ Description: Some useful string functions #include #include "atom/error/exception.hpp" -namespace Atom::Utils { +namespace atom::utils { bool hasUppercase(std::string_view str) { return std::any_of(str.begin(), str.end(), [](unsigned char ch) { return std::isupper(ch); }); @@ -179,4 +179,4 @@ std::string replaceStrings( } return result; } -} // namespace Atom::Utils \ No newline at end of file +} // namespace atom::utils \ No newline at end of file diff --git a/src/atom/utils/string.hpp b/src/atom/utils/string.hpp index e47b0cd0..33390525 100644 --- a/src/atom/utils/string.hpp +++ b/src/atom/utils/string.hpp @@ -19,7 +19,7 @@ Description: Some useful string functions #include #include -namespace Atom::Utils { +namespace atom::utils { /** * @brief Checks if the given string contains any uppercase characters. * @@ -127,6 +127,6 @@ replaceStrings(std::string_view text, const std::vector>& replacements); -} // namespace Atom::Utils +} // namespace atom::utils #endif \ No newline at end of file diff --git a/src/atom/utils/switch.hpp b/src/atom/utils/switch.hpp index a4783441..7288ccec 100644 --- a/src/atom/utils/switch.hpp +++ b/src/atom/utils/switch.hpp @@ -29,7 +29,7 @@ Description: Smart Switch just like javascript #include "atom/error/exception.hpp" #include "atom/type/noncopyable.hpp" -namespace Atom::Utils { +namespace atom::utils { /** * @brief A class for implementing a switch statement with string cases, * enhanced with C++17/20 features. @@ -112,6 +112,6 @@ class StringSwitch : public NonCopyable { DefaultFunc defaultFunc_; }; -} // namespace Atom::Utils +} // namespace atom::utils #endif \ No newline at end of file diff --git a/src/atom/utils/time.cpp b/src/atom/utils/time.cpp index 86d845d2..5c2c5b8a 100644 --- a/src/atom/utils/time.cpp +++ b/src/atom/utils/time.cpp @@ -18,7 +18,7 @@ Description: Some useful functions about time #include #include -namespace Atom::Utils { +namespace atom::utils { std::string getTimestampString() { auto now = std::chrono::system_clock::now(); auto time = std::chrono::system_clock::to_time_t(now); @@ -101,4 +101,4 @@ std::tm timestampToTime(long long timestamp) { std::time_t time = static_cast(timestamp / 1000); return *std::localtime(&time); } -} // namespace Atom::Utils +} // namespace atom::utils diff --git a/src/atom/utils/time.hpp b/src/atom/utils/time.hpp index ba9fad77..47074171 100644 --- a/src/atom/utils/time.hpp +++ b/src/atom/utils/time.hpp @@ -18,7 +18,7 @@ Description: Some useful functions about time #include #include -namespace Atom::Utils { +namespace atom::utils { /** * @brief 获取当前时间的字符串时间戳 * @@ -73,6 +73,6 @@ namespace Atom::Utils { * @return std::tm tm结构体 */ [[nodiscard]] std::tm timestampToTime(long long timestamp); -} // namespace Atom::Utils +} // namespace atom::utils #endif diff --git a/src/atom/utils/utf.cpp b/src/atom/utils/utf.cpp index 9287674b..1de1f937 100644 --- a/src/atom/utils/utf.cpp +++ b/src/atom/utils/utf.cpp @@ -21,7 +21,7 @@ Description: Some useful functions about utf string #include #include -namespace Atom::Utils { +namespace atom::utils { std::string toUTF8(std::wstring_view wstr) { #if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__) std::wstring_convert, char16_t> convert; @@ -134,4 +134,4 @@ std::u16string UTF32toUTF16(std::u32string_view str) { return result; } -} // namespace Atom::Utils +} // namespace atom::utils diff --git a/src/atom/utils/utf.hpp b/src/atom/utils/utf.hpp index 0436af49..80d1d3cb 100644 --- a/src/atom/utils/utf.hpp +++ b/src/atom/utils/utf.hpp @@ -17,7 +17,7 @@ Description: Some useful functions about utf string #include -namespace Atom::Utils { +namespace atom::utils { /** * @brief 将宽字符字符串转换为 UTF-8 字符串 * @@ -81,6 +81,6 @@ std::string UTF32toUTF8(std::u32string_view str); * @return std::u16string 转换后的 UTF-16 字符串 */ std::u16string UTF32toUTF16(std::u32string_view str); -} // namespace Atom::Utils +} // namespace atom::utils #endif diff --git a/src/atom/utils/uuid.cpp b/src/atom/utils/uuid.cpp index 010c82b8..aae33758 100644 --- a/src/atom/utils/uuid.cpp +++ b/src/atom/utils/uuid.cpp @@ -20,7 +20,7 @@ Description: UUID Generator #include #endif -namespace Atom::Utils { +namespace atom::utils { UUIDGenerator::UUIDGenerator() : gen_(rd_()), dis_(0, 0xFFFFFFFF) {} void UUIDGenerator::seed(unsigned int seed_value) const { @@ -95,4 +95,4 @@ std::string generateSystemUUID() { return uuid; } -} // namespace Atom::Utils +} // namespace atom::utils diff --git a/src/atom/utils/uuid.hpp b/src/atom/utils/uuid.hpp index f398bb1c..b02c1d12 100644 --- a/src/atom/utils/uuid.hpp +++ b/src/atom/utils/uuid.hpp @@ -19,7 +19,7 @@ Description: UUID Generator #include #include -namespace Atom::Utils { +namespace atom::utils { /** * @brief 生成UUID的类 * @@ -85,6 +85,6 @@ class UUIDGenerator { * UUID的格式为xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx,其中x为16进制数字,且大写或小写均可 */ [[maybe_unused]] [[nodiscard]] std::string generateSystemUUID(); -} // namespace Atom::Utils +} // namespace atom::utils #endif diff --git a/src/atom/utils/validate_aligned_storage.hpp b/src/atom/utils/validate_aligned_storage.hpp index b044d155..2a647742 100644 --- a/src/atom/utils/validate_aligned_storage.hpp +++ b/src/atom/utils/validate_aligned_storage.hpp @@ -18,7 +18,7 @@ Description: Validate aligned storage #include #include -namespace Atom::Utils { +namespace atom::utils { //! Aligned storage validator template @@ -28,6 +28,6 @@ class ValidateAlignedStorage; template class ValidateAlignedStorage= ImplSize) && ((StorageAlign % ImplAlign) == 0)>::type> {}; -} // namespace Atom::Utils +} // namespace atom::utils #endif // ATOM_UTILS_VALIDATE_ALIGNED_STORAGE_HPP diff --git a/src/atom/utils/xml.cpp b/src/atom/utils/xml.cpp index 84510974..117963e1 100644 --- a/src/atom/utils/xml.cpp +++ b/src/atom/utils/xml.cpp @@ -16,7 +16,7 @@ Description: A XML reader class using tinyxml2. #include -namespace Atom::Utils { +namespace atom::utils { XMLReader::XMLReader(const std::string &filePath) { if (doc_.LoadFile(filePath.c_str()) != tinyxml2::XML_SUCCESS) { throw std::runtime_error("Failed to load XML file"); @@ -183,4 +183,4 @@ tinyxml2::XMLElement *XMLReader::getElementByPath( } return element; } -} // namespace Atom::Utils +} // namespace atom::utils diff --git a/src/atom/utils/xml.hpp b/src/atom/utils/xml.hpp index 1c4d0cf8..3b832068 100644 --- a/src/atom/utils/xml.hpp +++ b/src/atom/utils/xml.hpp @@ -19,7 +19,7 @@ Description: A XML reader class using tinyxml2. #include #include -namespace Atom::Utils { +namespace atom::utils { /** * @brief A class for reading and manipulating data from an XML file. */ @@ -183,6 +183,6 @@ class XMLReader { */ tinyxml2::XMLElement *getElementByPath(const std::string &path) const; }; -} // namespace Atom::Utils +} // namespace atom::utils #endif diff --git a/src/preload.cpp b/src/preload.cpp index 52150710..3ddcf370 100644 --- a/src/preload.cpp +++ b/src/preload.cpp @@ -17,7 +17,7 @@ bool checkResources() { LOG_F(ERROR, "Resource file '{}' is missing.", key); return false; } - auto sha256_val = Atom::Utils::calculateSha256(key); + auto sha256_val = atom::utils::calculateSha256(key); if (!sha256_val.empty()) { LOG_F(ERROR, "Failed to calculate SHA256 value of '{}'.", key); value.second = true; @@ -46,7 +46,7 @@ void downloadResources() { for (auto &[key, value] : resource::LITHIUM_RESOURCES) { // 发送 HTTP GET 请求下载文件 - const auto url = Atom::Utils::joinStrings( + const auto url = atom::utils::joinStrings( {resource::LITHIUM_RESOURCE_SERVER, key}, "/"); // 添加下载任务到线程池 @@ -65,7 +65,7 @@ void downloadResources() { // 将下载的数据写入文件 std::ofstream outfile( - std::string(Atom::Utils::splitString(url, '/').back())); + std::string(atom::utils::splitString(url, '/').back())); outfile.write(res_body.dump().c_str(), res_body.dump().size()); DLOG_F(INFO, "Resource file '{}' downloaded.", url); diff --git a/src/server/websocket/template/error_message.hpp b/src/server/websocket/template/error_message.hpp index ad714b88..7e729a1a 100644 --- a/src/server/websocket/template/error_message.hpp +++ b/src/server/websocket/template/error_message.hpp @@ -6,7 +6,7 @@ LOG_F(ERROR, "{}: {}", __func__, msg); \ res["error"] = magic_enum::enum_name(code); \ res["message"] = msg; \ - res["timestamp"] = Atom::Utils::getChinaTimestampString(); \ + res["timestamp"] = atom::utils::getChinaTimestampString(); \ sendMessage(res.dump()); \ return; \ } while (0) @@ -17,7 +17,7 @@ LOG_F(ERROR, "{}: {}", __func__, msg); \ res["error"] = magic_enum::enum_name(code); \ res["message"] = msg; \ - res["timestamp"] = Atom::Utils::getChinaTimestampString(); \ + res["timestamp"] = atom::utils::getChinaTimestampString(); \ sendMessage(res.dump()); \ return nullptr; \ } while (0) @@ -39,7 +39,7 @@ LOG_F(ERROR, "{}: {}", __func__, msg); \ res["error"] = magic_enum::enum_name(code); \ res["message"] = msg; \ - res["timestamp"] = Atom::Utils::getChinaTimestampString(); \ + res["timestamp"] = atom::utils::getChinaTimestampString(); \ sendMessage(res.dump()); \ return nullptr; \ } while (0) diff --git a/src/task/manager.hpp b/src/task/manager.hpp index 49ecb132..640759eb 100644 --- a/src/task/manager.hpp +++ b/src/task/manager.hpp @@ -152,7 +152,7 @@ class TaskManager { std::weak_ptr m_TaskPool; std::weak_ptr m_TickScheduler; - std::unique_ptr m_Timer; + std::unique_ptr m_Timer; std::atomic_bool m_StopFlag; }; diff --git a/src/task/tick.cpp b/src/task/tick.cpp index 1e6b87fb..8a0f1755 100644 --- a/src/task/tick.cpp +++ b/src/task/tick.cpp @@ -27,7 +27,7 @@ TickScheduler::TickScheduler(size_t threads) schedulerThread = std::thread([this] { this->taskSchedulerLoop(); }); #endif pool = GetWeakPtr("lithium.task.pool"); - stopwatch = std::make_unique(); + stopwatch = std::make_unique(); } TickScheduler::~TickScheduler() { stopScheduler(); } diff --git a/src/task/tick.hpp b/src/task/tick.hpp index 6ed33da5..198ce01f 100644 --- a/src/task/tick.hpp +++ b/src/task/tick.hpp @@ -36,7 +36,7 @@ Description: Tick Sheduler, just like Minecraft's #include "pool.hpp" -namespace Atom::Utils { +namespace atom::utils { class StopWatcher; } @@ -307,7 +307,7 @@ class TickScheduler { #endif std::atomic_bool manualMode{false}; // 手动模式 std::atomic nextTaskId{0}; // 用于生成任务的唯一标识符 - std::unique_ptr stopwatch; + std::unique_ptr stopwatch; std::atomic concurrentTasks{0}; // 当前正在运行的任务数 std::size_t maxTasks{0}; // 最大同时运行的任务数,0 表示没有限制 diff --git a/tests/atom/algorithm/md5.cpp b/tests/atom/algorithm/md5.cpp index 3fcd3a55..a46d26c2 100644 --- a/tests/atom/algorithm/md5.cpp +++ b/tests/atom/algorithm/md5.cpp @@ -3,11 +3,11 @@ TEST(MD5Test, EncryptTest) { - Atom::Utils::MD5 md5; + atom::utils::MD5 md5; std::string input = "Hello, World!"; std::string expectedOutput = "5eb63bbbe01eeed093cb22bb8f5acdc3"; - std::string actualOutput = Atom::Utils::MD5::encrypt(input); + std::string actualOutput = atom::utils::MD5::encrypt(input); EXPECT_EQ(actualOutput, expectedOutput); } From 7c9323a52cbb2010830155f10c4a13dab1c96d0f Mon Sep 17 00:00:00 2001 From: Max Qian <64824374+AstroAir@users.noreply.github.com> Date: Mon, 29 Apr 2024 04:43:07 +0000 Subject: [PATCH 3/4] update finished --- CMakeLists.txt | 2 +- README.md | 1 + src/atom/CMakeLists.txt | 14 +++--- src/atom/components/CMakeLists.txt | 1 + src/atom/components/base/main.cpp | 11 ++--- src/atom/components/component.hpp | 13 +++-- src/atom/components/dispatch.hpp | 2 +- src/atom/components/dispatch.inl | 29 +++++------ src/atom/components/templates/shared.hpp | 1 + src/atom/components/var.hpp | 61 +++--------------------- src/atom/components/var.inl | 8 ++-- src/atom/error/CMakeLists.txt | 52 ++++++++++++++++++++ src/atom/log/CMakeLists.txt | 1 + src/atom/server/variables.hpp | 2 +- src/atom/type/message.cpp | 2 +- src/atom/type/trackable.hpp | 2 +- 16 files changed, 104 insertions(+), 98 deletions(-) create mode 100644 src/atom/error/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index f1305852..8e6c4678 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -240,7 +240,7 @@ set(Lithium_module add_library(lithium_server-library STATIC ${component_module} ${config_module} ${debug_module} ${module_module} ${device_module} ${task_module} ${script_module} ${Lithium_module}) target_link_libraries(lithium_server-library loguru) -add_executable(lithium_server ${lithium_src_dir}/app.cpp) +add_executable(lithium_server ${lithium_src_dir}/App.cpp) target_link_directories(lithium_server PUBLIC ${CMAKE_BINARY_DIR}/libs) target_link_libraries(lithium_server lithium_server-library) diff --git a/README.md b/README.md index 90e4a31b..4737cf1a 100644 --- a/README.md +++ b/README.md @@ -104,6 +104,7 @@ sudo apt-get install gcc-13 g++-13 # GCC13 is the best choice, clang is alse OK wget https://cmake.org/files/v3.28/cmake-3.28.0-rc5.tar.gz tar -zxvf cmake-3.28.0-rc5.tar.gz +cd cmake-3.28.0-rc5 ./bootstrap && make && sudo make install #install newest clang-format diff --git a/src/atom/CMakeLists.txt b/src/atom/CMakeLists.txt index 2565bfc4..5ab56792 100644 --- a/src/atom/CMakeLists.txt +++ b/src/atom/CMakeLists.txt @@ -23,14 +23,18 @@ option(ATOM_BUILD_PYTHON " Build Atom with Python support" OFF) find_package(Python COMPONENTS Interpreter Development REQUIRED) if(${PYTHON_FOUND}) message("-- Found Python ${PYTHON_VERSION_STRING}: ${PYTHON_EXECUTABLE}") - find_package(pybind11 REQUIRED) - set(ATOM_BUILD_PYTHON ON) + find_package(pybind11) + if (pybind11_FOUND) + message(STATUS "Found pybind11: ${pybind11_INCLUDE_DIRS}") + set(ATOM_BUILD_PYTHON ON) + endif() endif() add_subdirectory(algorithm) add_subdirectory(async) add_subdirectory(components) add_subdirectory(connection) add_subdirectory(driver) +add_subdirectory(error) add_subdirectory(io) add_subdirectory(log) add_subdirectory(server) @@ -46,9 +50,6 @@ if(NOT HAS_STD_FORMAT) endif() # Sources list(APPEND ${PROJECT_NAME}_SOURCES - error/error_stack.cpp - error/exception.cpp - log/logger.cpp log/global_logger.cpp log/syslog.cpp @@ -56,9 +57,6 @@ list(APPEND ${PROJECT_NAME}_SOURCES # Headers list(APPEND ${PROJECT_NAME}_HEADERS - error/error_code.hpp - error/error_stack.hpp - log/logger.hpp log/global_logger.hpp log/syslog.hpp diff --git a/src/atom/components/CMakeLists.txt b/src/atom/components/CMakeLists.txt index b1d2cd00..0fa5c510 100644 --- a/src/atom/components/CMakeLists.txt +++ b/src/atom/components/CMakeLists.txt @@ -14,6 +14,7 @@ list(APPEND ${PROJECT_NAME}_HEADERS list(APPEND ${PROJECT_NAME}_LIBS loguru + atom-error atom-type atom-utils atom-server diff --git a/src/atom/components/base/main.cpp b/src/atom/components/base/main.cpp index c10a3d42..01a402b3 100644 --- a/src/atom/components/base/main.cpp +++ b/src/atom/components/base/main.cpp @@ -2,7 +2,9 @@ #include -class MySharedComponent : public SharedComponent { +#include "atom/log/loguru.hpp" + +class MySharedComponent : public Component { public: explicit MySharedComponent(const std::string &name); virtual ~MySharedComponent(); @@ -15,24 +17,21 @@ class MySharedComponent : public SharedComponent { }; MySharedComponent::MySharedComponent(const std::string &name) - : SharedComponent(name) { + : Component(name) { LOG_F(INFO, "Load {}", name); initialize(); - registerCommand("helloWorld", - [this](const json ¶ms) { return helloWorld(params); }); + registerCommand("helloWorld", &MySharedComponent::helloWorld, PointerSentinel(shared_from_this())); } MySharedComponent::~MySharedComponent() {} bool MySharedComponent::initialize() { - SharedComponent::initialize(); return true; } bool MySharedComponent::destroy() { - Component::destroy(); return true; } diff --git a/src/atom/components/component.hpp b/src/atom/components/component.hpp index 110fd0de..84da029d 100644 --- a/src/atom/components/component.hpp +++ b/src/atom/components/component.hpp @@ -30,8 +30,7 @@ Description: Basic Component Definition #include "atom/type/noncopyable.hpp" template -class Component : public std::enable_shared_from_this, - public NonCopyable { +class Component : public std::enable_shared_from_this { public: /** * @brief Constructs a new Component object. @@ -296,15 +295,15 @@ class Component : public std::enable_shared_from_this, std::string m_infoPath; Type_Info m_typeInfo; - std::unique_ptr + std::shared_ptr m_CommandDispatcher; ///< The command dispatcher for managing commands. - std::unique_ptr + std::shared_ptr m_VariableManager; ///< The variable registry for managing variables. - std::unique_ptr m_ConfigManager; + std::shared_ptr m_ConfigManager; std::unordered_map> m_OtherComponents; - - std::mutex m_mutex; }; +#include "component.inl" + #endif diff --git a/src/atom/components/dispatch.hpp b/src/atom/components/dispatch.hpp index 58ea76c6..8a666a15 100644 --- a/src/atom/components/dispatch.hpp +++ b/src/atom/components/dispatch.hpp @@ -28,7 +28,7 @@ #include "proxy.hpp" -class CommandDispatcher : public NonCopyable { +class CommandDispatcher { public: template void registerCommand( diff --git a/src/atom/components/dispatch.inl b/src/atom/components/dispatch.inl index 93203d1a..951a0815 100644 --- a/src/atom/components/dispatch.inl +++ b/src/atom/components/dispatch.inl @@ -10,11 +10,12 @@ template void CommandDispatcher::registerCommand( const std::string& name, const std::string& group, const std::string& description, std::function func, - std::optional> precondition = std::nullopt, - std::optional> postcondition = std::nullopt) { + std::optional> precondition, + std::optional> postcondition) { auto it = commands.find(name); if (it == commands.end()) { Command cmd{{ProxyFunction(std::move(func))}, + {}, description, {}, std::move(precondition), @@ -29,8 +30,8 @@ void CommandDispatcher::registerCommand( template void CommandDispatcher::registerCommand(const std::string& name, Callable&& func, - const std::string& group = "", - const std::string& description = "") { + const std::string& group, + const std::string& description) { registerCommand(name, group, description, std::function(std::forward(func))); } @@ -38,8 +39,8 @@ void CommandDispatcher::registerCommand(const std::string& name, template void CommandDispatcher::registerCommand(const std::string& name, Ret (*func)(Args...), - const std::string& group = "", - const std::string& description = "") { + const std::string& group, + const std::string& description) { registerCommand(name, group, description, std::function([func](Args... args) { return func(std::forward(args)...); @@ -50,8 +51,8 @@ template void CommandDispatcher::registerCommand(const std::string& name, Ret (Class::*func)(Args...), const PointerSentinel& instance, - const std::string& group = "", - const std::string& description = "") { + const std::string& group, + const std::string& description) { registerCommand(name, group, description, std::function([instance, func](Args... args) { return std::invoke(func, instance.get(), @@ -63,8 +64,8 @@ template void CommandDispatcher::registerCommand(const std::string& name, Ret (Class::*func)(Args...) const, const PointerSentinel& instance, - const std::string& group = "", - const std::string& description = "") { + const std::string& group, + const std::string& description) { registerCommand(name, group, description, std::function([instance, func](Args... args) { return std::invoke(func, instance.get(), @@ -76,8 +77,8 @@ template void CommandDispatcher::registerCommand(const std::string& name, Ret (Class::*func)(Args...) noexcept, const PointerSentinel& instance, - const std::string& group = "", - const std::string& description = "") { + const std::string& group, + const std::string& description) { registerCommand(name, group, description, std::function([instance, func](Args... args) { return std::invoke(func, instance.get(), @@ -88,8 +89,8 @@ void CommandDispatcher::registerCommand(const std::string& name, template void CommandDispatcher::registerCommand(const std::string& name, Ret (*func)(Args...), - const std::string& group = "", - const std::string& description = "") { + const std::string& group, + const std::string& description) { registerCommand(name, group, description, std::function([func](Args... args) { return func(std::forward(args)...); diff --git a/src/atom/components/templates/shared.hpp b/src/atom/components/templates/shared.hpp index 76b6f32f..b7176997 100644 --- a/src/atom/components/templates/shared.hpp +++ b/src/atom/components/templates/shared.hpp @@ -7,6 +7,7 @@ template class SharedComponent : public Component { +public: explicit SharedComponent(const std::string &name); virtual ~SharedComponent() override; diff --git a/src/atom/components/var.hpp b/src/atom/components/var.hpp index f780b1e4..b604bbc5 100644 --- a/src/atom/components/var.hpp +++ b/src/atom/components/var.hpp @@ -21,74 +21,27 @@ #include "atom/type/trackable.hpp" #include "atom/utils/cstring.hpp" -class VariableManager : public NonCopyable { +class VariableManager { public: template void addVariable(const std::string& name, T initialValue, const std::string& description = "", const std::string& alias = "", - const std::string& group = "") { - auto variable = std::make_shared>(std::move(initialValue)); - variables_[name] = {std::move(variable), description, alias, group}; - } + const std::string& group = ""); template - void setRange(const std::string& name, T min, T max) { - if (auto variable = getVariable(name)) { - ranges_[name] = std::make_pair(std::move(min), std::move(max)); - } - } + void setRange(const std::string& name, T min, T max); void setStringOptions(const std::string& name, - std::vector options) { - if (auto variable = getVariable(name)) { - stringOptions_[name] = std::move(options); - } - } + std::vector options); template - std::shared_ptr> getVariable(const std::string& name) { - auto it = variables_.find(name); - if (it != variables_.end()) { - try { - return std::any_cast>>( - it->second.variable); - } catch (const std::bad_any_cast& e) { - THROW_EXCEPTION(concat("Type mismatch: ", name)); - } - } - return nullptr; - } + std::shared_ptr> getVariable(const std::string& name); - void setValue(const std::string& name, const char* newValue) { - setValue(name, std::string(newValue)); - } + void setValue(const std::string& name, const char* newValue); template - void setValue(const std::string& name, T newValue) { - if (auto variable = getVariable(name)) { - if constexpr (std::is_arithmetic_v) { - if (ranges_.count(name)) { - auto [min, max] = - std::any_cast>(ranges_[name]); - if (newValue < min || newValue > max) { - THROW_EXCEPTION("Value out of range"); - } - } - } else if constexpr (std::is_same_v) { - if (stringOptions_.count(name)) { - auto& options = stringOptions_[name]; - if (std::find(options.begin(), options.end(), newValue) == - options.end()) { - THROW_EXCEPTION("Invalid string option"); - } - } - } - *variable = std::move(newValue); - } else { - THROW_EXCEPTION("Variable not found"); - } - } + void setValue(const std::string& name, T newValue); private: struct VariableInfo { diff --git a/src/atom/components/var.inl b/src/atom/components/var.inl index 7f842f31..a2ffdeb4 100644 --- a/src/atom/components/var.inl +++ b/src/atom/components/var.inl @@ -5,9 +5,9 @@ template void VariableManager::addVariable(const std::string& name, T initialValue, - const std::string& description = "", - const std::string& alias = "", - const std::string& group = "") { + const std::string& description, + const std::string& alias, + const std::string& group) { auto variable = std::make_shared>(std::move(initialValue)); variables_[name] = {std::move(variable), description, alias, group}; } @@ -35,7 +35,7 @@ std::shared_ptr> VariableManager::getVariable( return std::any_cast>>( it->second.variable); } catch (const std::bad_any_cast& e) { - THROW_EXCEPTION(concat("Type mismatch: ", name)); + //THROW_EXCEPTION(concat("Type mismatch: ", name)); } } return nullptr; diff --git a/src/atom/error/CMakeLists.txt b/src/atom/error/CMakeLists.txt new file mode 100644 index 00000000..d31ab86a --- /dev/null +++ b/src/atom/error/CMakeLists.txt @@ -0,0 +1,52 @@ +# CMakeLists.txt for Atom-Error +# This project is licensed under the terms of the GPL3 license. +# +# Project Name: Atom-Error +# Description: Atom Error Library +# Author: Max Qian +# License: GPL3 + +cmake_minimum_required(VERSION 3.20) +project(atom-error C CXX) + +list(APPEND ${PROJECT_NAME}_SOURCES + error_stack.cpp + exception.cpp +) + +# Headers +list(APPEND ${PROJECT_NAME}_HEADERS + error_code.hpp + error_stack.hpp +) + +list(APPEND ${PROJECT_NAME}_LIBS + loguru + ) + +# Build Object Library +add_library(${PROJECT_NAME}_OBJECT OBJECT) +set_property(TARGET ${PROJECT_NAME}_OBJECT PROPERTY POSITION_INDEPENDENT_CODE 1) + +if(LINUX) +target_link_libraries(${PROJECT_NAME}_OBJECT dl) +endif() +target_link_libraries(${PROJECT_NAME}_OBJECT ${${PROJECT_NAME}_LIBS}) + +target_sources(${PROJECT_NAME}_OBJECT + PUBLIC + ${${PROJECT_NAME}_HEADERS} + PRIVATE + ${${PROJECT_NAME}_SOURCES} +) + +target_link_libraries(${PROJECT_NAME}_OBJECT ${${PROJECT_NAME}_LIBS}) + +add_library(${PROJECT_NAME} STATIC) + +target_link_libraries(${PROJECT_NAME} ${PROJECT_NAME}_OBJECT ${${PROJECT_NAME}_LIBS}) +target_include_directories(${PROJECT_NAME} PUBLIC .) + +install(TARGETS ${PROJECT_NAME} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} +) \ No newline at end of file diff --git a/src/atom/log/CMakeLists.txt b/src/atom/log/CMakeLists.txt index 7034d88a..ac7996b3 100644 --- a/src/atom/log/CMakeLists.txt +++ b/src/atom/log/CMakeLists.txt @@ -122,6 +122,7 @@ else() target_link_libraries(loguru PUBLIC Threads::Threads # pthreads (or equivalent) + dl ${_lib_dl_linkflag} # dl (or equivalent) ) endif() diff --git a/src/atom/server/variables.hpp b/src/atom/server/variables.hpp index 52dfb6f7..a814c669 100644 --- a/src/atom/server/variables.hpp +++ b/src/atom/server/variables.hpp @@ -30,7 +30,7 @@ Description: Variable Registry 类,用于注册、获取和观察变量值。 #endif #include "atom/type/noncopyable.hpp" -#include "atom/experiment/string.hpp" +#include "atom/type/string.hpp" #include "atom/error/error_stack.hpp" diff --git a/src/atom/type/message.cpp b/src/atom/type/message.cpp index d1eac52c..fafd23de 100644 --- a/src/atom/type/message.cpp +++ b/src/atom/type/message.cpp @@ -111,7 +111,7 @@ Args ParamsMessage::value() const { return params_; } shared_ptr MessageHelper::MakeVoidMessage(const string &name, const string &target, const string &origin) { - return make_shared(name, target, origin); + return make_shared(name, target, origin, true); } // MessageHelper diff --git a/src/atom/type/trackable.hpp b/src/atom/type/trackable.hpp index 30382ac9..d902c202 100644 --- a/src/atom/type/trackable.hpp +++ b/src/atom/type/trackable.hpp @@ -130,7 +130,7 @@ class Trackable { try { observer(oldVal, newVal); } catch (const std::exception& e) { - THROW_EXCEPTION(concat("Exception in observer.", e.what())); + //THROW_EXCEPTION(concat("Exception in observer.", e.what())); } catch (...) { THROW_EXCEPTION("Unknown exception in observer."); } From 2e69715516881b3df51c89d89af335ab3e6a3b7f Mon Sep 17 00:00:00 2001 From: Max Qian Date: Wed, 1 May 2024 01:43:48 +0800 Subject: [PATCH 4/4] update for 24m04b --- CMakeLists.txt | 9 - src/App.cpp | 42 +- src/LithiumApp.cpp | 387 +-------- src/LithiumApp.hpp | 148 +--- src/addon/addons.cpp | 4 +- src/addon/addons.hpp | 4 +- src/addon/compiler.cpp | 4 +- src/addon/compiler.hpp | 4 +- src/addon/component.hpp | 4 +- src/addon/loader.cpp | 6 +- src/addon/loader.hpp | 78 +- src/addon/loader.inl | 79 ++ src/addon/manager.cpp | 46 +- src/addon/manager.hpp | 44 +- src/addon/module.hpp | 4 +- src/addon/sandbox.cpp | 4 +- src/addon/sandbox.hpp | 2 +- src/addon/sort.cpp | 4 +- src/addon/sort.hpp | 2 +- src/atom/CMakeLists.txt | 2 - src/atom/algorithm/CMakeLists.txt | 2 + src/atom/algorithm/algorithm.cpp | 20 +- src/atom/algorithm/algorithm.hpp | 4 +- src/atom/algorithm/calculator.hpp | 363 ++++++++ src/atom/algorithm/convolve.cpp | 62 +- src/atom/{driver/pid => algorithm}/pid.cpp | 0 src/atom/{driver/pid => algorithm}/pid.hpp | 0 src/atom/async/pool.hpp | 18 +- src/atom/components/CMakeLists.txt | 2 +- src/atom/components/abilities.hpp | 4 +- src/atom/components/base/main.cpp | 89 +- src/atom/components/component.cpp | 124 +++ src/atom/components/component.hpp | 95 +-- src/atom/components/component.inl | 169 ---- src/atom/components/configor.cpp | 209 ----- src/atom/components/configor.hpp | 199 ----- src/atom/components/dispatch.hpp | 15 +- src/atom/components/dispatch.inl | 26 + .../components/templates/alone_component.cpp | 28 - .../components/templates/alone_component.hpp | 25 - .../components/templates/exe_component.cpp | 127 --- .../components/templates/exe_component.hpp | 35 - .../components/templates/script_component.cpp | 0 .../components/templates/script_component.hpp | 0 src/atom/components/templates/shared.hpp | 26 - src/atom/components/templates/shared.inl | 104 --- .../components/templates/task_component.cpp | 0 .../components/templates/task_component.hpp | 0 src/atom/components/var.inl | 10 +- src/atom/driver/CMakeLists.txt | 71 -- src/atom/driver/_pybind.cpp | 191 ----- src/atom/driver/camera.cpp | 323 ------- src/atom/driver/camera.hpp | 199 ----- src/atom/driver/camera_utils.cpp | 27 - src/atom/driver/camera_utils.hpp | 3 - src/atom/driver/code.hpp | 61 -- src/atom/driver/device.cpp | 78 -- src/atom/driver/device.hpp | 74 -- src/atom/driver/device_type.hpp | 55 -- src/atom/driver/exception.hpp | 71 -- src/atom/driver/filterwheel.cpp | 31 - src/atom/driver/filterwheel.hpp | 35 - src/atom/driver/focuser.cpp | 55 -- src/atom/driver/focuser.hpp | 144 ---- src/atom/driver/guider.cpp | 25 - src/atom/driver/guider.hpp | 38 - src/atom/driver/macro.hpp | 21 - src/atom/driver/main.cpp | 70 -- src/atom/driver/marco.hpp | 30 - src/atom/driver/meson.build | 66 -- src/atom/driver/solver.cpp | 101 --- src/atom/driver/solver.hpp | 100 --- src/atom/driver/telescope.cpp | 67 -- src/atom/driver/telescope.hpp | 167 ---- src/atom/{components => function}/proxy.hpp | 77 +- src/atom/function/stepper.hpp | 78 ++ src/atom/{driver => image}/fitskeyword.cpp | 30 +- .../fitskeyword.h => image/fitskeyword.hpp} | 37 +- src/atom/log/logger.cpp | 4 +- src/atom/log/logger.hpp | 4 +- src/atom/server/commander.hpp | 2 +- src/atom/server/deserialize.cpp | 4 +- src/atom/server/deserialize.hpp | 4 +- src/atom/server/json_checker.cpp | 4 +- src/atom/server/json_checker.hpp | 2 +- src/atom/server/message_bus.hpp | 4 +- src/atom/server/message_queue.hpp | 4 +- src/atom/server/serialize.cpp | 4 +- src/atom/server/serialize.hpp | 4 +- src/atom/system/crash_quotes.cpp | 2 +- src/atom/type/_script.hpp | 2 + src/atom/utils/aes.cpp | 4 +- src/atom/utils/random.hpp | 39 +- src/atom/utils/ranges.hpp | 59 ++ src/atom/web/downloader.cpp | 10 +- src/carbon/command/bad_boxed_cast.hpp | 4 +- src/carbon/command/bootstrap_stl.hpp | 2 +- src/carbon/command/boxed_cast.hpp | 2 +- src/carbon/command/boxed_cast_helper.hpp | 2 +- src/carbon/command/boxed_number.hpp | 2 +- src/carbon/command/boxed_value.hpp | 2 +- src/carbon/command/dispatchkit.hpp | 6 +- src/carbon/command/dynamic_object_detail.hpp | 2 +- src/carbon/command/proxy_functions.cpp | 2 +- src/carbon/command/proxy_functions.hpp | 2 +- src/carbon/command/proxy_functions_detail.hpp | 2 +- src/carbon/command/register_function.hpp | 2 +- src/carbon/command/type_conversions.hpp | 4 +- src/carbon/language/algebraic.hpp | 60 +- src/carbon/language/common.cpp | 2 +- src/carbon/language/common.hpp | 54 +- src/carbon/language/eval.hpp | 2 +- src/carbon/language/parser.hpp | 22 +- src/carbon/utils/json.hpp | 2 +- src/config/CMakeLists.txt | 9 + src/config/_component.cpp | 178 +--- src/config/_component.hpp | 38 +- src/config/_main.cpp | 7 +- src/config/_script.hpp | 4 +- src/config/_test.cpp | 33 + src/config/configor.cpp | 11 +- src/config/configor.hpp | 3 +- src/debug/terminal.cpp | 4 +- src/debug/terminal.hpp | 4 +- src/device/manager.cpp | 10 +- src/device/manager.hpp | 12 +- src/device/protector.cpp | 4 +- src/device/protector.hpp | 4 +- src/device/server/hydrogen.cpp | 18 +- src/device/server/hydrogen.hpp | 7 +- src/device/utils/utils.cpp | 2 +- src/device/utils/utils.hpp | 2 +- src/preload.cpp | 2 +- src/script/carbon.cpp | 12 +- src/script/carbon.hpp | 4 +- src/script/custom/config.cpp | 14 +- src/script/custom/os.cpp | 6 +- src/script/custom/sys.cpp | 4 +- src/script/manager.cpp | 4 +- src/script/manager.hpp | 4 +- src/script/sheller.cpp | 4 +- src/script/sheller.hpp | 4 +- src/server/Runner.cpp | 8 +- .../controller/AsyncConfigController.hpp | 6 +- .../controller/AsyncDeviceController.hpp | 794 ++++++++++-------- src/server/controller/AsyncIOController.hpp | 40 +- .../controller/AsyncModuleController.hpp | 18 +- src/server/controller/AsyncPHD2Controller.hpp | 6 +- src/task/checker.cpp | 4 +- src/task/checker.hpp | 4 +- src/task/container.cpp | 4 +- src/task/container.hpp | 4 +- src/task/generator.cpp | 11 +- src/task/generator.hpp | 7 +- src/task/list.cpp | 4 +- src/task/list.hpp | 4 +- src/task/loader.cpp | 4 +- src/task/loader.hpp | 4 +- src/task/manager.cpp | 4 +- src/task/manager.hpp | 4 +- src/task/pool.cpp | 4 +- src/task/pool.hpp | 4 +- src/task/singlepool.cpp | 4 +- src/task/singlepool.hpp | 4 +- src/task/tick.cpp | 4 +- src/task/tick.hpp | 4 +- 166 files changed, 1918 insertions(+), 4734 deletions(-) create mode 100644 src/addon/loader.inl create mode 100644 src/atom/algorithm/calculator.hpp rename src/atom/{driver/pid => algorithm}/pid.cpp (100%) rename src/atom/{driver/pid => algorithm}/pid.hpp (100%) create mode 100644 src/atom/components/component.cpp delete mode 100644 src/atom/components/component.inl delete mode 100644 src/atom/components/configor.cpp delete mode 100644 src/atom/components/configor.hpp delete mode 100644 src/atom/components/templates/alone_component.cpp delete mode 100644 src/atom/components/templates/alone_component.hpp delete mode 100644 src/atom/components/templates/exe_component.cpp delete mode 100644 src/atom/components/templates/exe_component.hpp delete mode 100644 src/atom/components/templates/script_component.cpp delete mode 100644 src/atom/components/templates/script_component.hpp delete mode 100644 src/atom/components/templates/shared.hpp delete mode 100644 src/atom/components/templates/shared.inl delete mode 100644 src/atom/components/templates/task_component.cpp delete mode 100644 src/atom/components/templates/task_component.hpp delete mode 100644 src/atom/driver/CMakeLists.txt delete mode 100644 src/atom/driver/_pybind.cpp delete mode 100644 src/atom/driver/camera.cpp delete mode 100644 src/atom/driver/camera.hpp delete mode 100644 src/atom/driver/camera_utils.cpp delete mode 100644 src/atom/driver/camera_utils.hpp delete mode 100644 src/atom/driver/code.hpp delete mode 100644 src/atom/driver/device.cpp delete mode 100644 src/atom/driver/device.hpp delete mode 100644 src/atom/driver/device_type.hpp delete mode 100644 src/atom/driver/exception.hpp delete mode 100644 src/atom/driver/filterwheel.cpp delete mode 100644 src/atom/driver/filterwheel.hpp delete mode 100644 src/atom/driver/focuser.cpp delete mode 100644 src/atom/driver/focuser.hpp delete mode 100644 src/atom/driver/guider.cpp delete mode 100644 src/atom/driver/guider.hpp delete mode 100644 src/atom/driver/macro.hpp delete mode 100644 src/atom/driver/main.cpp delete mode 100644 src/atom/driver/marco.hpp delete mode 100644 src/atom/driver/meson.build delete mode 100644 src/atom/driver/solver.cpp delete mode 100644 src/atom/driver/solver.hpp delete mode 100644 src/atom/driver/telescope.cpp delete mode 100644 src/atom/driver/telescope.hpp rename src/atom/{components => function}/proxy.hpp (58%) create mode 100644 src/atom/function/stepper.hpp rename src/atom/{driver => image}/fitskeyword.cpp (70%) rename src/atom/{driver/fitskeyword.h => image/fitskeyword.hpp} (57%) create mode 100644 src/config/_test.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 8e6c4678..a83d51fb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -185,15 +185,6 @@ elseif(LINUX) endif() set(component_module - ${lithium_src_dir}/device/server/ascom.cpp - ${lithium_src_dir}/device/server/hydrogen.cpp - ${lithium_src_dir}/device/server/hydrogen_driver.cpp - ${lithium_src_dir}/device/server/connector.cpp - - ${lithium_src_dir}/device/manager.cpp - - ${lithium_src_dir}/device/utils/utils.cpp - ${lithium_component_dir}/addons.cpp ${lithium_component_dir}/compiler.cpp ${lithium_component_dir}/loader.cpp diff --git a/src/App.cpp b/src/App.cpp index 3125a486..eaf921a5 100644 --- a/src/App.cpp +++ b/src/App.cpp @@ -25,7 +25,7 @@ Description: Main Entry #define ENABLE_TERMINAL 1 #if ENABLE_TERMINAL #include "debug/terminal.hpp" -using namespace Lithium::Terminal; +using namespace lithium::Terminal; #endif #include "server/App.hpp" @@ -116,9 +116,9 @@ int main(int argc, char *argv[]) { program.parse_args(argc, argv); - Lithium::InitLithiumApp(argc, argv); + lithium::InitLithiumApp(argc, argv); // Create shared instance - Lithium::MyApp = Lithium::LithiumApp::createShared(); + lithium::MyApp = lithium::LithiumApp::createShared(); // Parse arguments try { auto cmd_host = program.get("--host"); @@ -128,64 +128,66 @@ int main(int argc, char *argv[]) { auto cmd_web_panel = program.get("--web-panel"); auto cmd_debug = program.get("--debug"); + // TODO: We need a new way to handle command line arguments. + // Maybe we will generate a json object or a map and then given to the + // lithiumapp for initialization. + /* if (!cmd_host.empty()) { - Lithium::MyApp->SetConfig( + lithium::MyApp->SetConfig( {{"key", "config/server/host"}, {"value", cmd_host}}); DLOG_F(INFO, "Set server host to {}", cmd_host); } if (cmd_port != 8000) { DLOG_F(INFO, "Command line server port : {}", cmd_port); - auto port = Lithium::MyApp->GetConfig("config/server") + auto port = lithium::MyApp->GetConfig("config/server") .value("port", 8000); if (port != cmd_port) { - Lithium::MyApp->SetConfig( + lithium::MyApp->SetConfig( {{"key", "config/server/port"}, {"value", cmd_port}}); DLOG_F(INFO, "Set server port to {}", cmd_port); } } if (!cmd_config_path.empty()) { - Lithium::MyApp->SetConfig({{"key", "config/server/configpath"}, + lithium::MyApp->SetConfig({{"key", "config/server/configpath"}, {"value", cmd_config_path}}); DLOG_F(INFO, "Set server config path to {}", cmd_config_path); } if (!cmd_module_path.empty()) { - Lithium::MyApp->SetConfig({{"key", "config/server/modulepath"}, + lithium::MyApp->SetConfig({{"key", "config/server/modulepath"}, {"value", cmd_module_path}}); DLOG_F(INFO, "Set server module path to {}", cmd_module_path); } if (!cmd_web_panel) { - if (Lithium::MyApp->GetConfig("config/server/web").get()) { - Lithium::MyApp->SetConfig( + if (lithium::MyApp->GetConfig("config/server/web").get()) { + lithium::MyApp->SetConfig( {{"key", "config/server/web"}, {"value", false}}); DLOG_F(INFO, "Disable web panel"); } } if (cmd_debug) { - if (!Lithium::MyApp->GetConfig("config/server/debug").get()) { - Lithium::MyApp->SetConfig( + if (!lithium::MyApp->GetConfig("config/server/debug").get()) { + lithium::MyApp->SetConfig( {{"key", "config/server/debug"}, {"value", true}}); } } else { - Lithium::MyApp->SetConfig( + lithium::MyApp->SetConfig( {{"key", "config/server/debug"}, {"value", false}}); DLOG_F(INFO, "Disable debug mode"); } + */ + } catch (const std::bad_any_cast &e) { LOG_F(ERROR, "Invalid args format! Error: {}", e.what()); Atom::System::saveCrashLog(e.what()); return 1; } - // In debug mode run the terminal first and will not run the server - if (Lithium::MyApp->GetConfig("config/server/debug").get()) { - ConsoleTerminal terminal; - terminal.run(); - } else { - runServer(); - } + ConsoleTerminal terminal; + terminal.run(); + runServer(); return 0; } \ No newline at end of file diff --git a/src/LithiumApp.cpp b/src/LithiumApp.cpp index 58e78a71..c4bc6bbb 100644 --- a/src/LithiumApp.cpp +++ b/src/LithiumApp.cpp @@ -17,14 +17,11 @@ Description: Lithium App Enter #include "config.h" #include "addon/addons.hpp" +#include "addon/loader.hpp" #include "addon/manager.hpp" #include "config/configor.hpp" -#include "device/manager.hpp" -#include "device/server/ascom.hpp" -#include "device/server/hydrogen.hpp" - #include "task/manager.hpp" #include "script/manager.hpp" @@ -80,25 +77,13 @@ using json = nlohmann::json; #define GET_VALUE_D(type, key, defaultValue) \ type key = (params.contains(#key) ? params[#key].get() : defaultValue) -namespace Lithium { +namespace lithium { std::shared_ptr MyApp = nullptr; LithiumApp::LithiumApp() { DLOG_F(INFO, "LithiumApp Constructor"); try { - // Specialized Managers and Threads - m_ConfigManager = GetWeakPtr("lithium.config"); - CHECK_WEAK_PTR_EXPIRED(m_ConfigManager, - "load config manager from gpm: lithium.config"); - m_DeviceManager = GetWeakPtr("lithium.device"); - CHECK_WEAK_PTR_EXPIRED(m_DeviceManager, - "load device manager from gpm: lithium.device"); - m_ProcessManager = - GetWeakPtr("lithium.system.process"); - CHECK_WEAK_PTR_EXPIRED( - m_ProcessManager, - "load process manager from gpm: lithium.system.process"); - m_MessageBus = GetWeakPtr("lithium.bus"); + m_MessageBus = GetWeakPtr("lithium.bus"); CHECK_WEAK_PTR_EXPIRED(m_MessageBus, "load message bus from gpm: lithium.bus"); @@ -115,11 +100,6 @@ LithiumApp::LithiumApp() { m_MessageBus.lock()->StartProcessingThread(); DLOG_F(INFO, "Register LithiumApp Member Functions"); - - LiRegisterMemberFunc("GetConfig", &LithiumApp::GetConfig); - LiRegisterMemberFunc("SetConfig", &LithiumApp::SetConfig); - LiRegisterMemberFunc("DeleteConfig", &LithiumApp::DeleteConfig); - LiRegisterMemberFunc("SaveConfig", &LithiumApp::SaveConfig); } catch (const std::exception &e) { LOG_F(ERROR, "Failed to load Lithium App , error : {}", e.what()); throw std::runtime_error("Failed to load Lithium App"); @@ -138,16 +118,11 @@ std::shared_ptr LithiumApp::createShared() { void InitLithiumApp(int argc, char **argv) { LOG_F(INFO, "Init Lithium App"); - // Config - AddPtr("lithium.config", ConfigManager::createShared()); // Message Bus - AddPtr("lithium.bus", Atom::Server::MessageBus::createShared()); + AddPtr("lithium.bus", atom::server::MessageBus::createShared()); // AddPtr("ModuleLoader", ModuleLoader::createShared()); // AddPtr("lithium.async.thread", // Atom::Async::ThreadManager::createShared(GetIntConfig("config/server/maxthread"))); - AddPtr("lithium.system.process", - Atom::System::ProcessManager::createShared( - GetIntConfig("config/server/maxprocess"))); // AddPtr("PluginManager", // PluginManager::createShared(GetPtr("ProcessManager"))); // AddPtr("TaskManager", std::make_shared("tasks.json")); @@ -156,13 +131,8 @@ void InitLithiumApp(int argc, char **argv) { // AddPtr("TaskStack", std::make_shared()); // AddPtr("ScriptManager", // ScriptManager::createShared(GetPtr("MessageBus"))); - AddPtr("lithium.device", - DeviceManager::createShared( - GetPtr("lithium.bus").value(), - GetPtr("lithium.config").value())); - AddPtr("lithium.device.hydrogen", HydrogenManager::createShared()); - AddPtr("lithium.error.stack", std::make_shared()); + AddPtr("lithium.error.stack", std::make_shared()); AddPtr("lithium.task.container", TaskContainer::createShared()); AddPtr("lithiun.task.generator", TaskGenerator::createShared()); @@ -173,8 +143,6 @@ void InitLithiumApp(int argc, char **argv) { TickScheduler::createShared(std::thread::hardware_concurrency())); AddPtr("lithium.task.manager", TaskManager::createShared()); - AddPtr("lithium.cmd.global", CommandDispatcher::createShared()); - AddPtr("lithium.utils.env", atom::utils::Env::createShared(argc, argv)); // TODO: Addons path need to be configurable @@ -238,347 +206,4 @@ json createWarningResponse(const std::string &command, const json &warning, } return res; } - -// ---------------------------------------------------------------- -// Config -// ---------------------------------------------------------------- - -json LithiumApp::GetConfig(const json ¶ms) { - INIT_FUNC(); - CHECK_PARAM("key"); - std::string key_path = params["key"].get(); - json res; - if (auto value = m_ConfigManager.lock()->getValue(key_path); - value.has_value()) { - return createSuccessResponse(__func__, value.value()); - } - return createErrorResponse(__func__, json(), - std::format("Key {} not found", key_path)); -} - -json LithiumApp::SetConfig(const json ¶ms) { - INIT_FUNC(); - CHECK_PARAM("key"); - CHECK_PARAM("value"); - std::string key_path = params["key"].get(); - json value = params["value"]; - if (value.is_null()) { - return createErrorResponse(__func__, json(), "Value is null"); - } - if (m_ConfigManager.lock()->setValue(key_path, value)) { - return createSuccessResponse(__func__, value); - } - return createErrorResponse( - __func__, json(), - std::format("Failed to set value for key {}", key_path)); -} - -json LithiumApp::DeleteConfig(const json ¶ms) { - INIT_FUNC(); - CHECK_PARAM("key"); - std::string key_path = params["key"].get(); - if (m_ConfigManager.lock()->deleteValue(key_path)) { - return createSuccessResponse(__func__, json()); - } - return createErrorResponse( - __func__, json(), std::format("Failed to delete key {}", key_path)); -} - -json LithiumApp::SaveConfig(const json ¶ms) { - INIT_FUNC(); - GET_VALUE_D(std::string, path, "config/config.json"); - if (m_ConfigManager.lock()->saveToFile(path)) { - return createSuccessResponse(__func__, json()); - } - return createErrorResponse(__func__, json(), "Failed to save config"); -} - -// ----------------------------------------------------------------- -// Device -// ----------------------------------------------------------------- - -json LithiumApp::getDeviceList(const json ¶ms) { - INIT_FUNC(); - GET_VALUE_D(std::string, type, "all"); - json device_list; - if (type == "all") { - for (const auto &device : m_DeviceManager.lock()->getDeviceList()) { - device_list.push_back(device); - } - } else { - DeviceType d_type = StringToDeviceType(type); - if (d_type == DeviceType::NumDeviceTypes) { - return createErrorResponse( - __func__, json(), std::format("Unknown device type {}", type)); - } - for (const auto &device : - m_DeviceManager.lock()->getDeviceListByType(d_type)) { - device_list.push_back(device); - } - if (device_list.empty()) { - return createErrorResponse( - __func__, json(), - std::format("No device found for type {}", type)); - } - } - return createSuccessResponse(__func__, device_list); -} - -json LithiumApp::addDevice(const json ¶ms) { - INIT_FUNC(); - CHECK_PARAMS("type", "name", "lib_name"); - std::string type = params["type"].get(); - std::string name = params["name"].get(); - std::string lib_name = params["lib_name"].get(); - DeviceType d_type = StringToDeviceType(type); - if (d_type == DeviceType::NumDeviceTypes) { - return createErrorResponse(__func__, json(), - std::format("Unknown device type {}", type)); - } - if (m_DeviceManager.lock()->findDevice(d_type, name) != 0) { - return createErrorResponse( - __func__, json(), std::format("Device {} already exists", name)); - } - if (m_DeviceManager.lock()->addDevice(d_type, name, lib_name)) { - return createSuccessResponse(__func__, json()); - } - return createErrorResponse(__func__, json(), - std::format("Failed to add device {}", name)); -} - -json LithiumApp::addDeviceLibrary(const json ¶ms) { - INIT_FUNC(); - CHECK_PARAM("lib_path"); - CHECK_PARAM("lib_name"); - std::string lib_path = params["lib_path"].get(); - std::string lib_name = params["lib_name"].get(); - if (m_DeviceManager.lock()->addDeviceLibrary(lib_path, lib_name)) { - return createSuccessResponse(__func__, json()); - } - return createErrorResponse( - __func__, json(), - std::format("Failed to add device library {}", lib_name)); -} - -json LithiumApp::removeDevice(const json ¶ms) { - INIT_FUNC(); - CHECK_PARAMS("type", "name"); - std::string type = params["type"].get(); - std::string name = params["name"].get(); - DeviceType d_type = StringToDeviceType(type); - if (d_type == DeviceType::NumDeviceTypes) { - return createErrorResponse(__func__, json(), - std::format("Unknown device type {}", type)); - } - if (m_DeviceManager.lock()->removeDevice(d_type, name)) { - return createSuccessResponse(__func__, json()); - } - return createErrorResponse(__func__, json(), - std::format("Failed to remove device {}", name)); -} - -json LithiumApp::removeDeviceByName(const json ¶ms) { - INIT_FUNC(); - CHECK_PARAM("name"); - std::string name = params["name"].get(); - if (m_DeviceManager.lock()->removeDeviceByName(name)) { - return createSuccessResponse(__func__, json()); - } - return createErrorResponse(__func__, json(), - std::format("Failed to remove device {}", name)); -} - -json LithiumApp::removeDeviceLibrary(const json ¶ms) { - INIT_FUNC(); - CHECK_PARAM("lib_name"); - std::string lib_name = params["lib_name"].get(); - if (m_DeviceManager.lock()->removeDeviceLibrary(lib_name)) { - return createSuccessResponse(__func__, json()); - } - return createErrorResponse( - __func__, json(), - std::format("Failed to remove device library {}", lib_name)); -} - -/* - void LithiumApp::addDeviceObserver(DeviceType type, const std::string &name) - { - m_DeviceManager.lock()->addDeviceObserver(type, name); - } - - bool LithiumApp::removeDevice(DeviceType type, const std::string &name) - { - return m_DeviceManager.lock()->removeDevice(type, name); - } - - bool LithiumApp::removeDeviceByName(const std::string &name) - { - return m_DeviceManager.lock()->removeDeviceByName(name); - } - - bool LithiumApp::removeDeviceLibrary(const std::string &lib_name) - { - return m_DeviceManager.lock()->removeDeviceLibrary(lib_name); - } - - std::shared_ptr LithiumApp::getDevice(DeviceType type, const - std::string &name) - { - return m_DeviceManager.lock()->getDevice(type, name); - } - - size_t LithiumApp::findDevice(DeviceType type, const std::string &name) - { - return m_DeviceManager.lock()->findDevice(type, name); - } - - std::shared_ptr LithiumApp::findDeviceByName(const std::string - &name) const - { - return m_DeviceManager.lock()->findDeviceByName(name); - } - - std::shared_ptr LithiumApp::getTask(DeviceType type, const - std::string &device_name, const std::string &task_name, const json ¶ms) - { - return m_DeviceManager.lock()->getTask(type, device_name, task_name, - params); - } - - bool LithiumApp::getProperty(const std::string &name, const std::string - &property_name) - { - m_DeviceManager.lock()->findDeviceByName(name)->getStringProperty(property_name); - return true; - } - - bool LithiumApp::setProperty(const std::string &name, const std::string - &property_name, const std::string &property_value) - { - return true; - } -*/ - -// ------------------------------------------------------------------ -// Process -// ------------------------------------------------------------------ - -json LithiumApp::createProcess(const json ¶ms) { - INIT_FUNC(); - CHECK_PARAMS("command", "identifier"); - std::string command = params["command"].get(); - std::string identifier = params["identifier"].get(); - if (m_ProcessManager.lock()->hasProcess(identifier)) { - return createErrorResponse( - __func__, json(), - std::format("Process {} already exists", identifier)); - } - if (m_ProcessManager.lock()->createProcess(command, identifier)) { - return createSuccessResponse(__func__, json()); - } else { - return createErrorResponse( - __func__, json(), - std::format("Failed to create process {}", identifier)); - } -} - -json LithiumApp::runScript(const json ¶ms) { - INIT_FUNC(); - CHECK_PARAMS("script", "identifier"); - std::string script = params["script"].get(); - std::string identifier = params["identifier"].get(); - if (m_ProcessManager.lock()->runScript(script, identifier)) { - return createSuccessResponse(__func__, json()); - } else { - return createErrorResponse( - __func__, json(), - std::format("Failed to run script {}", identifier)); - } -} - -json LithiumApp::terminateProcess(const json ¶ms) { - INIT_FUNC(); - CHECK_PARAM("pid"); - int pid = params["pid"].get(); - int signal = params.value("signal", 15); - if (m_ProcessManager.lock()->terminateProcess(pid, signal)) { - return createSuccessResponse(__func__, json()); - } else { - return createErrorResponse( - __func__, json(), - std::format("Failed to terminate process {}", pid)); - } -} - -json LithiumApp::terminateProcessByName(const json ¶ms) { - INIT_FUNC(); - CHECK_PARAMS("name"); - std::string name = params["name"].get(); - int signal = params.value("signal", 15); - if (m_ProcessManager.lock()->terminateProcessByName(name, signal)) { - return createSuccessResponse(__func__, json()); - } - return createErrorResponse( - __func__, json(), std::format("Failed to terminate process {}", name)); -} - -json LithiumApp::getRunningProcesses(const json ¶ms) { - json running_process; - for (auto &process : m_ProcessManager.lock()->getRunningProcesses()) { - running_process["process"].push_back({{"pid", process.pid}, - {"name", process.name}, - {"status", process.status}, - {"output", process.output}}); - } - return createSuccessResponse(__func__, running_process["process"]); -} - -json LithiumApp::getProcessOutput(const json ¶ms) { - INIT_FUNC(); - CHECK_PARAM("identifier"); - std::string identifier = params["identifier"].get(); - if (!m_ProcessManager.lock()->hasProcess(identifier)) { - return createErrorResponse( - __func__, json(), - std::format("Process {} does not exist", identifier)); - } - json output; - for (auto &line : m_ProcessManager.lock()->getProcessOutput(identifier)) { - output.push_back(line); - } - return createSuccessResponse(__func__, output); -} - -json LithiumApp::DispatchCommand(const std::string &name, const json ¶ms) { - if (name.empty()) { - DLOG_F(ERROR, "Invalid command name or params"); - return json(); - } - if (m_CommandDispatcher) { - if (m_CommandDispatcher->hasHandler(name)) { - DLOG_F(INFO, "Dispatching command {}", name); -#if ENABLE_DEBUG - json res = m_CommandDispatcher->Dispatch(name, params); - DLOG_F(INFO, _("Dispatched command {} with result: {}"), name, - res.dump()); - return res; -#else - return m_CommandDispatcher->dispatch(name, params); -#endif - } else { - LOG_F(ERROR, "Command {} not found", name); - return json(); - } - } - LOG_F(ERROR, "Command dispatcher not found"); - return json(); -} - -bool LithiumApp::hasCommand(const std::string &name) { - if (m_CommandDispatcher) { - return m_CommandDispatcher->hasHandler(name); - } else { - return false; - } -} -} // namespace Lithium \ No newline at end of file +} // namespace lithium \ No newline at end of file diff --git a/src/LithiumApp.hpp b/src/LithiumApp.hpp index bd97ea3e..69641ea0 100644 --- a/src/LithiumApp.hpp +++ b/src/LithiumApp.hpp @@ -18,7 +18,7 @@ Description: Lithium App Enter #include -#include "atom/server/commander.hpp" +#include "atom/components/dispatch.hpp" #include "atom/server/message_bus.hpp" #include "atom/type/message.hpp" #include "atom/type/json.hpp" @@ -35,21 +35,23 @@ using json = nlohmann::json; // parameters. However, It is more convenient to use json object. // ------------------------------------------------------------------- -namespace Atom +namespace atom { - namespace Error + namespace error { class ErrorStack; } - namespace System + namespace system { class ProcessManager; } } -namespace Lithium { +namespace lithium { class PyScriptManager; // FWD +class CarbonScript; + class ComponentManager; // FWD class ConfigManager; @@ -58,8 +60,6 @@ class TaskPool; class TaskManager; -class DeviceManager; - class LithiumApp { public: LithiumApp(); @@ -71,143 +71,17 @@ class LithiumApp { static std::shared_ptr createShared(); - // ------------------------------------------------------------------- - // Config methods - // ------------------------------------------------------------------- - - json GetConfig(const json ¶ms); - json SetConfig(const json ¶ms); - json DeleteConfig(const json ¶ms); - json SaveConfig(const json ¶ms); - - // ------------------------------------------------------------------- - // Device methods - // ------------------------------------------------------------------- - - json getDeviceList(const json ¶ms); - json addDevice(const json ¶ms); - json addDeviceLibrary(const json ¶ms); - json removeDevice(const json ¶ms); - json removeDeviceByName(const json ¶ms); - json removeDeviceLibrary(const json ¶ms); - /* - void addDeviceObserver(DeviceType type, const std::string &name); - bool removeDevice(DeviceType type, const std::string &name); - bool removeDeviceByName(const std::string &name); - bool removeDeviceLibrary(const std::string &lib_name); - std::weak_ptr getDevice(DeviceType type, const std::string - &name); size_t findDevice(DeviceType type, const std::string &name); - std::weak_ptr findDeviceByName(const std::string &name) - const; std::weak_ptr getTask(DeviceType type, const - std::string &device_name, const std::string &task_name, const json - ¶ms); bool getProperty(const std::string &name, const std::string - &property_name); bool setProperty(const std::string &name, const - std::string &property_name, const std::string &property_value); - */ - - // ------------------------------------------------------------------- - // Process methods - // ------------------------------------------------------------------- - - json createProcess(const json ¶ms); - json runScript(const json ¶ms); - json terminateProcess(const json ¶ms); - json terminateProcessByName(const json ¶ms); - json getProcessOutput(const json ¶ms); - json getRunningProcesses(const json ¶ms); - - // ------------------------------------------------------------------- - // Message methods - // ------------------------------------------------------------------- - - template - void MSSubscribe(const std::string &topic, - std::function callback, - int priority = 0) { - m_MessageBus.lock()->Subscribe(topic, callback, priority); - } - - template - void MSUnsubscribe(const std::string &topic, - std::function callback) { - m_MessageBus.lock()->Unsubscribe(topic, callback); - } - - void sendStringMessage(const std::string &topic, - const std::string &message) { - m_MessageBus.lock()->Publish(topic, message); - } - - void sendJsonMessage(const std::string &topic, const json &message) { - if (message.is_null()) - return; - if (m_MessageBus.expired()) - return; - m_MessageBus.lock()->Publish(topic, message); - } - - ReturnMessage returnMessage(const std::string &message); - -public: - // ------------------------------------------------------------------- - // Lithium Command methods (the main entry point) - // ------------------------------------------------------------------- - // ------------------------------------------------------------------- - // NOTE: The handler must be registered before the websocket server starts. - // Though the handler can be registered after the websocket server - // starts, it is not guaranteed that the handler will be called. All - // of the servers (both websocket and tcp) will use the follow handler - // to handle the command. No private components exposed to theservers. - // ------------------------------------------------------------------- - - void LiRegisterFunc(const std::string &name, - std::function handler) { - m_CommandDispatcher->registerHandler(name, handler); - } - - template - void LiRegisterMemberFunc(const std::string &name, - json (T::*memberFunc)(const json &)) { - if (!m_CommandDispatcher) - m_CommandDispatcher = - std::make_unique>(); - m_CommandDispatcher->registerMemberHandler(name, this, memberFunc); - } - - // Max: The async func will be executed in a separate thread, and the return - // value will be ignored. - // So must use MessageBus to send the return value. - template - void LiRegisterAsyncMemberFunc(const std::string &name, - json (T::*memberFunc)(const json &), - bool async = false) { - if (!m_CommandDispatcher) - m_CommandDispatcher = - std::make_unique>(); - m_CommandDispatcher->registerMemberHandler(name + "_async", this, - memberFunc); - } - - json DispatchCommand(const std::string &name, const json ¶ms); - - bool hasCommand(const std::string &name); - -private: - std::unique_ptr> m_CommandDispatcher; - private: std::weak_ptr m_TaskPool; - std::weak_ptr m_ConfigManager; - std::weak_ptr m_DeviceManager; - std::weak_ptr m_ProcessManager; - std::weak_ptr m_MessageBus; - std::weak_ptr mStack; + std::weak_ptr m_MessageBus; + std::weak_ptr m_ErrorStack; std::weak_ptr m_ComponentManager; std::weak_ptr m_TaskManager; std::weak_ptr m_PyScriptManager; + std::weak_ptr m_CarbonScript; }; extern std::shared_ptr MyApp; void InitLithiumApp(int argc, char **argv); -} // namespace Lithium +} // namespace lithium diff --git a/src/addon/addons.cpp b/src/addon/addons.cpp index 4f6d5544..c4afd1ba 100644 --- a/src/addon/addons.cpp +++ b/src/addon/addons.cpp @@ -20,7 +20,7 @@ Description: Addon manager to solve the dependency problem. #include "atom/log/loguru.hpp" -namespace Lithium { +namespace lithium { bool AddonManager::addModule(const std::filesystem::path &path, const std::string &name) { if (m_modules.find(name) != m_modules.end()) { @@ -143,4 +143,4 @@ bool AddonManager::checkCircularDependencies( recursionStack[modName] = false; return false; } -} // namespace Lithium +} // namespace lithium diff --git a/src/addon/addons.hpp b/src/addon/addons.hpp index 6a030eea..34906304 100644 --- a/src/addon/addons.hpp +++ b/src/addon/addons.hpp @@ -25,7 +25,7 @@ Description: Addon manager to solve the dependency problem. #include "atom/type/json.hpp" using json = nlohmann::json; -namespace Lithium { +namespace lithium { /** * @brief This is the class which contains the dependencies relationships of the * modules. @@ -129,4 +129,4 @@ class AddonManager { bool checkMissingDependencies(const std::string &modName, std::vector &missingDeps); }; -} // namespace Lithium +} // namespace lithium diff --git a/src/addon/compiler.cpp b/src/addon/compiler.cpp index 6840addc..d5db6774 100644 --- a/src/addon/compiler.cpp +++ b/src/addon/compiler.cpp @@ -26,7 +26,7 @@ Description: Compiler using json = nlohmann::json; namespace fs = std::filesystem; -namespace Lithium { +namespace lithium { bool Compiler::compileToSharedLibrary(std::string_view code, std::string_view moduleName, std::string_view functionName, @@ -170,4 +170,4 @@ std::vector Compiler::findAvailableCompilers() { return availableCompilers; } -} // namespace Lithium +} // namespace lithium diff --git a/src/addon/compiler.hpp b/src/addon/compiler.hpp index 4a9b63b8..77d22ac4 100644 --- a/src/addon/compiler.hpp +++ b/src/addon/compiler.hpp @@ -21,7 +21,7 @@ Description: Compiler #include #include -namespace Lithium { +namespace lithium { class Compiler { public: /** @@ -84,5 +84,5 @@ class Compiler { std::unordered_map cache_; }; -} // namespace Lithium +} // namespace lithium #endif diff --git a/src/addon/component.hpp b/src/addon/component.hpp index 16ad10d1..01c0e188 100644 --- a/src/addon/component.hpp +++ b/src/addon/component.hpp @@ -17,7 +17,7 @@ Description: Component Entry, which is used to describe the component. #include #include -namespace Lithium { +namespace lithium { class ComponentEntry { public: std::string m_name; @@ -37,4 +37,4 @@ class ComponentEntry { m_project_name(project_name) {} }; -} // namespace Lithium +} // namespace lithium diff --git a/src/addon/loader.cpp b/src/addon/loader.cpp index a58bdfde..5dc772a3 100644 --- a/src/addon/loader.cpp +++ b/src/addon/loader.cpp @@ -44,7 +44,7 @@ namespace fs = std::filesystem; #define SET_CONFIG_VALUE(key) \ config[dir.path().string()][#key] = module_config.value(#key, ""); -namespace Lithium { +namespace lithium { ModuleLoader::ModuleLoader(const std::string &dir_name = "modules") { DLOG_F(INFO, "C++ module manager loaded successfully."); } @@ -78,7 +78,7 @@ bool ModuleLoader::LoadModule(const std::string &path, LOG_F(ERROR, "Module {} already loaded", name); return false; } - if (!Atom::IO::isFileExists(path)) { + if (!atom::io::isFileExists(path)) { LOG_F(ERROR, "Module {} does not exist", name); return false; } @@ -454,4 +454,4 @@ bool ModuleLoader::HasFunction(const std::string &name, return (LOAD_FUNCTION(handle_it->second->handle, function_name.c_str()) != nullptr); } -} // namespace Lithium \ No newline at end of file +} // namespace lithium \ No newline at end of file diff --git a/src/addon/loader.hpp b/src/addon/loader.hpp index c2327758..a9efd25b 100644 --- a/src/addon/loader.hpp +++ b/src/addon/loader.hpp @@ -12,7 +12,8 @@ Description: C++ and Modules Loader **************************************************/ -#pragma once +#ifndef LITHIUM_ADDON_LOADER_HPP +#define LITHIUM_ADDON_LOADER_HPP #include #include @@ -60,7 +61,7 @@ Description: C++ and Modules Loader using json = nlohmann::json; -namespace Lithium { +namespace lithium { /** * @brief 模块加载器类。 * @@ -352,73 +353,8 @@ class ModuleLoader { mutable std::shared_mutex m_SharedMutex; }; +} // namespace lithium -template -T ModuleLoader::GetFunction(const std::string &name, - const std::string &function_name) { - std::shared_lock lock(m_SharedMutex); - auto handle_it = modules_.find(name); - if (handle_it == modules_.end()) { - LOG_F(ERROR, "Failed to find module {}", name); - return nullptr; - } - - auto func_ptr = reinterpret_cast( - LOAD_FUNCTION(handle_it->second->handle, function_name.c_str())); - - if (!func_ptr) { - LOG_F(ERROR, "Failed to get symbol {} from module {}: {}", - function_name, name, dlerror()); - return nullptr; - } - - return func_ptr; -} - -template -std::shared_ptr ModuleLoader::GetInstance(const std::string &name, - const json &config, - const std::string &symbol_name) { - std::shared_lock lock(m_SharedMutex); - if (!HasModule(name)) { - LOG_F(ERROR, "Failed to find module {}", name); - return nullptr; - } - auto get_instance_func = - GetFunction (*)(const json &)>(name, symbol_name); - if (!get_instance_func) { - LOG_F(ERROR, "Failed to get symbol {} from module {}: {}", symbol_name, - name, dlerror()); - return nullptr; - } - - return get_instance_func(config); -} - -template -std::unique_ptr ModuleLoader::GetUniqueInstance( - const std::string &name, const json &config, - const std::string &instance_function_name) { - std::shared_lock lock(m_SharedMutex); - if (!HasModule(name)) { - LOG_F(ERROR, "Failed to find module {}", name); - return nullptr; - } - auto get_instance_func = GetFunction (*)(const json &)>( - name, instance_function_name); - if (!get_instance_func) { - LOG_F(ERROR, "Failed to get symbol {} from module {}: {}", - instance_function_name, name, dlerror()); - return nullptr; - } - - return get_instance_func(config); -} - -template -std::shared_ptr ModuleLoader::GetInstancePointer( - const std::string &name, const json &config, - const std::string &instance_function_name) { - return GetInstance(name, config, instance_function_name); -} -} // namespace Lithium \ No newline at end of file +#include "loader.inl" + +#endif diff --git a/src/addon/loader.inl b/src/addon/loader.inl new file mode 100644 index 00000000..3bce49a9 --- /dev/null +++ b/src/addon/loader.inl @@ -0,0 +1,79 @@ +#ifndef LITHIUM_ADDON_LOADER_INL +#define LITHIUM_ADDON_LOADER_INL + +#include "loader.hpp" + +namespace lithium { + +template +T ModuleLoader::GetFunction(const std::string &name, + const std::string &function_name) { + std::shared_lock lock(m_SharedMutex); + auto handle_it = modules_.find(name); + if (handle_it == modules_.end()) { + LOG_F(ERROR, "Failed to find module {}", name); + return nullptr; + } + + auto func_ptr = reinterpret_cast( + LOAD_FUNCTION(handle_it->second->handle, function_name.c_str())); + + if (!func_ptr) { + LOG_F(ERROR, "Failed to get symbol {} from module {}: {}", + function_name, name, dlerror()); + return nullptr; + } + + return func_ptr; +} + +template +std::shared_ptr ModuleLoader::GetInstance(const std::string &name, + const json &config, + const std::string &symbol_name) { + std::shared_lock lock(m_SharedMutex); + if (!HasModule(name)) { + LOG_F(ERROR, "Failed to find module {}", name); + return nullptr; + } + auto get_instance_func = + GetFunction (*)(const json &)>(name, symbol_name); + if (!get_instance_func) { + LOG_F(ERROR, "Failed to get symbol {} from module {}: {}", symbol_name, + name, dlerror()); + return nullptr; + } + + return get_instance_func(config); +} + +template +std::unique_ptr ModuleLoader::GetUniqueInstance( + const std::string &name, const json &config, + const std::string &instance_function_name) { + std::shared_lock lock(m_SharedMutex); + if (!HasModule(name)) { + LOG_F(ERROR, "Failed to find module {}", name); + return nullptr; + } + auto get_instance_func = GetFunction (*)(const json &)>( + name, instance_function_name); + if (!get_instance_func) { + LOG_F(ERROR, "Failed to get symbol {} from module {}: {}", + instance_function_name, name, dlerror()); + return nullptr; + } + + return get_instance_func(config); +} + +template +std::shared_ptr ModuleLoader::GetInstancePointer( + const std::string &name, const json &config, + const std::string &instance_function_name) { + return GetInstance(name, config, instance_function_name); +} + +} // namespace lithium + +#endif \ No newline at end of file diff --git a/src/addon/manager.cpp b/src/addon/manager.cpp index bdd93191..dd054e99 100644 --- a/src/addon/manager.cpp +++ b/src/addon/manager.cpp @@ -29,6 +29,8 @@ Description: Component Manager (the core of the plugin system) #include "utils/constant.hpp" #include "utils/marco.hpp" +#include + #define IS_ARGUMENT_EMPTY() \ if (params.is_null()) { \ return false; \ @@ -41,16 +43,16 @@ Description: Component Manager (the core of the plugin system) } \ type name = params[#name].get(); -namespace Lithium { +namespace lithium { ComponentManager::ComponentManager() : m_Sandbox(nullptr), m_Compiler(nullptr) { m_ModuleLoader = - GetWeakPtr(constants::LITHIUM_MODULE_LOADER); + GetWeakPtr(constants::LITHIUM_MODULE_LOADER); CHECK_WEAK_PTR_EXPIRED(m_ModuleLoader, "load module loader from gpm: lithium.addon.loader"); m_Env = GetWeakPtr(constants::LITHIUM_UTILS_ENV); CHECK_WEAK_PTR_EXPIRED(m_Env, "load env from gpm: lithium.utils.env"); m_AddonManager = - GetWeakPtr(constants::LITHIUM_ADDON_MANAGER); + GetWeakPtr(constants::LITHIUM_ADDON_MANAGER); CHECK_WEAK_PTR_EXPIRED(m_AddonManager, "load addon manager from gpm: lithium.addon.addon"); @@ -162,16 +164,14 @@ bool ComponentManager::Initialize() { } auto component_identifier = addon_name + module_name + component_entry; - if (auto component = - m_ModuleLoader.lock()->GetInstance( - module_name, {}, component_entry); + if (auto component = m_ModuleLoader.lock()->GetInstance( + module_name, {}, component_entry); component) { LOG_F(INFO, "Loaded shared component: {}", component_identifier); try { if (component->initialize()) { - m_SharedComponents[addon_name + module_name] = - component; + m_Components[addon_name + module_name] = component; LOG_F(INFO, "Loaded shared component: {}", component_identifier); } else { @@ -289,21 +289,21 @@ bool ComponentManager::checkComponent(const std::string &module_name, } // If not, load the module // Check component path - if (!Atom::IO::isFolderExists(module_path)) { + if (!atom::io::isFolderExists(module_path)) { LOG_F(ERROR, "Component path {} does not exist", module_path); return false; } // Check component package.json file, this is for the first time loading // And we need to know how to load component's ptr from this file - if (!Atom::IO::isFileExists(module_path + constants::PATH_SEPARATOR + + if (!atom::io::isFileExists(module_path + constants::PATH_SEPARATOR + constants::PACKAGE_NAME)) { LOG_F(ERROR, "Component path {} does not contain package.json", module_path); return false; } // Check component library files - std::vector files = Atom::IO::checkFileTypeInFolder( - module_path, constants::LIB_EXTENSION, Atom::IO::FileOption::Name); + std::vector files = atom::io::checkFileTypeInFolder( + module_path, constants::LIB_EXTENSION, atom::io::FileOption::Name); if (files.empty()) { LOG_F(ERROR, "Component path {} does not contain dll or so file", @@ -335,7 +335,7 @@ bool ComponentManager::loadComponentInfo(const std::string &module_path) { // Max: We will only load the root package.json std::string file_path = module_path + constants::PATH_SEPARATOR + constants::PACKAGE_NAME; - if (!Atom::IO::isFileExists(file_path)) { + if (!atom::io::isFileExists(file_path)) { LOG_F(ERROR, "Component path {} does not contain package.json", module_path); return false; @@ -419,7 +419,7 @@ bool ComponentManager::loadSharedComponent(const std::string &component_name) { LOG_F(ERROR, "Component name is empty"); return false; } - if (m_SharedComponents.find(component_name) != m_SharedComponents.end()) { + if (m_Components.find(component_name) != m_Components.end()) { LOG_F(ERROR, "Component {} has been loaded", component_name); return false; } @@ -431,8 +431,8 @@ bool ComponentManager::loadSharedComponent(const std::string &component_name) { } // There we need some json parameters support for better get the component // instance - if (std::shared_ptr component = - m_ModuleLoader.lock()->GetInstance( + if (std::shared_ptr component = + m_ModuleLoader.lock()->GetInstance( it->second->m_name, {}, it->second->m_func_name); component) { try { @@ -442,7 +442,7 @@ bool ComponentManager::loadSharedComponent(const std::string &component_name) { LOG_F(ERROR, "Failed to initialize component: {}", e.what()); return false; } - m_SharedComponents[component_name] = component; + m_Components[component_name] = component; } else { LOG_F(ERROR, "Failed to load module: {}'s library", component_name); return false; @@ -466,14 +466,4 @@ bool ComponentManager::reloadSharedComponent(const json ¶ms) { return true; } -bool ComponentManager::loadScriptComponent(const json ¶ms) { return true; } - -bool ComponentManager::unloadScriptComponent(const json ¶ms) { - return true; -} - -bool ComponentManager::reloadScriptComponent(const json ¶ms) { - return true; -} - -} // namespace Lithium +} // namespace lithium diff --git a/src/addon/manager.hpp b/src/addon/manager.hpp index 39640e5d..a059d121 100644 --- a/src/addon/manager.hpp +++ b/src/addon/manager.hpp @@ -15,18 +15,18 @@ Description: Component Manager (the core of the plugin system) #pragma once #include "atom/components/component.hpp" -#include "atom/components/templates/alone_component.hpp" -#include "atom/components/templates/exe_component.hpp" -#include "atom/components/templates/shared_component.hpp" #include "atom/components/types.hpp" #include "atom/type/args.hpp" #include "atom/utils/env.hpp" -namespace Lithium { - class AddonManager; - class Compiler; - class ModuleLoader; +#include "atom/type/json.hpp" +using json = nlohmann::json; + +namespace lithium { +class AddonManager; +class Compiler; +class ModuleLoader; class Sandbox; class ComponentEntry { @@ -238,37 +238,20 @@ class ComponentManager { bool unloadSharedComponent(const json& params); bool reloadSharedComponent(const json& params); - // ------------------------------------------------------------------- - // Components methods (for alone components) - // ------------------------------------------------------------------- - - bool loadAloneComponent(const json& params); - bool unloadAloneComponent(const json& params); - bool reloadAloneComponent(const json& params); - - // ------------------------------------------------------------------- - // Components methods (for script components) - // ------------------------------------------------------------------- - - bool loadScriptComponent(const json& params); - bool unloadScriptComponent(const json& params); - bool reloadScriptComponent(const json& params); - private: - /** * @brief Get all files in a directory * @param path The path of the directory * @return The files in the directory */ - std::vector getFilesInDir(const std::string &path); + std::vector getFilesInDir(const std::string& path); /** * @brief Get all sub directories in a directory * @param path The path of the directory * @return The sub directories in the directory */ - std::vector getQualifiedSubDirs(const std::string &path); + std::vector getQualifiedSubDirs(const std::string& path); private: std::weak_ptr m_ModuleLoader; @@ -295,11 +278,6 @@ class ComponentManager { // Max: Why not just use a single map of std::shared_ptr? // Maybe it is because the dynamic_cast will be slow // And we are surely about what the component is - std::unordered_map> - m_SharedComponents; - std::unordered_map> - m_AloneComponents; - std::unordered_map> - m_ExecutableComponents; + std::unordered_map> m_Components; }; -} // namespace Lithium +} // namespace lithium diff --git a/src/addon/module.hpp b/src/addon/module.hpp index f276c7d3..7a345ddc 100644 --- a/src/addon/module.hpp +++ b/src/addon/module.hpp @@ -20,7 +20,7 @@ Description: Module Information #include -namespace Lithium { +namespace lithium { struct FunctionInfo { std::string name; void *address; @@ -52,4 +52,4 @@ class ModuleInfo { // Module handle pointer void *handle; }; -} // namespace Lithium +} // namespace lithium diff --git a/src/addon/sandbox.cpp b/src/addon/sandbox.cpp index 63bb308e..55761652 100644 --- a/src/addon/sandbox.cpp +++ b/src/addon/sandbox.cpp @@ -27,7 +27,7 @@ Description: A sandbox for alone componnents, such as executables. #include #endif -namespace Lithium { +namespace lithium { bool Sandbox::setTimeLimit(int timeLimitMs) { m_timeLimit = timeLimitMs; #ifndef _WIN32 @@ -151,4 +151,4 @@ bool Sandbox::run() { } #endif } -} // namespace Lithium \ No newline at end of file +} // namespace lithium \ No newline at end of file diff --git a/src/addon/sandbox.hpp b/src/addon/sandbox.hpp index 929ed44e..079385ac 100644 --- a/src/addon/sandbox.hpp +++ b/src/addon/sandbox.hpp @@ -18,7 +18,7 @@ Description: A sandbox for alone componnents, such as executables. #include #include -namespace Lithium { +namespace lithium { /** * @brief Sandbox class for running programs with time and memory limits in a * restricted environment. diff --git a/src/addon/sort.cpp b/src/addon/sort.cpp index ef274be7..c8866c2c 100644 --- a/src/addon/sort.cpp +++ b/src/addon/sort.cpp @@ -10,7 +10,7 @@ using json = nlohmann::json; -namespace Lithium { +namespace lithium { std::vector removeDuplicates( const std::vector& input) { std::unordered_set seen; @@ -124,4 +124,4 @@ std::vector resolveDependencies( return removeDuplicates(sorted_packages); } -} // namespace Lithium +} // namespace lithium diff --git a/src/addon/sort.hpp b/src/addon/sort.hpp index 2bce1738..88a88481 100644 --- a/src/addon/sort.hpp +++ b/src/addon/sort.hpp @@ -4,7 +4,7 @@ #include #include -namespace Lithium { +namespace lithium { [[nodiscard("result is discarded")]] std::vector resolveDependencies(const std::vector& directories); } diff --git a/src/atom/CMakeLists.txt b/src/atom/CMakeLists.txt index 5ab56792..c1e5985f 100644 --- a/src/atom/CMakeLists.txt +++ b/src/atom/CMakeLists.txt @@ -33,7 +33,6 @@ add_subdirectory(algorithm) add_subdirectory(async) add_subdirectory(components) add_subdirectory(connection) -add_subdirectory(driver) add_subdirectory(error) add_subdirectory(io) add_subdirectory(log) @@ -76,7 +75,6 @@ list(APPEND ${PROJECT_NAME}_LIBS atom-async atom-task atom-io - atom-driver atom-component atom-type atom-utils diff --git a/src/atom/algorithm/CMakeLists.txt b/src/atom/algorithm/CMakeLists.txt index 4e9fed16..cfdb6bd3 100644 --- a/src/atom/algorithm/CMakeLists.txt +++ b/src/atom/algorithm/CMakeLists.txt @@ -19,6 +19,7 @@ set(${PROJECT_NAME}_SOURCES math.cpp md5.cpp mhash.cpp + pid.cpp ) # Headers @@ -33,6 +34,7 @@ set(${PROJECT_NAME}_HEADERS math.hpp md5.hpp mhash.hpp + pid.hpp ) # Build Object Library diff --git a/src/atom/algorithm/algorithm.cpp b/src/atom/algorithm/algorithm.cpp index 068e92f5..1c258e7c 100644 --- a/src/atom/algorithm/algorithm.cpp +++ b/src/atom/algorithm/algorithm.cpp @@ -10,9 +10,10 @@ KMP::KMP(std::string_view pattern) : pattern_(pattern) { std::vector KMP::Search(std::string_view text) { std::vector occurrences; - int n = static_cast(text.length()); - int m = static_cast(pattern_.length()); - int i = 0, j = 0; + auto n = static_cast(text.length()); + auto m = static_cast(pattern_.length()); + int i = 0; + int j = 0; while (i < n) { if (text[i] == pattern_[j]) { ++i; @@ -36,9 +37,10 @@ void KMP::SetPattern(std::string_view pattern) { } std::vector KMP::ComputeFailureFunction(std::string_view pattern) { - int m = static_cast(pattern.length()); + auto m = static_cast(pattern.length()); std::vector failure(m, 0); - int i = 1, j = 0; + int i = 1; + int j = 0; while (i < m) { if (pattern[i] == pattern[j]) { failure[i] = j + 1; @@ -83,7 +85,7 @@ std::vector MinHash::compute_signature( double MinHash::estimate_similarity( const std::vector& signature1, - const std::vector& signature2) { + const std::vector& signature2) const { int num_matches = 0; for (int i = 0; i < m_num_hash_functions; ++i) { if (signature1[i] == signature2[i]) { @@ -110,8 +112,8 @@ BoyerMoore::BoyerMoore(std::string_view pattern) : pattern_(pattern) { std::vector BoyerMoore::Search(std::string_view text) { std::vector occurrences; - int n = static_cast(text.length()); - int m = static_cast(pattern_.length()); + auto n = static_cast(text.length()); + auto m = static_cast(pattern_.length()); int i = 0; while (i <= n - m) { int j = m - 1; @@ -144,7 +146,7 @@ void BoyerMoore::ComputeBadCharacterShift() { } void BoyerMoore::ComputeGoodSuffixShift() { - int m = static_cast(pattern_.length()); + auto m = static_cast(pattern_.length()); good_suffix_shift_.resize(m, m); std::vector suffix(m, 0); int j = 0; diff --git a/src/atom/algorithm/algorithm.hpp b/src/atom/algorithm/algorithm.hpp index 9b79d30d..ddbaad40 100644 --- a/src/atom/algorithm/algorithm.hpp +++ b/src/atom/algorithm/algorithm.hpp @@ -1,5 +1,5 @@ /* - * base.hpp + * algorithm.hpp * * Copyright (C) 2023-2024 Max Qian */ @@ -93,7 +93,7 @@ class MinHash { */ double estimate_similarity( const std::vector& signature1, - const std::vector& signature2); + const std::vector& signature2) const; private: /** diff --git a/src/atom/algorithm/calculator.hpp b/src/atom/algorithm/calculator.hpp new file mode 100644 index 00000000..d35ba14d --- /dev/null +++ b/src/atom/algorithm/calculator.hpp @@ -0,0 +1,363 @@ +/* + * calculator.hpp + * + * Copyright (C) 2023-2024 Max Qian + */ + +/************************************************* + +Date: 2023-4-5 + +Description: A calculator implementation under C++20 + +**************************************************/ + +#ifndef ATOM_ALGORITHM_CALCULATOR_HPP +#define ATOM_ALGORITHM_CALCULATOR_HPP + +#include +#include +#include +#include +#include +#include +#include + +namespace atom::algorithm { + +class error : public std::runtime_error { +public: + error(std::string_view expr, std::string_view message) + : std::runtime_error(std::string(message)), expr_(expr) {} + std::string_view expression() const noexcept { return expr_; } + +private: + std::string expr_; +}; + +template +class ExpressionParser { +public: + T eval(std::string_view expr) { + T result = 0; + index_ = 0; + expr_ = expr; + try { + result = parseExpr(); + if (!isEnd()) + unexpected(); + } catch (const calculator::error&) { + stack_ = {}; + throw; + } + return result; + } + + T eval(char c) { return eval(std::string_view(&c, 1)); } + +private: + enum { + OPERATOR_NULL, + OPERATOR_BITWISE_OR, /// | + OPERATOR_BITWISE_XOR, /// ^ + OPERATOR_BITWISE_AND, /// & + OPERATOR_BITWISE_SHL, /// << + OPERATOR_BITWISE_SHR, /// >> + OPERATOR_ADDITION, /// + + OPERATOR_SUBTRACTION, /// - + OPERATOR_MULTIPLICATION, /// * + OPERATOR_DIVISION, /// / + OPERATOR_MODULO, /// % + OPERATOR_POWER, /// ** + OPERATOR_EXPONENT /// e, E + }; + + struct Operator { + int op; + int precedence; + char associativity; + constexpr Operator(int opr, int prec, char assoc) noexcept + : op(opr), precedence(prec), associativity(assoc) {} + }; + + struct OperatorValue { + Operator op; + T value; + constexpr OperatorValue(const Operator& opr, T val) noexcept + : op(opr), value(val) {} + constexpr int getPrecedence() const noexcept { return op.precedence; } + constexpr bool isNull() const noexcept { + return op.op == OPERATOR_NULL; + } + }; + + static T pow(T x, T n) { + T res = 1; + + while (n > 0) { + if (n % 2 != 0) { + res *= x; + n -= 1; + } + n /= 2; + + if (n > 0) + x *= x; + } + + return res; + } + + [[nodiscard]] T checkZero(T value) const { + if (value == 0) { + auto divOperators = std::string_view("/%"); + auto division = expr_.find_last_of(divOperators, index_ - 2); + std::ostringstream msg; + msg << "Parser error: division by 0"; + if (division != std::string_view::npos) + msg << " (error token is \"" + << expr_.substr(division, expr_.size() - division) << "\")"; + throw calculator::error(expr_, msg.str()); + } + return value; + } + + [[nodiscard]] constexpr T calculate(T v1, T v2, + const Operator& op) const noexcept { + switch (op.op) { + case OPERATOR_BITWISE_OR: + return v1 | v2; + case OPERATOR_BITWISE_XOR: + return v1 ^ v2; + case OPERATOR_BITWISE_AND: + return v1 & v2; + case OPERATOR_BITWISE_SHL: + return v1 << v2; + case OPERATOR_BITWISE_SHR: + return v1 >> v2; + case OPERATOR_ADDITION: + return v1 + v2; + case OPERATOR_SUBTRACTION: + return v1 - v2; + case OPERATOR_MULTIPLICATION: + return v1 * v2; + case OPERATOR_DIVISION: + return v1 / checkZero(v2); + case OPERATOR_MODULO: + return v1 % checkZero(v2); + case OPERATOR_POWER: + return pow(v1, v2); + case OPERATOR_EXPONENT: + return v1 * pow(10, v2); + default: + return 0; + } + } + + [[nodiscard]] constexpr bool isEnd() const noexcept { + return index_ >= expr_.size(); + } + + [[nodiscard]] constexpr char getCharacter() const noexcept { + if (!isEnd()) + return expr_[index_]; + return 0; + } + + void expect(std::string_view str) { + if (expr_.substr(index_, str.size()) != str) + unexpected(); + index_ += str.size(); + } + + [[noreturn]] void unexpected() const { + std::ostringstream msg; + msg << "Syntax error: unexpected token \"" << expr_.substr(index_) + << "\" at index " << index_; + throw calculator::error(expr_, msg.str()); + } + + constexpr void eatSpaces() noexcept { + while (std::isspace(getCharacter()) != 0) + index_++; + } + + [[nodiscard]] Operator parseOp() { + eatSpaces(); + switch (getCharacter()) { + case '|': + index_++; + return Operator(OPERATOR_BITWISE_OR, 4, 'L'); + case '^': + index_++; + return Operator(OPERATOR_BITWISE_XOR, 5, 'L'); + case '&': + index_++; + return Operator(OPERATOR_BITWISE_AND, 6, 'L'); + case '<': + expect("<<"); + return Operator(OPERATOR_BITWISE_SHL, 9, 'L'); + case '>': + expect(">>"); + return Operator(OPERATOR_BITWISE_SHR, 9, 'L'); + case '+': + index_++; + return Operator(OPERATOR_ADDITION, 10, 'L'); + case '-': + index_++; + return Operator(OPERATOR_SUBTRACTION, 10, 'L'); + case '/': + index_++; + return Operator(OPERATOR_DIVISION, 20, 'L'); + case '%': + index_++; + return Operator(OPERATOR_MODULO, 20, 'L'); + case '*': + index_++; + if (getCharacter() != '*') + return Operator(OPERATOR_MULTIPLICATION, 20, 'L'); + index_++; + return Operator(OPERATOR_POWER, 30, 'R'); + case 'e': + index_++; + return Operator(OPERATOR_EXPONENT, 40, 'R'); + case 'E': + index_++; + return Operator(OPERATOR_EXPONENT, 40, 'R'); + default: + return Operator(OPERATOR_NULL, 0, 'L'); + } + } + + [[nodiscard]] static constexpr T toInteger(char c) noexcept { + if (c >= '0' && c <= '9') + return c - '0'; + if (c >= 'a' && c <= 'f') + return c - 'a' + 0xa; + if (c >= 'A' && c <= 'F') + return c - 'A' + 0xa; + return 0xf + 1; + } + + [[nodiscard]] constexpr T getInteger() const noexcept { + return toInteger(getCharacter()); + } + + [[nodiscard]] T parseDecimal() { + T value = 0; + for (T d; (d = getInteger()) <= 9; index_++) + value = value * 10 + d; + return value; + } + + [[nodiscard]] T parseHex() { + index_ += 2; + T value = 0; + for (T h; (h = getInteger()) <= 0xf; index_++) + value = value * 0x10 + h; + return value; + } + + [[nodiscard]] constexpr bool isHex() const noexcept { + if (index_ + 2 < expr_.size()) { + char x = expr_[index_ + 1]; + char h = expr_[index_ + 2]; + return (std::tolower(x) == 'x' && toInteger(h) <= 0xf); + } + return false; + } + + [[nodiscard]] T parseValue() { + T val = 0; + eatSpaces(); + switch (getCharacter()) { + case '0': + if (isHex()) + val = parseHex(); + else + val = parseDecimal(); + break; + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + val = parseDecimal(); + break; + case '(': + index_++; + val = parseExpr(); + eatSpaces(); + if (getCharacter() != ')') { + if (!isEnd()) + unexpected(); + throw calculator::error( + expr_, + "Syntax error: `)' expected at end of expression"); + } + index_++; + break; + case '~': + index_++; + val = ~parseValue(); + break; + case '+': + index_++; + val = parseValue(); + break; + case '-': + index_++; + val = -parseValue(); + break; + default: + if (!isEnd()) + unexpected(); + throw calculator::error( + expr_, "Syntax error: value expected at end of expression"); + } + return val; + } + + T parseExpr() { + stack_.emplace(Operator(OPERATOR_NULL, 0, 'L'), 0); + T value = parseValue(); + + while (!stack_.empty()) { + Operator op(parseOp()); + while (op.precedence < stack_.top().getPrecedence() || + (op.precedence == stack_.top().getPrecedence() && + op.associativity == 'L')) { + if (stack_.top().isNull()) { + stack_.pop(); + return value; + } + value = calculate(stack_.top().value, value, stack_.top().op); + stack_.pop(); + } + + stack_.emplace(op, value); + value = parseValue(); + } + return 0; + } + + std::string_view expr_; + std::size_t index_ = 0; + std::stack stack_; +}; + +template +inline T eval(std::string_view expression) { + ExpressionParser parser; + return parser.eval(expression); +} + +inline int eval(const std::string& expression) { return eval(expression); } + +} // namespace atom::algorithm + +#endif \ No newline at end of file diff --git a/src/atom/algorithm/convolve.cpp b/src/atom/algorithm/convolve.cpp index 0417b529..11d9626b 100644 --- a/src/atom/algorithm/convolve.cpp +++ b/src/atom/algorithm/convolve.cpp @@ -19,10 +19,6 @@ and deconvolution. #include #include -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif - #include "atom/error/exception.hpp" namespace atom::algorithm { @@ -118,7 +114,7 @@ std::vector> convolve2D( // Use multiple threads if requested if (numThreads > 1) { - std::vector threads; + std::vector threads; int blockSize = (inputRows + numThreads - 1) / numThreads; int blockStartRow = kernelRows / 2; @@ -214,19 +210,19 @@ std::vector> deconvolve2D( // 二维离散傅里叶变换(2D DFT) std::vector>> DFT2D( const std::vector> &signal, int numThreads) { - const int M = signal.size(); - const int N = signal[0].size(); + const auto M = signal.size(); + const auto N = signal[0].size(); std::vector>> X( M, std::vector>(N, {0, 0})); // Lambda function to compute the DFT for a block of rows - auto computeDFT = [&](int startRow, int endRow) { + auto computeDFT = [&M, &N, &signal, &X](int startRow, int endRow) { for (int u = startRow; u < endRow; ++u) { for (int v = 0; v < N; ++v) { std::complex sum(0, 0); for (int m = 0; m < M; ++m) { for (int n = 0; n < N; ++n) { - double theta = -2 * M_PI * + double theta = -2 * std::numbers::pi * ((u * m / static_cast(M)) + (v * n / static_cast(N))); std::complex w(cos(theta), sin(theta)); @@ -240,11 +236,11 @@ std::vector>> DFT2D( // Multithreading support if (numThreads > 1) { - std::vector threads; - int rowsPerThread = M / numThreads; + std::vector threads; + auto rowsPerThread = M / numThreads; for (int i = 0; i < numThreads; ++i) { - int startRow = i * rowsPerThread; - int endRow = (i == numThreads - 1) ? M : startRow + rowsPerThread; + auto startRow = i * rowsPerThread; + auto endRow = (i == numThreads - 1) ? M : startRow + rowsPerThread; threads.emplace_back(computeDFT, startRow, endRow); } for (auto &thread : threads) { @@ -262,18 +258,18 @@ std::vector>> DFT2D( std::vector> IDFT2D( const std::vector>> &spectrum, int numThreads) { - const int M = spectrum.size(); - const int N = spectrum[0].size(); + const auto M = spectrum.size(); + const auto N = spectrum[0].size(); std::vector> x(M, std::vector(N, 0.0)); // Lambda function to compute the IDFT for a block of rows - auto computeIDFT = [&](int startRow, int endRow) { + auto computeIDFT = [&M, &N, &spectrum, &x](int startRow, int endRow) { for (int m = startRow; m < endRow; ++m) { for (int n = 0; n < N; ++n) { std::complex sum(0.0, 0.0); for (int u = 0; u < M; ++u) { for (int v = 0; v < N; ++v) { - double theta = 2 * M_PI * + double theta = 2 * std::numbers::pi * ((u * m / static_cast(M)) + (v * n / static_cast(N))); std::complex w(cos(theta), sin(theta)); @@ -287,11 +283,11 @@ std::vector> IDFT2D( // Multithreading support if (numThreads > 1) { - std::vector threads; - int rowsPerThread = M / numThreads; + std::vector threads; + auto rowsPerThread = M / numThreads; for (int i = 0; i < numThreads; ++i) { - int startRow = i * rowsPerThread; - int endRow = (i == numThreads - 1) ? M : startRow + rowsPerThread; + auto startRow = i * rowsPerThread; + auto endRow = (i == numThreads - 1) ? M : startRow + rowsPerThread; threads.emplace_back(computeIDFT, startRow, endRow); } for (auto &thread : threads) { @@ -315,7 +311,7 @@ std::vector> generateGaussianKernel(int size, for (int j = 0; j < size; ++j) { kernel[i][j] = exp(-0.5 * (pow((i - center) / sigma, 2.0) + pow((j - center) / sigma, 2.0))) / - (2 * M_PI * sigma * sigma); + (2 * std::numbers::pi * sigma * sigma); sum += kernel[i][j]; } } @@ -333,20 +329,22 @@ std::vector> generateGaussianKernel(int size, std::vector> applyGaussianFilter( const std::vector> &image, const std::vector> &kernel) { - int imageHeight = image.size(); - int imageWidth = image[0].size(); - int kernelSize = kernel.size(); - int kernelRadius = kernelSize / 2; + auto imageHeight = image.size(); + auto imageWidth = image[0].size(); + auto kernelSize = kernel.size(); + auto kernelRadius = kernelSize / 2; std::vector> filteredImage( imageHeight, std::vector(imageWidth, 0)); - for (int i = 0; i < imageHeight; ++i) { - for (int j = 0; j < imageWidth; ++j) { + for (auto i = 0; i < imageHeight; ++i) { + for (auto j = 0; j < imageWidth; ++j) { double sum = 0.0; - for (int k = -kernelRadius; k <= kernelRadius; ++k) { - for (int l = -kernelRadius; l <= kernelRadius; ++l) { - int x = std::max(0, std::min(i + k, imageHeight - 1)); - int y = std::max(0, std::min(j + l, imageWidth - 1)); + for (auto k = -kernelRadius; k <= kernelRadius; ++k) { + for (auto l = -kernelRadius; l <= kernelRadius; ++l) { + auto x = std::clamp(static_cast(i + k), 0, + static_cast(imageHeight) - 1); + auto y = std::clamp(static_cast(j + l), 0, + static_cast(imageWidth) - 1); sum += image[x][y] * kernel[kernelRadius + k][kernelRadius + l]; } diff --git a/src/atom/driver/pid/pid.cpp b/src/atom/algorithm/pid.cpp similarity index 100% rename from src/atom/driver/pid/pid.cpp rename to src/atom/algorithm/pid.cpp diff --git a/src/atom/driver/pid/pid.hpp b/src/atom/algorithm/pid.hpp similarity index 100% rename from src/atom/driver/pid/pid.hpp rename to src/atom/algorithm/pid.hpp diff --git a/src/atom/async/pool.hpp b/src/atom/async/pool.hpp index 8799182d..e643a3ad 100644 --- a/src/atom/async/pool.hpp +++ b/src/atom/async/pool.hpp @@ -36,11 +36,11 @@ class ThreadPool { * * @param n_threads 线程池大小 */ - explicit ThreadPool(std::size_t n_threads) : stop(false) { + explicit ThreadPool(std::size_t n_threads) { for (std::size_t i = 0; i < n_threads; ++i) { threads.emplace_back([this] { while (true) { - std::unique_lock lock(queue_mutex); + std::unique_lock lock(queue_mutex); condition.wait(lock, [this] { return stop || !tasks.empty(); }); if (stop && tasks.empty()) { @@ -62,7 +62,7 @@ class ThreadPool { */ ~ThreadPool() { { - std::unique_lock lock(queue_mutex); + std::unique_lock lock(queue_mutex); stop = true; } condition.notify_all(); @@ -89,11 +89,11 @@ class ThreadPool { using return_type = std::invoke_result_t; auto task = std::make_shared>( - std::bind(std::forward(f), std::forward(args)...)); + std::bind_front(std::forward(f), std::forward(args)...)); auto res = task->get_future(); { - std::unique_lock lock(queue_mutex); + std::unique_lock lock(queue_mutex); if (stop) { throw std::runtime_error("enqueue on stopped ThreadPool"); @@ -111,7 +111,7 @@ class ThreadPool { * 该函数会等待任务队列中的所有任务完成,然后返回。 */ void wait() { - std::unique_lock lock(queue_mutex); + std::unique_lock lock(queue_mutex); condition.wait(lock, [this] { return tasks.empty(); }); } @@ -128,17 +128,17 @@ class ThreadPool { * @return 任务队列中待执行的任务数量 */ std::size_t taskCount() const { - std::unique_lock lock(queue_mutex); + std::unique_lock lock(queue_mutex); return tasks.size(); } private: - std::vector threads; ///< 线程池中的线程列表 + std::vector threads; ///< 线程池中的线程列表 std::queue> tasks; ///< 任务队列 mutable std::mutex queue_mutex; ///< 任务队列的互斥锁 std::condition_variable condition; ///< 任务队列的条件变量 - bool stop; ///< 停止标志位 + bool stop{false}; ///< 停止标志位 }; } // namespace atom::async diff --git a/src/atom/components/CMakeLists.txt b/src/atom/components/CMakeLists.txt index 0fa5c510..922c5f44 100644 --- a/src/atom/components/CMakeLists.txt +++ b/src/atom/components/CMakeLists.txt @@ -3,7 +3,7 @@ project(atom-component C CXX) list(APPEND ${PROJECT_NAME}_SOURCES - configor.cpp + component.cpp dispatch.cpp types.cpp ) diff --git a/src/atom/components/abilities.hpp b/src/atom/components/abilities.hpp index d686c303..1d0f94af 100644 --- a/src/atom/components/abilities.hpp +++ b/src/atom/components/abilities.hpp @@ -1,6 +1,7 @@ #ifndef ATOM_COMPONENTS_ABILITIES_HPP #define ATOM_COMPONENTS_ABILITIES_HPP +#include #include template @@ -19,8 +20,7 @@ template struct has_setValue { template static constexpr auto check(int) -> decltype(std::declval().setValue( - std::declval(), - std::declval()), + std::declval()), std::true_type{}); template diff --git a/src/atom/components/base/main.cpp b/src/atom/components/base/main.cpp index 01a402b3..c6939e24 100644 --- a/src/atom/components/base/main.cpp +++ b/src/atom/components/base/main.cpp @@ -1,10 +1,10 @@ -#include "atom/components/templates/shared.hpp" +#include "atom/components/component.hpp" #include #include "atom/log/loguru.hpp" -class MySharedComponent : public Component { +class MySharedComponent : public Component { public: explicit MySharedComponent(const std::string &name); virtual ~MySharedComponent(); @@ -13,36 +13,95 @@ class MySharedComponent : public Component { virtual bool destroy() override; protected: - json helloWorld(const json ¶ms); + void helloWorld(const std::string ¶ms); + + void calc(int a, int b); + + int process(const std::vector ¶ms); }; MySharedComponent::MySharedComponent(const std::string &name) - : Component(name) { + : Component(name) { LOG_F(INFO, "Load {}", name); initialize(); - registerCommand("helloWorld", &MySharedComponent::helloWorld, PointerSentinel(shared_from_this())); + registerCommand("helloWorld", &MySharedComponent::helloWorld, + PointerSentinel(this)); + registerCommand("calc", &MySharedComponent::calc, PointerSentinel(this)); + registerCommand("process", &MySharedComponent::process, + PointerSentinel(this)); } -MySharedComponent::~MySharedComponent() {} - -bool MySharedComponent::initialize() { - return true; +MySharedComponent::~MySharedComponent() { + LOG_F(INFO, "Unload {}", getName()); } -bool MySharedComponent::destroy() { - return true; +bool MySharedComponent::initialize() { return true; } + +bool MySharedComponent::destroy() { return true; } + +void MySharedComponent::helloWorld(const std::string ¶ms) { + std::cout << "Hello " << params << std::endl; } -json MySharedComponent::helloWorld(const json ¶ms) { - LOG_F(INFO, "helloWorld with {}", params.dump()); - return {}; +void MySharedComponent::calc(int a, int b) { std::cout << a + b << std::endl; } + +int MySharedComponent::process(const std::vector ¶ms) { + int sum = 0; + for (auto ¶m : params) { + sum += param; + } + return sum; } +class MyOtherSharedComponent : public Component { +public: + explicit MyOtherSharedComponent(const std::string &name) : Component(name) + { + LOG_F(INFO, "Load {}", name); + registerCommand("helloWorld", &MyOtherSharedComponent::helloWorld, + PointerSentinel(this)); + } + virtual ~MyOtherSharedComponent() + { + LOG_F(INFO, "Unload {}", getName()); + } + + virtual bool initialize() override { return true; } + virtual bool destroy() override { return true; } + +protected: + void helloWorld(const std::string ¶ms) { + std::cout << "Hello " << params << std::endl; + } +}; + int main() { std::shared_ptr mycomponent = std::make_shared("mycomponent"); - mycomponent->dispatch("helloWorld", json::object({"message", "hello"})); + mycomponent->dispatch("helloWorld", std::string("aaa")); + mycomponent->dispatch("calc", 1, 2); + auto result = + mycomponent->dispatch("process", std::vector{1, 2, 3, 4, 5}); + std::cout << std::any_cast(result) << std::endl; + + + std::shared_ptr myothercomponent = + std::make_shared("myothercomponent"); + + mycomponent->addOtherComponent("other", myothercomponent); + mycomponent->getOtherComponent("other").lock()->dispatch("helloWorld", + std::string("bbb")); + + try + { + mycomponent->addOtherComponent("other", myothercomponent); + } + catch (const std::exception &e) + { + std::cerr << e.what() << '\n'; + } + return 0; } \ No newline at end of file diff --git a/src/atom/components/component.cpp b/src/atom/components/component.cpp new file mode 100644 index 00000000..c3d061d1 --- /dev/null +++ b/src/atom/components/component.cpp @@ -0,0 +1,124 @@ +#include "abilities.hpp" +#include "component.hpp" + +#include +#include +namespace fs = std::filesystem; + +#include "atom/error/exception.hpp" +#include "atom/log/loguru.hpp" +#include "atom/utils/string.hpp" + +#if __cplusplus >= 202002L +#include +#else +#include +#endif + +Component::Component(const std::string& name) + : m_name(name), + m_CommandDispatcher(std::make_unique()), + m_VariableManager(std::make_unique()), + m_typeInfo(user_type()) { + // Empty +} + +Component::~Component() { + // Empty +} + +std::weak_ptr Component::getInstance() const { + return shared_from_this(); +} + +bool Component::initialize() { + LOG_F(INFO, "Initializing component: {}", m_name); + return true; +} + +bool Component::destroy() { + LOG_F(INFO, "Destroying component: {}", m_name); + return true; +} + +std::string Component::getName() const { return m_name; } + +Type_Info Component::getTypeInfo() const { return m_typeInfo; } + +std::unordered_map Component::getComponentAbilities() const { + std::unordered_map abilities; + return abilities; +} + +bool Component::hasAbility(const std::string& ability) const { + return getComponentAbilities().contains(ability); +} + +void Component::addAlias(const std::string& name, const std::string& alias) { + m_CommandDispatcher->addAlias(name, alias); +} + +void Component::addGroup(const std::string& name, const std::string& group) { + m_CommandDispatcher->addGroup(name, group); +} + +void Component::setTimeout(const std::string& name, + std::chrono::milliseconds timeout) { + m_CommandDispatcher->setTimeout(name, timeout); +} + +void Component::clearCache() { m_CommandDispatcher->clearCache(); } + +void Component::removeCommand(const std::string& name) { + m_CommandDispatcher->removeCommand(name); +} + +std::vector Component::getCommandsInGroup( + const std::string& group) const { + return m_CommandDispatcher->getCommandsInGroup(group); +} + +std::string Component::getCommandDescription(const std::string& name) const { + return m_CommandDispatcher->getCommandDescription(name); +} + +#if ENABLE_FASTHASH +emhash::HashSet Component::getCommandAliases( + const std::string& name) const +#else +std::unordered_set Component::getCommandAliases( + const std::string& name) const +#endif +{ + return m_CommandDispatcher->getCommandAliases(name); +} + +std::vector Component::getNeededComponents() const { return {}; } + +void Component::addOtherComponent(const std::string& name, + const std::weak_ptr& component) { + if (m_OtherComponents.contains(name)) { + THROW_EXCEPTION( +#if __cplusplus >= 202002L + std::format("Other component with name {} already exists", +#else + fmt::format("Other component with name {} already exists", +#endif + name)); + } + m_OtherComponents[name] = std::move(component); +} + +void Component::removeOtherComponent(const std::string& name) { + m_OtherComponents.erase(name); +} + +void Component::clearOtherComponents() { m_OtherComponents.clear(); } + +std::weak_ptr Component::getOtherComponent( + const std::string& name) { + if (m_OtherComponents.contains(name)) { + return m_OtherComponents[name]; + } + return {}; +} diff --git a/src/atom/components/component.hpp b/src/atom/components/component.hpp index 84da029d..fe79abb2 100644 --- a/src/atom/components/component.hpp +++ b/src/atom/components/component.hpp @@ -24,13 +24,10 @@ Description: Basic Component Definition #include "dispatch.hpp" #include "var.hpp" -#include "configor.hpp" - #include "atom/function/type_info.hpp" #include "atom/type/noncopyable.hpp" -template -class Component : public std::enable_shared_from_this { +class Component : public std::enable_shared_from_this { public: /** * @brief Constructs a new Component object. @@ -42,6 +39,12 @@ class Component : public std::enable_shared_from_this { */ virtual ~Component(); + // ------------------------------------------------------------------- + // Inject methods + // ------------------------------------------------------------------- + + std::weak_ptr getInstance() const; + // ------------------------------------------------------------------- // Common methods // ------------------------------------------------------------------- @@ -79,56 +82,6 @@ class Component : public std::enable_shared_from_this { Type_Info getTypeInfo() const; - // ------------------------------------------------------------------- - // Component Configuration methods - // ------------------------------------------------------------------- - - [[nodiscard("config value should not be ignored!")]] std::optional - getValue(const std::string& key_path) const; - - /** - * @brief 添加或更新一个配置项 - * - * Add or update a configuration item. - * - * @param key_path 配置项的键路径,使用斜杠 / 进行分隔,如 - * "database/username" - * @param value 配置项的值,使用 JSON 格式进行表示 - * @return bool 成功返回 true,失败返回 false - */ - bool setValue(const std::string& key_path, const json& value); - - /** - * @brief 判断一个配置项是否存在 - * - * Determine if a configuration item exists. - * - * @param key_path 配置项的键路径,使用斜杠 / 进行分隔,如 - * "database/username" - * @return bool 存在返回 true,不存在返回 false - */ - [[nodiscard("status of the value should not be ignored")]] bool hasValue( - const std::string& key_path) const; - - /** - * @brief 从指定文件中加载JSON配置,并与原有配置进行合并 - * - * Load JSON configuration from the specified file and merge with the - * existing configuration. - * - * @param path 配置文件路径 - */ - bool loadFromFile(const fs::path& path); - - /** - * @brief 将当前配置保存到指定文件 - * - * Save the current configuration to the specified file. - * - * @param file_path 目标文件路径 - */ - bool saveToFile(const fs::path& file_path) const; - // ------------------------------------------------------------------- // Variable methods // ------------------------------------------------------------------- @@ -202,6 +155,27 @@ class Component : public std::enable_shared_from_this { m_CommandDispatcher->registerCommand(name, func, group, description); } + template + void registerCommand(const std::string& name, Ret (Class::*func)(Args...), + std::shared_ptr instance, + const std::string& group = "", + const std::string& description = "") + + { + m_CommandDispatcher->registerCommand(name, func, instance, group, + description); + } + + template + void registerCommand(const std::string& name, + Ret (Class::*func)(Args...) const, + std::shared_ptr instance, + const std::string& group = "", + const std::string& description = "") { + m_CommandDispatcher->registerCommand(name, func, instance, group, + description); + } + template void registerCommand(const std::string& name, Ret (Class::*func)(Args...), const PointerSentinel& instance, @@ -279,16 +253,19 @@ class Component : public std::enable_shared_from_this { /** * @return The names of the components that are needed by this component. * @note This will be called when the component is initialized. - */ + */ std::vector getNeededComponents() const; void addOtherComponent(const std::string& name, - const PointerSentinel& component); + const std::weak_ptr& component); void removeOtherComponent(const std::string& name); void clearOtherComponents(); + std::weak_ptr getOtherComponent( + const std::string& name); + private: std::string m_name; std::string m_configPath; @@ -299,11 +276,9 @@ class Component : public std::enable_shared_from_this { m_CommandDispatcher; ///< The command dispatcher for managing commands. std::shared_ptr m_VariableManager; ///< The variable registry for managing variables. - std::shared_ptr m_ConfigManager; - std::unordered_map> m_OtherComponents; + std::unordered_map> + m_OtherComponents; }; -#include "component.inl" - #endif diff --git a/src/atom/components/component.inl b/src/atom/components/component.inl deleted file mode 100644 index fb2c2831..00000000 --- a/src/atom/components/component.inl +++ /dev/null @@ -1,169 +0,0 @@ -#ifndef ATOM_COMPONENT_INL -#define ATOM_COMPONENT_INL - -#include "abilities.hpp" -#include "component.hpp" - -#include -#include -namespace fs = std::filesystem; - -#include "atom/error/exception.hpp" -#include "atom/log/loguru.hpp" -#include "atom/utils/string.hpp" - -#if __cplusplus >= 202002L -#include -#else -#include -#endif - -template -Component::Component(const std::string& name) - : m_name(name), - m_ConfigManager(std::make_unique()), - m_CommandDispatcher(std::make_unique()), - m_VariableManager(std::make_unique()), - m_typeInfo(user_type()) { - // Empty -} - -template -Component::~Component() { - // Empty -} -template -bool Component::initialize() { - return static_cast(this)->initialize(); -} - -template -bool Component::destroy() { - LOG_F(INFO, "Destroying component: {}", m_name); - return static_cast(this)->destroy(); -} - -template -std::string Component::getName() const { - return m_name; -} - -template -Type_Info Component::getTypeInfo() const { - return m_typeInfo; -} - -template -std::unordered_map -Component::getComponentAbilities() const { - std::unordered_map abilities; - bool has_getValue_ = has_getValue::value; - bool has_setValue_ = has_setValue::value; - return abilities; -} - -template -bool Component::hasAbility(const std::string& ability) const { - return getComponentAbilities().contains(ability); -} - -template -std::optional Component::getValue( - const std::string& key_path) const { - return m_ConfigManager->getValue(key_path); -} - -template -bool Component::setValue(const std::string& key_path, - const json& value) { - return m_ConfigManager->setValue(key_path, value); -} - -template -bool Component::hasValue(const std::string& key_path) const { - return getValue(key_path).has_value(); -} - -template -bool Component::loadFromFile(const fs::path& path) { - return m_ConfigManager->loadFromFile(path); -} - -template -bool Component::saveToFile(const fs::path& file_path) const { - return m_ConfigManager->saveToFile(file_path); -} - -template -void Component::addAlias(const std::string& name, - const std::string& alias) { - m_CommandDispatcher->addAlias(name, alias); -} - -template -void Component::addGroup(const std::string& name, - const std::string& group) { - m_CommandDispatcher->addGroup(name, group); -} - -template -void Component::setTimeout(const std::string& name, - std::chrono::milliseconds timeout) { - m_CommandDispatcher->setTimeout(name, timeout); -} - -template -void Component::clearCache() { - m_CommandDispatcher->clearCache(); -} - -template -void Component::removeCommand(const std::string& name) { - m_CommandDispatcher->removeCommand(name); -} - -template -std::vector Component::getCommandsInGroup( - const std::string& group) const { - return m_CommandDispatcher->getCommandsInGroup(group); -} - -template -std::string Component::getCommandDescription( - const std::string& name) const { - return m_CommandDispatcher->getCommandDescription(name); -} - -template -#if ENABLE_FASTHASH -emhash::HashSet Component::getCommandAliases( - const std::string& name) const -#else -std::unordered_set Component::getCommandAliases( - const std::string& name) const -#endif -{ - return m_CommandDispatcher->getCommandAliases(name); -} -template -std::vector Component::getNeededComponents() const { - return static_cast(this)->getNeededComponents(); -} - -template -void Component::addOtherComponent( - const std::string& name, const PointerSentinel& component) { - m_OtherComponents[name] = std::move(component); -} - -template -void Component::removeOtherComponent(const std::string& name) { - m_OtherComponents.erase(name); -} - -template -void Component::clearOtherComponents() { - m_OtherComponents.clear(); -} - -#endif diff --git a/src/atom/components/configor.cpp b/src/atom/components/configor.cpp deleted file mode 100644 index d2ca6a15..00000000 --- a/src/atom/components/configor.cpp +++ /dev/null @@ -1,209 +0,0 @@ -/* - * configor.cpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2023-4-30 - -Description: Configor - -**************************************************/ - -#include "configor.hpp" - -#include -#include -#include -#include -#if ENABLE_FASTHASH -#include "emhash/hash_table8.hpp" -#else -#include -#endif -#include "atom/utils/string.hpp" - -#include "atom/log/loguru.hpp" - -namespace fs = std::filesystem; - -class ConfigManagerImpl { -public: - mutable std::shared_mutex rw_mutex_; - json config_; -}; - -ConfigManager::ConfigManager() : m_impl(std::make_unique()) { - if (loadFromFile("config.json")) { - DLOG_F(INFO, "Config loaded successfully."); - } -} - -ConfigManager::~ConfigManager() { saveToFile("config.json"); } - -std::shared_ptr ConfigManager::createShared() { - static std::shared_ptr instance = - std::make_shared(); - return instance; -} - -std::unique_ptr ConfigManager::createUnique() { - return std::make_unique(); -} - -bool ConfigManager::loadFromFile(const fs::path& path) { - std::shared_lock lock(m_impl->rw_mutex_); - try { - std::ifstream ifs(path); - if (!ifs || ifs.peek() == std::ifstream::traits_type::eof()) { - LOG_F(ERROR, "Failed to open file: {}", path.string()); - return false; - } - json j = json::parse(ifs); - if (j.empty()) { - return false; - } - - mergeConfig(j); - return true; - } catch (const json::exception& e) { - LOG_F(ERROR, "Failed to parse file: {}, error message: {}", path.string(), - e.what()); - } catch (const std::exception& e) { - LOG_F(ERROR, "Failed to load config file: {}, error message: {}", path.string(), - e.what()); - } - return false; -} - -bool ConfigManager::loadFromDir(const fs::path& dir_path, bool recursive) { - std::shared_lock lock(m_impl->rw_mutex_); - try { - for (const auto& entry : fs::directory_iterator(dir_path)) { - if (entry.is_regular_file() && - entry.path().extension() == ".json") { - loadFromFile(entry.path()); - } else if (recursive && entry.is_directory()) { - loadFromDir(entry.path(), true); - } - } - } catch (const std::exception& e) { - LOG_F(ERROR, "Failed to load config file from: {}, error message: {}", - dir_path.string(), e.what()); - return false; - } - return true; -} - -std::optional ConfigManager::getValue(const std::string& key_path) const { - std::shared_lock lock(m_impl->rw_mutex_); - const json* p = &m_impl->config_; - for (const auto& key : key_path | std::views::split('/')) { - if (p->is_object() && - p->contains(std::string(key.begin(), key.end()))) { - p = &(*p)[std::string(key.begin(), key.end())]; - } else { - return std::nullopt; - } - } - return *p; -} - -bool ConfigManager::setValue(const std::string& key_path, const json& value) { - std::unique_lock lock(m_impl->rw_mutex_); - json* p = &m_impl->config_; - std::vector keys; - for (auto sub_range : key_path | std::views::split('/')) { - keys.emplace_back(sub_range.data(), sub_range.size()); - } - - for (auto it = keys.begin(); it != keys.end(); ++it) { - if (it + 1 == keys.end()) { - (*p)[*it] = value; - return true; - } - - if (!p->is_object()) { - return false; - } - - if (!p->contains(*it)) { - (*p)[*it] = json::object(); - } - - p = &(*p)[*it]; - } - - return true; -} - -bool ConfigManager::deleteValue(const std::string& key_path) { - std::unique_lock lock(m_impl->rw_mutex_); - std::vector keys; - for (auto sub_range : key_path | std::views::split('/')) { - keys.emplace_back(sub_range.data(), sub_range.size()); - } - json* p = &m_impl->config_; - for (auto it = keys.begin(); it != keys.end(); ++it) { - if (it + 1 == keys.end()) { // Last key - if (p->contains(*it)) { - p->erase(*it); - return true; - } - return false; - } - if (!p->contains(*it) || !(*p)[*it].is_object()) { - return false; - } - p = &(*p)[*it]; - } - return false; -} - -bool ConfigManager::hasValue(const std::string& key_path) const { - return getValue(key_path).has_value(); -} - -bool ConfigManager::saveToFile(const fs::path& file_path) const { - std::unique_lock lock(m_impl->rw_mutex_); - std::ofstream ofs(file_path); - if (!ofs) { - LOG_F(ERROR, "Failed to open file: {}", file_path.string()); - return false; - } - try { - ofs << m_impl->config_.dump(4); - ofs.close(); - return true; - } catch (const std::exception& e) { - LOG_F(ERROR, "Failed to save config to file: {}, error message: {}", - file_path.string(), e.what()); - return false; - } -} - -void ConfigManager::tidyConfig() { - std::unique_lock lock(m_impl->rw_mutex_); - json updated_config; - for (const auto& [key, value] : m_impl->config_.items()) { - json* p = &updated_config; - for (auto sub_key : key | std::views::split('/')) { - if (!p->contains(std::string(sub_key.begin(), sub_key.end()))) { - (*p)[std::string(sub_key.begin(), sub_key.end())] = - json::object(); - } - p = &(*p)[std::string(sub_key.begin(), sub_key.end())]; - } - *p = value; - } - m_impl->config_ = std::move(updated_config); -} - -void ConfigManager::mergeConfig(const json& src) { - m_impl->config_.merge_patch(src); -} - -void ConfigManager::clearConfig() { m_impl->config_.clear(); } - diff --git a/src/atom/components/configor.hpp b/src/atom/components/configor.hpp deleted file mode 100644 index e6798802..00000000 --- a/src/atom/components/configor.hpp +++ /dev/null @@ -1,199 +0,0 @@ -/* - * configor.cpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2023-4-4 - -Description: Configor - -**************************************************/ - -#ifndef ATOM_COMPONENT_CONFIG_HPP -#define ATOM_COMPONENT_CONFIG_HPP - -#include -#include -#include -namespace fs = std::filesystem; - -#include "atom/error/error_code.hpp" - -#include "atom/type/json.hpp" -using json = nlohmann::json; - -#define GetIntConfig(path) \ - GetPtr("lithium.config") \ - .value() \ - ->getValue(path) \ - .value() \ - .get() - -#define GetFloatConfig(path) \ - GetPtr("lithium.config") \ - .value() \ - ->getValue(path) \ - .value() \ - .get() - -#define GetBoolConfig(path) \ - GetPtr("lithium.config") \ - .value() \ - ->getValue(path) \ - .value() \ - .get() - -#define GetDoubleConfig(path) \ - GetPtr("lithium.config") \ - .value() \ - ->getValue(path) \ - .value() \ - .get() - -#define GetStringConfig(path) \ - GetPtr("lithium.config") \ - .value() \ - ->getValue(path) \ - .value() \ - .get() - -class ConfigManagerImpl; - -class ConfigManager { -public: - /** - * @brief 构造函数 - * - * Constructor. - */ - ConfigManager(); - - /** - * @brief 析构函数 - * - * Destructor. - */ - ~ConfigManager(); - - // ------------------------------------------------------------------- - // Common methods - // ------------------------------------------------------------------- - - /** - * @brief 创建ConfigManager的共享指针,但是全局唯一 - * - * Create a shared pointer of ConfigManager. But global only - */ - static std::shared_ptr createShared(); - - static std::unique_ptr createUnique(); - - // ------------------------------------------------------------------- - // Config methods - // ------------------------------------------------------------------- - - /** - * @brief 获取一个配置项的值 - * - * Get the value of a configuration item. - * - * @param key_path 配置项的键路径,使用斜杠 / 进行分隔,如 - * "database/username" - * @return json 配置项对应的值,如果键不存在则返回 nullptr - */ - [[nodiscard("config value should not be ignored!")]] std::optional - getValue(const std::string& key_path) const; - - /** - * @brief 添加或更新一个配置项 - * - * Add or update a configuration item. - * - * @param key_path 配置项的键路径,使用斜杠 / 进行分隔,如 - * "database/username" - * @param value 配置项的值,使用 JSON 格式进行表示 - * @return bool 成功返回 true,失败返回 false - */ - bool setValue(const std::string& key_path, const json& value); - /** - * @brief 删除一个配置项 - * - * Delete a configuration item. - * - * @param key_path 配置项的键路径,使用斜杠 / 进行分隔,如 - * "database/username" - */ - - bool deleteValue(const std::string& key_path); - - /** - * @brief 判断一个配置项是否存在 - * - * Determine if a configuration item exists. - * - * @param key_path 配置项的键路径,使用斜杠 / 进行分隔,如 - * "database/username" - * @return bool 存在返回 true,不存在返回 false - */ - [[nodiscard("status of the value should not be ignored")]] bool hasValue( - const std::string& key_path) const; - - /** - * @brief 从指定文件中加载JSON配置,并与原有配置进行合并 - * - * Load JSON configuration from the specified file and merge with the - * existing configuration. - * - * @param path 配置文件路径 - */ - bool loadFromFile(const fs::path& path); - - /** - * @brief 加载指定目录下的所有JSON配置文件 - * - * Load all JSON configuration files in the specified directory. - * - * @param dir_path 配置文件所在目录的路径 - */ - bool loadFromDir(const fs::path& dir_path, bool recursive = false); - - /** - * @brief 将当前配置保存到指定文件 - * - * Save the current configuration to the specified file. - * - * @param file_path 目标文件路径 - */ - bool saveToFile(const fs::path& file_path) const; - - /** - * @brief 清理配置项 - * - * Clean up configuration items. - */ - void tidyConfig(); - - /** - * @brief 清除所有配置(测试用) - * - * Clear all of the configurations, only used for test - */ - void clearConfig(); - -private: - std::unique_ptr m_impl; - - /** - * @brief 将 JSON 配置合并到当前配置中 - * - * Merge JSON configuration to the current configuration. - * - * @param j JSON 配置 - */ - void mergeConfig(const json& j); -}; - -#endif diff --git a/src/atom/components/dispatch.hpp b/src/atom/components/dispatch.hpp index 8a666a15..fa444f2c 100644 --- a/src/atom/components/dispatch.hpp +++ b/src/atom/components/dispatch.hpp @@ -26,7 +26,7 @@ #include "atom/type/noncopyable.hpp" #include "atom/type/pointer.hpp" -#include "proxy.hpp" +#include "atom/function/proxy.hpp" class CommandDispatcher { public: @@ -46,6 +46,19 @@ class CommandDispatcher { void registerCommand(const std::string& name, Ret (*func)(Args...), const std::string& group = "", const std::string& description = ""); + + template + void registerCommand(const std::string& name, Ret (Class::*func)(Args...), + std::shared_ptr instance, + const std::string& group = "", + const std::string& description = ""); + + template + void registerCommand(const std::string& name, + Ret (Class::*func)(Args...) const, + std::shared_ptr instance, + const std::string& group = "", + const std::string& description = ""); template void registerCommand(const std::string& name, Ret (Class::*func)(Args...), diff --git a/src/atom/components/dispatch.inl b/src/atom/components/dispatch.inl index 951a0815..3c275440 100644 --- a/src/atom/components/dispatch.inl +++ b/src/atom/components/dispatch.inl @@ -47,6 +47,32 @@ void CommandDispatcher::registerCommand(const std::string& name, })); } +template +void CommandDispatcher::registerCommand(const std::string& name, + Ret (Class::*func)(Args...), + std::shared_ptr instance, + const std::string& group, + const std::string& description) { + registerCommand(name, group, description, + std::function([instance, func](Args... args) { + return std::invoke(func, instance.get(), + std::forward(args)...); + })); +} + +template +void CommandDispatcher::registerCommand(const std::string& name, + Ret (Class::*func)(Args...) const, + std::shared_ptr instance, + const std::string& group, + const std::string& description) { + registerCommand(name, group, description, + std::function([instance, func](Args... args) { + return std::invoke(func, instance.get(), + std::forward(args)...); + })); +} + template void CommandDispatcher::registerCommand(const std::string& name, Ret (Class::*func)(Args...), diff --git a/src/atom/components/templates/alone_component.cpp b/src/atom/components/templates/alone_component.cpp deleted file mode 100644 index 51c8793a..00000000 --- a/src/atom/components/templates/alone_component.cpp +++ /dev/null @@ -1,28 +0,0 @@ -/* - * alone_component.cpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2023-7-13 - -Description: Alone component(run in different process) - -**************************************************/ - -#include "alone_component.hpp" -#include "atom/components/macro.hpp" - -#include "atom/log/loguru.hpp" -#include "atom/utils/random.hpp" - -#include -#include - -AloneComponent::AloneComponent(const std::string &name) - : Component(name) -{ - -} \ No newline at end of file diff --git a/src/atom/components/templates/alone_component.hpp b/src/atom/components/templates/alone_component.hpp deleted file mode 100644 index aca4fe40..00000000 --- a/src/atom/components/templates/alone_component.hpp +++ /dev/null @@ -1,25 +0,0 @@ -/* - * alone_component.hpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2023-7-13 - -Description: Alone component(run in different process) - -**************************************************/ - -#pragma once - -#include "atom/components/component.hpp" - - -class AloneComponent : public Component -{ -public: - explicit AloneComponent(const std::string &name); - -}; diff --git a/src/atom/components/templates/exe_component.cpp b/src/atom/components/templates/exe_component.cpp deleted file mode 100644 index 8f477d52..00000000 --- a/src/atom/components/templates/exe_component.cpp +++ /dev/null @@ -1,127 +0,0 @@ -/* - * exe_plugin.cpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2023-7-13 - -Description: Executable Plugin - -**************************************************/ - -#include "exe_component.hpp" -#include "atom/components/macro.hpp" - -#include "atom/log/loguru.hpp" -#include "atom/utils/random.hpp" - -#include -#include - -ExecutableComponent::ExecutableComponent(const std::string &name) - : Component(name) -{ - registerFunc("run_system_command", &ExecutableComponent::RunSystemCommand, this); - registerFunc("run_system_command_with_output", &ExecutableComponent::RunSystemCommandOutput, this); - registerFunc("run_script", &ExecutableComponent::RunScript, this); - registerFunc("run_script_with_output", &ExecutableComponent::RunScriptOutput, this); -} - -json ExecutableComponent::RunSystemCommand(const json ¶ms) -{ - CHECK_PARAM("command"); - CHECK_PARAM("identifier"); - std::string command = params["command"].get(); - std::string identifier = params["identifier"].get(); - DLOG_F(INFO, "Running command: {}", command); - if (m_ProcessManager) - { - if (!m_ProcessManager->createProcess(command, identifier.empty() ? atom::utils::generateRandomString(10) : identifier)) - { - LOG_F(ERROR, "Failed to run executable plugin : {}", command); - return createErrorResponse(__func__, json(), std::format("Failed to run executable plugin : {}", command)); - } - else - { - LOG_F(ERROR, "Started {} successfully", command); - return createSuccessResponse(__func__, json()); - } - } - LOG_F(ERROR, "Process manager is not initialized"); - return createErrorResponse(__func__, json(), "Process manager is not initialized"); -} - -json ExecutableComponent::RunSystemCommandOutput(const json ¶ms) -{ - CHECK_PARAM("command"); - CHECK_PARAM("identifier"); - std::string command = params["command"].get(); - std::string identifier = params["identifier"].get(); - if (m_ProcessManager) - { - DLOG_F(INFO, "Running command: {}", command); - if (m_ProcessManager->createProcess(command, identifier.empty() ? atom::utils::generateRandomString(10) : identifier)) - { - LOG_F(ERROR, "Started {} successfully", command); - return createSuccessResponse(__func__, json()); - } - else - { - LOG_F(ERROR, "Failed to run executable plugin : {}", command); - return createErrorResponse(__func__, json(), std::format("Failed to run executable plugin : {}", command)); - } - } - LOG_F(ERROR, "Process manager is not initialized"); - return createErrorResponse(__func__, json(), "Process manager is not initialized"); -} - -json ExecutableComponent::RunScript(const json ¶ms) -{ - CHECK_PARAM("script"); - CHECK_PARAM("identifier"); - std::string script = params["script"].get(); - std::string identifier = params["identifier"].get(); - if (m_ProcessManager) - { - DLOG_F(INFO, "Running script: {}", script); - if (m_ProcessManager->createProcess(script, identifier.empty() ? atom::utils::generateRandomString(10) : identifier)) - { - LOG_F(ERROR, "Started {} successfully", script); - return createSuccessResponse(__func__, json()); - } - else - { - LOG_F(ERROR, "Failed to run executable plugin : {}", script); - return createErrorResponse(__func__, json(), std::format("Failed to run executable plugin : {}", script)); - } - } - LOG_F(ERROR, "Process manager is not initialized"); - return createErrorResponse(__func__, json(), "Process manager is not initialized"); -} - -json ExecutableComponent::RunScriptOutput(const json ¶ms) -{ - CHECK_PARAM("script"); - CHECK_PARAM("identifier"); - std::string script = params["script"].get(); - std::string identifier = params["identifier"].get(); - if (m_ProcessManager) - { - DLOG_F(INFO, "Running script: {}", script); - if (m_ProcessManager->createProcess(script, identifier.empty() ? atom::utils::generateRandomString(10) : identifier)) - { - LOG_F(ERROR, "Started {} successfully", script); - return createSuccessResponse(__func__, json()); - } - else - { - LOG_F(ERROR, "Failed to run executable plugin : {}", script); - return createErrorResponse(__func__, json(), std::format("Failed to run executable plugin : {}", script)); - } - } - LOG_F(ERROR, "Process manager is not initialized"); - return createErrorResponse(__func__, json(), "Process manager is not initialized"); -} diff --git a/src/atom/components/templates/exe_component.hpp b/src/atom/components/templates/exe_component.hpp deleted file mode 100644 index 48dcd419..00000000 --- a/src/atom/components/templates/exe_component.hpp +++ /dev/null @@ -1,35 +0,0 @@ -/* - * exe_plugin.hpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2023-7-13 - -Description: Executable Plugin - -**************************************************/ - -#pragma once - -#include "atom/components/component.hpp" - -#include "atom/system/process.hpp" - -class ExecutableComponent : public Component -{ -public: - explicit ExecutableComponent(const std::string &name); - - json RunSystemCommand(const json &m_parmas); - - json RunSystemCommandOutput(const json &m_parmas); - - json RunScript(const json &m_parmas); - - json RunScriptOutput(const json &m_parmas); -private: - std::shared_ptr m_ProcessManager; -}; diff --git a/src/atom/components/templates/script_component.cpp b/src/atom/components/templates/script_component.cpp deleted file mode 100644 index e69de29b..00000000 diff --git a/src/atom/components/templates/script_component.hpp b/src/atom/components/templates/script_component.hpp deleted file mode 100644 index e69de29b..00000000 diff --git a/src/atom/components/templates/shared.hpp b/src/atom/components/templates/shared.hpp deleted file mode 100644 index b7176997..00000000 --- a/src/atom/components/templates/shared.hpp +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef ATOM_COMPONENT_SHARED_HPP -#define ATOM_COMPONENT_SHARED_HPP - -#include "atom/components/component.hpp" - -#include "atom/type/message.hpp" - -template -class SharedComponent : public Component { -public: - explicit SharedComponent(const std::string &name); - virtual ~SharedComponent() override; - - virtual bool initialize() override; - virtual bool destroy() override; - - void handleVoidMessage(const std::shared_ptr &message); - void handleTextMessage(const std::shared_ptr &message); - void handleNumberMessage(const std::shared_ptr &message); - void handleBooleanMessage(const std::shared_ptr &message); - -private: - std::function m_handleFunction; -}; - -#endif \ No newline at end of file diff --git a/src/atom/components/templates/shared.inl b/src/atom/components/templates/shared.inl deleted file mode 100644 index 22adaba1..00000000 --- a/src/atom/components/templates/shared.inl +++ /dev/null @@ -1,104 +0,0 @@ -#ifndef ATOM_COMPONENT_SHARED_INL -#define ATOM_COMPONENT_SHARED_INL - -#include "shared.hpp" - -#include "atom/error/exception.hpp" -#include "atom/log/loguru.hpp" -#include "atom/server/message_bus.hpp" -#include "atom/type/message.hpp" -#include "atom/utils/string.hpp" - -using namespace atom::error; - -template -SharedComponent::SharedComponent(const std::string &name) : Component(name) { - m_handleFunction = [shared_this = - shared_from_this()](const std::any &message) { - LOG_F(INFO, "SharedComponent::handleFunction"); - if (message.has_value()) { - if (message.type() == typeid(std::shared_ptr)) { - shared_this->dispatch( - "handleVoid", - std::any_cast>(message)); - } else if (message.type() == - typeid(std::shared_ptr)) { - shared_this->dispatch( - "handleNumber", - std::any_cast>(message)); - } else if (message.type() == typeid(std::shared_ptr)) { - shared_this->dispatch( - "handleText", - std::any_cast>(message)); - } else if (message.type() == - typeid(std::shared_ptr)) { - shared_this->dispatch( - "handleBoolean", - std::any_cast>(message)); - } else if (message.type() == - typeid(std::shared_ptr)) { - shared_this->dispatch( - "handleParams", - std::any_cast>(message)); - } else { - LOG_F(ERROR, - "SharedComponent::handleFunction: unknown message type"); - THROW_EXCEPTION( - "SharedComponent::handleFunction: unknown message type"); - } - } else { - LOG_F(ERROR, "SharedComponent::handleFunction: message is null"); - THROW_EXCEPTION("SharedComponent::handleFunction: message is null"); - } - }; - - registerCommand("handleNumber", handleNumberMessage); - registerCommand("handleText", handleTextMessage); - registerCommand("handleBoolean", handleBooleanMessage); - registerCommand("handleVoid", handleVoidMessage); -} - -template -SharedComponent::~SharedComponent() {} - -template -bool SharedComponent::initialize() { return true; } - -template -bool SharedComponent::destroy() { return true; } - -template -void SharedComponent::handleVoidMessage( - const std::shared_ptr &message) { - LOG_F(INFO, "SharedComponent::handleVoid"); - auto name = message->name(); - try - { - dispatch(name); - } - catch(const std::exception& e) - { - std::cerr << e.what() << '\n'; - } - -} - -template -void SharedComponent::handleTextMessage( - const std::shared_ptr &message) { - LOG_F(INFO, "SharedComponent::handleText"); -} - -template -void SharedComponent::handleBooleanMessage( - const std::shared_ptr &message) { - LOG_F(INFO, "SharedComponent::handleBoolean"); -} - -template -void SharedComponent::handleNumberMessage( - const std::shared_ptr &message) { - LOG_F(INFO, "SharedComponent::handleNumber"); -} - -#endif diff --git a/src/atom/components/templates/task_component.cpp b/src/atom/components/templates/task_component.cpp deleted file mode 100644 index e69de29b..00000000 diff --git a/src/atom/components/templates/task_component.hpp b/src/atom/components/templates/task_component.hpp deleted file mode 100644 index e69de29b..00000000 diff --git a/src/atom/components/var.inl b/src/atom/components/var.inl index a2ffdeb4..0b1b3f14 100644 --- a/src/atom/components/var.inl +++ b/src/atom/components/var.inl @@ -4,7 +4,7 @@ #include "var.hpp" template -void VariableManager::addVariable(const std::string& name, T initialValue, +inline void VariableManager::addVariable(const std::string& name, T initialValue, const std::string& description, const std::string& alias, const std::string& group) { @@ -13,7 +13,7 @@ void VariableManager::addVariable(const std::string& name, T initialValue, } template -void VariableManager::setRange(const std::string& name, T min, T max) { +inline void VariableManager::setRange(const std::string& name, T min, T max) { if (auto variable = getVariable(name)) { ranges_[name] = std::make_pair(std::move(min), std::move(max)); } @@ -27,7 +27,7 @@ inline void VariableManager::setStringOptions( } template -std::shared_ptr> VariableManager::getVariable( +inline std::shared_ptr> VariableManager::getVariable( const std::string& name) { auto it = variables_.find(name); if (it != variables_.end()) { @@ -41,12 +41,12 @@ std::shared_ptr> VariableManager::getVariable( return nullptr; } -void VariableManager::setValue(const std::string& name, const char* newValue) { +inline void VariableManager::setValue(const std::string& name, const char* newValue) { setValue(name, std::string(newValue)); } template -void VariableManager::setValue(const std::string& name, T newValue) { +inline void VariableManager::setValue(const std::string& name, T newValue) { if (auto variable = getVariable(name)) { if constexpr (std::is_arithmetic_v) { if (ranges_.count(name)) { diff --git a/src/atom/driver/CMakeLists.txt b/src/atom/driver/CMakeLists.txt deleted file mode 100644 index e90218fe..00000000 --- a/src/atom/driver/CMakeLists.txt +++ /dev/null @@ -1,71 +0,0 @@ -cmake_minimum_required(VERSION 3.20) -project(atom-driver C CXX) - -find_package(Threads REQUIRED) - -include_directories(.) -CHECK_INCLUDE_FILE(format HAS_STD_FORMAT) - -if(NOT HAS_STD_FORMAT) - find_package(fmt REQUIRED) -endif() -# Sources -list(APPEND ${PROJECT_NAME}_SOURCES - fitskeyword.cpp - - device.cpp - camera.cpp - telescope.cpp - focuser.cpp - filterwheel.cpp - guider.cpp -) - -# Headers -list(APPEND ${PROJECT_NAME}_HEADERS - fitskeyword.h - - device.hpp - camera.hpp - telescope.hpp - focuser.hpp - filterwheel.hpp - guider.hpp - solver.hpp -) - -# Build Object Library -add_library(${PROJECT_NAME}_OBJECT OBJECT) -set_property(TARGET ${PROJECT_NAME}_OBJECT PROPERTY POSITION_INDEPENDENT_CODE 1) - -target_sources(${PROJECT_NAME}_OBJECT - PUBLIC - ${${PROJECT_NAME}_HEADERS} - PRIVATE - ${${PROJECT_NAME}_SOURCES} -) - -target_link_libraries(${PROJECT_NAME}_OBJECT ${${PROJECT_NAME}_LIBS}) -target_link_libraries(${PROJECT_NAME}_OBJECT atom-component) -target_link_libraries(${PROJECT_NAME}_OBJECT atom-server) -target_link_libraries(${PROJECT_NAME}_OBJECT fmt::fmt) -if (LINUX) -target_link_libraries(${PROJECT_NAME}_OBJECT uuid) -endif() -add_library(${PROJECT_NAME} SHARED) - -target_link_libraries(${PROJECT_NAME} ${PROJECT_NAME}_OBJECT ${${PROJECT_NAME}_LIBS}) -target_include_directories(${PROJECT_NAME} PUBLIC .) - -set_target_properties(${PROJECT_NAME} PROPERTIES - VERSION ${CMAKE_HYDROGEN_VERSION_STRING} - SOVERSION ${HYDROGEN_SOVERSION} - OUTPUT_NAME ${PROJECT_NAME} -) - -install(TARGETS ${PROJECT_NAME} - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} -) - -add_executable(shared_driver_test main.cpp) -target_link_libraries(shared_driver_test atom-driver) \ No newline at end of file diff --git a/src/atom/driver/_pybind.cpp b/src/atom/driver/_pybind.cpp deleted file mode 100644 index 2d3e410c..00000000 --- a/src/atom/driver/_pybind.cpp +++ /dev/null @@ -1,191 +0,0 @@ -/* - * _pybind.cpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2024-4-13 - -Description: Python Binding of Atom-Driver - -**************************************************/ - -#include - -#include "camera.hpp" -#include "device.hpp" -#include "filterwheel.hpp" -#include "focuser.hpp" -#include "solver.hpp" -#include "telescope.hpp" - -#include "pid/pid.hpp" - -namespace py = pybind11; - -PYBIND11_MODULE(atom_driver, m) { - m.doc() = "Atom Driver Python Binding"; - - py::class_(m, "AtomDriver") - .def(py::init()) // 默认构造函数 - .def("initialize", &AtomDriver::initialize) // initialize 方法 - .def("connect", &AtomDriver::connect) // connect 方法 - .def("disconnect", &AtomDriver::disconnect) // disconnect 方法 - .def("reconnect", &AtomDriver::reconnect) // reconnect 方法 - .def("isConnected", &AtomDriver::isConnected) // isConnected 方法 - .def("Connect", &AtomDriver::Connect) // Connect 方法 - .def("Disconnect", &AtomDriver::Disconnect) // Disconnect 方法 - .def("Reconnect", &AtomDriver::Reconnect) // Reconnect 方法 - .def("IsConnected", &AtomDriver::IsConnected); // IsConnected 方法 - - py::class_(m, "AtomCamera") - .def(py::init()) // 默认构造函数 - .def("initialize", &AtomCamera::initialize) // initialize 方法 - .def("connect", &AtomCamera::connect) // connect 方法 - .def("disconnect", &AtomCamera::disconnect) // disconnect 方法 - .def("reconnect", &AtomCamera::reconnect) // reconnect 方法 - .def("isConnected", &AtomCamera::isConnected) // isConnected 方法 - .def("startExposure", &AtomCamera::startExposure) // startExposure 方法 - .def("abortExposure", &AtomCamera::abortExposure) // abortExposure 方法 - .def("getExposureStatus", - &AtomCamera::getExposureStatus) // getExposureStatus 方法 - .def("getExposureResult", - &AtomCamera::getExposureResult) // getExposureResult 方法 - .def("saveExposureResult", - &AtomCamera::saveExposureResult) // saveExposureResult 方法 - .def("startVideo", &AtomCamera::startVideo) // startVideo 方法 - .def("stopVideo", &AtomCamera::stopVideo) // stopVideo 方法 - .def("getVideoStatus", - &AtomCamera::getVideoStatus) // getVideoStatus 方法 - .def("getVideoResult", - &AtomCamera::getVideoResult) // getVideoResult 方法 - .def("saveVideoResult", - &AtomCamera::saveVideoResult) // saveVideoResult 方法 - .def("startCooling", &AtomCamera::startCooling) // startCooling 方法 - .def("stopCooling", &AtomCamera::stopCooling) // stopCooling 方法 - .def("getCoolingStatus", - &AtomCamera::getCoolingStatus) // getCoolingStatus 方法 - .def("isCoolingAvailable", - &AtomCamera::isCoolingAvailable) // isCoolingAvailable 方法 - .def("getTemperature", - &AtomCamera::getTemperature) // getTemperature 方法 - .def("getCoolingPower", - &AtomCamera::getCoolingPower) // getCoolingPower 方法 - .def("setTemperature", - &AtomCamera::setTemperature) // setTemperature 方法 - .def("setCoolingPower", - &AtomCamera::setCoolingPower) // setCoolingPower 方法 - .def("getGain", &AtomCamera::getGain) // getGain 方法 - .def("setGain", &AtomCamera::setGain) // setGain 方法 - .def("isGainAvailable", - &AtomCamera::isGainAvailable) // isGainAvailable 方法 - .def("getOffset", &AtomCamera::getOffset) // getOffset 方法 - .def("setOffset", &AtomCamera::setOffset) // setOffset 方法 - .def("isOffsetAvailable", - &AtomCamera::isOffsetAvailable) // isOffsetAvailable 方法 - .def("getISO", &AtomCamera::getISO) // getISO 方法 - .def("setISO", &AtomCamera::setISO) // setISO 方法 - .def("isISOAvailable", - &AtomCamera::isISOAvailable) // isISOAvailable 方法 - .def("getFrame", &AtomCamera::getFrame) // getFrame 方法 - .def("setFrame", &AtomCamera::setFrame) // setFrame 方法 - .def("isFrameSettingAvailable", - &AtomCamera::isFrameSettingAvailable) // isFrameSettingAvailable - // 方法 - .def("getBinning", &AtomCamera::getBinning) // getBinning 方法 - .def("setBinning", &AtomCamera::setBinning); // setBinning 方法 - - py::class_(m, "Telescope") - .def(py::init()) // 默认构造函数 - .def("connect", &Telescope::connect) // connect 方法 - .def("disconnect", &Telescope::disconnect) // disconnect 方法 - .def("reconnect", &Telescope::reconnect) // reconnect 方法 - .def("isConnected", &Telescope::isConnected) // isConnected 方法 - .def("SlewTo", &Telescope::SlewTo) // SlewTo 方法 - .def("Abort", &Telescope::Abort) // Abort 方法 - .def("isSlewing", &Telescope::isSlewing) // isSlewing 方法 - .def("getCurrentRA", &Telescope::getCurrentRA) // getCurrentRA 方法 - .def("getCurrentDec", &Telescope::getCurrentDec) // getCurrentDec 方法 - .def("StartTracking", &Telescope::StartTracking) // StartTracking 方法 - .def("StopTracking", &Telescope::StopTracking) // StopTracking 方法 - .def("setTrackingMode", - &Telescope::setTrackingMode) // setTrackingMode 方法 - .def("setTrackingSpeed", - &Telescope::setTrackingSpeed) // setTrackingSpeed 方法 - .def("getTrackingMode", - &Telescope::getTrackingMode) // getTrackingMode 方法 - .def("getTrackingSpeed", - &Telescope::getTrackingSpeed) // getTrackingSpeed 方法 - .def("Home", &Telescope::Home) // Home 方法 - .def("isAtHome", &Telescope::isAtHome) // isAtHome 方法 - .def("setHomePosition", - &Telescope::setHomePosition) // setHomePosition 方法 - .def("isHomeAvailable", - &Telescope::isHomeAvailable) // isHomeAvailable 方法 - .def("Park", &Telescope::Park) // Park 方法 - .def("Unpark", &Telescope::Unpark) // Unpark 方法 - .def("isAtPark", &Telescope::isAtPark) // isAtPark 方法 - .def("setParkPosition", - &Telescope::setParkPosition) // setParkPosition 方法 - .def("isParkAvailable", - &Telescope::isParkAvailable); // isParkAvailable 方法 - - // 继承 AtomDriver 的 Focuser 类 - py::class_(m, "Focuser") - .def(py::init()) // 默认构造函数 - .def("connect", &Focuser::connect) // connect 方法 - .def("disconnect", &Focuser::disconnect) // disconnect 方法 - .def("reconnect", &Focuser::reconnect) // reconnect 方法 - .def("isConnected", &Focuser::isConnected) // isConnected 方法 - .def("moveTo", &Focuser::moveTo) // moveTo 方法 - .def("moveToAbsolute", &Focuser::moveToAbsolute) // moveToAbsolute 方法 - .def("moveStep", &Focuser::moveStep) // moveStep 方法 - .def("moveStepAbsolute", - &Focuser::moveStepAbsolute) // moveStepAbsolute 方法 - .def("AbortMove", &Focuser::AbortMove) // AbortMove 方法 - .def("getMaxPosition", &Focuser::getMaxPosition) // getMaxPosition 方法 - .def("setMaxPosition", &Focuser::setMaxPosition) // setMaxPosition 方法 - .def("isGetTemperatureAvailable", - &Focuser::isGetTemperatureAvailable) // isGetTemperatureAvailable - // 方法 - .def("getTemperature", &Focuser::getTemperature) // getTemperature 方法 - .def("isAbsoluteMoveAvailable", - &Focuser::isAbsoluteMoveAvailable) // isAbsoluteMoveAvailable 方法 - .def("isManualMoveAvailable", - &Focuser::isManualMoveAvailable) // isManualMoveAvailable 方法 - .def("getCurrentPosition", - &Focuser::getCurrentPosition) // getCurrentPosition 方法 - .def("haveBacklash", &Focuser::haveBacklash) // haveBacklash 方法 - .def("setBacklash", &Focuser::setBacklash); // setBacklash 方法 - - py::class_(m, "Filterwheel") - .def(py::init()) // 默认构造函数 - .def("connect", &Filterwheel::connect) // connect 方法 - .def("disconnect", &Filterwheel::disconnect) // disconnect 方法 - .def("reconnect", &Filterwheel::reconnect) // reconnect 方法 - .def("isConnected", &Filterwheel::isConnected) // isConnected 方法 - .def("moveTo", &Filterwheel::moveTo) // moveTo 方法 - .def("getCurrentPosition", - &Filterwheel::getCurrentPosition); // getCurrentPosition 方法 - - py::class_(m, "PID") - .def(py::init()) // 构造函数 - .def("setIntegratorLimits", - &PID::setIntegratorLimits) // setIntegratorLimits 方法 - .def("setTau", &PID::setTau) // setTau 方法 - .def("calculate", &PID::calculate) // calculate 方法 - .def("propotionalTerm", &PID::propotionalTerm) // propotionalTerm 方法 - .def("integralTerm", &PID::integralTerm) // integralTerm 方法 - .def("derivativeTerm", &PID::derivativeTerm); // derivativeTerm 方法 - - py::class_(m, "Solver") - .def(py::init()) // 构造函数 - .def("solveImage", &Solver::solveImage) // solveImage 方法 - .def("getSolveResult", &Solver::getSolveResult) // getSolveResult 方法 - .def("getSolveStatus", &Solver::getSolveStatus) // getSolveStatus 方法 - .def("setSolveParams", &Solver::setSolveParams) // setSolveParams 方法 - .def("getSolveParams", &Solver::getSolveParams); // getSolveParams 方法 -} diff --git a/src/atom/driver/camera.cpp b/src/atom/driver/camera.cpp deleted file mode 100644 index 257badc7..00000000 --- a/src/atom/driver/camera.cpp +++ /dev/null @@ -1,323 +0,0 @@ -/* - * camera.cpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2023-3-29 - -Description: AtomCamera Simulator and Basic Definition - -**************************************************/ - -#include "camera.hpp" - -#include "code.hpp" -#include "magic_enum/magic_enum.hpp" -#include "marco.hpp" - -AtomCamera::AtomCamera(const std::string &name) : AtomDriver(name) {} - -AtomCamera::~AtomCamera() {} - -bool AtomCamera::initialize() { - AtomDriver::initialize(); - - // Primary CCD Exposure - registerVariable("CCD_EXPOSURE_VALUE", 1.0, "Duration (s)"); - registerVariableRanges("CCD_EXPOSURE_VALUE", 0.01, 3600); - registerVariable("CCD_EXPOSURE_STATUS", false, "Status"); - - // Primary CCD Abort - registerVariable("CCD_ABORT_EXPOSURE", false, "Abort"); - - registerVariable("CCD_VIDEO_STATUS", false, "Status"); - - registerVariable("CCD_GAIN", 20, "gain"); - registerVariableRanges("CCD_GAIN", 0, 256); - registerVariable("CCD_OFFSET", 0, "offset"); - registerVariableRanges("CCD_OFFSET", 0, 256); - - // CCD Temperature - registerVariable("CCD_TEMPERATURE_VALUE", 0.0, "Temperature (C)"); - registerVariableRanges("CCD_TEMPERATURE_VALUE", -50.0, 50.0); - - // AtomCamera temperature ramp - registerVariable("RAMP_SLOPE", 0, "Max. dT (C/min)"); - registerVariableRanges("RAMP_SLOPE", 0, 30); - registerVariable("RAMP_THRESHOLD", 0.2, "Threshold (C)"); - registerVariableRanges("RAMP_THRESHOLD", 0.1, 2); - - /**********************************************/ - /**************** Primary Chip ****************/ - /**********************************************/ - - // Primary CCD Region-Of-Interest (ROI) - registerVariable("X", 0.0, "Left"); - registerVariable("Y", 0.0, "Top"); - registerVariable("WIDTH", 0.0, "Width"); - registerVariable("HEIGHT", 0.0, "Height"); - - // Primary CCD Frame Type - registerVariable("FRAME_LIGHT", true, "Light"); - registerVariable("FRAME_BIAS", false, "Bias"); - registerVariable("FRAME_DARK", false, "Dark"); - registerVariable("FRAME_FLAT", false, "Flat"); - - // Primary CCD Binning - registerVariable("HOR_BIN", 1, "X"); - registerVariableRanges("HOR_BIN", 1, 4); - registerVariable("VER_BIN", 1, "Y"); - registerVariableRanges("VER_BIN", 1, 4); - - // Primary CCD Info - registerVariable("CCD_MAX_X", 0, "Max. Width"); - registerVariableRanges("CCD_MAX_X", 1, 16000); - registerVariable("CCD_MAX_Y", 0, "Max. Height"); - registerVariableRanges("CCD_MAX_Y", 1, 16000); - registerVariable("CCD_PIXEL_SIZE", 0, "Pixel size (um)"); - registerVariableRanges("CCD_PIXEL_SIZE", 1, 40); - - registerVariable("CCD_PIXEL_SIZE_X", 0.0, "Pixel size X"); - registerVariableRanges("CCD_PIXEL_SIZE_X", 0, 40); - registerVariable("CCD_PIXEL_SIZE_Y", 0.0, "Pixel size Y"); - registerVariableRanges("CCD_PIXEL_SIZE_Y", 0, 40); - registerVariable("CCD_BITSPERPIXEL", 0, "Bits per pixel"); - registerVariableRanges("CCD_BITSPERPIXEL", 8, 64); - - // Primary CCD Compression Options - registerVariable("CCD_COMPRESSION", false, "Compression"); - - /**********************************************/ - /******************** WCS *********************/ - /**********************************************/ - - registerVariable("WCS_ENABLE", false, "Enable"); - registerVariable("CCD_ROTATION_VALUE", 0, "Rotation"); - registerVariableRanges("CCD_ROTATION_VALUE", -360, 360); - registerVariable("FOCAL_LENGTH", 0, "Focal Length (mm)"); - registerVariableRanges("FOCAL_LENGTH", 10, 10000); - registerVariable("APERTURE", 0, "Aperture (mm)"); - registerVariableRanges("APERTURE", 10, 3000); - - /**********************************************/ - /************** Capture Format ***************/ - /**********************************************/ - - registerVariable("CCD_CAPTURE_FORMAT", "FTIS", "FitsFormat"); - - /**********************************************/ - /************** Upload Settings ***************/ - /**********************************************/ - - // Upload Mode - registerVariable("UPLOAD_MODE", "Both", "Upload"); - - // Upload Settings - registerVariable("UPLOAD_DIR", "", "Dir"); - registerVariable("UPLOAD_PREFIX", "IMAGE_XXX", "Prefix"); - registerVariable("CCD_FILE_PATH", "", "Filename"); - - /**********************************************/ - /****************** FITS Header****************/ - /**********************************************/ - registerVariable("FTIS_KEYWORD_NAME", "", "Name"); - registerVariable("FITS_KEYWORD_VALUE", "", "Value"); - registerVariable("KEYWORD_COMMENT", "", "Comment"); - - /**********************************************/ - /******************** Methods******************/ - /**********************************************/ - - registerFunc("startExposure", &AtomCamera::_startExposure, this); - registerFunc("abortExposure", &AtomCamera::_abortExposure, this); - registerFunc("getExposureStatus", &AtomCamera::_getExposureStatus, this); - registerFunc("getExposureResult", &AtomCamera::_getExposureResult, this); - - registerFunc("startVideo", &AtomCamera::_startVideo, this); - registerFunc("stopVideo", &AtomCamera::_stopVideo, this); - registerFunc("getVideoStatus", &AtomCamera::_getVideoStatus, this); - registerFunc("getVideoResult", &AtomCamera::_getVideoResult, this); - - registerFunc("startCooling", &AtomCamera::_startCooling, this); - registerFunc("stopCooling", &AtomCamera::_stopCooling, this); - registerFunc("getCoolingStatus", &AtomCamera::_getCoolingStatus, this); - registerFunc("getCoolingPower", &AtomCamera::_getCoolingPower, this); - registerFunc("setCoolingPower", &AtomCamera::_setCoolingPower, this); - registerFunc("getTemperature", &AtomCamera::_getTemperature, this); - registerFunc("setTemperature", &AtomCamera::_setTemperature, this); - - registerFunc("getGain", &AtomCamera::_getGain, this); - registerFunc("setGain", &AtomCamera::_setGain, this); - registerFunc("getOffset", &AtomCamera::_getOffset, this); - registerFunc("setOffset", &AtomCamera::_setOffset, this); - registerFunc("getISO", &AtomCamera::_getISO, this); - registerFunc("setISO", &AtomCamera::_setISO, this); - registerFunc("getBinning", &AtomCamera::_getBinning, this); - registerFunc("setBinning", &AtomCamera::_setBinning, this); - - registerFunc("getFrame", &AtomCamera::_getFrame, this); - registerFunc("setFrame", &AtomCamera::_setFrame, this); - return true; -} - -bool AtomCamera::connect(const json ¶ms) { return true; } - -bool AtomCamera::disconnect(const json ¶ms) { return true; } - -bool AtomCamera::reconnect(const json ¶ms) { return true; } - -bool AtomCamera::isConnected() { return true; } - -bool AtomCamera::startExposure(const double &duration) { return true; } - -bool AtomCamera::abortExposure() { return true; } - -bool AtomCamera::getExposureStatus() { return true; } - -bool AtomCamera::getExposureResult() { return true; } - -bool AtomCamera::saveExposureResult() { return true; } - -bool AtomCamera::startVideo() { return true; } - -bool AtomCamera::stopVideo() { return true; } - -bool AtomCamera::getVideoStatus() { return true; } - -bool AtomCamera::getVideoResult() { return true; } - -bool AtomCamera::saveVideoResult() { return true; } - -bool AtomCamera::startCooling() { return true; } - -bool AtomCamera::stopCooling() { return true; } - -bool AtomCamera::getCoolingStatus() { return true; } - -bool AtomCamera::isCoolingAvailable() { return true; } - -bool AtomCamera::getTemperature() { return true; } - -bool AtomCamera::getCoolingPower() { return true; } - -bool AtomCamera::setTemperature(const double &temperature) { return true; } - -bool AtomCamera::setCoolingPower(const double &power) { return true; } - -bool AtomCamera::getGain() { return true; } - -bool AtomCamera::setGain(const int &gain) { return true; } - -bool AtomCamera::isGainAvailable() { return true; } - -bool AtomCamera::getOffset() { return true; } - -bool AtomCamera::setOffset(const int &offset) { return true; } - -bool AtomCamera::isOffsetAvailable() { return true; } - -bool AtomCamera::getISO() { return true; } - -bool AtomCamera::setISO(const int &iso) { return true; } - -bool AtomCamera::isISOAvailable() { return true; } - -bool AtomCamera::getFrame() { return true; } - -bool AtomCamera::setFrame(const int &x, const int &y, const int &w, - const int &h) { - return true; -} - -bool AtomCamera::isFrameSettingAvailable() { return true; } - -bool AtomCamera::getBinning() { return true; } - -bool AtomCamera::setBinning(const int &hor, const int &ver) { return true; } - -bool AtomCamera::getFrameType() { return true; } - -bool AtomCamera::setFrameType(FrameType type) { return true; } - -bool AtomCamera::getUploadMode() { return true; } - -bool AtomCamera::setUploadMode(UploadMode mode) { return true; } - -json AtomCamera::_startExposure(const json ¶ms) { - CHECK_PARAM("exposure") - double exposure = params["exposure"].get(); - if (!setVariable("CCD_EXPOSURE_VALUE", exposure)) { - LOG_F(ERROR, "Failed to set exposure time!"); - return createErrorResponse( - __func__, - {"error", magic_enum::enum_name(DeviceError::InvalidValue)}, - "Invalid Value"); - } - setVariable("IS_EXPOSURE", true); - if (!startExposure(exposure)) { - LOG_F(ERROR, "Failed to start exposure"); - setVariable("IS_EXPOSURE", false); - return createErrorResponse( - __func__, - {"error", magic_enum::enum_name(CameraError::ExposureError)}, - "Exposure Error"); - } - setVariable("IS_EXPOSURE", false); - DLOG_F(INFO, "Exposure success"); - return createSuccessResponse(__func__, {}); -} - -json AtomCamera::_abortExposure(const json ¶ms) { return {}; } - -json AtomCamera::_getExposureStatus(const json ¶ms) { return {}; } - -json AtomCamera::_getExposureResult(const json ¶ms) { return {}; } - -json AtomCamera::_saveExposureResult(const json ¶ms) { return {}; } - -json AtomCamera::_startVideo(const json ¶ms) { return {}; } - -json AtomCamera::_stopVideo(const json ¶ms) { return {}; } - -json AtomCamera::_getVideoStatus(const json ¶ms) { return {}; } - -json AtomCamera::_getVideoResult(const json ¶ms) { return {}; } - -json AtomCamera::_saveVideoResult(const json ¶ms) { return {}; } - -json AtomCamera::_startCooling(const json ¶ms) { return {}; } - -json AtomCamera::_stopCooling(const json ¶ms) { return {}; } - -json AtomCamera::_getCoolingStatus(const json ¶ms) { return {}; } - -json AtomCamera::_getTemperature(const json ¶ms) { return {}; } - -json AtomCamera::_getCoolingPower(const json ¶ms) { return {}; } - -json AtomCamera::_setTemperature(const json ¶ms) { return {}; } - -json AtomCamera::_setCoolingPower(const json ¶ms) { return {}; } - -json AtomCamera::_getGain(const json ¶ms) { return {}; } - -json AtomCamera::_setGain(const json ¶ms) { return {}; } - -json AtomCamera::_getOffset(const json ¶ms) { return {}; } - -json AtomCamera::_setOffset(const json ¶ms) { return {}; } - -json AtomCamera::_getISO(const json ¶ms) { return {}; } - -json AtomCamera::_setISO(const json ¶ms) { return {}; } - -json AtomCamera::_getBinning(const json ¶ms) { return {}; } - -json AtomCamera::_setBinning(const json ¶ms) { return {}; } - -json AtomCamera::_getFrame(const json ¶ms) { return {}; } - -json AtomCamera::_setFrame(const json ¶ms) { return {}; } \ No newline at end of file diff --git a/src/atom/driver/camera.hpp b/src/atom/driver/camera.hpp deleted file mode 100644 index 673df1a1..00000000 --- a/src/atom/driver/camera.hpp +++ /dev/null @@ -1,199 +0,0 @@ -/* - * camera.hpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2023-6-1 - -Description: AtomCamera Simulator and Basic Definition - -*************************************************/ - -#pragma once - -#include "device.hpp" - -#ifdef ENABLE_SHARED_MEMORY -#include "shared_memory.hpp" -#endif - -class AtomCameraFrame { -public: - std::atomic_int binning_x; - std::atomic_int binning_y; - - std::atomic pixel; - std::atomic pixel_x; - std::atomic pixel_y; - std::atomic pixel_depth; - - std::atomic frame_x; - std::atomic frame_y; - std::atomic max_frame_x; - std::atomic max_frame_y; - - std::atomic_int frame_height; - std::atomic_int frame_width; - - std::string frame_type; - std::string frame_format; - std::string upload_mode; - std::atomic_bool is_fastread; -}; - -enum class FrameType { FITS, NATIVE, XISF, JPG, PNG, TIFF }; - -enum class UploadMode { CLIENT, LOCAL, BOTH, CLOUD }; -class AtomCamera : public AtomDriver { -public: - /** - * @brief 构造函数 - * - * @param name 摄像机名称 - */ - explicit AtomCamera(const std::string &name); - - virtual ~AtomCamera(); - - virtual bool initialize() override; - - virtual bool connect(const json ¶ms) override; - - virtual bool disconnect(const json ¶ms) override; - - virtual bool reconnect(const json ¶ms) override; - - virtual bool isConnected() override; - -public: - virtual bool startExposure(const double &duration); - - virtual bool abortExposure(); - - virtual bool getExposureStatus(); - - virtual bool getExposureResult(); - - virtual bool saveExposureResult(); - - virtual bool startVideo(); - - virtual bool stopVideo(); - - virtual bool getVideoStatus(); - - virtual bool getVideoResult(); - - virtual bool saveVideoResult(); - - virtual bool startCooling(); - - virtual bool stopCooling(); - - virtual bool getCoolingStatus(); - - virtual bool isCoolingAvailable(); - - virtual bool getTemperature(); - - virtual bool getCoolingPower(); - - virtual bool setTemperature(const double &temperature); - - virtual bool setCoolingPower(const double &power); - - virtual bool getGain(); - - virtual bool setGain(const int &gain); - - virtual bool isGainAvailable(); - - virtual bool getOffset(); - - virtual bool setOffset(const int &offset); - - virtual bool isOffsetAvailable(); - - virtual bool getISO(); - - virtual bool setISO(const int &iso); - - virtual bool isISOAvailable(); - - virtual bool getFrame(); - - virtual bool setFrame(const int &x, const int &y, const int &w, - const int &h); - - virtual bool isFrameSettingAvailable(); - - virtual bool getBinning(); - - virtual bool setBinning(const int &hor, const int &ver); - - virtual bool getFrameType(); - - virtual bool setFrameType(FrameType type); - - virtual bool getUploadMode(); - - virtual bool setUploadMode(UploadMode mode); - -protected: - json _startExposure(const json ¶ms); - - json _abortExposure(const json ¶ms); - - json _getExposureStatus(const json ¶ms); - - json _getExposureResult(const json ¶ms); - - json _saveExposureResult(const json ¶ms); - - json _startVideo(const json ¶ms); - - json _stopVideo(const json ¶ms); - - json _getVideoStatus(const json ¶ms); - - json _getVideoResult(const json ¶ms); - - json _saveVideoResult(const json ¶ms); - - json _startCooling(const json ¶ms); - - json _stopCooling(const json ¶ms); - - json _getCoolingStatus(const json ¶ms); - - json _getTemperature(const json ¶ms); - - json _getCoolingPower(const json ¶ms); - - json _setTemperature(const json ¶ms); - - json _setCoolingPower(const json ¶ms); - - json _getGain(const json ¶ms); - - json _setGain(const json ¶ms); - - json _getOffset(const json ¶ms); - - json _setOffset(const json ¶ms); - - json _getISO(const json ¶ms); - - json _setISO(const json ¶ms); - - json _getFrame(const json ¶ms); - - json _setFrame(const json ¶ms); - - json _getBinning(const json ¶ms); - - json _setBinning(const json ¶ms); -}; diff --git a/src/atom/driver/camera_utils.cpp b/src/atom/driver/camera_utils.cpp deleted file mode 100644 index e6006c25..00000000 --- a/src/atom/driver/camera_utils.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include "camera_utils.hpp" - -bool isValidISOValue(int isoValue, int minISO, int maxISO, int isoStep) { - if (isoValue < minISO || isoValue > maxISO) { - return false; - } - if ((isoValue - minISO) % isoStep != 0) { - return false; - } - return true; -} -/* -int isoValue = 800; // 假设设置ISO值为800 -int minISO = 100; // 假设最小ISO值为100 -int maxISO = 6400; // 假设最大ISO值为6400 -int isoStep = 100; // 假设ISO调整步长为100 - -bool isValid = IsValidISOValue(isoValue, minISO, maxISO, isoStep); -if (isValid) -{ - std::cout << "ISO " << isoValue << " is valid." << std::endl; -} -else -{ - std::cout << "ISO " << isoValue << " is not valid." << std::endl; -} -*/ \ No newline at end of file diff --git a/src/atom/driver/camera_utils.hpp b/src/atom/driver/camera_utils.hpp deleted file mode 100644 index 15cf24a5..00000000 --- a/src/atom/driver/camera_utils.hpp +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -bool isValidISOValue(int isoValue, int minISO, int maxISO, int isoStep); diff --git a/src/atom/driver/code.hpp b/src/atom/driver/code.hpp deleted file mode 100644 index bee8ca39..00000000 --- a/src/atom/driver/code.hpp +++ /dev/null @@ -1,61 +0,0 @@ -/* - * code.hpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2023-8-10 - -Description: All of the driver error code - -**************************************************/ - -#ifndef ATOM_DRVIER_CODE_HPP -#define ATOM_DRVIER_CODE_HPP - -enum class DeviceError { - None, - NotSpecific, - NotFound, - NotSupported, - NotConnected, - MissingValue, - InvalidValue, - Busy, - - // For Telescope - GotoError, - ParkError, - UnParkError, - ParkedError, - HomeError -}; - -enum class CameraError { - // For Camera - ExposureError, - GainError, - OffsetError, - ISOError, - CoolingError, -}; - -enum class DeviceWarning { - // For Camera - ExposureWarning, - GainWarning, - OffsetWarning, - ISOWarning, - CoolingWarning, - - // For Telescope - GotoWarning, - ParkWarning, - UnParkWarning, - ParkedWarning, - HomeWarning -}; - -#endif diff --git a/src/atom/driver/device.cpp b/src/atom/driver/device.cpp deleted file mode 100644 index 810a9779..00000000 --- a/src/atom/driver/device.cpp +++ /dev/null @@ -1,78 +0,0 @@ -/* - * device.cpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2023-6-1 - -Description: Basic Device Defination - -*************************************************/ - -#include "device.hpp" - -#include "atom/experiment/decorate.hpp" -#include "atom/utils/uuid.hpp" - -#ifdef __cpp_lib_format -#include -#else -#include -#endif -#include -#include - -AtomDriver::AtomDriver(const std::string &name) - : SharedComponent(name), m_name(name) {} - -AtomDriver::~AtomDriver() {} - -bool AtomDriver::initialize() { - SharedComponent::initialize(); - atom::utils::UUIDGenerator generator; - m_uuid = generator.generateUUID(); - - registerVariable("DEVICE_NAME", m_name); - registerVariable("DEVICE_ID", 0, "Device ID"); - registerVariable("DEVICE_UUID", m_uuid); - registerVariable("DEVICE_TYPE", "", "Device Type"); - registerVariable("DEVICE_VERSION", "1.0.0", "Device Version"); - registerVariable("DEVICE_MANUFACTURER", "Atom", "Device Manufacturer"); - registerVariable("DEVICE_MODEL", "Atom", "Device Model"); - registerVariable("DEVICE_SERIAL_NUMBER", "00000000", - "Device Serial Number"); - - registerVariable("DEVICE_CONNECTED", false, "Device Connected"); - registerVariable("DEVICE_CONNECTION_STATUS", "Disconnected", - "Device Connection Status"); - - registerFunc("connect", &AtomDriver::Connect, this); - registerFunc("disconnect", &AtomDriver::Disconnect, this); - registerFunc("reconnect", &AtomDriver::Reconnect, this); - registerFunc("isConnected", &AtomDriver::IsConnected, this); - return true; -} - -bool AtomDriver::connect(const json ¶ms) { return true; }; - -bool AtomDriver::disconnect(const json ¶ms) { return true; }; - -bool AtomDriver::reconnect(const json ¶ms) { return true; }; - -bool AtomDriver::isConnected() { return true; } - -json AtomDriver::Connect(const json ¶ms) { - if (!params.contains("name")) { - return {{"command", ""}}; - } - return {}; -} - -json AtomDriver::Disconnect(const json ¶ms) { return {}; } - -json AtomDriver::Reconnect(const json ¶ms) { return {}; } - -json AtomDriver::IsConnected(const json ¶ms) { return {}; } diff --git a/src/atom/driver/device.hpp b/src/atom/driver/device.hpp deleted file mode 100644 index 44460094..00000000 --- a/src/atom/driver/device.hpp +++ /dev/null @@ -1,74 +0,0 @@ -/* - * device.hpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2023-6-1 - -Description: Basic Device Defination - -*************************************************/ - -#ifndef ATOM_DRIVER_HPP -#define ATOM_DRIVER_HPP - -#include -#include -#include -#include - -#if ENABLE_FASTHASH -#include "emhash/hash_table8.hpp" -#else -#include -#endif - -#include "atom/components/templates/shared_component.hpp" - -#include "exception.hpp" - -class AtomDriver : public SharedComponent { -public: - // ------------------------------------------------------------------- - // Common methods - // ------------------------------------------------------------------- - - explicit AtomDriver(const std::string &name); - - virtual ~AtomDriver(); - - virtual bool initialize() override; - - // ------------------------------------------------------------------- - // Driver basic methods - // ------------------------------------------------------------------- - - virtual bool connect(const json ¶ms); - - virtual bool disconnect(const json ¶ms); - - virtual bool reconnect(const json ¶ms); - - virtual bool isConnected(); - - // ------------------------------------------------------------------- - // Driver basic methods vrapper (from command dispatcher) - // ------------------------------------------------------------------- - - json Connect(const json ¶ms); - - json Disconnect(const json ¶ms); - - json Reconnect(const json ¶ms); - - json IsConnected(const json ¶ms); - -private: - std::string m_name; - std::string m_uuid; -}; - -#endif diff --git a/src/atom/driver/device_type.hpp b/src/atom/driver/device_type.hpp deleted file mode 100644 index 3ff314c1..00000000 --- a/src/atom/driver/device_type.hpp +++ /dev/null @@ -1,55 +0,0 @@ -#pragma once - -enum class DeviceType { - Camera, - Telescope, - Focuser, - FilterWheel, - Solver, - Guider, - NumDeviceTypes -}; - -inline const char *DeviceTypeToString(DeviceType type) { - switch (type) { - case DeviceType::Camera: - return "Camera"; - break; - case DeviceType::Telescope: - return "Telescope"; - break; - case DeviceType::Focuser: - return "Focuser"; - break; - case DeviceType::FilterWheel: - return "FilterWheel"; - break; - case DeviceType::Solver: - return "Solver"; - break; - case DeviceType::Guider: - return "Guider"; - break; - default: - return "Unknown"; - break; - } - return "Unknown"; -} - -inline DeviceType StringToDeviceType(const std::string &type) { - if (type == "Camera") - return DeviceType::Camera; - else if (type == "Telescope") - return DeviceType::Telescope; - else if (type == "Focuser") - return DeviceType::Focuser; - else if (type == "FilterWheel") - return DeviceType::FilterWheel; - else if (type == "Solver") - return DeviceType::Solver; - else if (type == "Guider") - return DeviceType::Guider; - else - return DeviceType::NumDeviceTypes; -} \ No newline at end of file diff --git a/src/atom/driver/exception.hpp b/src/atom/driver/exception.hpp deleted file mode 100644 index b6017c3d..00000000 --- a/src/atom/driver/exception.hpp +++ /dev/null @@ -1,71 +0,0 @@ -/* - * exception.hpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2023-6-1 - -Description: Basic Device Exception Defination - -*************************************************/ - -#ifndef ATOM_DRIVER_EXCEPTION_HPP -#define ATOM_DRIVER_EXCEPTION_HPP - -#include -#include - -class InvalidDeviceType : public std::exception { -public: - explicit InvalidDeviceType(const std::string &message) : m_message(message) {} - - const char *what() const noexcept override { return m_message.c_str(); } - -private: - std::string m_message; -}; - -class InvalidParameters : public std::exception { -public: - explicit InvalidParameters(const std::string &message) : m_message(message) {} - - const char *what() const noexcept override { return m_message.c_str(); } - -private: - std::string m_message; -}; - -class InvalidProperty : public std::exception { -public: - explicit InvalidProperty(const std::string &message) : m_message(message) {} - - const char *what() const noexcept override { return m_message.c_str(); } - -private: - std::string m_message; -}; - -class InvalidReturn : public std::exception { -public: - explicit InvalidReturn(const std::string &message) : m_message(message) {} - - const char *what() const noexcept override { return m_message.c_str(); } - -private: - std::string m_message; -}; - -class DispatchError : public std::exception { -public: - explicit DispatchError(const std::string &message) : m_message(message) {} - - const char *what() const noexcept override { return m_message.c_str(); } - -private: - std::string m_message; -}; - -#endif diff --git a/src/atom/driver/filterwheel.cpp b/src/atom/driver/filterwheel.cpp deleted file mode 100644 index 3369062a..00000000 --- a/src/atom/driver/filterwheel.cpp +++ /dev/null @@ -1,31 +0,0 @@ -/* - * filterwheel.cpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2023-3-29 - -Description: Filterwheel Simulator and Basic Definition - -**************************************************/ - -#include "filterwheel.hpp" - -Filterwheel::Filterwheel(const std::string &name) : AtomDriver(name) {} - -Filterwheel::~Filterwheel() {} - -bool Filterwheel::connect(const json ¶ms) { return true; } - -bool Filterwheel::disconnect(const json ¶ms) { return true; } - -bool Filterwheel::reconnect(const json ¶ms) { return true; } - -bool Filterwheel::isConnected() { return true; } - -bool Filterwheel::moveTo(const json ¶ms) { return true; } - -bool Filterwheel::getCurrentPosition(const json ¶ms) { return true; } \ No newline at end of file diff --git a/src/atom/driver/filterwheel.hpp b/src/atom/driver/filterwheel.hpp deleted file mode 100644 index eccc3bcc..00000000 --- a/src/atom/driver/filterwheel.hpp +++ /dev/null @@ -1,35 +0,0 @@ -/* - * filterwheel.hpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2023-6-1 - -Description: Basic FilterWheel Defination - -*************************************************/ - -#pragma once - -#include "device.hpp" - -class Filterwheel : public AtomDriver { -public: - Filterwheel(const std::string &name); - ~Filterwheel(); - - virtual bool connect(const json ¶ms) override; - - virtual bool disconnect(const json ¶ms) override; - - virtual bool reconnect(const json ¶ms) override; - - virtual bool isConnected() override; - - virtual bool moveTo(const json ¶ms); - - virtual bool getCurrentPosition(const json ¶ms); -}; \ No newline at end of file diff --git a/src/atom/driver/focuser.cpp b/src/atom/driver/focuser.cpp deleted file mode 100644 index 5f798aa4..00000000 --- a/src/atom/driver/focuser.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/* - * focuser.cpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2023-3-29 - -Description: Focuser Simulator and Basic Definition - -**************************************************/ - -#include "focuser.hpp" - -Focuser::Focuser(const std::string &name) : AtomDriver(name) {} - -Focuser::~Focuser() {} - -bool Focuser::connect(const json ¶ms) { return true; } - -bool Focuser::disconnect(const json ¶ms) { return true; } - -bool Focuser::reconnect(const json ¶ms) { return true; } - -bool Focuser::isConnected() { return true; } - -bool Focuser::moveTo(const json ¶ms) { return true; } - -bool Focuser::moveToAbsolute(const json ¶ms) { return true; } - -bool Focuser::moveStep(const json ¶ms) { return true; } - -bool Focuser::moveStepAbsolute(const json ¶ms) { return true; } - -bool Focuser::AbortMove(const json ¶ms) { return true; } - -int Focuser::getMaxPosition(const json ¶ms) { return 0; } - -bool Focuser::setMaxPosition(const json ¶ms) { return true; } - -bool Focuser::isGetTemperatureAvailable(const json ¶ms) { return true; } - -double Focuser::getTemperature(const json ¶ms) { return 0.0; } - -bool Focuser::isAbsoluteMoveAvailable(const json ¶ms) { return true; } - -bool Focuser::isManualMoveAvailable(const json ¶ms) { return true; } - -int Focuser::getCurrentPosition(const json ¶ms) { return 0; } - -bool Focuser::haveBacklash(const json ¶ms) { return true; } - -bool Focuser::setBacklash(const json ¶ms) { return true; } \ No newline at end of file diff --git a/src/atom/driver/focuser.hpp b/src/atom/driver/focuser.hpp deleted file mode 100644 index 5c6ee8e5..00000000 --- a/src/atom/driver/focuser.hpp +++ /dev/null @@ -1,144 +0,0 @@ -/* - * focuser.hpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2023-6-1 - -Description: Basic Focuser Defination - -*************************************************/ - -#pragma once - -#include "device.hpp" - -class Focuser : public AtomDriver { -public: - /** - * @brief 构造函数,创建一个名为 name 的电调对象 - * - * @param name 电调名称 - */ - Focuser(const std::string &name); - - /** - * @brief 析构函数,释放资源 - */ - virtual ~Focuser(); - - virtual bool connect(const json ¶ms) override; - - virtual bool disconnect(const json ¶ms) override; - - virtual bool reconnect(const json ¶ms) override; - - virtual bool isConnected() override; - - /** - * @brief 将电调移动到 position 位置 - * - * @param position 相对移动的步数 - * @return bool 移动是否成功 - */ - virtual bool moveTo(const json ¶ms); - - /** - * @brief 将电调移动到绝对位置 position - * - * @param position 绝对位置步数 - * @return bool 移动是否成功 - */ - virtual bool moveToAbsolute(const json ¶ms); - - /** - * @brief 移动电调 step 个步长 - * - * @param step 移动步数 - * @return bool 移动是否成功 - */ - virtual bool moveStep(const json ¶ms); - - /** - * @brief 移动电调至绝对步数位置 - * - * @param step 绝对步数位置 - * @return bool 移动是否成功 - */ - virtual bool moveStepAbsolute(const json ¶ms); - - /** - * @brief 中止电调移动 - * - * @return bool 操作是否成功 - */ - virtual bool AbortMove(const json ¶ms); - - /** - * @brief 获取电调最大位置 - * - * @return int 电调最大位置 - */ - virtual int getMaxPosition(const json ¶ms); - - /** - * @brief 设置电调最大位置 - * - * @param max_position 电调最大位置 - * @return bool 操作是否成功 - */ - virtual bool setMaxPosition(const json ¶ms); - - /** - * @brief 判断是否支持获取温度功能 - * - * @return bool 是否支持获取温度功能 - */ - virtual bool isGetTemperatureAvailable(const json ¶ms); - - /** - * @brief 获取电调当前温度 - * - * @return double 当前温度 - */ - virtual double getTemperature(const json ¶ms); - - /** - * @brief 判断是否支持绝对移动功能 - * - * @return bool 是否支持绝对移动功能 - */ - virtual bool isAbsoluteMoveAvailable(const json ¶ms); - - /** - * @brief 判断是否支持手动移动功能 - * - * @return bool 是否支持手动移动功能 - */ - virtual bool isManualMoveAvailable(const json ¶ms); - - /** - * @brief 获取电调当前位置 - * - * @return int 当前位置 - */ - virtual int getCurrentPosition(const json ¶ms); - - /** - * @brief 判断电调是否存在反向间隙 - * - * @return bool 是否存在反向间隙 - */ - virtual bool haveBacklash(const json ¶ms); - - /** - * @brief 设置电调反向间隙值 - * - * @param value 反向间隙值 - * @return bool 操作是否成功 - */ - virtual bool setBacklash(const json ¶ms); -}; \ No newline at end of file diff --git a/src/atom/driver/guider.cpp b/src/atom/driver/guider.cpp deleted file mode 100644 index 626b72b6..00000000 --- a/src/atom/driver/guider.cpp +++ /dev/null @@ -1,25 +0,0 @@ -/* - * guider.cpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2023-3-29 - -Description: Guider Simulator and Basic Definition - -**************************************************/ - -#include "guider.hpp" - -Guider::Guider(const std::string &name) : AtomDriver(name) {} - -Guider::~Guider() {} - -bool Guider::connect(const nlohmann::json ¶ms) { return true; } - -bool Guider::disconnect(const nlohmann::json ¶ms) { return true; } - -bool Guider::reconnect(const nlohmann::json ¶ms) { return true; } \ No newline at end of file diff --git a/src/atom/driver/guider.hpp b/src/atom/driver/guider.hpp deleted file mode 100644 index 5b90d524..00000000 --- a/src/atom/driver/guider.hpp +++ /dev/null @@ -1,38 +0,0 @@ -/* - * guider.hpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2023-6-1 - -Description: Basic Guider Defination - -*************************************************/ - -#pragma once - -#include "device.hpp" - -class Guider : public AtomDriver { -public: - /** - * @brief 构造函数,创建一个名为 name 的电调对象 - * - * @param name 电调名称 - */ - Guider(const std::string &name); - - /** - * @brief 析构函数,释放资源 - */ - virtual ~Guider(); - - virtual bool connect(const nlohmann::json ¶ms) override; - - virtual bool disconnect(const nlohmann::json ¶ms) override; - - virtual bool reconnect(const nlohmann::json ¶ms) override; -}; \ No newline at end of file diff --git a/src/atom/driver/macro.hpp b/src/atom/driver/macro.hpp deleted file mode 100644 index 199a66cf..00000000 --- a/src/atom/driver/macro.hpp +++ /dev/null @@ -1,21 +0,0 @@ -#define GET_PARAM(type, name) \ - if (!params.contains(#name)) { \ - return false; \ - } \ - type name = params[#name].get(); - -#define TOGGLE_DEBUG(debug) \ - if (debug) { \ - LOG_F(INFO, "Debug mode is enabled"); \ - m_debug.store(true); \ - } else { \ - LOG_F(INFO, "Debug mode is disabled"); \ - m_debug.store(false); \ - } - -#define TOGGLE_TIMEOUT(timeout) \ - if (timeout > 0) { \ - m_timeout.store(timeout); \ - } else { \ - m_timeout.store(30); \ - } \ No newline at end of file diff --git a/src/atom/driver/main.cpp b/src/atom/driver/main.cpp deleted file mode 100644 index 51a43296..00000000 --- a/src/atom/driver/main.cpp +++ /dev/null @@ -1,70 +0,0 @@ -#include "atom/driver/camera.hpp" - -#include - -class MySharedDriver : public AtomCamera { -public: - explicit MySharedDriver(const std::string &name); - virtual ~MySharedDriver(); - - virtual bool initialize() override; - virtual bool destroy() override; - -protected: - json helloWorld(const json ¶ms); -}; - -MySharedDriver::MySharedDriver(const std::string &name) - : AtomCamera(name) { - LOG_F(INFO, "Load {}", name); - - initialize(); - - registerFunc("helloWorld", &MySharedDriver::helloWorld, this); - - registerVariable("var_x", 0, "a test var"); -} - -MySharedDriver::~MySharedDriver() {} - -bool MySharedDriver::initialize() { - AtomCamera::initialize(); - return true; -} - -bool MySharedDriver::destroy() { - Component::destroy(); - return true; -} - -json MySharedDriver::helloWorld(const json ¶ms) { - LOG_F(INFO, "helloWorld with {}", params.dump()); - return {}; -} - -int main() { - std::shared_ptr mycomponent = - std::make_shared("mycomponent"); - mycomponent->runFunc("helloWorld", {{"aaa", "aaaa"}}); - auto myvar = mycomponent->getVariable("var_x"); - std::cout << (myvar.has_value() ? myvar.value() : -1) << std::endl; - mycomponent->setVariable("var_x", 1); - myvar = mycomponent->getVariable("var_x"); - std::cout << (myvar.has_value() ? myvar.value() : -1) << std::endl; - - myvar = mycomponent->getVariable("CCD_TEMPERATURE_VALUE"); - std::cout << (myvar.has_value() ? myvar.value() : -1) << std::endl; - - if (!mycomponent->setVariable("CCD_TEMPERATURE_VALUE", 10.0)) - { - LOG_F(ERROR, "Failed to set temperature"); - } - - mycomponent->runFunc("startExposure", {{"exposure", 100}}); - - mycomponent->runFunc( - "registerVariable", - {{"name", "status"}, {"value", "ok"}, {"description", "a test value"}}); - std::cout << mycomponent->getVariableInfo("status") << std::endl; - return 0; -} \ No newline at end of file diff --git a/src/atom/driver/marco.hpp b/src/atom/driver/marco.hpp deleted file mode 100644 index 5c86a690..00000000 --- a/src/atom/driver/marco.hpp +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef ATOM_DRIVER_MARCO_HPP -#define ATOM_DRIVER_MARCO_HPP - -#define CHECK_PARAM(x) \ - if (!params.contains(x)) { \ - LOG_F(ERROR, "{} {}: Missing {} value", getName(), __func__, x); \ - return createErrorResponse( \ - __func__, \ - {{"error", magic_enum::enum_name(DeviceError::MissingValue)}, \ - {"value", x}}, \ - "Missing value"); \ - } - -#define GET_STR_VARIABLE(x) \ - auto _ #x = getVariable(#x); \ - if (!_ #x.has_value()) { \ - LOG_F(ERROR, "{} {}: Missing {} value", getName(), __func__, #x); \ - return false; \ - } \ - auto x = _ #x.value(); - -#define GET_INT_VARIABLE(x) \ - auto _ #x = getVariable(#x); \ - if (!_ #x.has_value()) { \ - LOG_F(ERROR, "{} {}: Missing {} value", getName(), __func__, #x); \ - return false; \ - } \ - auto x = _ #x.value(); - -#endif \ No newline at end of file diff --git a/src/atom/driver/meson.build b/src/atom/driver/meson.build deleted file mode 100644 index 0e00cc15..00000000 --- a/src/atom/driver/meson.build +++ /dev/null @@ -1,66 +0,0 @@ -project('atom-driver', 'cpp') - -# Set minimum Meson version required -meson_version = '>=0.59.0' - -# Define sources and headers -sources = [ - 'fitskeyword.cpp', - 'device.cpp', - 'camera.cpp', - 'telescope.cpp', - 'focuser.cpp', - 'filterwheel.cpp', - 'guider.cpp', - 'solver.cpp' -] -headers = [ - 'fitskeyword.h', - 'device.hpp', - 'camera.hpp', - 'telescope.hpp', - 'focuser.hpp', - 'filterwheel.hpp', - 'guider.hpp', - 'solver.hpp' -] - -# Check if fmt library is available -has_fmt = find_library('fmt') - -# Create object library -atom_driver_obj = library('atom_driver_obj', - sources + headers, - cpp_std: c_std -) - -# Link with necessary libraries -atom_driver_obj_link_libs = ['atom-component', 'atom-server'] -atom_driver_obj.link_with(atom_driver_obj_link_libs) - -if not has_fmt.found() - atom_driver_obj_link_libs += ['fmt'] -endif - -if host_machine.system() == 'linux' - atom_driver_obj_link_libs += ['uuid'] -endif - -atom_driver_obj.link_with(atom_driver_obj_link_libs) - -# Create shared library -atom_driver_shared = shared_library('atom_driver_shared', atom_driver_obj) - -# Set version properties -version = '1.0.0' # You should define your version here -soversion = '1' - -atom_driver_shared.version = version -atom_driver_shared.soversion = soversion -atom_driver_shared.basename = 'atom-driver' - -# Install target -install_targets(atom_driver_shared) - -# Create executable -shared_driver_test = executable('shared_driver_test', 'main.cpp', link_with : [atom_driver_shared]) diff --git a/src/atom/driver/solver.cpp b/src/atom/driver/solver.cpp deleted file mode 100644 index e1bbfabf..00000000 --- a/src/atom/driver/solver.cpp +++ /dev/null @@ -1,101 +0,0 @@ -/* - * solver.cpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2023-6-1 - -Description: Basic Solver Defination - -*************************************************/ - -#include "solver.hpp" - -#include "macro.hpp" - -Solver::Solver(const std::string &name) - : AtomDriver(name), m_debug(debug), m_imagePath("") { - SetVariable("debug", m_debug); - SetVariable("imagePath", m_imagePath); - SetVariable("solverPath", m_solverPath); - SetVariable("timeout", m_timeout); - SetVariable("target_ra", m_ra); - SetVariable("target_dec", m_dec); - SetVariable("target_az", m_az); - SetVariable("target_alt", m_alt); - SetVariable("radius", m_radius); - SetVariable("downsample", m_downsample); - SetVariable("depth", m_depth); - SetVariable("scale_low", m_scale_low); - SetVariable("scale_high", m_scale_high); - SetVariable("width", m_width); - SetVariable("height", m_height); - SetVariable("scale_units", m_scale_units); - SetVariable("overwrite", m_overwrite); - SetVariable("no_plot", m_no_plot); - SetVariable("verify", m_verify); - SetVariable("resort", m_resort); - SetVariable("continue", m_continue); - SetVariable("no_tweak", m_no_tweak); -} - -Solver::~Solver() {} - -bool Solver::connect(const json ¶ms) { return true; } - -bool Solver::disconnect(const json ¶ms) { return true; } - -bool Solver::reconnect(const json ¶ms) { return true; } - -bool Solver::isConnected() { return true; } - -bool Solver::_solveImage(const json ¶ms) { - GET_PARAM(std::string, image) - GET_PARAM(int, timeout) - GET_PARAM(bool, debug) - - // Check image path - // Max: image must be a fits file. Whether it is a little bit a problem? - if (image.empty() || image.find(".fits") == std::string::npos) { - LOG_F(ERROR, "Failed to execute solveImage: Invalid Parameters"); - return false; - } else { - SetVariable("imagePath", image); - } - - TOGGLE_DEBUG(debug) - TOGGLE_TIMEOUT(timeout) - - if (!solveImage(GetVariable("imagePath").value(), - GetVariable("timeout").value(), - GetVariable("debug").value())) { - LOG_F(ERROR, "Failed to execute solveImage: Solve Failed"); - return false; - } - - return true; -} - -bool Solver::solveImage(const std::string &image, const int &timeout = 30, - const bool &debug = false) {} - -bool Solver::_getSolveParams(const json ¶ms) { return true; } - -bool Solver::getSolveParams() {} - -bool Solver::_getSolveResult(const json ¶ms) { return true; } - -bool Solver::getSolveResult(const int &timeout = 30, - const bool &debug = false) {} - -bool Solver::_getSolveStatus(const json ¶ms) { return true; } - -bool Solver::getSolveStatus(const int &timeout = 30, - const bool &debug = false) {} - -bool Solver::_setSolveParams(const json ¶ms) { return true; } - -bool Solver::setSolveParams(const json ¶ms) {} \ No newline at end of file diff --git a/src/atom/driver/solver.hpp b/src/atom/driver/solver.hpp deleted file mode 100644 index 5de8c152..00000000 --- a/src/atom/driver/solver.hpp +++ /dev/null @@ -1,100 +0,0 @@ -/* - * solver.hpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2023-6-1 - -Description: Basic Solver Defination - -*************************************************/ - -#pragma once - -#include "device.hpp" - -enum class SolveStatus { - Success = 0, - Error = 1, - Timeout = 2, - Invalid = 3, - Unknown = 4, -}; - -struct SolveResult { - std::string ra; - std::string dec; - double fov_x = 0; - double fov_y = 0; - double fov_avg = 0; - double rotation = 0; - - std::string error; -}; - -class Solver : public AtomDriver { -public: - Solver(const std::string &name); - ~Solver(); - - virtual bool connect(const json ¶ms) override; - - virtual bool disconnect(const json ¶ms) override; - - virtual bool reconnect(const json ¶ms) override; - - virtual bool isConnected() override; - -public: - virtual bool _solveImage(const json ¶ms); - - virtual bool solveImage(const std::string &image, const int &timeout, - const bool &debug); - - virtual bool _getSolveResult(const json ¶ms); - - virtual bool getSolveResult(const int &timeout, const bool &debug); - - virtual bool _getSolveStatus(const json ¶ms); - - virtual bool getSolveStatus(const int &timeout, const bool &debug); - - virtual bool _setSolveParams(const json ¶ms); - - virtual bool setSolveParams(const json ¶ms); - - virtual json _getSolveParams(const json ¶ms); - - virtual json getSolveParams(); - -private: - std::atomic_bool m_debug; - std::string m_imagePath; - std::string m_solverPath; - - int m_timeout; - - std::string m_ra; - std::string m_dec; - std::string m_az; - std::string m_alt; - double m_radius; - int m_downsample; - std::vector m_depth; - double m_scale_low; - double m_scale_high; - int m_width; - int m_height; - std::string m_scale_units; - bool m_overwrite; - bool m_no_plot; - bool m_verify; - bool m_resort; - bool m_continue; - bool m_no_tweak; - - SolveStatus m_status; -}; \ No newline at end of file diff --git a/src/atom/driver/telescope.cpp b/src/atom/driver/telescope.cpp deleted file mode 100644 index c646f1f6..00000000 --- a/src/atom/driver/telescope.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/* - * telescope.cpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2023-3-29 - -Description: Telescope Simulator and Basic Definition - -**************************************************/ - -#include "telescope.hpp" - -Telescope::Telescope(const std::string &name) : AtomDriver(name) {} - -Telescope::~Telescope() {} - -bool Telescope::connect(const json ¶ms) { return true; } - -bool Telescope::disconnect(const json ¶ms) { return true; } - -bool Telescope::reconnect(const json ¶ms) { return true; } - -bool Telescope::isConnected() { return true; } - -bool Telescope::SlewTo(const json ¶ms) { return true; } - -bool Telescope::Abort(const json ¶ms) { return true; } - -bool Telescope::isSlewing(const json ¶ms) { return true; } - -std::string Telescope::getCurrentRA(const json ¶ms) { return ""; } - -std::string Telescope::getCurrentDec(const json ¶ms) { return ""; } - -bool Telescope::StartTracking(const json ¶ms) { return true; } - -bool Telescope::StopTracking(const json ¶ms) { return true; } - -bool Telescope::setTrackingMode(const json ¶ms) { return true; } - -bool Telescope::setTrackingSpeed(const json ¶ms) { return true; } - -std::string Telescope::getTrackingMode(const json ¶ms) { return ""; } - -std::string Telescope::getTrackingSpeed(const json ¶ms) { return ""; } - -bool Telescope::Home(const json ¶ms) { return true; } - -bool Telescope::isAtHome(const json ¶ms) { return true; } - -bool Telescope::setHomePosition(const json ¶ms) { return true; } - -bool Telescope::isHomeAvailable(const json ¶ms) { return true; } - -bool Telescope::Park(const json ¶ms) { return true; } - -bool Telescope::Unpark(const json ¶ms) { return true; } - -bool Telescope::isAtPark(const json ¶ms) { return true; } - -bool Telescope::setParkPosition(const json ¶ms) { return true; } - -bool Telescope::isParkAvailable(const json ¶ms) { return true; } diff --git a/src/atom/driver/telescope.hpp b/src/atom/driver/telescope.hpp deleted file mode 100644 index e68ffc04..00000000 --- a/src/atom/driver/telescope.hpp +++ /dev/null @@ -1,167 +0,0 @@ -/* - * telescope.hpp - * - * Copyright (C) 2023-2024 Max Qian - */ - -/************************************************* - -Date: 2023-6-1 - -Description: Basic Telescope Defination - -*************************************************/ - -#pragma once - -#include "device.hpp" - -class Telescope : public AtomDriver { -public: - /** - * @brief 构造函数 - * @param name 望远镜名称 - */ - Telescope(const std::string &name); - - /** - * @brief 析构函数 - */ - virtual ~Telescope(); - - virtual bool connect(const json ¶ms) override; - - virtual bool disconnect(const json ¶ms) override; - - virtual bool reconnect(const json ¶ms) override; - - virtual bool isConnected() override; - -public: - /** - * @brief 指向新目标 - * @param ra 目标赤经 - * @param dec 目标赤纬 - * @param j2000 是否使用J2000坐标系,默认为false,表示使用本地坐标系 - * @return 是否成功指向新目标 - */ - virtual bool SlewTo(const json ¶ms); - - /** - * @brief 中止望远镜的指向 - * @return 是否成功中止指向 - */ - virtual bool Abort(const json ¶ms); - - /** - * @brief 获取望远镜是否在指向新目标 - * @return 返回 true 表示正在指向新目标,否则返回 false - */ - virtual bool isSlewing(const json ¶ms); - - /** - * @brief 获取当前赤经位置 - * @return 当前赤经位置 - */ - virtual std::string getCurrentRA(const json ¶ms); - - /** - * @brief 获取当前赤纬位置 - * @return 当前赤纬位置 - */ - virtual std::string getCurrentDec(const json ¶ms); - - /** - * @brief 开始跟踪运动目标 - * @param model 跟踪模式,包括恒星跟踪、太阳跟踪和月球跟踪 - * @param speed 跟踪速度,默认为1 - * @return 是否成功开始跟踪运动目标 - */ - virtual bool StartTracking(const json ¶ms); - - /** - * @brief 停止跟踪运动目标 - * @return 是否成功停止跟踪运动目标 - */ - virtual bool StopTracking(const json ¶ms); - - /** - * @brief 设置跟踪模式 - * @param mode 跟踪模式,包括恒星跟踪、太阳跟踪和月球跟踪 - * @return 是否成功设置跟踪模式 - */ - virtual bool setTrackingMode(const json ¶ms); - - /** - * @brief 设置跟踪速度 - * @param speed 跟踪速度 - * @return 是否成功设置跟踪速度 - */ - virtual bool setTrackingSpeed(const json ¶ms); - - /** - * @brief 获取当前跟踪模式 - * @return 当前跟踪模式,包括恒星跟踪、太阳跟踪和月球跟踪 - */ - virtual std::string getTrackingMode(const json ¶ms); - - /** - * @brief 获取当前跟踪速度 - * @return 当前跟踪速度 - */ - virtual std::string getTrackingSpeed(const json ¶ms); - - /** - * @brief 将望远镜回到家位置 - * @return 是否成功将望远镜回到家位置 - */ - virtual bool Home(const json ¶ms); - - /** - * @brief 判断望远镜是否在家位置 - * @return 返回 true 表示望远镜在家位置,否则返回 false - */ - virtual bool isAtHome(const json ¶ms); - - /** - * @brief 设置家位置 - * @return 是否成功设置家位置 - */ - virtual bool setHomePosition(const json ¶ms); - - /** - * @brief 获取望远镜是否可以回到家位置 - * @return 返回 true 表示望远镜可以回到家位置,否则返回 false - */ - virtual bool isHomeAvailable(const json ¶ms); - - /** - * @brief 停车 - * @return 是否成功停车 - */ - virtual bool Park(const json ¶ms); - - /** - * @brief 解除停车状态 - * @return 是否成功解除停车状态 - */ - virtual bool Unpark(const json ¶ms); - - /** - * @brief 判断望远镜是否在停车位置 - * @return 返回 true 表示位于停车位置,否则返回 false - */ - virtual bool isAtPark(const json ¶ms); - - /** - * @brief 设置停车位置 - * @return 是否成功设置停车位置 - */ - virtual bool setParkPosition(const json ¶ms); - - /** - * @brief 获取望远镜是否可以停车 - * @return 返回 true 表示望远镜可以停车,否则返回 false - */ - virtual bool isParkAvailable(const json ¶ms); -}; \ No newline at end of file diff --git a/src/atom/components/proxy.hpp b/src/atom/function/proxy.hpp similarity index 58% rename from src/atom/components/proxy.hpp rename to src/atom/function/proxy.hpp index da804b94..edf34bf5 100644 --- a/src/atom/components/proxy.hpp +++ b/src/atom/function/proxy.hpp @@ -12,15 +12,21 @@ Description: Proxy Function Implementation **************************************************/ -#ifndef ATOM_COMPONENT_PROXY_HPP -#define ATOM_COMPONENT_PROXY_HPP +#ifndef ATOM_FUNCTION_PROXY_HPP +#define ATOM_FUNCTION_PROXY_HPP #include +#include #include #include +#include #include +#include #include #include +#include + +#include "atom/error/exception.hpp" template struct ProxyFunction { @@ -31,7 +37,7 @@ struct ProxyFunction { std::any operator()(const std::vector& args) { if (args.size() != N) - throw std::runtime_error("Number of arguments does not match"); + THROW_EXCEPTION("Number of arguments does not match"); return call(args, std::make_index_sequence()); } @@ -60,7 +66,7 @@ struct ProxyFunction { std::any operator()(const std::vector& args) { if (args.size() != N) - throw std::runtime_error("Number of arguments does not match"); + THROW_EXCEPTION("Number of arguments does not match"); return call(args, std::make_index_sequence()); } @@ -89,7 +95,7 @@ struct ProxyFunction { std::any operator()(const std::vector& args) { if (args.size() != N) - throw std::runtime_error("Number of arguments does not match"); + THROW_EXCEPTION("Number of arguments does not match"); return call(args, std::make_index_sequence()); } @@ -109,4 +115,65 @@ struct ProxyFunction { } }; +template +struct TimerProxyFunction; + +template +struct TimerProxyFunction { + std::function func; + static constexpr std::size_t N = sizeof...(Args); + + template + explicit TimerProxyFunction(F&& f) : func(std::forward(f)) {} + + template + explicit TimerProxyFunction(Ret (C::*f)(Args...)) { + func = [f](Args... args) { + C* obj = nullptr; + return (obj->*f)(std::forward(args)...); + }; + } + + template + explicit TimerProxyFunction(Ret (C::*f)(Args...) const) { + func = [f](Args... args) { + const C* obj = nullptr; + return (obj->*f)(std::forward(args)...); + }; + } + + std::any operator()(const std::vector& args, + std::chrono::milliseconds timeout) { + if (args.size() != N) + THROW_EXCEPTION("Number of arguments does not match"); + + std::packaged_task task([this, &args]() { + return call(args, std::make_index_sequence()); + }); + std::future future = task.get_future(); + std::jthread thread(std::move(task)); + + if (future.wait_for(timeout) == std::future_status::timeout) { + thread.request_stop(); + THROW_EXCEPTION("Function execution timed out"); + } + + return future.get(); + } + +private: + template + std::any call(const std::vector& args, + std::index_sequence) { + if constexpr (std::is_void_v) { + std::invoke(func, + std::any_cast>(args[Is])...); + return {}; + } else { + return std::make_any(std::invoke( + func, std::any_cast>(args[Is])...)); + } + } +}; + #endif diff --git a/src/atom/function/stepper.hpp b/src/atom/function/stepper.hpp new file mode 100644 index 00000000..008fe743 --- /dev/null +++ b/src/atom/function/stepper.hpp @@ -0,0 +1,78 @@ +#ifndef ATOM_FUNCTION_STEPPER_HPP +#define ATOM_FUNCTION_STEPPER_HPP + +#include "proxy.hpp" + +#include "atom/error/exception.hpp" + +template +class FunctionChain { +public: + void register_function(std::function func) { + functions.emplace_back(std::move(func)); + } + + std::any run(const std::vector& args) { + try { + std::any result; + for (const auto& func : functions) { + result = ProxyFunction(func)(args); + } + return result; + } catch (const std::exception& e) { + THROW_EXCEPTION("Exception caught"); + } + } + + std::vector run_all(const std::vector& args) { + std::vector results; + try { + for (const auto& func : functions) { + results.emplace_back(ProxyFunction(func)(args)); + } + } catch (const std::exception& e) { + THROW_EXCEPTION("Exception caught"); + } + return results; + } + +private: + std::vector> functions; +}; + +template +class FunctionStepper { +public: + void register_function(std::function func) { + functions.emplace_back(std::move(func)); + } + + std::any run(const std::vector& args) { + try { + std::any result; + for (const auto& func : functions) { + result = ProxyFunction(func)(args); + } + return result; + } catch (const std::exception& e) { + THROW_EXCEPTION("Exception caught"); + } + } + + std::vector run_all(const std::vector& args) { + std::vector results; + try { + for (const auto& func : functions) { + results.emplace_back(ProxyFunction(func)(args)); + } + } catch (const std::exception& e) { + THROW_EXCEPTION("Exception caught"); + } + return results; + } + +private: + std::vector> functions; +}; + +#endif diff --git a/src/atom/driver/fitskeyword.cpp b/src/atom/image/fitskeyword.cpp similarity index 70% rename from src/atom/driver/fitskeyword.cpp rename to src/atom/image/fitskeyword.cpp index 51f9538f..07ad4627 100644 --- a/src/atom/driver/fitskeyword.cpp +++ b/src/atom/image/fitskeyword.cpp @@ -1,24 +1,18 @@ -/** HYDROGEN LIB - * FITS keyword class - * Copyright (C) 2023 Dusan Poizl +/* + * fitskeyword.cpp * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - * USA + * Copyright (C) 2023-2024 Max Qian */ -#include "fitskeyword.h" +/************************************************* + +Date: 2023-3-29 + +Description: FITS Keyword + +**************************************************/ + +#include "fitskeyword.hpp" #include #include diff --git a/src/atom/driver/fitskeyword.h b/src/atom/image/fitskeyword.hpp similarity index 57% rename from src/atom/driver/fitskeyword.h rename to src/atom/image/fitskeyword.hpp index 1e46e03e..25dab282 100644 --- a/src/atom/driver/fitskeyword.h +++ b/src/atom/image/fitskeyword.hpp @@ -1,30 +1,25 @@ -/** HYDROGEN LIB - * FITS keyword class - * Copyright (C) 2023 Dusan Poizl +/* + * fitskeyword.hpp * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - * USA + * Copyright (C) 2023-2024 Max Qian */ -#pragma once +/************************************************* + +Date: 2023-3-29 + +Description: FITS Keyword + +**************************************************/ + +#ifndef ATOM_IMAGE_FITSKEYWORD_HPP +#define ATOM_IMAGE_FITSKEYWORD_HPP #include #include #include -namespace HYDROGEN { +namespace atom::image { class FITSRecord { public: @@ -67,4 +62,6 @@ class FITSRecord { int m_decimal = 6; }; -} // namespace HYDROGEN +} // namespace atom::image + +#endif \ No newline at end of file diff --git a/src/atom/log/logger.cpp b/src/atom/log/logger.cpp index ecbf7730..aa6da18c 100644 --- a/src/atom/log/logger.cpp +++ b/src/atom/log/logger.cpp @@ -27,7 +27,7 @@ Description: Custom Logger Manager #include "atom/log/loguru.hpp" #include "cpp_httplib/httplib.h" -namespace Lithium { +namespace lithium { void LoggerManager::scanLogsFolder(const std::string &folderPath) { for (const auto &entry : std::filesystem::directory_iterator(folderPath)) { DLOG_F(INFO, "Scanning log file: {}", entry.path().generic_string()); @@ -169,4 +169,4 @@ std::string LoggerManager::getMostCommonErrorMessage( } return mostCommonErrorMessage; } -} // namespace Lithium +} // namespace lithium diff --git a/src/atom/log/logger.hpp b/src/atom/log/logger.hpp index 5c530232..fc87404e 100644 --- a/src/atom/log/logger.hpp +++ b/src/atom/log/logger.hpp @@ -19,7 +19,7 @@ Description: Custom Logger Manager #include #include -namespace Lithium { +namespace lithium { struct LogEntry { std::string fileName; int lineNumber; @@ -103,6 +103,6 @@ class LoggerManager { std::vector logEntries; // 存储日志条目的向量 }; -} // namespace Lithium +} // namespace lithium #endif diff --git a/src/atom/server/commander.hpp b/src/atom/server/commander.hpp index 81fbe067..ce6d3450 100644 --- a/src/atom/server/commander.hpp +++ b/src/atom/server/commander.hpp @@ -27,7 +27,7 @@ Description: Commander #include #endif -#include "atom/experiment/decorate.hpp" +#include "atom/function/decorate.hpp" #include "atom/type/noncopyable.hpp" /** diff --git a/src/atom/server/deserialize.cpp b/src/atom/server/deserialize.cpp index d2df5cb9..72558825 100644 --- a/src/atom/server/deserialize.cpp +++ b/src/atom/server/deserialize.cpp @@ -37,7 +37,7 @@ std::optional JsonDeserializer::deserialize( } } -namespace Atom::Server { +namespace atom::server { void DeserializationEngine::addDeserializeEngine( const std::string &name, const std::shared_ptr &DeserializeEngine) { @@ -77,4 +77,4 @@ bool DeserializationEngine::setCurrentDeserializeEngine( name); return false; } -} // namespace Atom::Server \ No newline at end of file +} // namespace atom::server \ No newline at end of file diff --git a/src/atom/server/deserialize.hpp b/src/atom/server/deserialize.hpp index ffa45bf6..aee8ce74 100644 --- a/src/atom/server/deserialize.hpp +++ b/src/atom/server/deserialize.hpp @@ -39,7 +39,7 @@ class JsonDeserializer : public DeserializeEngine { std::optional deserialize(const std::string &data) const override; }; -namespace Atom::Server { +namespace atom::server { /** * @class DeserializationEngine * @brief A class responsible for deserializing data using different @@ -116,6 +116,6 @@ std::optional DeserializationEngine::deserialize( return std::nullopt; } -} // namespace Atom::Server +} // namespace atom::server #endif diff --git a/src/atom/server/json_checker.cpp b/src/atom/server/json_checker.cpp index dc1bd508..7d5284a0 100644 --- a/src/atom/server/json_checker.cpp +++ b/src/atom/server/json_checker.cpp @@ -14,7 +14,7 @@ Description: Json Checker interface implementation #include "json_checker.hpp" -namespace Atom::Server { +namespace atom::server { JsonChecker::JsonChecker() { // 初始化默认规则 addDefaultRule( @@ -42,4 +42,4 @@ void JsonChecker::setFailureCallback( failureCallback_ = std::move(callback); } -} // namespace Atom::Server +} // namespace atom::server diff --git a/src/atom/server/json_checker.hpp b/src/atom/server/json_checker.hpp index 29c87d7e..147317d9 100644 --- a/src/atom/server/json_checker.hpp +++ b/src/atom/server/json_checker.hpp @@ -25,7 +25,7 @@ Description: Json Checker interface implementation using json = nlohmann::json; -namespace Atom::Server +namespace atom::server { /** * @brief Json Checker class. diff --git a/src/atom/server/message_bus.hpp b/src/atom/server/message_bus.hpp index 4b985221..1228a963 100644 --- a/src/atom/server/message_bus.hpp +++ b/src/atom/server/message_bus.hpp @@ -38,7 +38,7 @@ Description: Main Message Bus #include "atom/log/loguru.hpp" -namespace Atom::Server { +namespace atom::server { class MessageBus { public: MessageBus() {} @@ -345,6 +345,6 @@ class MessageBus { GlobalSubscriberList globalSubscribers_; std::shared_mutex globalSubscribersLock_; }; -} // namespace Atom::Server +} // namespace atom::server #endif \ No newline at end of file diff --git a/src/atom/server/message_queue.hpp b/src/atom/server/message_queue.hpp index dfcbd68d..b2fce29b 100644 --- a/src/atom/server/message_queue.hpp +++ b/src/atom/server/message_queue.hpp @@ -32,7 +32,7 @@ Description: A simple message queue (just learn something) #include #endif -namespace Atom::Server { +namespace atom::server { /** * @brief A message queue that allows subscribers to receive messages of type T. * @@ -248,6 +248,6 @@ size_t MessageQueue::getSubscriberCount() const { return m_subscribers.size(); } -} // namespace Atom::Server +} // namespace atom::server #endif \ No newline at end of file diff --git a/src/atom/server/serialize.cpp b/src/atom/server/serialize.cpp index 037eded2..3d915b7d 100644 --- a/src/atom/server/serialize.cpp +++ b/src/atom/server/serialize.cpp @@ -123,7 +123,7 @@ std::string IniSerializationEngine::serialize(const std::any &data, return oss.str(); } -namespace Atom::Server { +namespace atom::server { SerializationEngine::SerializationEngine() { // 添加默认的渲染引擎 auto jsonSerializationEngine = std::make_shared(); @@ -165,7 +165,7 @@ bool SerializationEngine::setCurrentSerializationEngine( name); return false; } -} // namespace Atom::Server +} // namespace atom::server /* diff --git a/src/atom/server/serialize.hpp b/src/atom/server/serialize.hpp index fc6cfcad..2b04d34a 100644 --- a/src/atom/server/serialize.hpp +++ b/src/atom/server/serialize.hpp @@ -85,7 +85,7 @@ class IniSerializationEngine : public Serialization { bool format = false) const override; }; -namespace Atom::Server { +namespace atom::server { /** * @brief 序列化引擎类 * @@ -177,6 +177,6 @@ std::optional SerializationEngine::serialize(const T &data, return std::nullopt; } -} // namespace Atom::Server +} // namespace atom::server #endif diff --git a/src/atom/system/crash_quotes.cpp b/src/atom/system/crash_quotes.cpp index 1faca655..289a412d 100644 --- a/src/atom/system/crash_quotes.cpp +++ b/src/atom/system/crash_quotes.cpp @@ -69,7 +69,7 @@ void QuoteManager::loadQuotesFromFile(const std::string &filename) { file.close(); } } catch (const std::exception &e) { - throw Error::FileUnknown(e.what()); + THROW_EXCEPTION("QuoteManager::loadQuotesFromFile", e.what()); } } diff --git a/src/atom/type/_script.hpp b/src/atom/type/_script.hpp index e9f01210..63e7cc0c 100644 --- a/src/atom/type/_script.hpp +++ b/src/atom/type/_script.hpp @@ -22,6 +22,8 @@ Description: Carbon binding for Atom-Type #include "ini.hpp" #include "small_vector.hpp" +using namespace atom::type; + namespace Atom::_Script::Type { /** * Adds the String Methods to the given Carbon module. diff --git a/src/atom/utils/aes.cpp b/src/atom/utils/aes.cpp index 100f486d..719a0727 100644 --- a/src/atom/utils/aes.cpp +++ b/src/atom/utils/aes.cpp @@ -30,7 +30,7 @@ const int AES_BLOCK_SIZE = 16; namespace atom::utils { std::string encryptAES(std::string_view plaintext, std::string_view key) { EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); - EVP_EncryptInit_ex(ctx, EVP_aes_128_ecb(), nullptr, + EVP_EncryptInit_ex(ctx, EVP_aes_128_gcm(), nullptr, reinterpret_cast(key.data()), nullptr); @@ -56,7 +56,7 @@ std::string encryptAES(std::string_view plaintext, std::string_view key) { std::string decryptAES(std::string_view ciphertext, std::string_view key) { EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); - EVP_DecryptInit_ex(ctx, EVP_aes_128_ecb(), nullptr, + EVP_DecryptInit_ex(ctx, EVP_aes_128_gcm(), nullptr, reinterpret_cast(key.data()), nullptr); diff --git a/src/atom/utils/random.hpp b/src/atom/utils/random.hpp index eb0a9927..58a7ecf5 100644 --- a/src/atom/utils/random.hpp +++ b/src/atom/utils/random.hpp @@ -15,12 +15,14 @@ Description: Simple random number generator #ifndef ATOM_UTILS_RANDOM_HPP #define ATOM_UTILS_RANDOM_HPP +#include +#include #include #include +#include namespace atom::utils { -template > +template class random : public Distribution { using base_t = Distribution; @@ -34,14 +36,35 @@ class random : public Distribution { engine_type engine_; public: - template - random(T &&...args) - : base_t(std::forward(args)...), engine_(std::random_device{}()) {} + random(result_type min, result_type max) + : base_t(min, max), engine_(std::random_device{}()) {} - result_type operator()() { return static_cast(*this)(engine_); } + template + random(Seed&& seed, Args&&... args) + : base_t(std::forward(args)...), + engine_(std::forward(seed)) {} - result_type operator()(const param_type &parm) { - return static_cast(*this)(engine_, parm); + void seed(result_type value = std::random_device{}()) { + engine_.seed(value); + } + + result_type operator()() { + return base_t::operator()(engine_, base_t::param()); + } + + result_type operator()(const param_type& parm) { + return base_t::operator()(engine_, parm); + } + + template + void generate(OutputIt first, OutputIt last) { + std::generate(first, last, *this); + } + + std::vector vector(size_t count) { + std::vector vec(count); + generate(vec.begin(), vec.end()); + return vec; } }; diff --git a/src/atom/utils/ranges.hpp b/src/atom/utils/ranges.hpp index d70955fe..4dd3c58f 100644 --- a/src/atom/utils/ranges.hpp +++ b/src/atom/utils/ranges.hpp @@ -244,4 +244,63 @@ auto accumulate(Range&& range, T init, BinaryOp&& op) { std::forward(op)); } +/** + * @brief Slices a range into a new range. + * + * @tparam Iterator The type of the iterator. + * @param begin The beginning of the range. + * @param end The end of the range. + * @param start The starting index of the slice. + * @param length The length of the slice. + * @return A new range containing the sliced elements. + * + * @usage + * auto sliced_numbers = Slice(numbers.begin(), numbers.end(), 2, 4); + * for (auto x : sliced_numbers) { + * std::cout << x << " "; + * } + * std::cout << std::endl; + */ +template +std::vector Slice(Iterator begin, Iterator end, + size_t start, size_t length) { + std::vector result; + if (start >= std::distance(begin, end)) { + return result; + } + std::advance(begin, start); + auto it = begin; + for (size_t i = 0; i < length && it != end; ++i, ++it) { + result.push_back(*it); + } + return result; +} + +/** + * @brief Slices a container into a new container. + * + * @tparam Container The type of the container. + * @tparam Index The type of the index. + * @param c The input container. + * @param start The starting index of the slice. + * @param end The ending index of the slice. + * @return A new container containing the sliced elements. + * + * @usage + * auto sliced_numbers = slice(numbers, 2, 4); + * for (auto x : sliced_numbers) { + * std::cout << x << " "; + * } + * std::cout << std::endl; + */ +template +auto slice(Container& c, Index start, Index end) { + auto first = std::begin(c) + start; + auto last = (end == std::numeric_limits::max()) + ? std::end(c) + : std::begin(c) + end; + + return std::vector(first, last); +} + #endif \ No newline at end of file diff --git a/src/atom/web/downloader.cpp b/src/atom/web/downloader.cpp index c4c6ff80..bb88b424 100644 --- a/src/atom/web/downloader.cpp +++ b/src/atom/web/downloader.cpp @@ -29,7 +29,7 @@ DownloadManager::DownloadManager(const std::string &task_file) std::ifstream infile(task_file_); if (!infile) { LOG_F(ERROR, "Failed to open task file {}", task_file_); - throw Error::FileNotWritable("Failed to open task file."); + THROW_EXCEPTION("Failed to open task file."); } while (infile >> std::ws && !infile.eof()) { std::string url, filepath; @@ -41,7 +41,7 @@ DownloadManager::DownloadManager(const std::string &task_file) infile.close(); } catch (const std::exception &e) { LOG_F(ERROR, "Error: {}", e.what()); - throw Error::FileUnknown(fmt::format("Error: {}", e.what()).c_str()); + THROW_EXCEPTION(fmt::format("Error: {}", e.what()).c_str()); } } @@ -53,13 +53,13 @@ void DownloadManager::add_task(const std::string &url, std::ofstream outfile(task_file_, std::ios_base::app); if (!outfile) { LOG_F(ERROR, "Failed to open task file {}", task_file_); - throw Error::FileNotWritable("Failed to open task file."); + THROW_EXCEPTION("Failed to open task file."); } outfile << url << " " << filepath << std::endl; outfile.close(); } catch (const std::exception &e) { LOG_F(ERROR, "Error: {}", e.what()); - throw Error::FileUnknown(fmt::format("Error: {}", e.what()).c_str()); + THROW_EXCEPTION(fmt::format("Error: {}", e.what()).c_str()); } tasks_.push_back({url, filepath, false, false, 0, priority}); } @@ -247,7 +247,7 @@ void DownloadManager::save_task_list_to_file() { outfile.close(); } catch (const std::exception &e) { LOG_F(ERROR, "Error: {}", e.what()); - throw Error::FileUnknown(fmt::format("Error: {}", e.what()).c_str()); + THROW_EXCEPTION("Error: ", e.what()); } } } // namespace Atom::Web diff --git a/src/carbon/command/bad_boxed_cast.hpp b/src/carbon/command/bad_boxed_cast.hpp index c417e9e6..0f4e47f0 100644 --- a/src/carbon/command/bad_boxed_cast.hpp +++ b/src/carbon/command/bad_boxed_cast.hpp @@ -7,8 +7,8 @@ #include #include "../defines.hpp" -#include "atom/experiment/sstring.hpp" -#include "atom/experiment/type_info.hpp" +#include "atom/type/static_string.hpp" +#include "atom/function/type_info.hpp" namespace Carbon { namespace exception { diff --git a/src/carbon/command/bootstrap_stl.hpp b/src/carbon/command/bootstrap_stl.hpp index 21b3e383..fa7653b1 100644 --- a/src/carbon/command/bootstrap_stl.hpp +++ b/src/carbon/command/bootstrap_stl.hpp @@ -9,7 +9,7 @@ #include #include -#include "atom/experiment/type_info.hpp" +#include "atom/function/type_info.hpp" #include "bootstrap.hpp" #include "boxed_value.hpp" #include "dispatchkit.hpp" diff --git a/src/carbon/command/boxed_cast.hpp b/src/carbon/command/boxed_cast.hpp index 0957a6f8..d409ff4e 100644 --- a/src/carbon/command/boxed_cast.hpp +++ b/src/carbon/command/boxed_cast.hpp @@ -8,7 +8,7 @@ #include "boxed_cast_helper.hpp" #include "boxed_value.hpp" #include "type_conversions.hpp" -#include "atom/experiment/type_info.hpp" +#include "atom/function/type_info.hpp" namespace Carbon { class Type_Conversions; diff --git a/src/carbon/command/boxed_cast_helper.hpp b/src/carbon/command/boxed_cast_helper.hpp index d8d71736..ef04b35a 100644 --- a/src/carbon/command/boxed_cast_helper.hpp +++ b/src/carbon/command/boxed_cast_helper.hpp @@ -7,7 +7,7 @@ #include #include "boxed_value.hpp" -#include "atom/experiment/type_info.hpp" +#include "atom/function/type_info.hpp" namespace Carbon { class Type_Conversions_State; diff --git a/src/carbon/command/boxed_number.hpp b/src/carbon/command/boxed_number.hpp index 3a4c26a4..f955d466 100644 --- a/src/carbon/command/boxed_number.hpp +++ b/src/carbon/command/boxed_number.hpp @@ -12,7 +12,7 @@ #include "boxed_cast.hpp" #include "boxed_cast_helper.hpp" #include "boxed_value.hpp" -#include "atom/experiment/type_info.hpp" +#include "atom/function/type_info.hpp" namespace Carbon { class Type_Conversions; diff --git a/src/carbon/command/boxed_value.hpp b/src/carbon/command/boxed_value.hpp index bdfbb479..2154154a 100644 --- a/src/carbon/command/boxed_value.hpp +++ b/src/carbon/command/boxed_value.hpp @@ -7,7 +7,7 @@ #include "../defines.hpp" #include "any.hpp" -#include "atom/experiment/type_info.hpp" +#include "atom/function/type_info.hpp" #include "atom/type/pointer.hpp" namespace Carbon { diff --git a/src/carbon/command/dispatchkit.hpp b/src/carbon/command/dispatchkit.hpp index 42a63d24..6478f19f 100644 --- a/src/carbon/command/dispatchkit.hpp +++ b/src/carbon/command/dispatchkit.hpp @@ -18,9 +18,9 @@ #include "../defines.hpp" #include "../threading.hpp" -#include "atom/experiment/flatmap.hpp" -#include "atom/experiment/short_alloc.hpp" -#include "atom/experiment/type_info.hpp" +#include "atom/type/flatmap.hpp" +#include "atom/memory/short_alloc.hpp" +#include "atom/function/type_info.hpp" #include "bad_boxed_cast.hpp" #include "boxed_cast.hpp" #include "boxed_cast_helper.hpp" diff --git a/src/carbon/command/dynamic_object_detail.hpp b/src/carbon/command/dynamic_object_detail.hpp index 7d681bf3..7188dd85 100644 --- a/src/carbon/command/dynamic_object_detail.hpp +++ b/src/carbon/command/dynamic_object_detail.hpp @@ -21,7 +21,7 @@ #include "boxed_value.hpp" #include "dynamic_object.hpp" #include "proxy_functions.hpp" -#include "atom/experiment/type_info.hpp" +#include "atom/function/type_info.hpp" namespace Carbon { class Type_Conversions; diff --git a/src/carbon/command/proxy_functions.cpp b/src/carbon/command/proxy_functions.cpp index e33a61f4..532997da 100644 --- a/src/carbon/command/proxy_functions.cpp +++ b/src/carbon/command/proxy_functions.cpp @@ -12,7 +12,7 @@ #include "proxy_functions.hpp" #include "../defines.hpp" -#include "atom/experiment/type_info.hpp" +#include "atom/function/type_info.hpp" #include "boxed_cast.hpp" #include "boxed_value.hpp" #include "dynamic_object.hpp" diff --git a/src/carbon/command/proxy_functions.hpp b/src/carbon/command/proxy_functions.hpp index d3c5f2aa..3150ed37 100644 --- a/src/carbon/command/proxy_functions.hpp +++ b/src/carbon/command/proxy_functions.hpp @@ -12,7 +12,7 @@ #include #include "../defines.hpp" -#include "atom/experiment/type_info.hpp" +#include "atom/function/type_info.hpp" #include "boxed_cast.hpp" #include "boxed_value.hpp" #include "dynamic_object.hpp" diff --git a/src/carbon/command/proxy_functions_detail.hpp b/src/carbon/command/proxy_functions_detail.hpp index 0b3eca40..b70f0b7a 100644 --- a/src/carbon/command/proxy_functions_detail.hpp +++ b/src/carbon/command/proxy_functions_detail.hpp @@ -13,7 +13,7 @@ #include "boxed_value.hpp" #include "function_params.hpp" #include "handle_return.hpp" -#include "atom/experiment/type_info.hpp" +#include "atom/function/type_info.hpp" namespace Carbon { class Type_Conversions_State; diff --git a/src/carbon/command/register_function.hpp b/src/carbon/command/register_function.hpp index de32bdeb..e0f8f200 100644 --- a/src/carbon/command/register_function.hpp +++ b/src/carbon/command/register_function.hpp @@ -4,7 +4,7 @@ #include -#include "atom/experiment/bind_first.hpp" +#include "atom/function/bind_first.hpp" #include "function_signature.hpp" #include "proxy_functions.hpp" diff --git a/src/carbon/command/type_conversions.hpp b/src/carbon/command/type_conversions.hpp index 9c483429..42bda3f4 100644 --- a/src/carbon/command/type_conversions.hpp +++ b/src/carbon/command/type_conversions.hpp @@ -12,8 +12,8 @@ #include #include "../threading.hpp" -#include "atom/experiment/sstring.hpp" -#include "atom/experiment/type_info.hpp" +#include "atom/type/static_string.hpp" +#include "atom/function/type_info.hpp" #include "bad_boxed_cast.hpp" #include "boxed_cast_helper.hpp" #include "boxed_value.hpp" diff --git a/src/carbon/language/algebraic.hpp b/src/carbon/language/algebraic.hpp index 7c0d5d77..1641a4fd 100644 --- a/src/carbon/language/algebraic.hpp +++ b/src/carbon/language/algebraic.hpp @@ -61,93 +61,93 @@ struct Operators { #pragma warning(disable : 4307) #endif - const auto op_hash = Atom::Algorithm::fnv1a_hash(t_str); + const auto op_hash = atom::algorithm::fnv1a_hash(t_str); switch (op_hash) { - case Atom::Algorithm::fnv1a_hash("=="): { + case atom::algorithm::fnv1a_hash("=="): { return Opers::equals; } - case Atom::Algorithm::fnv1a_hash("<"): { + case atom::algorithm::fnv1a_hash("<"): { return Opers::less_than; } - case Atom::Algorithm::fnv1a_hash(">"): { + case atom::algorithm::fnv1a_hash(">"): { return Opers::greater_than; } - case Atom::Algorithm::fnv1a_hash("<="): { + case atom::algorithm::fnv1a_hash("<="): { return Opers::less_than_equal; } - case Atom::Algorithm::fnv1a_hash(">="): { + case atom::algorithm::fnv1a_hash(">="): { return Opers::greater_than_equal; } - case Atom::Algorithm::fnv1a_hash("!="): { + case atom::algorithm::fnv1a_hash("!="): { return Opers::not_equal; } - case Atom::Algorithm::fnv1a_hash("="): { + case atom::algorithm::fnv1a_hash("="): { return Opers::assign; } - case Atom::Algorithm::fnv1a_hash("++"): { + case atom::algorithm::fnv1a_hash("++"): { return Opers::pre_increment; } - case Atom::Algorithm::fnv1a_hash("--"): { + case atom::algorithm::fnv1a_hash("--"): { return Opers::pre_decrement; } - case Atom::Algorithm::fnv1a_hash("*="): { + case atom::algorithm::fnv1a_hash("*="): { return Opers::assign_product; } - case Atom::Algorithm::fnv1a_hash("+="): { + case atom::algorithm::fnv1a_hash("+="): { return Opers::assign_sum; } - case Atom::Algorithm::fnv1a_hash("-="): { + case atom::algorithm::fnv1a_hash("-="): { return Opers::assign_difference; } - case Atom::Algorithm::fnv1a_hash("&="): { + case atom::algorithm::fnv1a_hash("&="): { return Opers::assign_bitwise_and; } - case Atom::Algorithm::fnv1a_hash("|="): { + case atom::algorithm::fnv1a_hash("|="): { return Opers::assign_bitwise_or; } - case Atom::Algorithm::fnv1a_hash("<<="): { + case atom::algorithm::fnv1a_hash("<<="): { return Opers::assign_shift_left; } - case Atom::Algorithm::fnv1a_hash(">>="): { + case atom::algorithm::fnv1a_hash(">>="): { return Opers::assign_shift_right; } - case Atom::Algorithm::fnv1a_hash("%="): { + case atom::algorithm::fnv1a_hash("%="): { return Opers::assign_remainder; } - case Atom::Algorithm::fnv1a_hash("^="): { + case atom::algorithm::fnv1a_hash("^="): { return Opers::assign_bitwise_xor; } - case Atom::Algorithm::fnv1a_hash("<<"): { + case atom::algorithm::fnv1a_hash("<<"): { return Opers::shift_left; } - case Atom::Algorithm::fnv1a_hash(">>"): { + case atom::algorithm::fnv1a_hash(">>"): { return Opers::shift_right; } - case Atom::Algorithm::fnv1a_hash("%"): { + case atom::algorithm::fnv1a_hash("%"): { return Opers::remainder; } - case Atom::Algorithm::fnv1a_hash("&"): { + case atom::algorithm::fnv1a_hash("&"): { return Opers::bitwise_and; } - case Atom::Algorithm::fnv1a_hash("|"): { + case atom::algorithm::fnv1a_hash("|"): { return Opers::bitwise_or; } - case Atom::Algorithm::fnv1a_hash("^"): { + case atom::algorithm::fnv1a_hash("^"): { return Opers::bitwise_xor; } - case Atom::Algorithm::fnv1a_hash("~"): { + case atom::algorithm::fnv1a_hash("~"): { return Opers::bitwise_complement; } - case Atom::Algorithm::fnv1a_hash("+"): { + case atom::algorithm::fnv1a_hash("+"): { return t_is_unary ? Opers::unary_plus : Opers::sum; } - case Atom::Algorithm::fnv1a_hash("-"): { + case atom::algorithm::fnv1a_hash("-"): { return t_is_unary ? Opers::unary_minus : Opers::difference; } - case Atom::Algorithm::fnv1a_hash("/"): { + case atom::algorithm::fnv1a_hash("/"): { return Opers::quotient; } - case Atom::Algorithm::fnv1a_hash("*"): { + case atom::algorithm::fnv1a_hash("*"): { return Opers::product; } default: { diff --git a/src/carbon/language/common.cpp b/src/carbon/language/common.cpp index 6d47ffdb..7a3363c1 100644 --- a/src/carbon/language/common.cpp +++ b/src/carbon/language/common.cpp @@ -12,7 +12,7 @@ #include "../command/dispatchkit.hpp" #include "../command/proxy_functions.hpp" #include "../defines.hpp" -#include "atom/experiment/type_info.hpp" +#include "atom/function/type_info.hpp" namespace Carbon { Parse_Location::Parse_Location(std::string t_fname, const int t_start_line, diff --git a/src/carbon/language/common.hpp b/src/carbon/language/common.hpp index ad424898..7291e0ea 100644 --- a/src/carbon/language/common.hpp +++ b/src/carbon/language/common.hpp @@ -15,7 +15,7 @@ #include "../command/dispatchkit.hpp" #include "../command/proxy_functions.hpp" #include "../defines.hpp" -#include "atom/experiment/type_info.hpp" +#include "atom/function/type_info.hpp" namespace Carbon { struct AST_Node; @@ -30,32 +30,32 @@ struct Name_Validator { template static bool is_reserved_word(const T &s) noexcept { const static std::unordered_set words{ - Atom::Algorithm::fnv1a_hash("def"), - Atom::Algorithm::fnv1a_hash("fun"), - Atom::Algorithm::fnv1a_hash("while"), - Atom::Algorithm::fnv1a_hash("for"), - Atom::Algorithm::fnv1a_hash("if"), - Atom::Algorithm::fnv1a_hash("else"), - Atom::Algorithm::fnv1a_hash("&&"), - Atom::Algorithm::fnv1a_hash("||"), - Atom::Algorithm::fnv1a_hash(","), - Atom::Algorithm::fnv1a_hash("auto"), - Atom::Algorithm::fnv1a_hash("return"), - Atom::Algorithm::fnv1a_hash("break"), - Atom::Algorithm::fnv1a_hash("true"), - Atom::Algorithm::fnv1a_hash("false"), - Atom::Algorithm::fnv1a_hash("class"), - Atom::Algorithm::fnv1a_hash("attr"), - Atom::Algorithm::fnv1a_hash("var"), - Atom::Algorithm::fnv1a_hash("global"), - Atom::Algorithm::fnv1a_hash("GLOBAL"), - Atom::Algorithm::fnv1a_hash("_"), - Atom::Algorithm::fnv1a_hash("__LINE__"), - Atom::Algorithm::fnv1a_hash("__FILE__"), - Atom::Algorithm::fnv1a_hash("__FUNC__"), - Atom::Algorithm::fnv1a_hash("__CLASS__")}; - - return words.count(Atom::Algorithm::fnv1a_hash(s)) == 1; + atom::algorithm::fnv1a_hash("def"), + atom::algorithm::fnv1a_hash("fun"), + atom::algorithm::fnv1a_hash("while"), + atom::algorithm::fnv1a_hash("for"), + atom::algorithm::fnv1a_hash("if"), + atom::algorithm::fnv1a_hash("else"), + atom::algorithm::fnv1a_hash("&&"), + atom::algorithm::fnv1a_hash("||"), + atom::algorithm::fnv1a_hash(","), + atom::algorithm::fnv1a_hash("auto"), + atom::algorithm::fnv1a_hash("return"), + atom::algorithm::fnv1a_hash("break"), + atom::algorithm::fnv1a_hash("true"), + atom::algorithm::fnv1a_hash("false"), + atom::algorithm::fnv1a_hash("class"), + atom::algorithm::fnv1a_hash("attr"), + atom::algorithm::fnv1a_hash("var"), + atom::algorithm::fnv1a_hash("global"), + atom::algorithm::fnv1a_hash("GLOBAL"), + atom::algorithm::fnv1a_hash("_"), + atom::algorithm::fnv1a_hash("__LINE__"), + atom::algorithm::fnv1a_hash("__FILE__"), + atom::algorithm::fnv1a_hash("__FUNC__"), + atom::algorithm::fnv1a_hash("__CLASS__")}; + + return words.count(atom::algorithm::fnv1a_hash(s)) == 1; } template diff --git a/src/carbon/language/eval.hpp b/src/carbon/language/eval.hpp index 17758a3c..52a8e6be 100644 --- a/src/carbon/language/eval.hpp +++ b/src/carbon/language/eval.hpp @@ -22,7 +22,7 @@ #include "../command/proxy_functions.hpp" #include "../command/proxy_functions_detail.hpp" #include "../command/register_function.hpp" -#include "atom/experiment/type_info.hpp" +#include "atom/function/type_info.hpp" #include "algebraic.hpp" #include "common.hpp" diff --git a/src/carbon/language/parser.hpp b/src/carbon/language/parser.hpp index aaf6e6ed..f395cf9a 100644 --- a/src/carbon/language/parser.hpp +++ b/src/carbon/language/parser.hpp @@ -14,7 +14,7 @@ #include "../command/boxed_value.hpp" #include "atom/algorithm/hash.hpp" -#include "atom/experiment/sstring.hpp" +#include "atom/type/static_string.hpp" #include "common.hpp" #include "optimizer.hpp" #include "tracer.hpp" @@ -1001,7 +1001,7 @@ class Carbon_Parser final : public Carbon_Parser_Base { const auto start = m_position; if (Id_()) { auto text = Position::str(start, m_position); - const auto text_hash = Atom::Algorithm::fnv1a_hash(text); + const auto text_hash = atom::algorithm::fnv1a_hash(text); if (validate) { validate_object_name(text); @@ -1013,43 +1013,43 @@ class Carbon_Parser final : public Carbon_Parser_Base { #endif switch (text_hash) { - case Atom::Algorithm::fnv1a_hash("true"): { + case atom::algorithm::fnv1a_hash("true"): { m_match_stack.push_back( make_node>( text, start.line, start.col, const_var(true))); } break; - case Atom::Algorithm::fnv1a_hash("false"): { + case atom::algorithm::fnv1a_hash("false"): { m_match_stack.push_back( make_node>( text, start.line, start.col, const_var(false))); } break; - case Atom::Algorithm::fnv1a_hash("Infinity"): { + case atom::algorithm::fnv1a_hash("Infinity"): { m_match_stack.push_back( make_node>( text, start.line, start.col, const_var( std::numeric_limits::infinity()))); } break; - case Atom::Algorithm::fnv1a_hash("NaN"): { + case atom::algorithm::fnv1a_hash("NaN"): { m_match_stack.push_back( make_node>( text, start.line, start.col, const_var( std::numeric_limits::quiet_NaN()))); } break; - case Atom::Algorithm::fnv1a_hash("__LINE__"): { + case atom::algorithm::fnv1a_hash("__LINE__"): { m_match_stack.push_back( make_node>( text, start.line, start.col, const_var(start.line))); } break; - case Atom::Algorithm::fnv1a_hash("__FILE__"): { + case atom::algorithm::fnv1a_hash("__FILE__"): { m_match_stack.push_back( make_node>( text, start.line, start.col, const_var(m_filename))); } break; - case Atom::Algorithm::fnv1a_hash("__FUNC__"): { + case atom::algorithm::fnv1a_hash("__FUNC__"): { std::string fun_name = "NOT_IN_FUNCTION"; for (size_t idx = m_match_stack.empty() ? 0 @@ -1067,7 +1067,7 @@ class Carbon_Parser final : public Carbon_Parser_Base { make_node>( text, start.line, start.col, const_var(fun_name))); } break; - case Atom::Algorithm::fnv1a_hash("__CLASS__"): { + case atom::algorithm::fnv1a_hash("__CLASS__"): { std::string fun_name = "NOT_IN_CLASS"; for (size_t idx = m_match_stack.empty() ? 0 @@ -1088,7 +1088,7 @@ class Carbon_Parser final : public Carbon_Parser_Base { std::move(text), start.line, start.col, const_var(fun_name))); } break; - case Atom::Algorithm::fnv1a_hash("_"): { + case atom::algorithm::fnv1a_hash("_"): { m_match_stack.push_back( make_node>( std::move(text), start.line, start.col, diff --git a/src/carbon/utils/json.hpp b/src/carbon/utils/json.hpp index 711fb1d4..d0b6ef3d 100644 --- a/src/carbon/utils/json.hpp +++ b/src/carbon/utils/json.hpp @@ -15,7 +15,7 @@ #include #include #include "../defines.hpp" -#include "atom/experiment/flatmap.hpp" +#include "atom/type/flatmap.hpp" namespace Carbon::json { using std::enable_if; diff --git a/src/config/CMakeLists.txt b/src/config/CMakeLists.txt index 2076c950..9fc1fa15 100644 --- a/src/config/CMakeLists.txt +++ b/src/config/CMakeLists.txt @@ -55,4 +55,13 @@ install(TARGETS ${PROJECT_NAME} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ) +add_executable(${PROJECT_NAME}_TEST _test.cpp) +target_link_libraries(${PROJECT_NAME}_TEST ${PROJECT_NAME}) +if(CMAKE_BUILD_TYPE STREQUAL "Debug") + target_compile_definitions(${PROJECT_NAME}_TEST PRIVATE _DEBUG) +endif() +set_target_properties(${PROJECT_NAME}_TEST PROPERTIES + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR} +) + diff --git a/src/config/_component.cpp b/src/config/_component.cpp index 96a02226..b41545bb 100644 --- a/src/config/_component.cpp +++ b/src/config/_component.cpp @@ -18,174 +18,36 @@ Description: Config Component for Atom Addon #include "atom/log/loguru.hpp" -#define CONFIG_MANAGER_CHECK \ - if (!m_configManager) { \ - LOG_F(ERROR, "ConfigComponent::{}: configManager is nullptr", \ - __func__); \ - return createErrorResponse(__func__, {"error", "key not found"}, \ - "key not found"); \ - } - -#define LITHIUM_CONFIG_KEY_CHECK(key) \ - if (!m_params.contains(key) || !m_params[key].is_string()) { \ - LOG_F(ERROR, "ConfigComponent::{}: {} not found", __func__, key); \ - return createErrorResponse(__func__, \ - {"error", std::string("missing ") + key}, \ - std::string("missing ") + key); \ - } - ConfigComponent::ConfigComponent(const std::string& name) - : SharedComponent(name), - m_configManager(Lithium::ConfigManager::createUnique()) { - DLOG_F(INFO, "ConfigComponent::Constructor"); - - DLOG_F(INFO, "Injecting commands"); - registerFunc("getConfig", &ConfigComponent::getConfig, this); - registerFunc("setConfig", &ConfigComponent::setConfig, this); - registerFunc("deleteConfig", &ConfigComponent::deleteConfig, this); - registerFunc("loadConfig", &ConfigComponent::loadConfig, this); - registerFunc("saveConfig", &ConfigComponent::saveConfig, this); - registerFunc("hasConfig", &ConfigComponent::hasConfig, this); - registerFunc("loadConfigs", &ConfigComponent::loadConfigs, this); + : Component(name), m_configManager(ConfigManager::createShared()) { + LOG_F(INFO, "Config Component Constructed"); + registerCommand("getConfig", &ConfigManager::getValue, m_configManager); + registerCommand("setConfig", &ConfigManager::setValue, m_configManager); + registerCommand("hasConfig", &ConfigManager::hasValue, m_configManager); + registerCommand("deleteConfig", &ConfigManager::deleteValue, + m_configManager); + registerCommand("loadConfig", &ConfigManager::loadFromFile, + m_configManager); + registerCommand("loadConfigs", &ConfigManager::loadFromDir, + m_configManager); + registerCommand("saveConfig", &ConfigManager::saveToFile, m_configManager); + registerCommand("tidyConfig", &ConfigManager::tidyConfig, m_configManager); + registerCommand("clearConfig", &ConfigManager::clearConfig, + m_configManager); + + addVariable("config.instance", m_configManager, "ConfigManager Instance"); } ConfigComponent::~ConfigComponent() { - DLOG_F(INFO, "ConfigComponent::Destructor"); + LOG_F(INFO, "Config Component Destructed"); } bool ConfigComponent::initialize() { - DLOG_F(INFO, "ConfigComponent::initialize"); + LOG_F(INFO, "Config Component Initialized"); return true; } bool ConfigComponent::destroy() { - DLOG_F(INFO, "ConfigComponent::destroy"); + LOG_F(INFO, "Config Component Destroyed"); return true; -} - -json ConfigComponent::getConfig(const json& m_params) { - CONFIG_MANAGER_CHECK; - LITHIUM_CONFIG_KEY_CHECK("key"); - std::string key = m_params["key"].get(); - if (!m_configManager->hasValue(key)) { - LOG_F(ERROR, "ConfigComponent::getConfig: key not found"); - return createErrorResponse("getConfig", {"error", "key not found"}, - "key not found"); - } - if (auto value = m_configManager->getValue(key); value.has_value()) { - return createSuccessResponse("getConfig", {"value", value.value()}); - } - return createErrorResponse( - "getConfig", {"error", {"error", "failed to get config by key"}}, - "failed to get config by key"); -} - -json ConfigComponent::setConfig(const json& m_params) { - CONFIG_MANAGER_CHECK; - if (!m_params.contains("key") || !m_params.contains("value")) { - LOG_F(ERROR, - "ConfigComponent::setConfig: m_params does not contain key"); - return createErrorResponse("setConfig", {"error", "key not set"}, - "key not set"); - } - if (!m_params["key"].is_string() || !m_params["value"].is_primitive()) { - LOG_F(ERROR, - "ConfigComponent::setConfig: m_params is not a string or " - "primitive"); - return createErrorResponse("setConfig", {"error", "key not set"}, - "key not set"); - } - if (!setVariable(m_params["key"].get(), m_params["value"])) { - LOG_F(ERROR, "ConfigComponent::setConfig: setVariable failed"); - return createErrorResponse( - "setConfig", {"error", {"error", "key not set"}}, "key not set"); - } - return createSuccessResponse("setConfig", {}); -} - -json ConfigComponent::deleteConfig(const json& m_params) { - CONFIG_MANAGER_CHECK; - LITHIUM_CONFIG_KEY_CHECK("key"); - try { - if (!m_configManager->deleteValue(m_params["key"].get())) { - LOG_F(ERROR, "ConfigComponent::deleteConfig: deleteValue failed"); - return createErrorResponse(__func__, {"error", "key not set"}, - "key not set"); - } - } catch (const json::exception& e) { - LOG_F(ERROR, "ConfigComponent::deleteConfig: json exception: {}", - e.what()); - return createErrorResponse(__func__, {"error", e.what()}, - "key not set"); - } - return createSuccessResponse(__func__, {}); -} - -json ConfigComponent::hasConfig(const json& m_params) { - CONFIG_MANAGER_CHECK; - LITHIUM_CONFIG_KEY_CHECK("key"); - try { - if (!m_configManager->hasValue(m_params["key"].get())) { - LOG_F(ERROR, "ConfigComponent::hasConfig: hasValue failed"); - return createErrorResponse(__func__, {"error", "key not set"}, - "key not set"); - } - } catch (const json::exception& e) { - LOG_F(ERROR, "ConfigComponent::hasConfig: json exception: {}", - e.what()); - return createErrorResponse(__func__, {"error", e.what()}, - "key not set"); - } - return createSuccessResponse(__func__, {}); -} - -json ConfigComponent::loadConfig(const json& m_params) { - CONFIG_MANAGER_CHECK; - if (!m_params.contains("path") || !m_params["path"].is_string()) { - LOG_F(ERROR, "ConfigComponent::loadConfig: path not set"); - return createErrorResponse("loadConfig", {"error", "path not set"}, - "path not set"); - } - if (!m_configManager->loadFromFile(m_params["path"].get())) { - LOG_F(ERROR, "ConfigComponent::loadConfig: loadFromFile failed"); - return createErrorResponse("loadConfig", {"error", "path not set"}, - "path not set"); - } - return createSuccessResponse("loadConfig", {}); -} - -json ConfigComponent::saveConfig(const json& m_params) { - CONFIG_MANAGER_CHECK; - if (!m_params.contains("path") || !m_params["path"].is_string()) { - LOG_F(ERROR, "ConfigComponent::saveConfig: path not set"); - return createErrorResponse("saveConfig", {"error", "path not set"}, - "path not set"); - } - if (!m_configManager->saveToFile(m_params["path"].get())) { - LOG_F(ERROR, "ConfigComponent::saveConfig: saveToFile failed"); - return createErrorResponse(__func__, {"error", "path not set"}, - "path not set"); - } - return createSuccessResponse(__func__, {}); -} - -json ConfigComponent::loadConfigs(const json& m_params) { - CONFIG_MANAGER_CHECK; - if (!m_params.contains("path") || !m_params["path"].is_string()) { - LOG_F(ERROR, "ConfigComponent::loadConfigs: path not set"); - return createErrorResponse("loadConfigs", {"error", "path not set"}, - "path not set"); - } - if (!m_configManager->loadFromFile(m_params["path"].get())) { - LOG_F(ERROR, "ConfigComponent::loadConfigs: loadFromFile failed"); - return createErrorResponse(__func__, {"error", "path not set"}, - "path not set"); - } - return createSuccessResponse(__func__, {}); -} - -json ConfigComponent::tidyConfig(const json& m_params) { - CONFIG_MANAGER_CHECK; - m_configManager->tidyConfig(); - return createSuccessResponse(__func__, {}); } \ No newline at end of file diff --git a/src/config/_component.hpp b/src/config/_component.hpp index e7242c83..e51e1771 100644 --- a/src/config/_component.hpp +++ b/src/config/_component.hpp @@ -15,40 +15,22 @@ Description: Config Component for Atom Addon #ifndef LITHIUM_CONFIG_COMPONENT_HPP #define LITHIUM_CONFIG_COMPONENT_HPP -#include "atom/components/templates/shared_component.hpp" +#include "atom/components/component.hpp" -namespace Lithium { class ConfigManager; -} -class ConfigComponent : public SharedComponent { -public: - explicit ConfigComponent(const std::string &name); - ~ConfigComponent(); +class ConfigComponent : public Component +{ + public: + explicit ConfigComponent(const std::string& name); + virtual ~ConfigComponent(); - // ------------------------------------------------------------------- - // Common methods - // ------------------------------------------------------------------- + bool initialize() override; + bool destroy() override; - bool initialize() override; - bool destroy() override; + private: - // ------------------------------------------------------------------- - // Config methods - // ------------------------------------------------------------------- - - json getConfig(const json &m_params); - json setConfig(const json &m_params); - json deleteConfig(const json &m_params); - json hasConfig(const json &m_params); - - json loadConfig(const json &m_params); - json loadConfigs(const json &m_params); - json saveConfig(const json &m_params); - json tidyConfig(const json &m_params); - -private: - std::unique_ptr m_configManager; + std::shared_ptr m_configManager; }; #endif diff --git a/src/config/_main.cpp b/src/config/_main.cpp index 1c5ca8c1..7853d17b 100644 --- a/src/config/_main.cpp +++ b/src/config/_main.cpp @@ -14,15 +14,16 @@ Description: Main Entry #include "_component.hpp" +#include "atom/type/json.hpp" +using json = nlohmann::json; + extern "C" { -std::shared_ptr getInstance( - [[maybe_unused]] const json ¶ms) { +std::shared_ptr getInstance([[maybe_unused]] const json ¶ms) { if (params.contains("name") && params["name"].is_string()) { return std::make_shared( params["name"].get()); } return std::make_shared("lithium.config"); } - } \ No newline at end of file diff --git a/src/config/_script.hpp b/src/config/_script.hpp index 788c4fd8..5dc53a74 100644 --- a/src/config/_script.hpp +++ b/src/config/_script.hpp @@ -22,7 +22,7 @@ Description: Carbon Binding of ConfigManager #include "atom/log/loguru.hpp" #include "atom/server/global_ptr.hpp" -namespace Lithium::_Script::Config { +namespace lithium::_Script::Config { /** * Adds the String Methods to the given Carbon m. */ @@ -185,6 +185,6 @@ Carbon::ModulePtr bootstrap( return nullptr; } } -} // namespace Lithium::_Script::Config +} // namespace lithium::_Script::Config #endif diff --git a/src/config/_test.cpp b/src/config/_test.cpp new file mode 100644 index 00000000..878ca12d --- /dev/null +++ b/src/config/_test.cpp @@ -0,0 +1,33 @@ +/* + * _test.cpp + * + * Copyright (C) 2023-2024 Max Qian + */ + +/************************************************* + +Date: 2024-4-13 + +Description: Test Script + +**************************************************/ + +#include "_component.hpp" + +#include "atom/type/json.hpp" +using json = nlohmann::json; + +int main(int argc, char* argv[]) { + auto config = std::make_shared("lithium.config"); + json test_value = {{"key", "value"}}; + auto result = + config->dispatch("getConfig", std::string("config/server/host")); + try { + std::cout << std::any_cast>(result).value().dump() + << std::endl; + } catch (const std::bad_any_cast& e) { + std::cout << "Error: " << e.what() << std::endl; + } + std::cout << "Hello, World!" << std::endl; + return 0; +} \ No newline at end of file diff --git a/src/config/configor.cpp b/src/config/configor.cpp index d2ca6a15..15111329 100644 --- a/src/config/configor.cpp +++ b/src/config/configor.cpp @@ -29,6 +29,8 @@ Description: Configor namespace fs = std::filesystem; +namespace lithium { + class ConfigManagerImpl { public: mutable std::shared_mutex rw_mutex_; @@ -69,11 +71,11 @@ bool ConfigManager::loadFromFile(const fs::path& path) { mergeConfig(j); return true; } catch (const json::exception& e) { - LOG_F(ERROR, "Failed to parse file: {}, error message: {}", path.string(), - e.what()); + LOG_F(ERROR, "Failed to parse file: {}, error message: {}", + path.string(), e.what()); } catch (const std::exception& e) { - LOG_F(ERROR, "Failed to load config file: {}, error message: {}", path.string(), - e.what()); + LOG_F(ERROR, "Failed to load config file: {}, error message: {}", + path.string(), e.what()); } return false; } @@ -207,3 +209,4 @@ void ConfigManager::mergeConfig(const json& src) { void ConfigManager::clearConfig() { m_impl->config_.clear(); } +} // namespace lithium \ No newline at end of file diff --git a/src/config/configor.hpp b/src/config/configor.hpp index 2d008e64..2ec7b802 100644 --- a/src/config/configor.hpp +++ b/src/config/configor.hpp @@ -60,8 +60,8 @@ using json = nlohmann::json; .value() \ .get() +namespace lithium { class ConfigManagerImpl; - class ConfigManager { public: /** @@ -195,5 +195,6 @@ class ConfigManager { */ void mergeConfig(const json& j); }; +} // namespace lithium #endif diff --git a/src/debug/terminal.cpp b/src/debug/terminal.cpp index ff1d06a2..92a2aeeb 100644 --- a/src/debug/terminal.cpp +++ b/src/debug/terminal.cpp @@ -19,7 +19,7 @@ Description: Terminal namespace fs = std::filesystem; -namespace Lithium::Terminal { +namespace lithium::Terminal { ConsoleTerminal::ConsoleTerminal() { #ifdef _WIN32 @@ -188,4 +188,4 @@ void ConsoleTerminal::clearConsole() { #endif } -} // namespace Lithium::Terminal +} // namespace lithium::Terminal diff --git a/src/debug/terminal.hpp b/src/debug/terminal.hpp index ce7e6cbb..d4db5457 100644 --- a/src/debug/terminal.hpp +++ b/src/debug/terminal.hpp @@ -18,7 +18,7 @@ #include #endif -namespace Lithium::Terminal { +namespace lithium::Terminal { class ConsoleTerminal { public: using CommandFunction = @@ -78,6 +78,6 @@ class ConsoleTerminal { void clearConsole(); }; -} // namespace Lithium::Terminal +} // namespace lithium::Terminal #endif diff --git a/src/device/manager.cpp b/src/device/manager.cpp index b93fe20c..e65cfd0e 100644 --- a/src/device/manager.cpp +++ b/src/device/manager.cpp @@ -37,11 +37,11 @@ Description: Device Manager #include "atom/log/loguru.hpp" #include "magic_enum/magic_enum.hpp" -namespace Lithium { +namespace lithium { // Constructor DeviceManager::DeviceManager( - std::shared_ptr messageBus, + std::shared_ptr messageBus, std::shared_ptr configManager) { m_ModuleLoader = ModuleLoader::createShared("drivers"); m_ConfigManager = configManager; @@ -64,13 +64,13 @@ DeviceManager::~DeviceManager() { } std::shared_ptr DeviceManager::createShared( - std::shared_ptr messageBus, + std::shared_ptr messageBus, std::shared_ptr configManager) { return std::make_shared(messageBus, configManager); } std::unique_ptr DeviceManager::createUnique( - std::shared_ptr messageBus, + std::shared_ptr messageBus, std::shared_ptr configManager) { return std::make_unique(messageBus, configManager); } @@ -602,4 +602,4 @@ bool DeviceManager::stopHydrogenDriver(const json &m_params) { #endif return true; } -} // namespace Lithium +} // namespace lithium diff --git a/src/device/manager.hpp b/src/device/manager.hpp index a79a8377..15a978fa 100644 --- a/src/device/manager.hpp +++ b/src/device/manager.hpp @@ -42,7 +42,7 @@ class Solver; using json = nlohmann::json; -namespace Lithium { +namespace lithium { /** * @class DeviceManager * @brief 设备管理器类,用于管理各种设备对象。 @@ -54,7 +54,7 @@ class DeviceManager { * @param messageBus 消息总线对象的共享指针。 * @param configManager 配置管理器对象的共享指针。 */ - explicit DeviceManager(std::shared_ptr messageBus, + explicit DeviceManager(std::shared_ptr messageBus, std::shared_ptr configManager); /** @@ -73,11 +73,11 @@ class DeviceManager { * @return 返回一个指向设备管理器对象的共享指针。 */ static std::shared_ptr createShared( - std::shared_ptr messageBus, + std::shared_ptr messageBus, std::shared_ptr configManager); static std::unique_ptr createUnique( - std::shared_ptr messageBus, + std::shared_ptr messageBus, std::shared_ptr configManager); // ------------------------------------------------------------------- @@ -224,7 +224,7 @@ class DeviceManager { std::shared_ptr m_ModuleLoader; ///< 模块加载器对象的共享指针。 - std::shared_ptr + std::shared_ptr m_MessageBus; ///< 消息总线对象的共享指针。 std::shared_ptr m_ConfigManager; ///< 配置管理器对象的共享指针。 @@ -257,4 +257,4 @@ class DeviceManager { #endif }; -} // namespace Lithium \ No newline at end of file +} // namespace lithium \ No newline at end of file diff --git a/src/device/protector.cpp b/src/device/protector.cpp index 93c2afa6..bfb98f9b 100644 --- a/src/device/protector.cpp +++ b/src/device/protector.cpp @@ -34,7 +34,7 @@ directories and taking action upon changes. #include "atom/log/loguru.hpp" -namespace Lithium { +namespace lithium { /** * @class LicenseProtectorImpl * @brief 实现文件或目录监控的具体逻辑。 @@ -306,4 +306,4 @@ void LicenseProtector::startMonitoring() { pImpl->startMonitoring(); } void LicenseProtector::stopMonitoring() { pImpl->stopMonitoring(); } -} // namespace Lithium +} // namespace lithium diff --git a/src/device/protector.hpp b/src/device/protector.hpp index e65d3172..19eed34b 100644 --- a/src/device/protector.hpp +++ b/src/device/protector.hpp @@ -17,7 +17,7 @@ directories and taking action upon changes. #include -namespace Lithium { +namespace lithium { class LicenseProtectorImpl; // 前向声明实现类 Forward declaration of the // implementation class @@ -74,4 +74,4 @@ class LicenseProtector { pImpl; ///< 指向具体实现的指针。Pointer to the implementation. }; -} // namespace Lithium +} // namespace lithium diff --git a/src/device/server/hydrogen.cpp b/src/device/server/hydrogen.cpp index 75368f94..5d293d59 100644 --- a/src/device/server/hydrogen.cpp +++ b/src/device/server/hydrogen.cpp @@ -28,7 +28,7 @@ Description: Hydrogen Device Manager #include "atom/log/loguru.hpp" #include "atom/system/system.hpp" -namespace Lithium { +namespace lithium { HydrogenManager::HydrogenManager(const std::string &hst, int prt, const std::string &cfg, const std::string &dta, const std::string &fif) { @@ -53,16 +53,6 @@ std::unique_ptr HydrogenManager::createUnique( return std::make_unique(hst, prt, cfg, dta, fif); } -std::vector>> HydrogenManager::getFunctions() -{ - std::vector>> functions; - //auto startServer = make_decorator(std::function( - // &HydrogenManager::_startServer - //)); - //functions.push_back(startServer); - return functions; -} - json HydrogenManager::_startServer(const json ¶ms) { if (!isInstalled()) { @@ -96,7 +86,7 @@ bool HydrogenManager::startServer() { stopServer(); } DLOG_F(INFO, "Deleting fifo pipe at: {}", fifo_path); - if (!Atom::IO::removeFile(fifo_path)) { + if (!atom::io::removeFile(fifo_path)) { LOG_F(ERROR, "Failed to delete fifo pipe at: {}", fifo_path); return false; } @@ -130,7 +120,7 @@ bool HydrogenManager::startServer() { } // Clear old fifo pipe and create new one DLOG_F(INFO, "Deleting fifo pipe at: {}", fifo_path); - if (!Atom::IO::removeFile(fifo_path)) { + if (!atom::io::removeFile(fifo_path)) { LOG_F(ERROR, "Failed to delete fifo pipe at: {}", fifo_path); return false; } @@ -386,4 +376,4 @@ HydrogenManager::getDevices() } return devices; } -} // namespace Lithium +} // namespace lithium diff --git a/src/device/server/hydrogen.hpp b/src/device/server/hydrogen.hpp index a1380854..a7b67aa9 100644 --- a/src/device/server/hydrogen.hpp +++ b/src/device/server/hydrogen.hpp @@ -28,9 +28,8 @@ Description: Hydrogen Device Manager #include #endif #include "hydrogen_driver.hpp" -#include "atom/experiment/decorate.hpp" -namespace Lithium { +namespace lithium { class HydrogenManager : public BasicManager { public: @@ -59,8 +58,6 @@ class HydrogenManager : public BasicManager { const std::string &dta = "/usr/share/hydrogen", const std::string &fif = "/tmp/hydrogenFIFO"); - std::vector>> getFunctions(); - /** * @brief 启动Hydrogen服务器 */ @@ -165,6 +162,6 @@ class HydrogenManager : public BasicManager { running_drivers; ///< 正在运行的驱动程序列表 #endif }; -} // namespace Lithium +} // namespace lithium #endif diff --git a/src/device/utils/utils.cpp b/src/device/utils/utils.cpp index 07104ff7..e17ebf84 100644 --- a/src/device/utils/utils.cpp +++ b/src/device/utils/utils.cpp @@ -32,7 +32,7 @@ Description: Device Utilities #include "atom/log/loguru.hpp" -namespace Lithium +namespace lithium { #ifdef _WIN32 diff --git a/src/device/utils/utils.hpp b/src/device/utils/utils.hpp index 9a9015a9..7c254fce 100644 --- a/src/device/utils/utils.hpp +++ b/src/device/utils/utils.hpp @@ -16,7 +16,7 @@ Description: Device Utilities #include -namespace Lithium +namespace lithium { /** * @brief Execute a command and return the output. diff --git a/src/preload.cpp b/src/preload.cpp index 3ddcf370..1427d295 100644 --- a/src/preload.cpp +++ b/src/preload.cpp @@ -13,7 +13,7 @@ bool checkResources() { for (auto &[key, value] : resource::LITHIUM_RESOURCES) { - if (!Atom::IO::isFileExists(key.data())) { + if (!atom::io::isFileExists(key.data())) { LOG_F(ERROR, "Resource file '{}' is missing.", key); return false; } diff --git a/src/script/carbon.cpp b/src/script/carbon.cpp index 1a3f1bc7..b18b9214 100644 --- a/src/script/carbon.cpp +++ b/src/script/carbon.cpp @@ -14,17 +14,17 @@ #include "config/_script.hpp" #include "atom/async/pool.hpp" -#include "atom/experiment/noncopyable.hpp" +#include "atom/type/noncopyable.hpp" #include "atom/log/loguru.hpp" -namespace Lithium { +namespace lithium { // Pimpl implementation class CarbonScriptImpl : public NonCopyable { public: explicit CarbonScriptImpl(const fs::path &script_dir = "./script", int cache_expiry_seconds = 60) : m_carbon(std::make_unique()) { - if (!Atom::IO::isFolderExists(script_dir)) { + if (!atom::io::isFolderExists(script_dir)) { throw std::runtime_error("Script directory does not exist: " + script_dir_.string()); } @@ -46,7 +46,7 @@ class CarbonScriptImpl : public NonCopyable { m_carbon->add(Atom::_Script::System::bootstrap()); m_carbon->add(Atom::_Script::Type::bootstrap()); - m_carbon->add(Lithium::_Script::Config::bootstrap()); + m_carbon->add(lithium::_Script::Config::bootstrap()); // Add additional sub-modules if needed } @@ -108,7 +108,7 @@ class CarbonScriptImpl : public NonCopyable { void cacheScript(const std::string &script_name) { auto script_path = script_dir_ / (script_name + ".li"); - if (!Atom::IO::isFileExists(script_path)) { + if (!atom::io::isFileExists(script_path)) { LOG_F(ERROR, "Script not found: {}", script_name); return; } @@ -180,4 +180,4 @@ bool CarbonScript::RunScript(const std::string &filename) { return impl_->RunScript(filename); } -} // namespace Lithium +} // namespace lithium diff --git a/src/script/carbon.hpp b/src/script/carbon.hpp index 09d6ae9a..f6603361 100644 --- a/src/script/carbon.hpp +++ b/src/script/carbon.hpp @@ -6,7 +6,7 @@ #include -namespace Lithium { +namespace lithium { class CarbonScriptImpl; class CarbonScript { @@ -29,4 +29,4 @@ class CarbonScript { std::unique_ptr impl_; }; -} // namespace Lithium +} // namespace lithium diff --git a/src/script/custom/config.cpp b/src/script/custom/config.cpp index 086b9c29..41a57bc2 100644 --- a/src/script/custom/config.cpp +++ b/src/script/custom/config.cpp @@ -23,11 +23,11 @@ using namespace pkpy; using json = nlohmann::json; -namespace Lithium { +namespace lithium { template pkpy::PyObject *get_config(pkpy::VM *vm, pkpy::Str &key, const std::string &log_type) { - json value = GetPtr("lithium.config") + json value = GetPtr("lithium.config") .value() ->getValue(key.str()) .value(); @@ -41,7 +41,7 @@ pkpy::PyObject *get_config(pkpy::VM *vm, pkpy::Str &key, template pkpy::PyObject *set_config(pkpy::VM *vm, pkpy::Str &key, T value) { - return pkpy::py_var(vm, GetPtr("lithium.config") + return pkpy::py_var(vm, GetPtr("lithium.config") .value() ->setValue(key.str(), value)); } @@ -132,7 +132,7 @@ void addConfigModule(VM *vm) { pkpy::PyObject *key_obj = args[0]; pkpy::Str &key = pkpy::py_cast(vm, key_obj); return pkpy::py_var( - vm, GetPtr("lithium.config") + vm, GetPtr("lithium.config") .value() ->deleteValue(key.str())); }); @@ -143,7 +143,7 @@ void addConfigModule(VM *vm) { pkpy::PyObject *path_obj = args[0]; pkpy::Str &path = pkpy::py_cast(vm, path_obj); return pkpy::py_var( - vm, GetPtr("lithium.config") + vm, GetPtr("lithium.config") .value() ->saveToFile(path.str().empty() ? "config/config.json" : path.str())); @@ -156,10 +156,10 @@ void addConfigModule(VM *vm) { pkpy::PyObject *path_obj = args[0]; pkpy::Str &path = pkpy::py_cast(vm, path_obj); return pkpy::py_var( - vm, GetPtr("lithium.config") + vm, GetPtr("lithium.config") .value() ->loadFromFile(path.str().empty() ? "config/config.json" : path.str())); }); } -} // namespace Lithium +} // namespace lithium diff --git a/src/script/custom/os.cpp b/src/script/custom/os.cpp index a35a690c..f869b1d8 100644 --- a/src/script/custom/os.cpp +++ b/src/script/custom/os.cpp @@ -22,7 +22,7 @@ Description: OS module for PocketPy(builtin) using namespace pkpy; -namespace Lithium { +namespace lithium { void addOSModule(VM* vm) { PyObject* mod = vm->new_module("li_os"); vm->setattr(mod, "version", VAR("1.0.0")); @@ -34,7 +34,7 @@ void addOSModule(VM* vm) { } else { sv = CAST(Str&, args[0]).sv(); } - if (!Atom::IO::isFolderExists(std::string(sv))) { + if (!atom::io::isFolderExists(std::string(sv))) { LOG_F(ERROR, "Folder is not existing: {}", sv); return vm->None; } @@ -49,4 +49,4 @@ void addOSModule(VM* vm) { return vm->py_json(args[0]); }); } -} // namespace Lithium +} // namespace lithium diff --git a/src/script/custom/sys.cpp b/src/script/custom/sys.cpp index d334e46e..7b5a37f3 100644 --- a/src/script/custom/sys.cpp +++ b/src/script/custom/sys.cpp @@ -26,7 +26,7 @@ using namespace pkpy; #include "atom/log/loguru.hpp" -namespace Lithium { +namespace lithium { /* struct Wrapped_Process { @@ -332,4 +332,4 @@ void addSysModule(VM *vm) { return py_var(vm, std::move(d)); }); } -} // namespace Lithium +} // namespace lithium diff --git a/src/script/manager.cpp b/src/script/manager.cpp index c50d32f7..aa9511fb 100644 --- a/src/script/manager.cpp +++ b/src/script/manager.cpp @@ -23,7 +23,7 @@ using namespace pkpy; #include "atom/io/io.hpp" -namespace Lithium { +namespace lithium { class PyManagerImpl { public: PyManagerImpl() : vm(new VM()) {} @@ -36,4 +36,4 @@ PyScriptManager::PyScriptManager(/* args */) PyScriptManager::~PyScriptManager() { } -} // namespace Lithium +} // namespace lithium diff --git a/src/script/manager.hpp b/src/script/manager.hpp index 6ffc539c..df541513 100644 --- a/src/script/manager.hpp +++ b/src/script/manager.hpp @@ -19,7 +19,7 @@ Description: Lithium Python scripting engine #include "config/configor.hpp" -namespace Lithium { +namespace lithium { class PyManagerImpl; @@ -32,6 +32,6 @@ class PyScriptManager { std::unique_ptr m_impl; }; -} // namespace Lithium +} // namespace lithium #endif diff --git a/src/script/sheller.cpp b/src/script/sheller.cpp index c9b997e2..cff81d90 100644 --- a/src/script/sheller.cpp +++ b/src/script/sheller.cpp @@ -26,7 +26,7 @@ const std::string SHELL_COMMAND = "sh -c"; #include "atom/log/loguru.hpp" -namespace Lithium { +namespace lithium { void ScriptManager::RegisterScript(const std::string &name, const Script &script) { if (scripts.find(name) != scripts.end()) { @@ -208,4 +208,4 @@ void ScriptManager::LogError(const std::string &message) { #if ENABLE_PEGTL #endif -} // namespace Lithium +} // namespace lithium diff --git a/src/script/sheller.hpp b/src/script/sheller.hpp index 6d0d7e87..1ad9e65b 100644 --- a/src/script/sheller.hpp +++ b/src/script/sheller.hpp @@ -34,7 +34,7 @@ using ScriptMap = emhash8::HashMap; using ScriptMap = std::unordered_map; #endif -namespace Lithium { +namespace lithium { /** * @brief Manages the registration, execution, and monitoring of scripts. */ @@ -123,4 +123,4 @@ class ScriptManager { private: std::shared_mutex m_sharedMutex; }; -} // namespace Lithium +} // namespace lithium diff --git a/src/server/Runner.cpp b/src/server/Runner.cpp index 4990ec34..71799bb8 100644 --- a/src/server/Runner.cpp +++ b/src/server/Runner.cpp @@ -17,8 +17,8 @@ Description: Lithium Server Runner #include "ErrorHandler.hpp" #include "controller/AsyncClientController.hpp" -#include "controller/AsyncConfigController.hpp" -#include "controller/AsyncDeviceController.hpp" +//#include "controller/AsyncConfigController.hpp" +//#include "controller/AsyncDeviceController.hpp" #include "controller/AsyncIOController.hpp" #include "controller/AsyncStaticController.hpp" #include "controller/AsyncSystemController.hpp" @@ -124,8 +124,8 @@ Runner::Runner(const oatpp::Object& config, oatpp::web::server::api::Endpoints docEndpoints; ADD_CONTROLLER(ClientController, hostServer); - ADD_CONTROLLER(ConfigController, hostServer); - ADD_CONTROLLER(DeviceController, hostServer); + //ADD_CONTROLLER(ConfigController, hostServer); + //ADD_CONTROLLER(DeviceController, hostServer); ADD_CONTROLLER(IOController, hostServer); ADD_CONTROLLER(StaticController, hostServer); ADD_CONTROLLER(SystemController, hostServer); diff --git a/src/server/controller/AsyncConfigController.hpp b/src/server/controller/AsyncConfigController.hpp index 19ca78c8..5dfaa6ba 100644 --- a/src/server/controller/AsyncConfigController.hpp +++ b/src/server/controller/AsyncConfigController.hpp @@ -30,11 +30,11 @@ Description: Async Config Controller class ConfigController : public oatpp::web::server::api::ApiController { public: - static std::weak_ptr m_configManager; + static std::weak_ptr m_configManager; ConfigController(const std::shared_ptr& objectMapper) : oatpp::web::server::api::ApiController(objectMapper) { - m_configManager = GetWeakPtr("lithium.config"); + m_configManager = GetWeakPtr("lithium.config"); } // ---------------------------------------------------------------- @@ -268,7 +268,7 @@ class ConfigController : public oatpp::web::server::api::ApiController { }; }; -std::weak_ptr ConfigController::m_configManager = {}; +std::weak_ptr ConfigController::m_configManager = {}; #include OATPP_CODEGEN_END(ApiController) //<- End Codegen diff --git a/src/server/controller/AsyncDeviceController.hpp b/src/server/controller/AsyncDeviceController.hpp index 4131f856..920cb11e 100644 --- a/src/server/controller/AsyncDeviceController.hpp +++ b/src/server/controller/AsyncDeviceController.hpp @@ -23,7 +23,59 @@ Description: Device Routes #include "data/DeviceDto.hpp" #include "data/IODto.hpp" -#include "atom/driver/device_type.hpp" +enum class DeviceType { + Camera, + Telescope, + Focuser, + FilterWheel, + Solver, + Guider, + NumDeviceTypes +}; + +inline const char* DeviceTypeToString(DeviceType type) { + switch (type) { + case DeviceType::Camera: + return "Camera"; + break; + case DeviceType::Telescope: + return "Telescope"; + break; + case DeviceType::Focuser: + return "Focuser"; + break; + case DeviceType::FilterWheel: + return "FilterWheel"; + break; + case DeviceType::Solver: + return "Solver"; + break; + case DeviceType::Guider: + return "Guider"; + break; + default: + return "Unknown"; + break; + } + return "Unknown"; +} + +inline DeviceType StringToDeviceType(const std::string& type) { + if (type == "Camera") + return DeviceType::Camera; + else if (type == "Telescope") + return DeviceType::Telescope; + else if (type == "Focuser") + return DeviceType::Focuser; + else if (type == "FilterWheel") + return DeviceType::FilterWheel; + else if (type == "Solver") + return DeviceType::Solver; + else if (type == "Guider") + return DeviceType::Guider; + else + return DeviceType::NumDeviceTypes; +} #include "magic_enum/magic_enum.hpp" @@ -55,406 +107,434 @@ class DeviceController : public oatpp::web::server::api::ApiController { "application/json"); } ENDPOINT_ASYNC("GET", "/api/device/add_device_library", - getUIAddDeviceLibrary){ - ENDPOINT_ASYNC_INIT(getUIAddDeviceLibrary) Action act() override{ + getUIAddDeviceLibrary) { + ENDPOINT_ASYNC_INIT(getUIAddDeviceLibrary); + Action act() override { return request ->readBodyToDtoAsync>( controller->getDefaultObjectMapper()) .callbackTo(&getUIAddDeviceLibrary::returnResponse); -} + } -Action -returnResponse(const oatpp::Object& body) { - auto res = StatusDto::createShared(); - if (body->library_path.getValue("") == "" || - body->library_name.getValue("") == "") { - res->error = "Invalid Parameters"; - res->message = "Device library path and name is required"; - } else { - auto library_path = body->library_path.getValue(""); - auto library_name = body->library_name.getValue(""); - if (!Lithium::MyApp->addDeviceLibrary( - {{"lib_path", library_path}, {"lib_name", library_name}})) { - res->error = "DeviceError"; - res->message = "Failed to add device library"; + Action returnResponse(const oatpp::Object& body) { + auto res = StatusDto::createShared(); + if (body->library_path.getValue("") == "" || + body->library_name.getValue("") == "") { + res->error = "Invalid Parameters"; + res->message = "Device library path and name is required"; + } else { + auto library_path = body->library_path.getValue(""); + auto library_name = body->library_name.getValue(""); + if (!lithium::MyApp->addDeviceLibrary( + {{"lib_path", library_path}, + {"lib_name", library_name}})) { + res->error = "DeviceError"; + res->message = "Failed to add device library"; + } + } + return _return( + controller->createDtoResponse(Status::CODE_200, res)); } - } - return _return(controller->createDtoResponse(Status::CODE_200, res)); -} -} -; + }; -ENDPOINT_INFO(getUIRemoveDeviceLibrary) { - info->summary = "Remove device library with information from DeviceManager"; - info->addConsumes>("application/json"); - info->addResponse>(Status::CODE_200, "application/json"); -} -ENDPOINT_ASYNC("GET", "/api/device/remove_device_library", - getUIRemoveDeviceLibrary){ - ENDPOINT_ASYNC_INIT(getUIRemoveDeviceLibrary) Action act() override{ - return request - ->readBodyToDtoAsync>( - controller->getDefaultObjectMapper()) - .callbackTo(&getUIRemoveDeviceLibrary::returnResponse); -} + ENDPOINT_INFO(getUIRemoveDeviceLibrary) { + info->summary = + "Remove device library with information from DeviceManager"; + info->addConsumes>("application/json"); + info->addResponse>(Status::CODE_200, + "application/json"); + } + ENDPOINT_ASYNC("GET", "/api/device/remove_device_library", + getUIRemoveDeviceLibrary) { + ENDPOINT_ASYNC_INIT(getUIRemoveDeviceLibrary); + Action act() override { + return request + ->readBodyToDtoAsync>( + controller->getDefaultObjectMapper()) + .callbackTo(&getUIRemoveDeviceLibrary::returnResponse); + } -Action returnResponse(const oatpp::Object& body) { - auto res = StatusDto::createShared(); - if (body->library_name.getValue("") == "") { - res->error = "Invalid Parameters"; - res->message = "Device library path and name is required"; - } else { - auto library_name = body->library_name.getValue(""); - if (!Lithium::MyApp->removeDeviceLibrary(library_name)) { - res->error = "DeviceError"; - res->message = "Failed to add device library"; + Action returnResponse( + const oatpp::Object& body) { + auto res = StatusDto::createShared(); + if (body->library_name.getValue("") == "") { + res->error = "Invalid Parameters"; + res->message = "Device library path and name is required"; + } else { + auto library_name = body->library_name.getValue(""); + if (!lithium::MyApp->removeDeviceLibrary(library_name)) { + res->error = "DeviceError"; + res->message = "Failed to add device library"; + } + } + return _return( + controller->createDtoResponse(Status::CODE_200, res)); } - } - return _return(controller->createDtoResponse(Status::CODE_200, res)); -} -} -; + }; -// ---------------------------------------------------------------- -// Device Http Handler -// ---------------------------------------------------------------- + // ---------------------------------------------------------------- + // Device Http Handler + // ---------------------------------------------------------------- -ENDPOINT_INFO(getUIAddDevice) { - info->summary = "Add device from device library into DeviceManager"; - info->addConsumes>("application/json"); - info->addResponse>(Status::CODE_200, "application/json"); -} -ENDPOINT_ASYNC("GET", "/api/device/add_device", getUIAddDevice){ - ENDPOINT_ASYNC_INIT(getUIAddDevice) Action act() - override{return request - ->readBodyToDtoAsync>( - controller->getDefaultObjectMapper()) - .callbackTo(&getUIAddDevice::returnResponse); -} + ENDPOINT_INFO(getUIAddDevice) { + info->summary = "Add device from device library into DeviceManager"; + info->addConsumes>("application/json"); + info->addResponse>(Status::CODE_200, + "application/json"); + } + ENDPOINT_ASYNC("GET", "/api/device/add_device", getUIAddDevice) { + ENDPOINT_ASYNC_INIT(getUIAddDevice); + Action act() override { + return request + ->readBodyToDtoAsync>( + controller->getDefaultObjectMapper()) + .callbackTo(&getUIAddDevice::returnResponse); + } -Action returnResponse(const oatpp::Object& body) { - auto res = StatusDto::createShared(); - if (body->device_name.getValue("") == "" || - body->device_type.getValue("") == "" || - body->library_name.getValue("") == "") { - res->error = "Invalid Parameters"; - res->message = - "Device library path and device name and type are required"; - } else { - auto device_name = body->device_name.getValue(""); - auto device_type = body->device_type.getValue(""); - auto library_name = body->library_name.getValue(""); - - DeviceType device_type_ = StringToDeviceType(device_type); - if (device_type_ == DeviceType::NumDeviceTypes) { - res->error = "Invalid Parameters"; - res->message = "Unsupported device type"; - } else { - if (!Lithium::MyApp->addDevice({{"type", device_type}, - {"device_name", device_name}, - {"library_name", library_name}})) - ; - { - res->error = "DeviceError"; - res->message = "Failed to add device"; + Action returnResponse(const oatpp::Object& body) { + auto res = StatusDto::createShared(); + if (body->device_name.getValue("") == "" || + body->device_type.getValue("") == "" || + body->library_name.getValue("") == "") { + res->error = "Invalid Parameters"; + res->message = + "Device library path and device name and type are required"; + } else { + auto device_name = body->device_name.getValue(""); + auto device_type = body->device_type.getValue(""); + auto library_name = body->library_name.getValue(""); + + DeviceType device_type_ = StringToDeviceType(device_type); + if (device_type_ == DeviceType::NumDeviceTypes) { + res->error = "Invalid Parameters"; + res->message = "Unsupported device type"; + } else { + if (!lithium::MyApp->addDevice( + {{"type", device_type}, + {"device_name", device_name}, + {"library_name", library_name}})) + ; + { + res->error = "DeviceError"; + res->message = "Failed to add device"; + } + } } + return _return( + controller->createDtoResponse(Status::CODE_200, res)); } - } - return _return(controller->createDtoResponse(Status::CODE_200, res)); -} -} -; + }; -ENDPOINT_INFO(getUIRemoveDevice) { - info->summary = "Remove device with information from DeviceManager"; - info->addConsumes>("application/json"); - info->addResponse>(Status::CODE_200, "application/json"); -} -ENDPOINT_ASYNC("GET", "/api/device/remove_device", getUIRemoveDevice){ - ENDPOINT_ASYNC_INIT(getUIRemoveDevice) Action act() - override{return request - ->readBodyToDtoAsync>( - controller->getDefaultObjectMapper()) - .callbackTo(&getUIRemoveDevice::returnResponse); -} + ENDPOINT_INFO(getUIRemoveDevice) { + info->summary = "Remove device with information from DeviceManager"; + info->addConsumes>("application/json"); + info->addResponse>(Status::CODE_200, + "application/json"); + } + ENDPOINT_ASYNC("GET", "/api/device/remove_device", getUIRemoveDevice) { + ENDPOINT_ASYNC_INIT(getUIRemoveDevice); + Action act() override { + return request + ->readBodyToDtoAsync>( + controller->getDefaultObjectMapper()) + .callbackTo(&getUIRemoveDevice::returnResponse); + } -Action returnResponse(const oatpp::Object& body) { - auto res = StatusDto::createShared(); - if (body->device_name.getValue("") == "") { - res->error = "Invalid Parameters"; - res->message = "Device name is required"; - } else { - auto device_name = body->device_name.getValue(""); - if (!Lithium::MyApp->removeDeviceByName(device_name)) { - res->error = "DeviceError"; - res->message = "Failed to remove device"; + Action returnResponse(const oatpp::Object& body) { + auto res = StatusDto::createShared(); + if (body->device_name.getValue("") == "") { + res->error = "Invalid Parameters"; + res->message = "Device name is required"; + } else { + auto device_name = body->device_name.getValue(""); + if (!lithium::MyApp->removeDeviceByName(device_name)) { + res->error = "DeviceError"; + res->message = "Failed to remove device"; + } + } + return _return( + controller->createDtoResponse(Status::CODE_200, res)); } - } - return _return(controller->createDtoResponse(Status::CODE_200, res)); -} -} -; + }; -// ---------------------------------------------------------------- -// Device Property Functions -// ---------------------------------------------------------------- + // ---------------------------------------------------------------- + // Device Property Functions + // ---------------------------------------------------------------- -ENDPOINT_INFO(getUIGetProperty) { - info->summary = "Get a specific property from the specified device"; - info->addConsumes>("application/json"); - info->addResponse>(Status::CODE_200, "application/json"); -} -ENDPOINT_ASYNC("GET", "/api/device/get_property", getUIGetProperty){ - ENDPOINT_ASYNC_INIT(getUIGetProperty) Action act() - override{return request - ->readBodyToDtoAsync>( - controller->getDefaultObjectMapper()) - .callbackTo(&getUIGetProperty::returnResponse); -} + ENDPOINT_INFO(getUIGetProperty) { + info->summary = "Get a specific property from the specified device"; + info->addConsumes>("application/json"); + info->addResponse>(Status::CODE_200, + "application/json"); + } + ENDPOINT_ASYNC("GET", "/api/device/get_property", getUIGetProperty) { + ENDPOINT_ASYNC_INIT(getUIGetProperty); + Action act() override { + return request + ->readBodyToDtoAsync>( + controller->getDefaultObjectMapper()) + .callbackTo(&getUIGetProperty::returnResponse); + } -Action returnResponse(const oatpp::Object& body) { - auto res = StatusDto::createShared(); - if (body->device_name.getValue("") == "") { - res->error = "Invalid Parameters"; - res->message = "Device name is required"; - } else { - auto device_name = body->device_name.getValue(""); - if (!Lithium::MyApp->removeDeviceByName(device_name)) { - res->error = "DeviceError"; - res->message = "Failed to remove device"; + Action returnResponse(const oatpp::Object& body) { + auto res = StatusDto::createShared(); + if (body->device_name.getValue("") == "") { + res->error = "Invalid Parameters"; + res->message = "Device name is required"; + } else { + auto device_name = body->device_name.getValue(""); + if (!lithium::MyApp->removeDeviceByName(device_name)) { + res->error = "DeviceError"; + res->message = "Failed to remove device"; + } + } + return _return( + controller->createDtoResponse(Status::CODE_200, res)); } + }; + + ENDPOINT_INFO(getUISetProperty) { + info->summary = + "Set a specific property from the specified device with new " + "property " + "value"; + info->addConsumes>("application/json"); + info->addResponse>(Status::CODE_200, + "application/json"); } - return _return(controller->createDtoResponse(Status::CODE_200, res)); -} -} -; - -ENDPOINT_INFO(getUISetProperty) { - info->summary = - "Set a specific property from the specified device with new property " - "value"; - info->addConsumes>("application/json"); - info->addResponse>(Status::CODE_200, "application/json"); -} -ENDPOINT_ASYNC("GET", "/api/device/set_property", getUISetProperty){ - ENDPOINT_ASYNC_INIT(getUISetProperty) Action act() - override{return request - ->readBodyToDtoAsync>( - controller->getDefaultObjectMapper()) - .callbackTo(&getUISetProperty::returnResponse); -} + ENDPOINT_ASYNC("GET", "/api/device/set_property", getUISetProperty) { + ENDPOINT_ASYNC_INIT(getUISetProperty); + Action act() override { + return request + ->readBodyToDtoAsync>( + controller->getDefaultObjectMapper()) + .callbackTo(&getUISetProperty::returnResponse); + } -Action returnResponse(const oatpp::Object& body) { - auto res = StatusDto::createShared(); - if (body->device_name.getValue("") == "") { - res->error = "Invalid Parameters"; - res->message = "Device name is required"; - } else { - auto device_name = body->device_name.getValue(""); - if (!Lithium::MyApp->removeDeviceByName(device_name)) { - res->error = "DeviceError"; - res->message = "Failed to remove device"; + Action returnResponse(const oatpp::Object& body) { + auto res = StatusDto::createShared(); + if (body->device_name.getValue("") == "") { + res->error = "Invalid Parameters"; + res->message = "Device name is required"; + } else { + auto device_name = body->device_name.getValue(""); + if (!lithium::MyApp->removeDeviceByName(device_name)) { + res->error = "DeviceError"; + res->message = "Failed to remove device"; + } + } + return _return( + controller->createDtoResponse(Status::CODE_200, res)); } - } - return _return(controller->createDtoResponse(Status::CODE_200, res)); -} -} -; + }; -// ---------------------------------------------------------------- -// Device Task Functions -// ---------------------------------------------------------------- + // ---------------------------------------------------------------- + // Device Task Functions + // ---------------------------------------------------------------- -ENDPOINT_INFO(getUIRunDeviceFunc) { - info->summary = "Run a specific task from device"; - info->addConsumes>("application/json"); - info->addResponse>(Status::CODE_200, "application/json"); -} -ENDPOINT_ASYNC("GET", "/api/device/run_device_func", getUIRunDeviceFunc){ - ENDPOINT_ASYNC_INIT(getUIRunDeviceFunc) Action act() - override{return request - ->readBodyToDtoAsync>( - controller->getDefaultObjectMapper()) - .callbackTo(&getUIRunDeviceFunc::returnResponse); -} + ENDPOINT_INFO(getUIRunDeviceFunc) { + info->summary = "Run a specific task from device"; + info->addConsumes>("application/json"); + info->addResponse>(Status::CODE_200, + "application/json"); + } + ENDPOINT_ASYNC("GET", "/api/device/run_device_func", getUIRunDeviceFunc) { + ENDPOINT_ASYNC_INIT(getUIRunDeviceFunc); + Action act() override { + return request + ->readBodyToDtoAsync>( + controller->getDefaultObjectMapper()) + .callbackTo(&getUIRunDeviceFunc::returnResponse); + } -Action returnResponse(const oatpp::Object& body) { - auto res = StatusDto::createShared(); - if (body->device_name.getValue("") == "") { - res->error = "Invalid Parameters"; - res->message = "Device name is required"; - } else { - auto device_name = body->device_name.getValue(""); - if (!Lithium::MyApp->removeDeviceByName(device_name)) { - res->error = "DeviceError"; - res->message = "Failed to remove device"; + Action returnResponse(const oatpp::Object& body) { + auto res = StatusDto::createShared(); + if (body->device_name.getValue("") == "") { + res->error = "Invalid Parameters"; + res->message = "Device name is required"; + } else { + auto device_name = body->device_name.getValue(""); + if (!lithium::MyApp->removeDeviceByName(device_name)) { + res->error = "DeviceError"; + res->message = "Failed to remove device"; + } + } + return _return( + controller->createDtoResponse(Status::CODE_200, res)); } - } - return _return(controller->createDtoResponse(Status::CODE_200, res)); -} -} -; + }; -ENDPOINT_INFO(getUIGetDeviceFunc) { - info->summary = "Get a specific task's infomation from device"; - info->addConsumes>("application/json"); - info->addResponse>(Status::CODE_200, "application/json"); -} -ENDPOINT_ASYNC("GET", "/api/device/get_device_func", getUIGetDeviceFunc){ - ENDPOINT_ASYNC_INIT(getUIGetDeviceFunc) Action act() - override{return request - ->readBodyToDtoAsync>( - controller->getDefaultObjectMapper()) - .callbackTo(&getUIGetDeviceFunc::returnResponse); -} + ENDPOINT_INFO(getUIGetDeviceFunc) { + info->summary = "Get a specific task's infomation from device"; + info->addConsumes>("application/json"); + info->addResponse>(Status::CODE_200, + "application/json"); + } + ENDPOINT_ASYNC("GET", "/api/device/get_device_func", getUIGetDeviceFunc) { + ENDPOINT_ASYNC_INIT(getUIGetDeviceFunc); + Action act() override { + return request + ->readBodyToDtoAsync>( + controller->getDefaultObjectMapper()) + .callbackTo(&getUIGetDeviceFunc::returnResponse); + } -Action returnResponse(const oatpp::Object& body) { - auto res = StatusDto::createShared(); - if (body->device_name.getValue("") == "") { - res->error = "Invalid Parameters"; - res->message = "Device name is required"; - } else { - auto device_name = body->device_name.getValue(""); - if (!Lithium::MyApp->removeDeviceByName(device_name)) { - res->error = "DeviceError"; - res->message = "Failed to remove device"; + Action returnResponse(const oatpp::Object& body) { + auto res = StatusDto::createShared(); + if (body->device_name.getValue("") == "") { + res->error = "Invalid Parameters"; + res->message = "Device name is required"; + } else { + auto device_name = body->device_name.getValue(""); + if (!lithium::MyApp->removeDeviceByName(device_name)) { + res->error = "DeviceError"; + res->message = "Failed to remove device"; + } + } + return _return( + controller->createDtoResponse(Status::CODE_200, res)); } - } - return _return(controller->createDtoResponse(Status::CODE_200, res)); -} -} -; + }; -// ---------------------------------------------------------------- -// Device Common Interface -// ---------------------------------------------------------------- + // ---------------------------------------------------------------- + // Device Common Interface + // ---------------------------------------------------------------- -ENDPOINT_INFO(getUIConnectDevice) { - info->summary = "Connect to a specific device with name (must be unique)."; - info->addConsumes>("application/json"); - info->addResponse>(Status::CODE_200, "application/json"); -} -ENDPOINT_ASYNC("GET", "/api/device/connect", getUIConnectDevice){ - ENDPOINT_ASYNC_INIT(getUIConnectDevice) Action act() - override{return request - ->readBodyToDtoAsync>( - controller->getDefaultObjectMapper()) - .callbackTo(&getUIConnectDevice::returnResponse); -} + ENDPOINT_INFO(getUIConnectDevice) { + info->summary = + "Connect to a specific device with name (must be unique)."; + info->addConsumes>("application/json"); + info->addResponse>(Status::CODE_200, + "application/json"); + } + ENDPOINT_ASYNC("GET", "/api/device/connect", getUIConnectDevice) { + ENDPOINT_ASYNC_INIT(getUIConnectDevice); + Action act() override { + return request + ->readBodyToDtoAsync>( + controller->getDefaultObjectMapper()) + .callbackTo(&getUIConnectDevice::returnResponse); + } -Action returnResponse(const oatpp::Object& body) { - auto res = StatusDto::createShared(); - if (body->device_name.getValue("") == "") { - res->error = "Invalid Parameters"; - res->message = "Device name is required"; - } else { - auto device_name = body->device_name.getValue(""); - if (!Lithium::MyApp->removeDeviceByName(device_name)) { - res->error = "DeviceError"; - res->message = "Failed to remove device"; + Action returnResponse(const oatpp::Object& body) { + auto res = StatusDto::createShared(); + if (body->device_name.getValue("") == "") { + res->error = "Invalid Parameters"; + res->message = "Device name is required"; + } else { + auto device_name = body->device_name.getValue(""); + if (!lithium::MyApp->removeDeviceByName(device_name)) { + res->error = "DeviceError"; + res->message = "Failed to remove device"; + } + } + return _return( + controller->createDtoResponse(Status::CODE_200, res)); } - } - return _return(controller->createDtoResponse(Status::CODE_200, res)); -} -} -; + }; -ENDPOINT_INFO(getUIDisconnectDevice) { - info->summary = - "Disconnect from a specific device with name (must be unique)."; - info->addConsumes>("application/json"); - info->addResponse>(Status::CODE_200, "application/json"); -} -ENDPOINT_ASYNC("GET", "/api/device/disconnect", getUIDisconnectDevice){ - ENDPOINT_ASYNC_INIT(getUIDisconnectDevice) Action act() - override{return request - ->readBodyToDtoAsync>( - controller->getDefaultObjectMapper()) - .callbackTo(&getUIDisconnectDevice::returnResponse); -} + ENDPOINT_INFO(getUIDisconnectDevice) { + info->summary = + "Disconnect from a specific device with name (must be unique)."; + info->addConsumes>("application/json"); + info->addResponse>(Status::CODE_200, + "application/json"); + } + ENDPOINT_ASYNC("GET", "/api/device/disconnect", getUIDisconnectDevice) { + ENDPOINT_ASYNC_INIT(getUIDisconnectDevice); + Action act() override { + return request + ->readBodyToDtoAsync>( + controller->getDefaultObjectMapper()) + .callbackTo(&getUIDisconnectDevice::returnResponse); + } -Action returnResponse(const oatpp::Object& body) { - auto res = StatusDto::createShared(); - if (body->device_name.getValue("") == "") { - res->error = "Invalid Parameters"; - res->message = "Device name is required"; - } else { - auto device_name = body->device_name.getValue(""); - if (!Lithium::MyApp->removeDeviceByName(device_name)) { - res->error = "DeviceError"; - res->message = "Failed to remove device"; + Action returnResponse(const oatpp::Object& body) { + auto res = StatusDto::createShared(); + if (body->device_name.getValue("") == "") { + res->error = "Invalid Parameters"; + res->message = "Device name is required"; + } else { + auto device_name = body->device_name.getValue(""); + if (!lithium::MyApp->removeDeviceByName(device_name)) { + res->error = "DeviceError"; + res->message = "Failed to remove device"; + } + } + return _return( + controller->createDtoResponse(Status::CODE_200, res)); } + }; + + ENDPOINT_INFO(getUIReconnectDevice) { + info->summary = + "Reconnect to a specific device with name (must be unique and the " + "device must already connect successfully)."; + info->addConsumes>("application/json"); + info->addResponse>(Status::CODE_200, + "application/json"); } - return _return(controller->createDtoResponse(Status::CODE_200, res)); -} -} -; - -ENDPOINT_INFO(getUIReconnectDevice) { - info->summary = - "Reconnect to a specific device with name (must be unique and the " - "device must already connect successfully)."; - info->addConsumes>("application/json"); - info->addResponse>(Status::CODE_200, "application/json"); -} -ENDPOINT_ASYNC("GET", "/api/device/reconnect", getUIReconnectDevice){ - ENDPOINT_ASYNC_INIT(getUIReconnectDevice) Action act() - override{return request - ->readBodyToDtoAsync>( - controller->getDefaultObjectMapper()) - .callbackTo(&getUIReconnectDevice::returnResponse); -} + ENDPOINT_ASYNC("GET", "/api/device/reconnect", getUIReconnectDevice) { + ENDPOINT_ASYNC_INIT(getUIReconnectDevice); + Action act() override { + return request + ->readBodyToDtoAsync>( + controller->getDefaultObjectMapper()) + .callbackTo(&getUIReconnectDevice::returnResponse); + } -Action returnResponse(const oatpp::Object& body) { - auto res = StatusDto::createShared(); - if (body->device_name.getValue("") == "") { - res->error = "Invalid Parameters"; - res->message = "Device name is required"; - } else { - auto device_name = body->device_name.getValue(""); - if (!Lithium::MyApp->removeDeviceByName(device_name)) { - res->error = "DeviceError"; - res->message = "Failed to remove device"; + Action returnResponse(const oatpp::Object& body) { + auto res = StatusDto::createShared(); + if (body->device_name.getValue("") == "") { + res->error = "Invalid Parameters"; + res->message = "Device name is required"; + } else { + auto device_name = body->device_name.getValue(""); + if (!lithium::MyApp->removeDeviceByName(device_name)) { + res->error = "DeviceError"; + res->message = "Failed to remove device"; + } + } + return _return( + controller->createDtoResponse(Status::CODE_200, res)); } + }; + + ENDPOINT_INFO(getUIScanDevice) { + info->summary = + "Scan a specific type of the devices and return a list of " + "available " + "devices."; + info->addConsumes>("application/json"); + info->addResponse>(Status::CODE_200, + "application/json"); } - return _return(controller->createDtoResponse(Status::CODE_200, res)); -} -} -; - -ENDPOINT_INFO(getUIScanDevice) { - info->summary = - "Scan a specific type of the devices and return a list of available " - "devices."; - info->addConsumes>("application/json"); - info->addResponse>(Status::CODE_200, "application/json"); -} -ENDPOINT_ASYNC("GET", "/api/device/scan", getUIScanDevice){ - ENDPOINT_ASYNC_INIT(getUIScanDevice) Action act() - override{return request - ->readBodyToDtoAsync>( - controller->getDefaultObjectMapper()) - .callbackTo(&getUIScanDevice::returnResponse); -} + ENDPOINT_ASYNC("GET", "/api/device/scan", getUIScanDevice) { + ENDPOINT_ASYNC_INIT(getUIScanDevice); + Action act() override { + return request + ->readBodyToDtoAsync>( + controller->getDefaultObjectMapper()) + .callbackTo(&getUIScanDevice::returnResponse); + } -Action returnResponse(const oatpp::Object& body) { - auto res = StatusDto::createShared(); - if (body->device_type.getValue("") == "") { - res->error = "Invalid Parameters"; - res->message = "Device name is required"; - } else { - auto device_name = body->device_type.getValue(""); - if (!Lithium::MyApp->removeDeviceByName(device_name)) { - res->error = "DeviceError"; - res->message = "Failed to remove device"; + Action returnResponse(const oatpp::Object& body) { + auto res = StatusDto::createShared(); + if (body->device_type.getValue("") == "") { + res->error = "Invalid Parameters"; + res->message = "Device name is required"; + } else { + auto device_name = body->device_type.getValue(""); + if (!lithium::MyApp->removeDeviceByName(device_name)) { + res->error = "DeviceError"; + res->message = "Failed to remove device"; + } + } + return _return( + controller->createDtoResponse(Status::CODE_200, res)); } - } - return _return(controller->createDtoResponse(Status::CODE_200, res)); -} -} -; -} -; + }; +}; #include OATPP_CODEGEN_END(ApiController) //<- End Codegen diff --git a/src/server/controller/AsyncIOController.hpp b/src/server/controller/AsyncIOController.hpp index 388f782a..d4405ff1 100644 --- a/src/server/controller/AsyncIOController.hpp +++ b/src/server/controller/AsyncIOController.hpp @@ -71,12 +71,12 @@ class IOController : public oatpp::web::server::api::ApiController { res->command = "createDirectory"; auto path = body->path.getValue(""); auto isAbsolute = body->isAbsolute.getValue(false); - if (isAbsolute && !Atom::IO::isAbsolutePath(path)) { + if (isAbsolute && !atom::io::isAbsolutePath(path)) { res->status = "error"; res->error = "Invalid Parameters"; res->message = "Directory path must be a absolute path"; } else { - if (!Atom::IO::createDirectory(path)) { + if (!atom::io::createDirectory(path)) { res->status = "error"; res->error = "IO Failed"; res->code = 500; @@ -116,13 +116,13 @@ class IOController : public oatpp::web::server::api::ApiController { auto path = body->path.getValue(""); auto isAbsolute = body->isAbsolute.getValue(false); - if (isAbsolute && !Atom::IO::isAbsolutePath(path)) { + if (isAbsolute && !atom::io::isAbsolutePath(path)) { res->status = "error"; res->code = 500; res->error = "Invalid Parameters"; res->message = "Directory path must be a absolute path"; } else { - if (!Atom::IO::removeDirectory(path)) { + if (!atom::io::removeDirectory(path)) { res->status = "error"; res->code = 500; res->error = "IO Failed"; @@ -166,19 +166,19 @@ class IOController : public oatpp::web::server::api::ApiController { auto isAbsolute = body->isAbsolute.getValue(false); auto name = body->name.getValue(""); - if (!Atom::IO::isFolderNameValid(name)) { + if (!atom::io::isFolderNameValid(name)) { res->status = "error"; res->code = 500; res->error = "Invalid Parameters"; res->message = "New folder name must be valid"; } - if (isAbsolute && !Atom::IO::isAbsolutePath(path)) { + if (isAbsolute && !atom::io::isAbsolutePath(path)) { res->status = "error"; res->code = 500; res->error = "Invalid Parameters"; res->message = "Directory path must be a absolute path"; } else { - if (!Atom::IO::renameDirectory(path, name)) { + if (!atom::io::renameDirectory(path, name)) { res->status = "error"; res->code = 500; res->error = "IO Failed"; @@ -219,14 +219,14 @@ class IOController : public oatpp::web::server::api::ApiController { res->command = "moveDirectory"; auto old_path = body->path.getValue(""); auto new_path = body->new_path.getValue(""); - if ((!Atom::IO::isAbsolutePath(old_path) || - !Atom::IO::isAbsolutePath(new_path))) { + if ((!atom::io::isAbsolutePath(old_path) || + !atom::io::isAbsolutePath(new_path))) { res->status = "error"; res->code = 500; res->error = "Invalid Parameters"; res->message = "Directory path must be a absolute path"; } else { - if (!Atom::IO::moveDirectory(old_path, new_path)) { + if (!atom::io::moveDirectory(old_path, new_path)) { res->status = "error"; res->code = 500; res->error = "IO Failed"; @@ -269,14 +269,14 @@ class IOController : public oatpp::web::server::api::ApiController { auto new_path = body->new_path.getValue(""); auto isAbsolute = body->isAbsolute.getValue(false); - if (isAbsolute && !Atom::IO::isAbsolutePath(old_path) || - !Atom::IO::isAbsolutePath(new_path)) { + if (isAbsolute && !atom::io::isAbsolutePath(old_path) || + !atom::io::isAbsolutePath(new_path)) { res->status = "error"; res->code = 500; res->error = "Invalid Parameters"; res->message = "Directory path must be a absolute path"; } else { - if (!Atom::IO::copyFile(old_path, new_path)) { + if (!atom::io::copyFile(old_path, new_path)) { res->status = "error"; res->code = 500; res->error = "IO Failed"; @@ -320,14 +320,14 @@ class IOController : public oatpp::web::server::api::ApiController { auto new_path = body->new_path.getValue(""); auto isAbsolute = body->isAbsolute.getValue(false); - if (isAbsolute && !Atom::IO::isAbsolutePath(old_path) || - !Atom::IO::isAbsolutePath(new_path)) { + if (isAbsolute && !atom::io::isAbsolutePath(old_path) || + !atom::io::isAbsolutePath(new_path)) { res->status = "error"; res->code = 500; res->error = "Invalid Parameters"; res->message = "Directory path must be a absolute path"; } else { - if (!Atom::IO::copyFile(old_path, new_path)) { + if (!atom::io::copyFile(old_path, new_path)) { res->status = "error"; res->code = 500; res->error = "IO Failed"; @@ -371,13 +371,13 @@ class IOController : public oatpp::web::server::api::ApiController { auto new_name = body->new_name.getValue(""); auto isAbsolute = body->isAbsolute.getValue(false); - if (isAbsolute && !Atom::IO::isAbsolutePath(old_name)) { + if (isAbsolute && !atom::io::isAbsolutePath(old_name)) { res->status = "error"; res->code = 500; res->error = "Invalid Parameters"; res->message = "Directory path must be a absolute path"; } else { - if (!Atom::IO::renameFile(old_name, new_name)) { + if (!atom::io::renameFile(old_name, new_name)) { res->status = "error"; res->code = 500; res->error = "IO Failed"; @@ -418,13 +418,13 @@ class IOController : public oatpp::web::server::api::ApiController { auto name = body->path.getValue(""); auto isAbsolute = body->isAbsolute.getValue(false); - if (isAbsolute && !Atom::IO::isAbsolutePath(name)) { + if (isAbsolute && !atom::io::isAbsolutePath(name)) { res->status = "error"; res->code = 500; res->error = "Invalid Parameters"; res->message = "Directory path must be a absolute path"; } - if (!Atom::IO::removeFile(name)) { + if (!atom::io::removeFile(name)) { res->error = "IO Failed"; res->message = "Failed to remove file"; } diff --git a/src/server/controller/AsyncModuleController.hpp b/src/server/controller/AsyncModuleController.hpp index ae03625f..de8312a5 100644 --- a/src/server/controller/AsyncModuleController.hpp +++ b/src/server/controller/AsyncModuleController.hpp @@ -38,7 +38,7 @@ Description: Module Route class ModuleController : public oatpp::web::server::api::ApiController { public: - static std::shared_ptr m_moduleLoader; + static std::shared_ptr m_moduleLoader; ModuleController(const std::shared_ptr& objectMapper) : oatpp::web::server::api::ApiController(objectMapper) {} @@ -106,7 +106,7 @@ Action returnResponse(const oatpp::Object& body) { OATPP_ASSERT_HTTP(body->plugin_name.getValue("") != "", Status::CODE_400, "Invalid Parameters"); auto plugin_name = body->plugin_name.getValue(""); - if (!Lithium::MyApp->unloadModule(plugin_name)) { + if (!lithium::MyApp->unloadModule(plugin_name)) { res->error = "ModuleError"; res->message = fmt::format("Failed to unload module: {}", plugin_name); } @@ -135,7 +135,7 @@ Action returnResponse(const oatpp::Object& body) { OATPP_ASSERT_HTTP(body->plugin_path.getValue("") != "", Status::CODE_400, "Invalid Parameters"); auto plugin_path = body->plugin_path.getValue(""); - auto module_list = Lithium::MyApp->getModuleList(); + auto module_list = lithium::MyApp->getModuleList(); for (auto module : module_list) { res->module_list->push_back(module); OATPP_LOGD("ModuleController", "Module: %s", module.c_str()); @@ -187,7 +187,7 @@ Action returnResponse(const oatpp::Object& body) { OATPP_ASSERT_HTTP(body->plugin_name.getValue("") != "", Status::CODE_400, "Invalid Parameters"); auto plugin_name = body->plugin_name.getValue(""); - if (!Lithium::MyApp->enableModule(plugin_name)) { + if (!lithium::MyApp->enableModule(plugin_name)) { res->error = "ModuleError"; res->message = fmt::format("Failed to enable module: {}", plugin_name); } @@ -216,7 +216,7 @@ Action returnResponse(const oatpp::Object& body) { OATPP_ASSERT_HTTP(body->plugin_name.getValue("") != "", Status::CODE_400, "Invalid Parameters"); auto plugin_name = body->plugin_name.getValue(""); - if (!Lithium::MyApp->disableModule(plugin_name)) { + if (!lithium::MyApp->disableModule(plugin_name)) { res->error = "ModuleError"; res->message = fmt::format("Failed to disable module: {}", plugin_name); } @@ -245,7 +245,7 @@ Action returnResponse(const oatpp::Object& body) { OATPP_ASSERT_HTTP(body->module_name.getValue("") != "", Status::CODE_400, "Invalid Parameters"); auto module_name = body->module_name.getValue(""); - auto module_status = Lithium::MyApp->getModuleStatus(module_name); + auto module_status = lithium::MyApp->getModuleStatus(module_name); if (module_status) { res->module_status = module_status; } else { @@ -278,7 +278,7 @@ Action returnResponse(const oatpp::Object& body) { OATPP_ASSERT_HTTP(body->module_name.getValue("") != "", Status::CODE_400, "Invalid Parameters"); auto module_name = body->module_name.getValue(""); - auto module_config = Lithium::MyApp->getModuleConfig(module_name); + auto module_config = lithium::MyApp->getModuleConfig(module_name); if (!module_config.empty()) { res->module_config = module_config.dump(4); } else { @@ -319,11 +319,11 @@ Action returnResponse(const oatpp::Object& body) { CHECK_VARIABLE(get_func, "Invalid Parameters") if (instance_type == "plugin" || instance_type == "module") { AddPtr(instance_name, - GetPtr("ModuleLoader") + GetPtr("ModuleLoader") ->GetInstance(module_name, {}, instance_type)); } else if (instance_type == "device") { AddPtr(instance_name, - GetPtr("ModuleLoader") + GetPtr("ModuleLoader") ->GetInstance(module_name, {}, instance_type)); } else { res->error = "ModuleError"; diff --git a/src/server/controller/AsyncPHD2Controller.hpp b/src/server/controller/AsyncPHD2Controller.hpp index 6c5ee817..14a89004 100644 --- a/src/server/controller/AsyncPHD2Controller.hpp +++ b/src/server/controller/AsyncPHD2Controller.hpp @@ -66,7 +66,7 @@ returnResponse(const oatpp::Object &body) { if (params != "") { try { nlohmann::json params_ = nlohmann::json::parse(params); - if (!Lithium::MyApp->createProcess("phd2", "phd2")) { + if (!lithium::MyApp->createProcess("phd2", "phd2")) { res->error = "Process Failed"; res->message = "Failed to start PHD2"; } @@ -93,7 +93,7 @@ ENDPOINT_ASYNC("GET", "/api/phd2/stop", getUIStopPHD2ParamAPI){ Action act() override{auto res = StatusDto::createShared(); res->command = "StopPHD2"; -if (!Lithium::MyApp->terminateProcessByName("phd2")) { +if (!lithium::MyApp->terminateProcessByName("phd2")) { res->error = "Process Failed"; res->message = "Failed to stop PHD2"; } @@ -127,7 +127,7 @@ Action returnResponse(const oatpp::Object &body) { // OATPP_ASSERT_HTTP(param_name && param_value, Status::CODE_400, "parameter // name and id should not be null"); bool phd2_running = false; - for (auto process : Lithium::MyApp->getRunningProcesses()) { + for (auto process : lithium::MyApp->getRunningProcesses()) { if (process.name == "phd2") { phd2_running = true; } diff --git a/src/task/checker.cpp b/src/task/checker.cpp index 57682a64..b33b4505 100644 --- a/src/task/checker.cpp +++ b/src/task/checker.cpp @@ -14,7 +14,7 @@ Description: Task Stack (just log the task) #include "task_stack.hpp" -namespace Lithium::Task { +namespace lithium::Task { void TaskStack::AddTask(std::shared_ptr task) { tasks_.push_back(task); task_status_.push_back(TaskStatus::Pending); @@ -80,7 +80,7 @@ bool TaskStack::IsTaskInStack(const std::string &taskName) const { return std::find(task_names_.begin(), task_names_.end(), taskName) != task_names_.end(); } -} // namespace Lithium::Task +} // namespace lithium::Task /* int main() diff --git a/src/task/checker.hpp b/src/task/checker.hpp index 0b9454b3..638b1570 100644 --- a/src/task/checker.hpp +++ b/src/task/checker.hpp @@ -30,7 +30,7 @@ Description: Task Stack enum class TaskStatus { Pending, Executing, Completed, Failed, Cancelled }; -namespace Lithium::Task { +namespace lithium::Task { /** * @brief Represents a stack of tasks. */ @@ -96,4 +96,4 @@ class TaskStack { bool IsTaskInStack(const std::string &taskName) const; }; -} // namespace Lithium::Task +} // namespace lithium::Task diff --git a/src/task/container.cpp b/src/task/container.cpp index ee793c5b..37e133f0 100644 --- a/src/task/container.cpp +++ b/src/task/container.cpp @@ -16,7 +16,7 @@ Description: Task container class. #include "atom/log/loguru.hpp" -namespace Lithium { +namespace lithium { std::shared_ptr TaskContainer::createShared() { return std::make_shared(); } @@ -115,4 +115,4 @@ void TaskContainer::batchModifyTasks( modifyFunc(task); } } -} // namespace Lithium +} // namespace lithium diff --git a/src/task/container.hpp b/src/task/container.hpp index 2da915bf..1bfda0c5 100644 --- a/src/task/container.hpp +++ b/src/task/container.hpp @@ -25,7 +25,7 @@ Description: Task container class. #include "atom/task/task.hpp" -namespace Lithium { +namespace lithium { /** * @brief Task management container class. @@ -173,6 +173,6 @@ class TaskContainer { tasks; ///< The container holding tasks. std::mutex mutex; ///< Mutex for thread-safe operations on the container. }; -} // namespace Lithium +} // namespace lithium #endif diff --git a/src/task/generator.cpp b/src/task/generator.cpp index 20471b09..07bec10e 100644 --- a/src/task/generator.cpp +++ b/src/task/generator.cpp @@ -22,9 +22,8 @@ Description: Task Generator #include #include -namespace Lithium { +namespace lithium { TaskGenerator::TaskGenerator() { - m_DeviceManager = GetWeakPtr("lithium.device"); } std::shared_ptr TaskGenerator::createShared() { @@ -33,7 +32,7 @@ std::shared_ptr TaskGenerator::createShared() { bool TaskGenerator::loadMacros(const std::string ¯oFileName) { try { - if (!Atom::IO::isFileExists(macroFileName)) { + if (!atom::io::isFileExists(macroFileName)) { LOG_F(ERROR, "Macro file not found: {}", macroFileName); return false; } @@ -55,7 +54,7 @@ bool TaskGenerator::loadMacros(const std::string ¯oFileName) { } bool TaskGenerator::loadMacrosFromFolder(const std::string &folderPath) { - if (!Atom::IO::isFolderExists(folderPath)) { + if (!atom::io::isFolderExists(folderPath)) { LOG_F(ERROR, "Invalid folder path: {}", folderPath); return false; } @@ -99,7 +98,7 @@ std::optional TaskGenerator::getMacroContent( } void TaskGenerator::processMacroFile(const std::string &sfilePath) { - if (!Atom::IO::isFileExists(sfilePath)) { + if (!atom::io::isFileExists(sfilePath)) { LOG_F(ERROR, "Macro file not found: {}", sfilePath); return; } @@ -175,4 +174,4 @@ void TaskGenerator::saveTasksToJson(const std::string &jsonFileName, return; } } -} // namespace Lithium +} // namespace lithium diff --git a/src/task/generator.hpp b/src/task/generator.hpp index de350dcc..c96a0253 100644 --- a/src/task/generator.hpp +++ b/src/task/generator.hpp @@ -24,11 +24,10 @@ Description: Task Generator #include #include "atom/task/task.hpp" -#include "device/manager.hpp" using json = nlohmann::json; -namespace Lithium { +namespace lithium { class TaskGenerator { public: explicit TaskGenerator(); @@ -79,9 +78,7 @@ class TaskGenerator { #endif std::mutex m_Mutex; - - std::weak_ptr m_DeviceManager; }; -} // namespace Lithium +} // namespace lithium #endif diff --git a/src/task/list.cpp b/src/task/list.cpp index 89cf9a50..c9d74f57 100644 --- a/src/task/list.cpp +++ b/src/task/list.cpp @@ -19,7 +19,7 @@ Description: Thread safe task list #include -namespace Lithium { +namespace lithium { std::shared_ptr TaskList::createShared() { return std::make_shared(); } @@ -74,4 +74,4 @@ void TaskList::listTasks() const { } std::unordered_map TaskList::getTasks() { return tasks; } -} // namespace Lithium +} // namespace lithium diff --git a/src/task/list.hpp b/src/task/list.hpp index 736094ea..73297b25 100644 --- a/src/task/list.hpp +++ b/src/task/list.hpp @@ -28,7 +28,7 @@ Description: Thread safe task list #include "atom/type/json.hpp" using json = nlohmann::json; -namespace Lithium { +namespace lithium { class TaskList { public: static std::shared_ptr createShared(); @@ -54,6 +54,6 @@ class TaskList { std::unordered_map tasks; #endif }; -} // namespace Lithium +} // namespace lithium #endif \ No newline at end of file diff --git a/src/task/loader.cpp b/src/task/loader.cpp index c9e0db3a..99424709 100644 --- a/src/task/loader.cpp +++ b/src/task/loader.cpp @@ -21,7 +21,7 @@ Description: Json file manager #include "atom/log/loguru.hpp" -namespace Lithium { +namespace lithium { std::shared_ptr TaskLoader::createShared() { return std::make_shared(); } @@ -192,7 +192,7 @@ void TaskLoader::batchProcessDirectory( std::function onComplete) { batchProcessDirectory(fs::path(directoryPath), process, onComplete); } -} // namespace Lithium +} // namespace lithium /* int main() diff --git a/src/task/loader.hpp b/src/task/loader.hpp index f64eab89..d82ec824 100644 --- a/src/task/loader.hpp +++ b/src/task/loader.hpp @@ -26,7 +26,7 @@ Description: Json file manager using json = nlohmann::json; namespace fs = std::filesystem; -namespace Lithium { +namespace lithium { /** * @brief JSON文件管理器 * @details @@ -186,6 +186,6 @@ class TaskLoader { std::function)> process, std::function onComplete); }; -} // namespace Lithium +} // namespace lithium #endif \ No newline at end of file diff --git a/src/task/manager.cpp b/src/task/manager.cpp index 82fd766d..05d6bc69 100644 --- a/src/task/manager.cpp +++ b/src/task/manager.cpp @@ -17,7 +17,7 @@ Description: Task Manager #include "atom/log/loguru.hpp" #include "atom/server/global_ptr.hpp" -namespace Lithium { +namespace lithium { TaskManager::TaskManager() : m_StopFlag(false) { // Load Task Component from Global Ptr Manager m_TaskContainer = GetWeakPtr("lithium.task.contianer"); @@ -126,4 +126,4 @@ void TaskManager::stopTask() { m_StopFlag.store(true); } bool TaskManager::executeTaskByName(const std::string &name) { return false; } bool TaskManager::saveTasksToJson() const { return true; } -} // namespace Lithium \ No newline at end of file +} // namespace lithium \ No newline at end of file diff --git a/src/task/manager.hpp b/src/task/manager.hpp index 640759eb..b7b6da3c 100644 --- a/src/task/manager.hpp +++ b/src/task/manager.hpp @@ -41,7 +41,7 @@ Description: Task Manager #include "atom/utils/stopwatcher.hpp" -namespace Lithium { +namespace lithium { /** * @brief 任务管理器类,用于管理任务列表和相关操作。 */ @@ -157,6 +157,6 @@ class TaskManager { std::atomic_bool m_StopFlag; }; -} // namespace Lithium +} // namespace lithium #endif diff --git a/src/task/pool.cpp b/src/task/pool.cpp index f0580fef..c175e0ee 100644 --- a/src/task/pool.cpp +++ b/src/task/pool.cpp @@ -14,7 +14,7 @@ Description: Specialized task pool #include "pool.hpp" -namespace Lithium { +namespace lithium { // Initialize static thread_local variables thread_local WorkerQueue *TaskPool::t_localQueue = nullptr; thread_local size_t TaskPool::t_index = 0; @@ -126,4 +126,4 @@ void TaskPool::stop() { } } } -} // namespace Lithium +} // namespace lithium diff --git a/src/task/pool.hpp b/src/task/pool.hpp index 917ab257..60b13979 100644 --- a/src/task/pool.hpp +++ b/src/task/pool.hpp @@ -32,7 +32,7 @@ Description: Specialized task pool #include -namespace Lithium { +namespace lithium { /** * @struct Task * @brief Represents a task that can be executed by the thread pool. @@ -221,6 +221,6 @@ class TaskPool { */ void stop(); }; -} // namespace Lithium +} // namespace lithium #endif diff --git a/src/task/singlepool.cpp b/src/task/singlepool.cpp index 23d7bdf8..bb399329 100644 --- a/src/task/singlepool.cpp +++ b/src/task/singlepool.cpp @@ -17,7 +17,7 @@ Description: Single thread pool for executing temporary tasks asynchronously. #include #include -namespace Lithium { +namespace lithium { class SingleThreadPoolPrivate { public: @@ -153,4 +153,4 @@ void SingleThreadPool::tryStartDetach( } void SingleThreadPool::quit() { start(nullptr); } -} // namespace Lithium +} // namespace lithium diff --git a/src/task/singlepool.hpp b/src/task/singlepool.hpp index cb2ab0cd..d549527c 100644 --- a/src/task/singlepool.hpp +++ b/src/task/singlepool.hpp @@ -21,7 +21,7 @@ Description: Single thread pool for executing temporary tasks asynchronously. #include -namespace Lithium { +namespace lithium { class SingleThreadPoolPrivate; class SingleThreadPool { @@ -45,6 +45,6 @@ class SingleThreadPool { private: std::shared_ptr d_ptr; }; -} // namespace Lithium +} // namespace lithium #endif \ No newline at end of file diff --git a/src/task/tick.cpp b/src/task/tick.cpp index 8a0f1755..b2ea3643 100644 --- a/src/task/tick.cpp +++ b/src/task/tick.cpp @@ -18,7 +18,7 @@ Description: Tick Sheduler, just like Minecraft's #include "atom/server/global_ptr.hpp" #include "atom/utils/stopwatcher.hpp" -namespace Lithium { +namespace lithium { TickScheduler::TickScheduler(size_t threads) : currentTick(0), stop(false), tickLength(100) { #if __cplusplus >= 202002L @@ -205,4 +205,4 @@ void TickScheduler::stopScheduler() { schedulerThread.join(); } } -} // namespace Lithium +} // namespace lithium diff --git a/src/task/tick.hpp b/src/task/tick.hpp index 198ce01f..105cceeb 100644 --- a/src/task/tick.hpp +++ b/src/task/tick.hpp @@ -40,7 +40,7 @@ namespace atom::utils { class StopWatcher; } -namespace Lithium { +namespace lithium { /** * @brief 任务结构体,表示一个待执行的任务 */ @@ -328,6 +328,6 @@ class TickScheduler { */ void stopScheduler(); }; -} // namespace Lithium +} // namespace lithium #endif \ No newline at end of file