• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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