1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #pragma once 18 19 #include <deque> 20 #include <functional> 21 #include <memory> 22 #include <optional> 23 #include <ostream> 24 #include <string> 25 #include <unordered_set> 26 #include <vector> 27 28 #include "androidfw/StringPiece.h" 29 30 namespace aapt { 31 32 class Command { 33 public: Command(android::StringPiece name)34 explicit Command(android::StringPiece name) : Command(name, {}) { 35 } 36 Command(android::StringPiece name,android::StringPiece short_name)37 explicit Command(android::StringPiece name, android::StringPiece short_name) 38 : name_(name), short_name_(short_name), full_subcommand_name_(name) { 39 flags_.emplace_back("--help", "Displays this help menu", false, 0, 40 [this](android::StringPiece arg, std::ostream* out) { 41 Usage(out); 42 return false; 43 }); 44 } 45 46 Command(Command&&) = default; 47 Command& operator=(Command&&) = default; 48 49 virtual ~Command() = default; 50 51 // Behavior flags used with the following functions that change how the command flags are parsed 52 // displayed. 53 enum : uint32_t { 54 // Indicates the arguments are file or folder paths. On Windows, paths that exceed the maximum 55 // path length will be converted to use the extended path prefix '//?/'. Without this 56 // conversion, files with long paths cannot be opened. 57 kPath = 1 << 0, 58 }; 59 60 void AddRequiredFlag(android::StringPiece name, android::StringPiece description, 61 std::string* value, uint32_t flags = 0); 62 63 void AddRequiredFlagList(android::StringPiece name, android::StringPiece description, 64 std::vector<std::string>* value, uint32_t flags = 0); 65 66 void AddOptionalFlag(android::StringPiece name, android::StringPiece description, 67 std::optional<std::string>* value, uint32_t flags = 0); 68 69 void AddOptionalFlagList(android::StringPiece name, android::StringPiece description, 70 std::vector<std::string>* value, uint32_t flags = 0); 71 72 void AddOptionalFlagList(android::StringPiece name, android::StringPiece description, 73 std::unordered_set<std::string>* value); 74 75 void AddOptionalSwitch(android::StringPiece name, android::StringPiece description, bool* value); 76 77 void AddOptionalSubcommand(std::unique_ptr<Command>&& subcommand, bool experimental = false); 78 79 void SetDescription(android::StringPiece name); 80 81 // Prints the help menu of the command. 82 void Usage(std::ostream* out); 83 84 // Parses the command line arguments, sets the flag variable values, and runs the action of 85 // the command. If the arguments fail to parse to the command and its subcommands, then the action 86 // will not be run and the usage will be printed instead. 87 int Execute(std::vector<android::StringPiece>& args, std::ostream* out_error); 88 89 // Same, but for a temporary vector of args. Execute(std::vector<android::StringPiece> && args,std::ostream * out_error)90 int Execute(std::vector<android::StringPiece>&& args, std::ostream* out_error) { 91 return Execute(args, out_error); 92 } 93 94 // The action to preform when the command is executed. 95 virtual int Action(const std::vector<std::string>& args) = 0; 96 97 private: 98 struct Flag { FlagFlag99 explicit Flag(android::StringPiece name, android::StringPiece description, bool is_required, 100 const size_t num_args, 101 std::function<bool(android::StringPiece value, std::ostream* out_err)>&& action) 102 : name(name), 103 description(description), 104 action(std::move(action)), 105 num_args(num_args), 106 is_required(is_required) { 107 } 108 109 std::string name; 110 std::string description; 111 std::function<bool(android::StringPiece value, std::ostream* out_error)> action; 112 size_t num_args; 113 bool is_required; 114 bool found = false; 115 }; 116 117 const std::string& addEnvironmentArg(const Flag& flag, const char* env); 118 void parseFlagsFromEnvironment(std::vector<android::StringPiece>& args); 119 120 std::string name_; 121 std::string short_name_; 122 std::string description_; 123 std::string full_subcommand_name_; 124 125 std::vector<Flag> flags_; 126 std::vector<std::unique_ptr<Command>> subcommands_; 127 std::vector<std::unique_ptr<Command>> experimental_subcommands_; 128 // A collection of arguments loaded from environment variables, with stable positions 129 // in memory - we add them to the vector of string views so the pointers may not change, 130 // with or without short string buffer utilization in std::string. 131 std::deque<std::string> environment_args_; 132 }; 133 134 } // namespace aapt 135