Junxiao Shi | 64567bb | 2016-09-04 16:00:27 +0000 | [diff] [blame] | 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ |
Eric Newberry | 84d3adc | 2017-08-09 23:31:40 -0400 | [diff] [blame] | 2 | /* |
Davide Pesavento | b7bfcb9 | 2022-05-22 23:55:23 -0400 | [diff] [blame] | 3 | * Copyright (c) 2014-2022, Regents of the University of California, |
Junxiao Shi | 64567bb | 2016-09-04 16:00:27 +0000 | [diff] [blame] | 4 | * Arizona Board of Regents, |
| 5 | * Colorado State University, |
| 6 | * University Pierre & Marie Curie, Sorbonne University, |
| 7 | * Washington University in St. Louis, |
| 8 | * Beijing Institute of Technology, |
| 9 | * The University of Memphis. |
| 10 | * |
| 11 | * This file is part of NFD (Named Data Networking Forwarding Daemon). |
| 12 | * See AUTHORS.md for complete list of NFD authors and contributors. |
| 13 | * |
| 14 | * NFD is free software: you can redistribute it and/or modify it under the terms |
| 15 | * of the GNU General Public License as published by the Free Software Foundation, |
| 16 | * either version 3 of the License, or (at your option) any later version. |
| 17 | * |
| 18 | * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; |
| 19 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
| 20 | * PURPOSE. See the GNU General Public License for more details. |
| 21 | * |
| 22 | * You should have received a copy of the GNU General Public License along with |
| 23 | * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>. |
| 24 | */ |
| 25 | |
| 26 | #ifndef NFD_TOOLS_NFDC_COMMAND_DEFINITION_HPP |
| 27 | #define NFD_TOOLS_NFDC_COMMAND_DEFINITION_HPP |
| 28 | |
| 29 | #include "command-arguments.hpp" |
| 30 | |
Davide Pesavento | e422f9e | 2022-06-03 01:30:23 -0400 | [diff] [blame] | 31 | namespace nfd::tools::nfdc { |
Junxiao Shi | 64567bb | 2016-09-04 16:00:27 +0000 | [diff] [blame] | 32 | |
Davide Pesavento | aa9e3b2 | 2022-10-21 17:00:07 -0400 | [diff] [blame] | 33 | /** \brief Indicates argument value type. |
Junxiao Shi | 64567bb | 2016-09-04 16:00:27 +0000 | [diff] [blame] | 34 | */ |
| 35 | enum class ArgValueType { |
Davide Pesavento | aa9e3b2 | 2022-10-21 17:00:07 -0400 | [diff] [blame] | 36 | /** \brief Boolean argument without value. |
Junxiao Shi | 64567bb | 2016-09-04 16:00:27 +0000 | [diff] [blame] | 37 | * |
Davide Pesavento | e422f9e | 2022-06-03 01:30:23 -0400 | [diff] [blame] | 38 | * The argument appears in CommandArguments as bool value `true`. |
Junxiao Shi | 64567bb | 2016-09-04 16:00:27 +0000 | [diff] [blame] | 39 | * It must not be declared as positional. |
| 40 | */ |
| 41 | NONE, |
| 42 | |
Davide Pesavento | aa9e3b2 | 2022-10-21 17:00:07 -0400 | [diff] [blame] | 43 | /** \brief Any arguments. |
Junxiao Shi | 64567bb | 2016-09-04 16:00:27 +0000 | [diff] [blame] | 44 | * |
| 45 | * The argument appears in CommandArguments as std::vector<std::string>. |
| 46 | * It must be declared as positional, and will consume all subsequent tokens. |
| 47 | */ |
| 48 | ANY, |
| 49 | |
Davide Pesavento | aa9e3b2 | 2022-10-21 17:00:07 -0400 | [diff] [blame] | 50 | /** \brief Boolean. |
Eric Newberry | 84d3adc | 2017-08-09 23:31:40 -0400 | [diff] [blame] | 51 | * |
| 52 | * The argument appears in CommandArguments as bool. |
| 53 | */ |
| 54 | BOOLEAN, |
| 55 | |
Davide Pesavento | aa9e3b2 | 2022-10-21 17:00:07 -0400 | [diff] [blame] | 56 | /** \brief Non-negative integer. |
Junxiao Shi | 64567bb | 2016-09-04 16:00:27 +0000 | [diff] [blame] | 57 | * |
| 58 | * The argument appears in CommandArguments as uint64_t. |
| 59 | * Acceptable input range is [0, std::numeric_limits<int64_t>::max()]. |
| 60 | */ |
| 61 | UNSIGNED, |
| 62 | |
Davide Pesavento | aa9e3b2 | 2022-10-21 17:00:07 -0400 | [diff] [blame] | 63 | /** \brief Arbitrary string. |
Junxiao Shi | 64567bb | 2016-09-04 16:00:27 +0000 | [diff] [blame] | 64 | * |
| 65 | * The argument appears in CommandArguments as std::string. |
| 66 | */ |
| 67 | STRING, |
| 68 | |
Davide Pesavento | aa9e3b2 | 2022-10-21 17:00:07 -0400 | [diff] [blame] | 69 | /** \brief Report format 'xml' or 'text'. |
Junxiao Shi | 64567bb | 2016-09-04 16:00:27 +0000 | [diff] [blame] | 70 | * |
| 71 | * The argument appears in CommandArguments as nfd::tools::nfdc::ReportFormat. |
| 72 | */ |
| 73 | REPORT_FORMAT, |
| 74 | |
Davide Pesavento | aa9e3b2 | 2022-10-21 17:00:07 -0400 | [diff] [blame] | 75 | /** \brief Name prefix. |
Junxiao Shi | 64567bb | 2016-09-04 16:00:27 +0000 | [diff] [blame] | 76 | * |
| 77 | * The argument appears in CommandArguments as ndn::Name. |
| 78 | */ |
| 79 | NAME, |
| 80 | |
Davide Pesavento | aa9e3b2 | 2022-10-21 17:00:07 -0400 | [diff] [blame] | 81 | /** \brief FaceUri. |
Junxiao Shi | 64567bb | 2016-09-04 16:00:27 +0000 | [diff] [blame] | 82 | * |
Junxiao Shi | 83be1da | 2017-06-30 13:37:37 +0000 | [diff] [blame] | 83 | * The argument appears in CommandArguments as ndn::FaceUri. |
Junxiao Shi | 64567bb | 2016-09-04 16:00:27 +0000 | [diff] [blame] | 84 | */ |
| 85 | FACE_URI, |
| 86 | |
Davide Pesavento | aa9e3b2 | 2022-10-21 17:00:07 -0400 | [diff] [blame] | 87 | /** \brief FaceId or FaceUri. |
Junxiao Shi | 64567bb | 2016-09-04 16:00:27 +0000 | [diff] [blame] | 88 | * |
Junxiao Shi | 83be1da | 2017-06-30 13:37:37 +0000 | [diff] [blame] | 89 | * The argument appears in CommandArguments as either uint64_t or ndn::FaceUri. |
Junxiao Shi | 64567bb | 2016-09-04 16:00:27 +0000 | [diff] [blame] | 90 | */ |
| 91 | FACE_ID_OR_URI, |
| 92 | |
Davide Pesavento | aa9e3b2 | 2022-10-21 17:00:07 -0400 | [diff] [blame] | 93 | /** \brief Face persistency 'persistent' or 'permanent'. |
Junxiao Shi | 64567bb | 2016-09-04 16:00:27 +0000 | [diff] [blame] | 94 | * |
| 95 | * The argument appears in CommandArguments as ndn::nfd::FacePersistency. |
| 96 | */ |
Junxiao Shi | 8eda682 | 2017-04-12 02:53:14 +0000 | [diff] [blame] | 97 | FACE_PERSISTENCY, |
| 98 | |
Davide Pesavento | aa9e3b2 | 2022-10-21 17:00:07 -0400 | [diff] [blame] | 99 | /** \brief Route origin. |
Junxiao Shi | 8eda682 | 2017-04-12 02:53:14 +0000 | [diff] [blame] | 100 | * |
| 101 | * The argument appears in CommandArguments as ndn::nfd::RouteOrigin. |
| 102 | */ |
| 103 | ROUTE_ORIGIN, |
Junxiao Shi | 64567bb | 2016-09-04 16:00:27 +0000 | [diff] [blame] | 104 | }; |
| 105 | |
| 106 | std::ostream& |
| 107 | operator<<(std::ostream& os, ArgValueType vt); |
| 108 | |
Davide Pesavento | aa9e3b2 | 2022-10-21 17:00:07 -0400 | [diff] [blame] | 109 | /** \brief Indicates whether an argument is required. |
Junxiao Shi | 64567bb | 2016-09-04 16:00:27 +0000 | [diff] [blame] | 110 | */ |
| 111 | enum class Required { |
| 112 | NO = false, ///< argument is optional |
| 113 | YES = true ///< argument is required |
| 114 | }; |
| 115 | |
Davide Pesavento | aa9e3b2 | 2022-10-21 17:00:07 -0400 | [diff] [blame] | 116 | /** \brief Indicates whether an argument can be specified as positional. |
Junxiao Shi | 64567bb | 2016-09-04 16:00:27 +0000 | [diff] [blame] | 117 | */ |
| 118 | enum class Positional { |
| 119 | NO = false, ///< argument must be named |
| 120 | YES = true ///< argument can be specified as positional |
| 121 | }; |
| 122 | |
Davide Pesavento | a3a7a4e | 2022-05-29 16:06:22 -0400 | [diff] [blame] | 123 | /** |
Davide Pesavento | aa9e3b2 | 2022-10-21 17:00:07 -0400 | [diff] [blame] | 124 | * \brief Defines a command. |
Junxiao Shi | 64567bb | 2016-09-04 16:00:27 +0000 | [diff] [blame] | 125 | */ |
| 126 | class CommandDefinition |
| 127 | { |
| 128 | public: |
| 129 | class Error : public std::invalid_argument |
| 130 | { |
| 131 | public: |
Davide Pesavento | 8b663a9 | 2018-11-21 22:57:20 -0500 | [diff] [blame] | 132 | using std::invalid_argument::invalid_argument; |
Junxiao Shi | 64567bb | 2016-09-04 16:00:27 +0000 | [diff] [blame] | 133 | }; |
| 134 | |
Davide Pesavento | a3a7a4e | 2022-05-29 16:06:22 -0400 | [diff] [blame] | 135 | CommandDefinition(std::string_view noun, std::string_view verb); |
Junxiao Shi | 64567bb | 2016-09-04 16:00:27 +0000 | [diff] [blame] | 136 | |
| 137 | ~CommandDefinition(); |
| 138 | |
Davide Pesavento | a3a7a4e | 2022-05-29 16:06:22 -0400 | [diff] [blame] | 139 | const std::string& |
Junxiao Shi | 64567bb | 2016-09-04 16:00:27 +0000 | [diff] [blame] | 140 | getNoun() const |
| 141 | { |
| 142 | return m_noun; |
| 143 | } |
| 144 | |
Davide Pesavento | a3a7a4e | 2022-05-29 16:06:22 -0400 | [diff] [blame] | 145 | const std::string& |
Junxiao Shi | 64567bb | 2016-09-04 16:00:27 +0000 | [diff] [blame] | 146 | getVerb() const |
| 147 | { |
| 148 | return m_verb; |
| 149 | } |
| 150 | |
| 151 | public: // help |
Junxiao Shi | 6c13562 | 2016-11-21 14:30:33 +0000 | [diff] [blame] | 152 | /** \return one-line description |
Junxiao Shi | 64567bb | 2016-09-04 16:00:27 +0000 | [diff] [blame] | 153 | */ |
| 154 | const std::string& |
Junxiao Shi | 6c13562 | 2016-11-21 14:30:33 +0000 | [diff] [blame] | 155 | getTitle() const |
Junxiao Shi | 64567bb | 2016-09-04 16:00:27 +0000 | [diff] [blame] | 156 | { |
Junxiao Shi | 6c13562 | 2016-11-21 14:30:33 +0000 | [diff] [blame] | 157 | return m_title; |
Junxiao Shi | 64567bb | 2016-09-04 16:00:27 +0000 | [diff] [blame] | 158 | } |
| 159 | |
Davide Pesavento | aa9e3b2 | 2022-10-21 17:00:07 -0400 | [diff] [blame] | 160 | /** \brief Set one-line description. |
Junxiao Shi | 6c13562 | 2016-11-21 14:30:33 +0000 | [diff] [blame] | 161 | * \param title one-line description, written in lower case |
Junxiao Shi | 64567bb | 2016-09-04 16:00:27 +0000 | [diff] [blame] | 162 | */ |
| 163 | CommandDefinition& |
Davide Pesavento | a3a7a4e | 2022-05-29 16:06:22 -0400 | [diff] [blame] | 164 | setTitle(std::string_view title) |
Junxiao Shi | 64567bb | 2016-09-04 16:00:27 +0000 | [diff] [blame] | 165 | { |
Junxiao Shi | 6c13562 | 2016-11-21 14:30:33 +0000 | [diff] [blame] | 166 | m_title = title; |
Junxiao Shi | 64567bb | 2016-09-04 16:00:27 +0000 | [diff] [blame] | 167 | return *this; |
| 168 | } |
| 169 | |
| 170 | public: // arguments |
Davide Pesavento | aa9e3b2 | 2022-10-21 17:00:07 -0400 | [diff] [blame] | 171 | /** \brief Declare an argument. |
Junxiao Shi | 64567bb | 2016-09-04 16:00:27 +0000 | [diff] [blame] | 172 | * \param name argument name, must be unique |
| 173 | * \param valueType argument value type |
| 174 | * \param isRequired whether the argument is required |
| 175 | * \param allowPositional whether the argument value can be specified as positional |
| 176 | * \param metavar displayed argument value placeholder |
| 177 | */ |
| 178 | CommandDefinition& |
| 179 | addArg(const std::string& name, ArgValueType valueType, |
| 180 | Required isRequired = Required::NO, |
| 181 | Positional allowPositional = Positional::NO, |
| 182 | const std::string& metavar = ""); |
| 183 | |
Davide Pesavento | aa9e3b2 | 2022-10-21 17:00:07 -0400 | [diff] [blame] | 184 | /** \brief Parse a command line. |
Junxiao Shi | 64567bb | 2016-09-04 16:00:27 +0000 | [diff] [blame] | 185 | * \param tokens command line tokens |
| 186 | * \param start command line start position, after noun and verb |
| 187 | * \throw Error command line is invalid |
| 188 | */ |
| 189 | CommandArguments |
| 190 | parse(const std::vector<std::string>& tokens, size_t start = 0) const; |
| 191 | |
| 192 | private: |
Davide Pesavento | a3a7a4e | 2022-05-29 16:06:22 -0400 | [diff] [blame] | 193 | static std::any |
| 194 | parseValue(ArgValueType valueType, const std::string& token); |
Junxiao Shi | 64567bb | 2016-09-04 16:00:27 +0000 | [diff] [blame] | 195 | |
| 196 | private: |
Davide Pesavento | a3a7a4e | 2022-05-29 16:06:22 -0400 | [diff] [blame] | 197 | const std::string m_noun; |
| 198 | const std::string m_verb; |
Junxiao Shi | 6c13562 | 2016-11-21 14:30:33 +0000 | [diff] [blame] | 199 | std::string m_title; |
Junxiao Shi | 64567bb | 2016-09-04 16:00:27 +0000 | [diff] [blame] | 200 | |
| 201 | struct Arg |
| 202 | { |
| 203 | std::string name; |
| 204 | ArgValueType valueType; |
| 205 | bool isRequired; |
| 206 | std::string metavar; |
| 207 | }; |
Davide Pesavento | 8b663a9 | 2018-11-21 22:57:20 -0500 | [diff] [blame] | 208 | std::map<std::string, Arg> m_args; |
Junxiao Shi | 64567bb | 2016-09-04 16:00:27 +0000 | [diff] [blame] | 209 | std::set<std::string> m_requiredArgs; |
| 210 | std::vector<std::string> m_positionalArgs; |
| 211 | }; |
| 212 | |
Davide Pesavento | e422f9e | 2022-06-03 01:30:23 -0400 | [diff] [blame] | 213 | } // namespace nfd::tools::nfdc |
Junxiao Shi | 64567bb | 2016-09-04 16:00:27 +0000 | [diff] [blame] | 214 | |
| 215 | #endif // NFD_TOOLS_NFDC_COMMAND_DEFINITION_HPP |