1//! @file configure.hpp
2//! @author ryftchen
3//! @brief The declarations (configure) in the application module.
4//! @version 0.1.0
5//! @copyright Copyright (c) 2022-2026 ryftchen. All rights reserved.
6
7#pragma once
8
9#include "utility/include/json.hpp"
10#include "utility/include/macro.hpp"
11#include "utility/include/memory.hpp"
12#include "utility/include/thread.hpp"
13
14//! @brief The application module.
15namespace application // NOLINT(modernize-concat-nested-namespaces)
16{
17//! @brief Configuration-related functions in the application module.
18namespace configure
19{
20//! @brief The literal string of the field.
21namespace field
22{
23//! @brief The literal string of the "activateHelper" field.
24constexpr const char* const activateHelper = MACRO_STRINGIFY(activateHelper);
25//! @brief The literal string of the "helperList" field.
26constexpr const char* const helperList = MACRO_STRINGIFY(helperList);
27//! @brief The literal string of the "properties" field in the object of "helpList".
28constexpr const char* const properties = MACRO_STRINGIFY(properties);
29//! @brief The literal string of the "required" field in the object of "helpList".
30constexpr const char* const required = MACRO_STRINGIFY(required);
31//! @brief The literal string of the "logger" field of "helpList".
32constexpr const char* const logger = MACRO_STRINGIFY(logger);
33//! @brief The literal string of the "filePath" field in the properties of "logger" object of "helpList".
34constexpr const char* const filePath = MACRO_STRINGIFY(filePath);
35//! @brief The literal string of the "priorityLevel" field in the properties of "logger" object of "helpList".
36constexpr const char* const priorityLevel = MACRO_STRINGIFY(priorityLevel);
37//! @brief The literal string of the "targetType" field in the properties of "logger" object of "helpList".
38constexpr const char* const targetType = MACRO_STRINGIFY(targetType);
39//! @brief The literal string of the "writeMode" field in the properties of "logger" object of "helpList".
40constexpr const char* const writeMode = MACRO_STRINGIFY(writeMode);
41//! @brief The literal string of the "viewer" field of "helpList".
42constexpr const char* const viewer = MACRO_STRINGIFY(viewer);
43//! @brief The literal string of the "tcpHost" field in the properties of "viewer" object of "helpList".
44constexpr const char* const tcpHost = MACRO_STRINGIFY(tcpHost);
45//! @brief The literal string of the "tcpPort" field in the properties of "viewer" object of "helpList".
46constexpr const char* const tcpPort = MACRO_STRINGIFY(tcpPort);
47//! @brief The literal string of the "udpHost" field in the properties of "viewer" object of "helpList".
48constexpr const char* const udpHost = MACRO_STRINGIFY(udpHost);
49//! @brief The literal string of the "udpPort" field in the properties of "viewer" object of "helpList".
50constexpr const char* const udpPort = MACRO_STRINGIFY(udpPort);
51//! @brief The literal string of the "helperTimeout" field.
52constexpr const char* const helperTimeout = MACRO_STRINGIFY(helperTimeout);
53} // namespace field
54
55//! @brief Maximum access limit.
56constexpr std::uint8_t maxAccessLimit = 10;
57//! @brief Default configuration filename.
58constexpr std::string_view defaultConfigFile = "conf/foo.json";
59//! @brief Get the full path to the configuration file.
60//! @param filename - configuration file path
61//! @return full path to the configuration file
62std::string getFullConfigPath(const std::string_view filename = defaultConfigFile);
63
64//! @brief Configuration.
65class Configure final
66{
67public:
68 //! @brief Destroy the Configure object.
69 ~Configure() = default;
70 //! @brief Construct a new Configure object.
71 Configure(const Configure&) = delete;
72 //! @brief Construct a new Configure object.
73 Configure(Configure&&) = delete;
74 //! @brief The operator (=) overloading of Configure class.
75 //! @return reference of the Configure object
76 Configure& operator=(const Configure&) = delete;
77 //! @brief The operator (=) overloading of Configure class.
78 //! @return reference of the Configure object
79 Configure& operator=(Configure&&) = delete;
80
81 friend const Configure& getInstance(const std::string_view filename);
82
83private:
84 //! @brief Construct a new Configure object.
85 //! @param filename - configure file path
86 explicit Configure(const std::string_view filename) :
87 filePath{getFullConfigPath(filename)}, dataRepo(parseConfigFile(configFile: filePath))
88 {
89 }
90
91 //! @brief Full path to the configuration file.
92 const std::string filePath;
93 //! @brief Configuration data repository.
94 const utility::json::JSON dataRepo;
95
96 friend class Retrieve;
97 //! @brief Parse the configuration file.
98 //! @param configFile - configuration file
99 //! @return configuration data
100 static utility::json::JSON parseConfigFile(const std::string_view configFile);
101 //! @brief Verify the configuration data.
102 //! @param configData - configuration data
103 static void verifyConfigData(const utility::json::JSON& configData);
104 //! @brief Check the object in the helper list.
105 //! @tparam Helper - type of helper
106 //! @param helper - object of helper
107 template <typename Helper>
108 static void checkObjectInHelperList(const utility::json::JSON& helper);
109};
110
111//! @brief Guard for retrieve configuration.
112class Retrieve final
113{
114public:
115 //! @brief Construct a new Retrieve object.
116 //! @param sem - semaphore for configuration access control
117 explicit Retrieve(std::counting_semaphore<maxAccessLimit>& sem);
118 //! @brief Destroy the Retrieve object.
119 ~Retrieve();
120 //! @brief Construct a new Retrieve object.
121 Retrieve(const Retrieve&) = default;
122 //! @brief Construct a new Retrieve object.
123 Retrieve(Retrieve&&) noexcept = default;
124 //! @brief The operator (=) overloading of Retrieve class.
125 //! @return reference of the Retrieve object
126 Retrieve& operator=(const Retrieve&) = delete;
127 //! @brief The operator (=) overloading of Retrieve class.
128 //! @return reference of the Retrieve object
129 Retrieve& operator=(Retrieve&&) = delete;
130
131 //! @brief The operator (/) overloading of Retrieve class.
132 //! @param field - field name
133 //! @return const reference of the JSON object
134 const utility::json::JSON& operator/(const std::string& field) const;
135 //! @brief The operator (()) overloading of Retrieve class.
136 //! @return const reference of the JSON object
137 explicit operator const utility::json::JSON&() const;
138
139private:
140 //! @brief Semaphore that controls the maximum access limit.
141 std::counting_semaphore<maxAccessLimit>& sem;
142};
143
144extern Retrieve retrieveDataRepo();
145extern utility::json::JSON dumpDefaultConfig();
146extern bool loadSettings(const std::string_view filename = defaultConfigFile);
147
148//! @brief Access controller. For the instance.
149//! @tparam Helper - type of helper
150template <typename Helper>
151class Controller
152{
153public:
154 //! @brief Wait for the helper to start.
155 void startup() const;
156 //! @brief Wait for the helper to stop.
157 void shutdown() const;
158 //! @brief Request to reset the helper.
159 void reload() const;
160
161private:
162 //! @brief Instance to be accessed.
163 const std::shared_ptr<Helper> srv{Helper::getInstance()};
164};
165
166//! @brief Configuration details.
167namespace detail
168{
169//! @brief The operator (/) overloading of JSON class.
170//! @param json - specific JSON object
171//! @param field - field name
172//! @return const reference of the JSON object
173inline const utility::json::JSON& operator/(const utility::json::JSON& json, const std::string& field)
174{
175 return json.at(key: field);
176}
177
178//! @brief Query the "activateHelper" configuration.
179//! @return "activateHelper" configuration
180inline auto activateHelper() noexcept
181{
182 return (retrieveDataRepo() / field::activateHelper).asBoolean();
183}
184//! @brief Query the "filePath" configuration in the properties of "logger" object of "helpList".
185//! @return "filePath" configuration in the properties of "logger" object of "helpList"
186inline auto filePath4Logger() noexcept
187{
188 return (retrieveDataRepo() / field::helperList / field::logger / field::properties / field::filePath).asString();
189}
190//! @brief Query the "priorityLevel" configuration in the properties of "logger" object of "helpList".
191//! @return "priorityLevel" configuration in the properties of "logger" object of "helpList"
192inline auto priorityLevel4Logger() noexcept
193{
194 return (retrieveDataRepo() / field::helperList / field::logger / field::properties / field::priorityLevel)
195 .asIntegral();
196}
197//! @brief Query the "targetType" configuration in the properties of "logger" object of "helpList".
198//! @return "targetType" configuration in the properties of "logger" object of "helpList"
199inline auto targetType4Logger() noexcept
200{
201 return (retrieveDataRepo() / field::helperList / field::logger / field::properties / field::targetType)
202 .asIntegral();
203}
204//! @brief Query the "writeMode" configuration in the properties of "logger" object of "helpList".
205//! @return "writeMode" configuration in the properties of "logger" object of "helpList"
206inline auto writeMode4Logger() noexcept
207{
208 return (retrieveDataRepo() / field::helperList / field::logger / field::properties / field::writeMode).asIntegral();
209}
210//! @brief Query the "tcpHost" configuration in the properties of "viewer" object of "helpList".
211//! @return "tcpHost" configuration in the properties of "viewer" object of "helpList"
212inline auto tcpHost4Viewer() noexcept
213{
214 return (retrieveDataRepo() / field::helperList / field::viewer / field::properties / field::tcpHost).asString();
215}
216//! @brief Query the "tcpPort" configuration in the properties of "viewer" object of "helpList".
217//! @return "tcpPort" configuration in the properties of "viewer" object of "helpList"
218inline auto tcpPort4Viewer() noexcept
219{
220 return (retrieveDataRepo() / field::helperList / field::viewer / field::properties / field::tcpPort).asIntegral();
221}
222//! @brief Query the "udpHost" configuration in the properties of "viewer" object of "helpList".
223//! @return "udpHost" configuration in the properties of "viewer" object of "helpList"
224inline auto udpHost4Viewer() noexcept
225{
226 return (retrieveDataRepo() / field::helperList / field::viewer / field::properties / field::udpHost).asString();
227}
228//! @brief Query the "udpPort" configuration in the properties of "viewer" object of "helpList".
229//! @return "udpPort" configuration in the properties of "viewer" object of "helpList"
230inline auto udpPort4Viewer() noexcept
231{
232 return (retrieveDataRepo() / field::helperList / field::viewer / field::properties / field::udpPort).asIntegral();
233}
234//! @brief Query the "helperTimeout" configuration.
235//! @return "helperTimeout" configuration
236inline auto helperTimeout() noexcept
237{
238 return (retrieveDataRepo() / field::helperTimeout).asIntegral();
239}
240} // namespace detail
241
242//! @brief Activity configuration applied to tasks.
243namespace task
244{
245//! @brief Alias for the memory pool for task when making multi-threading.
246using Pooling = utility::memory::Memory<utility::thread::Thread>;
247extern Pooling& resourcePool();
248//! @brief Preset full name for the task.
249//! @param cli - sub-cli name
250//! @param cat - category name
251//! @param cho - choice name
252//! @return full name
253inline std::string presetName(const std::string_view cli, const std::string_view cat, const std::string_view cho)
254{
255 return '@' + std::string{cli} + '_' + std::string{cat} + '_' + std::string{cho};
256}
257} // namespace task
258} // namespace configure
259} // namespace application
260