TYPE3
[iec.git] / src / type3_AndroidCloud / anbox-master / src / anbox / cli.h
1 /*
2  * Copyright (C) 2016 Canonical, Ltd.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License as published by
6  * the Free Software Foundation; version 3.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU Lesser General Public License for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public License
14  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
15  *
16  * Authored by: Thomas Voß <thomas.voss@canonical.com>
17  *
18  */
19 #ifndef BIOMETRY_UTIL_CLI_H_
20 #define BIOMETRY_UTIL_CLI_H_
21
22 #include <iomanip>
23 #include <iostream>
24 #include <memory>
25 #include <set>
26 #include <sstream>
27 #include <stdexcept>
28 #include <string>
29 #include <unordered_map>
30
31 #include "anbox/do_not_copy_or_move.h"
32 #include "anbox/optional.h"
33
34 #include <boost/program_options.hpp>
35
36 namespace anbox {
37 namespace cli {
38
39 template <std::size_t max>
40 class SizeConstrainedString {
41  public:
42   SizeConstrainedString(const std::string& s) : s{s} {
43     if (s.size() > max)
44       throw std::logic_error{"Max size exceeded " + std::to_string(max)};
45   }
46
47   const std::string& as_string() const { return s; }
48
49   operator std::string() const { return s; }
50
51  private:
52   std::string s;
53 };
54
55 template <std::size_t max>
56 bool operator<(const SizeConstrainedString<max>& lhs,
57                const SizeConstrainedString<max>& rhs) {
58   return lhs.as_string() < rhs.as_string();
59 }
60
61 template <std::size_t max>
62 bool operator==(const SizeConstrainedString<max>& lhs,
63                 const SizeConstrainedString<max>& rhs) {
64   return lhs.as_string() == rhs.as_string();
65 }
66
67 template <std::size_t max>
68 std::ostream& operator<<(std::ostream& out,
69                          const SizeConstrainedString<max>& scs) {
70   return out << std::setw(max) << std::left << scs.as_string();
71 }
72
73 // We are imposing size constraints to ensure a consistent CLI layout.
74 typedef SizeConstrainedString<30> Name;
75 typedef SizeConstrainedString<60> Usage;
76 typedef SizeConstrainedString<100> Description;
77
78 /// @brief Flag models an input parameter to a command.
79 class Flag : public DoNotCopyOrMove {
80  public:
81   typedef boost::program_options::value_semantic* Specification;
82
83   // Safe us some typing.
84   typedef std::shared_ptr<Flag> Ptr;
85
86   /// @brief name returns the name of the Flag.
87   const Name& name() const;
88   /// @brief description returns a human-readable description of the flag.
89   const Description& description() const;
90
91   /// @brief specify the program option of the flag.
92   virtual void specify_option(Specification& spec) = 0;
93
94  protected:
95   /// @brief Flag creates a new instance, initializing name and description
96   /// from the given values.
97   Flag(const Name& name, const Description& description);
98
99  private:
100   Name name_;
101   Description description_;
102 };
103
104 /// @brief TypedFlag implements Flag relying on operator<< and operator>> to
105 /// read/write values to/from strings.
106 template <typename T>
107 class TypedFlag : public Flag {
108  public:
109   typedef std::shared_ptr<TypedFlag<T>> Ptr;
110
111   TypedFlag(const Name& name, const Description& description)
112       : Flag{name, description} {}
113
114   /// @brief value installs the given value in the flag.
115   TypedFlag& value(const T& value) {
116     value_ = value;
117     return *this;
118   }
119
120   /// @brief value returns the optional value associated with the flag.
121   const Optional<T>& value() const { return value_; }
122
123   /// @brief Option generated by specify_option tries to unwrap a value
124   /// of type T from value.
125   void specify_option(Flag::Specification& spec) override {
126     spec = boost::program_options::value<std::string>()->notifier([&](const std::string& s) {
127       std::stringstream ss{s};
128       T value;
129       ss >> value;
130       value_ = value;
131     });
132   }
133
134  private:
135   Optional<T> value_;
136 };
137
138 /// @brief TypedReferenceFlag implements Flag, relying on operator<</>> to
139 /// convert to/from string representations,
140 /// updating the given mutable reference to a value of type T.
141 template <typename T>
142 class TypedReferenceFlag : public Flag {
143  public:
144   // Safe us some typing.
145   typedef std::shared_ptr<TypedReferenceFlag<T>> Ptr;
146
147   /// @brief TypedReferenceFlag initializes a new instance with name,
148   /// description and value.
149   TypedReferenceFlag(const Name& name, const Description& description, T& value)
150       : Flag{name, description}, value_{value} {}
151
152   /// @brief Option generated by specify_option tries to unwrap a value of type T
153   /// from value, relying on operator>> to read from given string s.
154   void specify_option(Flag::Specification& spec) override {
155     spec = boost::program_options::value<std::string>()->notifier([&](const std::string& s) {
156       std::stringstream ss{s};
157       ss >> value_.get();
158     });
159   }
160
161  private:
162   std::reference_wrapper<T> value_;
163 };
164
165 /// @brief OptionalTypedReferenceFlag handles Optional<T> references, making
166 /// sure that a value is always read on notify, even if the Optional<T> wasn't
167 /// initialized previously.
168 template <typename T>
169 class OptionalTypedReferenceFlag : public Flag {
170  public:
171   typedef std::shared_ptr<OptionalTypedReferenceFlag<T>> Ptr;
172
173   OptionalTypedReferenceFlag(const Name& name, const Description& description,
174                              Optional<T>& value)
175       : Flag{name, description}, value_{value} {}
176
177   /// @brief Option generated by specify_option tries to unwrap a value of
178   /// type T from value.
179   void specify_option(Flag::Specification& spec) override {
180     spec = boost::program_options::value<std::string>()->notifier([&](const std::string& s) {
181       std::stringstream ss{s};
182       T value;
183       ss >> value;
184       value_.get() = value;
185     });
186   }
187
188  private:
189   std::reference_wrapper<Optional<T>> value_;
190 };
191
192 /// @brief BoolSwitchFlag implements Flag, updating the given mutable reference
193 /// to a boolean value.
194 class BoolSwitchFlag : public Flag {
195  public:
196   typedef std::shared_ptr<BoolSwitchFlag> Ptr;
197
198   BoolSwitchFlag(const Name& name, const Description& description, bool& value)
199     : Flag{name, description}, value_(value) {}
200
201   /// @brief Option generated by specify_option tries to unwrap a boolean
202   /// value from value.
203   void specify_option(Flag::Specification& spec) override {
204     spec = boost::program_options::bool_switch(&value_.get());
205   }
206
207  private:
208   std::reference_wrapper<bool> value_;
209 };
210
211 /// @brief Command abstracts an individual command available from the daemon.
212 class Command : public DoNotCopyOrMove {
213  public:
214   // Safe us some typing
215   typedef std::shared_ptr<Command> Ptr;
216
217   /// @brief FlagsMissing is thrown if at least one required flag is missing.
218   struct FlagsMissing : public std::runtime_error {
219     /// @brief FlagsMissing initializes a new instance.
220     FlagsMissing();
221   };
222
223   /// @brief FlagsWithWrongValue is thrown if a value passed on the command line
224   /// is invalid.
225   struct FlagsWithInvalidValue : public std::runtime_error {
226     /// @brief FlagsWithInvalidValue initializes a new instance.
227     FlagsWithInvalidValue();
228   };
229
230   /// @brief Context bundles information passed to Command::run invocations.
231   struct Context {
232     std::istream& cin;              ///< The std::istream that should be used for reading.
233     std::ostream& cout;             ///< The std::ostream that should be used for writing.
234     std::vector<std::string> args;  ///< The command line args.
235   };
236
237   /// @brief name returns the Name of the command.
238   virtual Name name() const;
239
240   /// @brief usage returns a short usage string for the command.
241   virtual Usage usage() const;
242
243   /// @brief description returns a longer string explaining the command.
244   virtual Description description() const;
245
246   /// @brief hidden returns if the command is hidden from the user or not.
247   virtual bool hidden() const;
248
249   /// @brief run puts the command to execution.
250   virtual int run(const Context& context) = 0;
251
252   /// @brief help prints information about a command to out.
253   virtual void help(std::ostream& out) = 0;
254
255  protected:
256   /// @brief Command initializes a new instance with the given name, usage and
257   /// description.
258   Command(const Name& name, const Usage& usage, const Description& description, bool hidden = false);
259
260   /// @brief name adjusts the name of the command to n.
261   // virtual void name(const Name& n);
262   /// @brief usage adjusts the usage string of the comand to u.
263   // virtual void usage(const Usage& u);
264   /// @brief description adjusts the description string of the command to d.
265   // virtual void description(const Description& d);
266
267  private:
268   Name name_;
269   Usage usage_;
270   Description description_;
271   bool hidden_;
272 };
273
274 /// @brief CommandWithSubcommands implements Command, selecting one of a set of
275 /// actions.
276 class CommandWithSubcommands : public Command {
277  public:
278   typedef std::shared_ptr<CommandWithSubcommands> Ptr;
279   typedef std::function<int(const Context&)> Action;
280
281   /// @brief CommandWithSubcommands initializes a new instance with the given
282   /// name, usage and description.
283   CommandWithSubcommands(const Name& name, const Usage& usage,
284                          const Description& description);
285
286   /// @brief command adds the given command to the set of known commands.
287   CommandWithSubcommands& command(const Command::Ptr& command);
288
289   /// @brief flag adds the given flag to the set of known flags.
290   CommandWithSubcommands& flag(const Flag::Ptr& flag);
291
292   // From Command
293   int run(const Context& context) override;
294   void help(std::ostream& out) override;
295
296  private:
297   std::unordered_map<std::string, Command::Ptr> commands_;
298   std::set<Flag::Ptr> flags_;
299 };
300
301 /// @brief CommandWithFlagsAction implements Command, executing an Action after
302 /// handling
303 class CommandWithFlagsAndAction : public Command {
304  public:
305   typedef std::shared_ptr<CommandWithFlagsAndAction> Ptr;
306   typedef std::function<int(const Context&)> Action;
307
308   /// @brief CommandWithFlagsAndAction initializes a new instance with the given
309   /// name, usage and description. Optionally the command can be marked as hidden.
310   CommandWithFlagsAndAction(const Name& name, const Usage& usage,
311                             const Description& description, bool hidden = false);
312
313   /// @brief flag adds the given flag to the set of known flags.
314   CommandWithFlagsAndAction& flag(const Flag::Ptr& flag);
315
316   /// @brief action installs the given action.
317   CommandWithFlagsAndAction& action(const Action& action);
318
319   // From Command
320   int run(const Context& context) override;
321   void help(std::ostream& out) override;
322
323  private:
324   std::set<Flag::Ptr> flags_;
325   Action action_;
326 };
327
328 namespace cmd {
329 /// @brief HelpFor prints a help message for the given command on execution.
330 class Help : public Command {
331  public:
332   /// @brief HelpFor initializes a new instance with the given reference to a
333   /// cmd.
334   explicit Help(Command& cmd);
335
336   // From Command
337   int run(const Context& context) override;
338   void help(std::ostream& out) override;
339
340  private:
341   /// @cond
342   Command& command;
343   /// @endcond
344 };
345 }
346
347 /// @brief args returns a vector of strings assembled from argc and argv.
348 std::vector<std::string> args(int argc, char** argv);
349
350 /// @brief make_flag returns a flag with the given name and description.
351 template <typename T>
352 typename TypedFlag<T>::Ptr make_flag(const Name& name,
353                                      const Description& description) {
354   return std::make_shared<TypedFlag<T>>(name, description);
355 }
356
357 /// @brief make_flag returns a flag with the given name and description,
358 /// notifying updates to value.
359 template <typename T>
360 typename TypedReferenceFlag<T>::Ptr make_flag(const Name& name,
361                                               const Description& desc,
362                                               T& value) {
363   return std::make_shared<TypedReferenceFlag<T>>(name, desc, value);
364 }
365
366 /// @brief make_flag returns a flag with the given name and description,
367 /// updating the given optional value.
368 template <typename T>
369 typename OptionalTypedReferenceFlag<T>::Ptr make_flag(const Name& name,
370                                                       const Description& desc,
371                                                       Optional<T>& value) {
372   return std::make_shared<OptionalTypedReferenceFlag<T>>(name, desc, value);
373 }
374
375 /// @brief make_flag returns a flag with the given name and description,
376 /// updating the given boolean value.
377 inline BoolSwitchFlag::Ptr make_flag(const Name& name,
378                                      const Description &desc,
379                                      bool &value) {
380   return std::make_shared<BoolSwitchFlag>(name, desc, value);
381 }
382
383 }  // namespace cli
384 }  // namespace anbox
385
386 #endif