Mercurial > irccd
diff lib/irccd/command/command.h @ 72:98ac3c79009f
Irccd: start making a library, #429
author | David Demelier <markand@malikania.fr> |
---|---|
date | Thu, 24 Mar 2016 14:07:30 +0100 |
parents | |
children | 8ee1178f1219 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/irccd/command/command.h Thu Mar 24 14:07:30 2016 +0100 @@ -0,0 +1,298 @@ +#ifndef _REMOTE_COMMAND_H_ +#define _REMOTE_COMMAND_H_ + +#include <cassert> +#include <cstdint> +#include <map> +#include <vector> + +#include <irccd/json.h> + +namespace irccd { + +class Irccd; +class Irccdctl; + +/** + * @class RemoteCommandOption + * @brief Describe a command line option + */ +class RemoteCommandOption { +public: + enum { + Argument = (1 << 0) //!< option requires an argument + }; + +private: + std::string m_id; + std::string m_simple; + std::string m_long; + std::string m_description; + std::uint8_t m_flags; + +public: + /** + * Constructor an option description. + * + * @pre id must not be empty + * @pre at least simpleKey or longKey must not be empty + * @pre description must not be empty + * @param key the key the option key + * @param description the description + * @param flags the optional flags + */ + inline RemoteCommandOption(std::string id, + std::string simpleKey, + std::string longKey, + std::string description, + std::uint8_t flags = 0) noexcept + : m_id(std::move(id)) + , m_simple(std::move(simpleKey)) + , m_long(std::move(longKey)) + , m_description(std::move(description)) + , m_flags(flags) + { + assert(!m_id.empty()); + assert(!m_simple.empty() || !m_long.empty()); + assert(!m_description.empty()); + } + + /** + * Get the id. + * + * @return the id + */ + inline const std::string &id() const noexcept + { + return m_id; + } + + /** + * Get the option key. + * + * @return the key + */ + inline const std::string &simpleKey() const noexcept + { + return m_simple; + } + + /** + * Get the long option. + * + * @return the long option + */ + inline const std::string &longKey() const noexcept + { + return m_long; + } + + /** + * Get the option description. + * + * @return the description + */ + inline const std::string &description() const noexcept + { + return m_description; + } + + /** + * Get the option flags. + * + * @return the flags + */ + inline std::uint8_t flags() const noexcept + { + return m_flags; + } +}; + +/** + * @brief List of command line options. + */ +using RemoteCommandOptions = std::vector<RemoteCommandOption>; + +using RemoteCommandArg = std::pair<std::string, bool>; + +/** + * @brief List of arguments to pass to the command. + * + * Any argument must have a non-empty name an can be optional if the boolean is set to false. + */ +using RemoteCommandArgs = std::vector<std::pair<std::string, bool>>; + +class RemoteCommandRequest { +private: + std::multimap<std::string, std::string> m_options; + std::vector<std::string> m_args; + +public: + inline RemoteCommandRequest(std::multimap<std::string, std::string> options, std::vector<std::string> args) noexcept + : m_options(std::move(options)) + , m_args(std::move(args)) + { + } + + inline const std::vector<std::string> &args() const noexcept + { + return m_args; + } + + inline const std::multimap<std::string, std::string> &options() const noexcept + { + return m_options; + } + + inline unsigned length() const noexcept + { + return m_args.size(); + } + + inline bool has(const std::string &option) const noexcept + { + return m_options.count(option) != 0; + } + + const std::string &arg(unsigned index) const noexcept; + + std::string argOr(unsigned index, std::string defaultValue) const noexcept; + + const std::string &option(const std::string &key) const noexcept; + + std::string optionOr(const std::string &key, std::string defaultValue) const noexcept; +}; + +class RemoteCommand { +private: + std::string m_name; + std::string m_category; + bool m_visible; + +public: + inline RemoteCommand(std::string name, std::string category, bool visible = true) noexcept + : m_name(std::move(name)) + , m_category(std::move(category)) + , m_visible(visible) + { + assert(!m_name.empty()); + assert(!m_category.empty()); + } + + /** + * Default destructor virtual. + */ + virtual ~RemoteCommand() = default; + + /** + * Return the command name, must not have spaces. + * + * @return the command name + */ + inline const std::string &name() const noexcept + { + return m_name; + } + + /** + * Get the command category. + * + * Irccdctl will sort commands by categories. + * + * @return the category + */ + inline const std::string &category() const noexcept + { + return m_category; + } + + /** + * Hide the command in non-verbose mode. + * + * @return true if the command should be visible in non-verbose mode + */ + inline bool visible() const noexcept + { + return m_visible; + } + + /** + * Return the command usage, without the prefix. (e.g. host port). + * + * Options are prepended automatically + * + * @return the usage + */ + std::string usage() const; + + /** + * Return the help message for irccdctl invocation. + * + * @return the help + */ + virtual std::string help() const = 0; + + /** + * Get the supported irccdctl options. + * + * @return the options + */ + virtual RemoteCommandOptions options() const + { + return RemoteCommandOptions(); + } + + /** + * Get the supported arguments. + * + * @return the arguments + */ + virtual RemoteCommandArgs args() const + { + return RemoteCommandArgs(); + } + + /** + * Prepare a JSON request to the daemon. + * + * If the command is local and does not need to send anything to irccd's instance, return a null JSON value. + * + * The default implementation just send the command name with no arguments. + * + * @param irccdctl the irccdctl instance + * @param args the command line arguments and options + * @return the JSON object to send to the daemon + * @post the returned JSON value must be an object + */ + virtual json::Value request(Irccdctl &irccdctl, const RemoteCommandRequest &args) const; + + /** + * Execute the command in the daemon. + * + * The user can return an object with any properties to forward to the client. Irccd will automatically + * add the command name and the appropriate status code. + * + * The default return an empty object which indicates success. + * + * If any exception is thrown from this function, it is forwarded to the client as error status. + * + * @param irccd the instance + * @param request the JSON request + * @return the response + */ + virtual json::Value exec(Irccd &irccd, const json::Value &request) const; + + /** + * What to do when receiving the response from irccd. + * + * This default implementation just check for an error string and shows it if any. + * + * @param irccdctl the irccdctl instane + * @param object the result + */ + virtual void result(Irccdctl &irccdctl, const json::Value &response) const; +}; + +} // !irccd + +#endif // !_REMOTE_COMMAND_H_