TYPE3
[iec.git] / src / type3_AndroidCloud / anbox-master / src / anbox / cli.h
diff --git a/src/type3_AndroidCloud/anbox-master/src/anbox/cli.h b/src/type3_AndroidCloud/anbox-master/src/anbox/cli.h
new file mode 100644 (file)
index 0000000..09a06e3
--- /dev/null
@@ -0,0 +1,386 @@
+/*
+ * Copyright (C) 2016 Canonical, Ltd.
+ *
+ * This program 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; version 3.
+ *
+ * This program 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 program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Thomas Voß <thomas.voss@canonical.com>
+ *
+ */
+#ifndef BIOMETRY_UTIL_CLI_H_
+#define BIOMETRY_UTIL_CLI_H_
+
+#include <iomanip>
+#include <iostream>
+#include <memory>
+#include <set>
+#include <sstream>
+#include <stdexcept>
+#include <string>
+#include <unordered_map>
+
+#include "anbox/do_not_copy_or_move.h"
+#include "anbox/optional.h"
+
+#include <boost/program_options.hpp>
+
+namespace anbox {
+namespace cli {
+
+template <std::size_t max>
+class SizeConstrainedString {
+ public:
+  SizeConstrainedString(const std::string& s) : s{s} {
+    if (s.size() > max)
+      throw std::logic_error{"Max size exceeded " + std::to_string(max)};
+  }
+
+  const std::string& as_string() const { return s; }
+
+  operator std::string() const { return s; }
+
+ private:
+  std::string s;
+};
+
+template <std::size_t max>
+bool operator<(const SizeConstrainedString<max>& lhs,
+               const SizeConstrainedString<max>& rhs) {
+  return lhs.as_string() < rhs.as_string();
+}
+
+template <std::size_t max>
+bool operator==(const SizeConstrainedString<max>& lhs,
+                const SizeConstrainedString<max>& rhs) {
+  return lhs.as_string() == rhs.as_string();
+}
+
+template <std::size_t max>
+std::ostream& operator<<(std::ostream& out,
+                         const SizeConstrainedString<max>& scs) {
+  return out << std::setw(max) << std::left << scs.as_string();
+}
+
+// We are imposing size constraints to ensure a consistent CLI layout.
+typedef SizeConstrainedString<30> Name;
+typedef SizeConstrainedString<60> Usage;
+typedef SizeConstrainedString<100> Description;
+
+/// @brief Flag models an input parameter to a command.
+class Flag : public DoNotCopyOrMove {
+ public:
+  typedef boost::program_options::value_semantic* Specification;
+
+  // Safe us some typing.
+  typedef std::shared_ptr<Flag> Ptr;
+
+  /// @brief name returns the name of the Flag.
+  const Name& name() const;
+  /// @brief description returns a human-readable description of the flag.
+  const Description& description() const;
+
+  /// @brief specify the program option of the flag.
+  virtual void specify_option(Specification& spec) = 0;
+
+ protected:
+  /// @brief Flag creates a new instance, initializing name and description
+  /// from the given values.
+  Flag(const Name& name, const Description& description);
+
+ private:
+  Name name_;
+  Description description_;
+};
+
+/// @brief TypedFlag implements Flag relying on operator<< and operator>> to
+/// read/write values to/from strings.
+template <typename T>
+class TypedFlag : public Flag {
+ public:
+  typedef std::shared_ptr<TypedFlag<T>> Ptr;
+
+  TypedFlag(const Name& name, const Description& description)
+      : Flag{name, description} {}
+
+  /// @brief value installs the given value in the flag.
+  TypedFlag& value(const T& value) {
+    value_ = value;
+    return *this;
+  }
+
+  /// @brief value returns the optional value associated with the flag.
+  const Optional<T>& value() const { return value_; }
+
+  /// @brief Option generated by specify_option tries to unwrap a value
+  /// of type T from value.
+  void specify_option(Flag::Specification& spec) override {
+    spec = boost::program_options::value<std::string>()->notifier([&](const std::string& s) {
+      std::stringstream ss{s};
+      T value;
+      ss >> value;
+      value_ = value;
+    });
+  }
+
+ private:
+  Optional<T> value_;
+};
+
+/// @brief TypedReferenceFlag implements Flag, relying on operator<</>> to
+/// convert to/from string representations,
+/// updating the given mutable reference to a value of type T.
+template <typename T>
+class TypedReferenceFlag : public Flag {
+ public:
+  // Safe us some typing.
+  typedef std::shared_ptr<TypedReferenceFlag<T>> Ptr;
+
+  /// @brief TypedReferenceFlag initializes a new instance with name,
+  /// description and value.
+  TypedReferenceFlag(const Name& name, const Description& description, T& value)
+      : Flag{name, description}, value_{value} {}
+
+  /// @brief Option generated by specify_option tries to unwrap a value of type T
+  /// from value, relying on operator>> to read from given string s.
+  void specify_option(Flag::Specification& spec) override {
+    spec = boost::program_options::value<std::string>()->notifier([&](const std::string& s) {
+      std::stringstream ss{s};
+      ss >> value_.get();
+    });
+  }
+
+ private:
+  std::reference_wrapper<T> value_;
+};
+
+/// @brief OptionalTypedReferenceFlag handles Optional<T> references, making
+/// sure that a value is always read on notify, even if the Optional<T> wasn't
+/// initialized previously.
+template <typename T>
+class OptionalTypedReferenceFlag : public Flag {
+ public:
+  typedef std::shared_ptr<OptionalTypedReferenceFlag<T>> Ptr;
+
+  OptionalTypedReferenceFlag(const Name& name, const Description& description,
+                             Optional<T>& value)
+      : Flag{name, description}, value_{value} {}
+
+  /// @brief Option generated by specify_option tries to unwrap a value of
+  /// type T from value.
+  void specify_option(Flag::Specification& spec) override {
+    spec = boost::program_options::value<std::string>()->notifier([&](const std::string& s) {
+      std::stringstream ss{s};
+      T value;
+      ss >> value;
+      value_.get() = value;
+    });
+  }
+
+ private:
+  std::reference_wrapper<Optional<T>> value_;
+};
+
+/// @brief BoolSwitchFlag implements Flag, updating the given mutable reference
+/// to a boolean value.
+class BoolSwitchFlag : public Flag {
+ public:
+  typedef std::shared_ptr<BoolSwitchFlag> Ptr;
+
+  BoolSwitchFlag(const Name& name, const Description& description, bool& value)
+    : Flag{name, description}, value_(value) {}
+
+  /// @brief Option generated by specify_option tries to unwrap a boolean
+  /// value from value.
+  void specify_option(Flag::Specification& spec) override {
+    spec = boost::program_options::bool_switch(&value_.get());
+  }
+
+ private:
+  std::reference_wrapper<bool> value_;
+};
+
+/// @brief Command abstracts an individual command available from the daemon.
+class Command : public DoNotCopyOrMove {
+ public:
+  // Safe us some typing
+  typedef std::shared_ptr<Command> Ptr;
+
+  /// @brief FlagsMissing is thrown if at least one required flag is missing.
+  struct FlagsMissing : public std::runtime_error {
+    /// @brief FlagsMissing initializes a new instance.
+    FlagsMissing();
+  };
+
+  /// @brief FlagsWithWrongValue is thrown if a value passed on the command line
+  /// is invalid.
+  struct FlagsWithInvalidValue : public std::runtime_error {
+    /// @brief FlagsWithInvalidValue initializes a new instance.
+    FlagsWithInvalidValue();
+  };
+
+  /// @brief Context bundles information passed to Command::run invocations.
+  struct Context {
+    std::istream& cin;              ///< The std::istream that should be used for reading.
+    std::ostream& cout;             ///< The std::ostream that should be used for writing.
+    std::vector<std::string> args;  ///< The command line args.
+  };
+
+  /// @brief name returns the Name of the command.
+  virtual Name name() const;
+
+  /// @brief usage returns a short usage string for the command.
+  virtual Usage usage() const;
+
+  /// @brief description returns a longer string explaining the command.
+  virtual Description description() const;
+
+  /// @brief hidden returns if the command is hidden from the user or not.
+  virtual bool hidden() const;
+
+  /// @brief run puts the command to execution.
+  virtual int run(const Context& context) = 0;
+
+  /// @brief help prints information about a command to out.
+  virtual void help(std::ostream& out) = 0;
+
+ protected:
+  /// @brief Command initializes a new instance with the given name, usage and
+  /// description.
+  Command(const Name& name, const Usage& usage, const Description& description, bool hidden = false);
+
+  /// @brief name adjusts the name of the command to n.
+  // virtual void name(const Name& n);
+  /// @brief usage adjusts the usage string of the comand to u.
+  // virtual void usage(const Usage& u);
+  /// @brief description adjusts the description string of the command to d.
+  // virtual void description(const Description& d);
+
+ private:
+  Name name_;
+  Usage usage_;
+  Description description_;
+  bool hidden_;
+};
+
+/// @brief CommandWithSubcommands implements Command, selecting one of a set of
+/// actions.
+class CommandWithSubcommands : public Command {
+ public:
+  typedef std::shared_ptr<CommandWithSubcommands> Ptr;
+  typedef std::function<int(const Context&)> Action;
+
+  /// @brief CommandWithSubcommands initializes a new instance with the given
+  /// name, usage and description.
+  CommandWithSubcommands(const Name& name, const Usage& usage,
+                         const Description& description);
+
+  /// @brief command adds the given command to the set of known commands.
+  CommandWithSubcommands& command(const Command::Ptr& command);
+
+  /// @brief flag adds the given flag to the set of known flags.
+  CommandWithSubcommands& flag(const Flag::Ptr& flag);
+
+  // From Command
+  int run(const Context& context) override;
+  void help(std::ostream& out) override;
+
+ private:
+  std::unordered_map<std::string, Command::Ptr> commands_;
+  std::set<Flag::Ptr> flags_;
+};
+
+/// @brief CommandWithFlagsAction implements Command, executing an Action after
+/// handling
+class CommandWithFlagsAndAction : public Command {
+ public:
+  typedef std::shared_ptr<CommandWithFlagsAndAction> Ptr;
+  typedef std::function<int(const Context&)> Action;
+
+  /// @brief CommandWithFlagsAndAction initializes a new instance with the given
+  /// name, usage and description. Optionally the command can be marked as hidden.
+  CommandWithFlagsAndAction(const Name& name, const Usage& usage,
+                            const Description& description, bool hidden = false);
+
+  /// @brief flag adds the given flag to the set of known flags.
+  CommandWithFlagsAndAction& flag(const Flag::Ptr& flag);
+
+  /// @brief action installs the given action.
+  CommandWithFlagsAndAction& action(const Action& action);
+
+  // From Command
+  int run(const Context& context) override;
+  void help(std::ostream& out) override;
+
+ private:
+  std::set<Flag::Ptr> flags_;
+  Action action_;
+};
+
+namespace cmd {
+/// @brief HelpFor prints a help message for the given command on execution.
+class Help : public Command {
+ public:
+  /// @brief HelpFor initializes a new instance with the given reference to a
+  /// cmd.
+  explicit Help(Command& cmd);
+
+  // From Command
+  int run(const Context& context) override;
+  void help(std::ostream& out) override;
+
+ private:
+  /// @cond
+  Command& command;
+  /// @endcond
+};
+}
+
+/// @brief args returns a vector of strings assembled from argc and argv.
+std::vector<std::string> args(int argc, char** argv);
+
+/// @brief make_flag returns a flag with the given name and description.
+template <typename T>
+typename TypedFlag<T>::Ptr make_flag(const Name& name,
+                                     const Description& description) {
+  return std::make_shared<TypedFlag<T>>(name, description);
+}
+
+/// @brief make_flag returns a flag with the given name and description,
+/// notifying updates to value.
+template <typename T>
+typename TypedReferenceFlag<T>::Ptr make_flag(const Name& name,
+                                              const Description& desc,
+                                              T& value) {
+  return std::make_shared<TypedReferenceFlag<T>>(name, desc, value);
+}
+
+/// @brief make_flag returns a flag with the given name and description,
+/// updating the given optional value.
+template <typename T>
+typename OptionalTypedReferenceFlag<T>::Ptr make_flag(const Name& name,
+                                                      const Description& desc,
+                                                      Optional<T>& value) {
+  return std::make_shared<OptionalTypedReferenceFlag<T>>(name, desc, value);
+}
+
+/// @brief make_flag returns a flag with the given name and description,
+/// updating the given boolean value.
+inline BoolSwitchFlag::Ptr make_flag(const Name& name,
+                                     const Description &desc,
+                                     bool &value) {
+  return std::make_shared<BoolSwitchFlag>(name, desc, value);
+}
+
+}  // namespace cli
+}  // namespace anbox
+
+#endif