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