1//! @file command.hpp
2//! @author ryftchen
3//! @brief The declarations (command) 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 "build.hpp"
10#include "console.hpp"
11#include "schedule.hpp"
12
13#include "utility/include/argument.hpp"
14
15//! @brief The application module.
16namespace application // NOLINT(modernize-concat-nested-namespaces)
17{
18//! @brief Command-line-related functions in the application module.
19namespace command
20{
21//! @brief Instance title.
22inline constexpr std::string title = "commander";
23
24//! @brief Alias for the native categories.
25using Category = schedule::native::Category;
26//! @brief Alias for the representing of the maximum value of an enum.
27//! @tparam Enum - type of specific enum
28template <typename Enum>
29using Bottom = schedule::native::Bottom<Enum>;
30class Command;
31//! @brief Alias for the local notifier.
32using LocalNotifier = schedule::native::Notifier<Command>;
33
34//! @brief Execute the command line.
35class Command final
36{
37public:
38 //! @brief Destroy the Command object.
39 ~Command();
40 //! @brief Construct a new Command object.
41 Command(const Command&) = delete;
42 //! @brief Construct a new Command object.
43 Command(Command&&) = delete;
44 //! @brief The operator (=) overloading of Command class.
45 //! @return reference of the Command object
46 Command& operator=(const Command&) = delete;
47 //! @brief The operator (=) overloading of Command class.
48 //! @return reference of the Command object
49 Command& operator=(Command&&) = delete;
50
51 friend Command& getInstance();
52
53private:
54 //! @brief Construct a new Command object.
55 Command();
56
57 //! @brief Mutex for controlling parser.
58 mutable std::mutex parserMtx;
59 //! @brief The synchronization condition for foreground and background. Use with parserMtx.
60 std::condition_variable parserCond;
61 //! @brief Flag to indicate whether parsing of arguments is completed.
62 std::atomic_bool isParsed{false};
63 //! @brief Alias for the argument parser.
64 using Argument = utility::argument::Argument;
65 //! @brief The main argument parser.
66 Argument mainCLI{"foo", build::version()};
67 //! @brief The argument parser used to apply algorithm.
68 Argument subCLIAppAlgo{schedule::meta::name<reg_algo::ApplyAlgorithm>(), reg_algo::version()};
69 //! @brief The argument parser used to apply design pattern.
70 Argument subCLIAppDp{schedule::meta::name<reg_dp::ApplyDesignPattern>(), reg_dp::version()};
71 //! @brief The argument parser used to apply data structure.
72 Argument subCLIAppDs{schedule::meta::name<reg_ds::ApplyDataStructure>(), reg_ds::version()};
73 //! @brief The argument parser used to apply numeric.
74 Argument subCLIAppNum{schedule::meta::name<reg_num::ApplyNumeric>(), reg_num::version()};
75 //! @brief The short prefix for the option.
76 const std::string shortPrefix{"-"};
77 //! @brief The Long prefix for the option.
78 const std::string longPrefix{"--"};
79 //! @brief Flag to indicate whether the command is faulty.
80 std::atomic_bool isFaulty{false};
81
82 friend bool executeCLI(const int argc, const char* const argv[]);
83 //! @brief Interface used to execute.
84 //! @param argc - argument count
85 //! @param argv - argument vector
86 //! @return successful or failed to execute
87 bool doExecute(const int argc, const char* const argv[]);
88 //! @brief Initialize the parse argument helpers for native.
89 void initializeNativeCLI();
90 //! @brief Initialize the parse argument helpers for extra.
91 void initializeExtraCLI();
92 //! @brief Set up the main command line interface.
93 void mainCLISetup();
94 //! @brief Build a simple flag in the main cli.
95 //! @tparam Cat - target native category
96 template <Category Cat>
97 void buildSimpleFlagInMainCLI();
98 //! @brief Build a custom option in the main cli.
99 //! @tparam Cat - target native category
100 template <Category Cat>
101 void buildCustomOptionInMainCLI();
102 //! @brief Set up the sub-command line interface.
103 //! @tparam SubCLI - type of sub-cli
104 template <typename SubCLI>
105 void subCLISetup();
106 //! @brief Inject a new sub-cli.
107 //! @tparam SubCLI - type of sub-cli
108 //! @tparam Intf - type of wrapped interface
109 template <typename SubCLI, typename Intf>
110 void injectNewSubCLI(Intf&& intf);
111 //! @brief Add a new category registration to the sub-cli.
112 //! @tparam Cat - type of sub-cli's category
113 //! @param version - category version
114 template <typename Cat>
115 void addNewCategoryToSubCLI(const std::string_view version);
116 //! @brief Resolve target sub-cli.
117 //! @tparam Mapped - type of sub-cli or sub-cli's category
118 //! @return parse argument helper to apply
119 template <typename Mapped>
120 auto& resolveSubCLI();
121 //! @brief Front-end handler for parsing command line arguments.
122 //! @param argc - argument count
123 //! @param argv - argument vector
124 void frontEndHandler(const int argc, const char* const argv[]);
125 //! @brief Back-end handler for performing the specific tasks.
126 void backEndHandler();
127 //! @brief Precheck the native type or extra type task.
128 void precheckSchedule();
129 //! @brief Check whether any type tasks exist.
130 //! @return any type tasks exist or do not exist
131 bool anySelected() const;
132 //! @brief Clear all type tasks.
133 void clearSelected();
134 //! @brief Dispatch all specific tasks.
135 void dispatchTasks();
136 //! @brief Check for excessive arguments.
137 void checkExcessArgs();
138 //! @brief Execute the command line of console mode.
139 void executeInConsole() const;
140 //! @brief Show help message.
141 void showHelpMessage() const;
142 //! @brief Dump configuration.
143 static void dumpConfiguration();
144 //! @brief Display version information.
145 void displayVersionInfo() const;
146 //! @brief Validate the version of all dependencies.
147 void validateDependencies() const;
148
149 friend LocalNotifier;
150 //! @brief Local notification for native type tasks.
151 LocalNotifier builtInNotifier{};
152 //! @brief Forward messages for extra type tasks.
153 schedule::extra::MessageForwarder applyingForwarder{};
154 //! @brief Dispatch all types of tasks.
155 schedule::TaskScheduler scheduleDispatcher{};
156 //! @brief Alias for the pair of the sub-cli name and the sub-cli version.
157 using VerLinkKey = std::pair<std::string, std::string>;
158 //! @brief Mapping hash value for the related versions.
159 struct VerLinkHash
160 {
161 //! @brief The operator (()) overloading of VerLinkHash struct.
162 //! @param key - pair of the sub-cli name and the sub-cli version
163 //! @return hash value
164 std::size_t operator()(const VerLinkKey& key) const
165 {
166 constexpr std::size_t magicNumber = 0x9E3779B9;
167 constexpr std::size_t leftShift = 6;
168 constexpr std::size_t rightShift = 2;
169 std::size_t seed = 0;
170 seed ^= std::hash<std::string>()(key.first) + magicNumber + (seed << leftShift) + (seed >> rightShift);
171 seed ^= std::hash<std::string>()(key.second) + magicNumber + (seed << leftShift) + (seed >> rightShift);
172 return seed;
173 }
174 };
175 //! @brief Mapping table of related versions. Fill as needed.
176 std::unordered_multimap<VerLinkKey, std::string, VerLinkHash> versionLinks;
177
178 //! @brief Go to console mode for troubleshooting.
179 static void enterConsoleMode();
180 //! @brief Register the command line to console mode.
181 //! @tparam Sock - type of client
182 //! @param session - console to be registered
183 //! @param client - client used to send
184 template <typename Sock>
185 static void registerOnConsole(console::Console& session, std::shared_ptr<Sock>& client);
186 //! @brief Process the inputs in console mode.
187 //! @param handling - handling for inputs
188 //! @return console return code
189 static auto processConsoleInputs(const std::function<void()>& handling);
190};
191
192extern bool executeCLI(const int argc, const char* const argv[]);
193} // namespace command
194} // namespace application
195