@@ -38,79 +38,71 @@ struct NumberOption final : IOptionHandler
3838 void handle (const std::string &value) override { std::cout << " number is: " << std::stoi (value) << std::endl; }
3939};
4040
41- class CliHandler
41+ struct IOptionParser
4242{
43+ virtual std::pair<std::string, std::string> parse (const std::string &option) = 0;
44+
45+ virtual ~IOptionParser () = default ;
46+ };
47+
48+ struct OptionParser final : IOptionParser
49+ {
50+ std::pair<std::string, std::string> parse (const std::string &option) override
51+ {
52+ if (const auto splitIndex = option.find_first_of (' =' ); splitIndex != std::string::npos)
53+ {
54+ return {option.substr (0 , splitIndex), option.substr (splitIndex + 1 )};
55+ }
56+ return {option, " " };
57+ }
58+ };
59+
60+ struct ICliHandler
61+ {
62+ virtual void handle (int argc, char *argv[]) = 0;
63+
64+ virtual ~ICliHandler () = default ;
65+ };
66+
67+ class CliHandler final : public ICliHandler
68+ {
69+ IOptionParser &_optionParser;
4370 std::unordered_map<std::string, IOptionHandler *> _options;
4471
4572 public:
46- explicit CliHandler (std::vector<IOptionHandler *> optionHandlers)
73+ explicit CliHandler (IOptionParser &optionParser, std::vector<IOptionHandler *> optionHandlers)
74+ : _optionParser(optionParser)
4775 {
4876 for (const auto handler : optionHandlers)
4977 {
5078 _options[handler->getName ()] = handler;
5179 }
5280 }
5381
54- void handle (const int argc, char *argv[])
82+ void handle (const int argc, char *argv[]) override
5583 {
5684 for (int i = 1 ; i < argc; ++i)
5785 {
58- auto [name, value] = parseOption (argv[i]);
86+ auto [name, value] = _optionParser. parse (argv[i]);
5987 if (auto it = _options.find (name); it != _options.end ())
6088 {
6189 const auto handler = it->second ;
6290 handler->handle (value);
6391 }
92+ else
93+ {
94+ std::cout << " Unrecognized option: " << argv[i] << std::endl;
95+ }
6496 }
6597 }
66-
67- private:
68- static std::pair<std::string, std::string> parseOption (const std::string &option)
69- {
70- int idx = eatDashes (option);
71- return {getName (idx, option), getValue (idx, option)};
72- }
73-
74- static int eatDashes (const std::string &option)
75- {
76- if (option.size () > 1 && option[0 ] == ' -' && option[1 ] == ' -' )
77- {
78- return 2 ;
79- }
80- throw std::runtime_error (" wrong option scheme use -- before each options" );
81- }
82-
83- static std::string getName (int &index, const std::string &option)
84- {
85- const int begin = index;
86- while (index < option.size () && option[index] != ' =' )
87- {
88- index++;
89- }
90- auto name = option.substr (begin, index - begin);
91- if (name.empty ())
92- {
93- throw std::runtime_error (" option cannot be empty" );
94- }
95- return name;
96- }
97-
98- static std::string getValue (int &index, const std::string &option)
99- {
100- if (index < option.size () && option[index] == ' =' )
101- {
102- index++;
103- }
104- return option.substr (index);
105- }
10698};
10799
108100class Application
109101{
110- CliHandler &_cliHandler;
102+ ICliHandler &_cliHandler;
111103
112104 public:
113- explicit Application (CliHandler * cliHandler) : _cliHandler(* cliHandler) {}
105+ explicit Application (ICliHandler & cliHandler) : _cliHandler(cliHandler) {}
114106
115107 int run (const int argc, char *argv[]) const
116108 {
@@ -125,13 +117,15 @@ class Application
125117 return 0 ;
126118 }
127119};
120+
128121int main (int argc, char *argv[])
129122{
130123 ServiceProvider provider = ServiceCollection{}
131124 .addSingleton <IOptionHandler, HelpOption>()
132125 .addSingleton <IOptionHandler, InfoOption>()
133126 .addSingleton <IOptionHandler, NumberOption>()
134- .addSingleton <CliHandler>()
127+ .addSingleton <IOptionParser, OptionParser>()
128+ .addSingleton <ICliHandler, CliHandler>()
135129 .addScoped <Application>()
136130 .buildServiceProvider ();
137131
0 commit comments