Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
command_line.cc
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "flutter/fml/command_line.h"
6
7namespace fml {
8
9// CommandLine -----------------------------------------------------------------
10
11CommandLine::Option::Option(const std::string& name) : name(name) {}
12
13CommandLine::Option::Option(const std::string& name, const std::string& value)
14 : name(name), value(value) {}
15
16CommandLine::CommandLine() = default;
17
18CommandLine::CommandLine(const CommandLine& from) = default;
19
21
23 const std::vector<Option>& options,
24 const std::vector<std::string>& positional_args)
25 : has_argv0_(true),
26 argv0_(argv0),
27 options_(options),
28 positional_args_(positional_args) {
29 for (size_t i = 0; i < options_.size(); i++) {
30 option_index_[options_[i].name] = i;
31 }
32}
33
35
36CommandLine& CommandLine::operator=(const CommandLine& from) = default;
37
39
40bool CommandLine::HasOption(std::string_view name, size_t* index) const {
41 auto it = option_index_.find(name.data());
42 if (it == option_index_.end()) {
43 return false;
44 }
45 if (index) {
46 *index = it->second;
47 }
48 return true;
49}
50
51bool CommandLine::GetOptionValue(std::string_view name,
52 std::string* value) const {
53 size_t index;
54 if (!HasOption(name, &index)) {
55 return false;
56 }
57 *value = options_[index].value;
58 return true;
59}
60
61std::vector<std::string_view> CommandLine::GetOptionValues(
62 std::string_view name) const {
63 std::vector<std::string_view> ret;
64 for (const auto& option : options_) {
65 if (option.name == name) {
66 ret.push_back(option.value);
67 }
68 }
69 return ret;
70}
71
73 std::string_view name,
74 std::string_view default_value) const {
75 size_t index;
76 if (!HasOption(name, &index)) {
77 return {default_value.data(), default_value.size()};
78 }
79 return options_[index].value;
80}
81
82// Factory functions (etc.) ----------------------------------------------------
83
84namespace internal {
85
88
89bool CommandLineBuilder::ProcessArg(const std::string& arg) {
90 if (!has_argv0_) {
91 has_argv0_ = true;
92 argv0_ = arg;
93 return false;
94 }
95
96 // If we've seen a positional argument, then the remaining arguments are also
97 // positional.
98 if (started_positional_args_) {
99 bool rv = positional_args_.empty();
100 positional_args_.push_back(arg);
101 return rv;
102 }
103
104 // Anything that doesn't start with "--" is a positional argument.
105 if (arg.size() < 2u || arg[0] != '-' || arg[1] != '-') {
106 bool rv = positional_args_.empty();
107 started_positional_args_ = true;
108 positional_args_.push_back(arg);
109 return rv;
110 }
111
112 // "--" ends option processing, but isn't stored as a positional argument.
113 if (arg.size() == 2u) {
114 started_positional_args_ = true;
115 return false;
116 }
117
118 // Note: The option name *must* be at least one character, so start at
119 // position 3 -- "--=foo" will yield a name of "=foo" and no value. (Passing a
120 // starting |pos| that's "too big" is OK.)
121 size_t equals_pos = arg.find('=', 3u);
122 if (equals_pos == std::string::npos) {
123 options_.push_back(CommandLine::Option(arg.substr(2u)));
124 return false;
125 }
126
127 options_.push_back(CommandLine::Option(arg.substr(2u, equals_pos - 2u),
128 arg.substr(equals_pos + 1u)));
129 return false;
130}
131
133 if (!has_argv0_) {
134 return CommandLine();
135 }
136 return CommandLine(argv0_, options_, positional_args_);
137}
138
139} // namespace internal
140
141std::vector<std::string> CommandLineToArgv(const CommandLine& command_line) {
142 if (!command_line.has_argv0()) {
143 return std::vector<std::string>();
144 }
145
146 std::vector<std::string> argv;
147 const std::vector<CommandLine::Option>& options = command_line.options();
148 const std::vector<std::string>& positional_args =
149 command_line.positional_args();
150 // Reserve space for argv[0], options, maybe a "--" (if needed), and the
151 // positional arguments.
152 argv.reserve(1u + options.size() + 1u + positional_args.size());
153
154 argv.push_back(command_line.argv0());
155 for (const auto& option : options) {
156 if (option.value.empty()) {
157 argv.push_back("--" + option.name);
158 } else {
159 argv.push_back("--" + option.name + "=" + option.value);
160 }
161 }
162
163 if (!positional_args.empty()) {
164 // Insert a "--" if necessary.
165 if (positional_args[0].size() >= 2u && positional_args[0][0] == '-' &&
166 positional_args[0][1] == '-') {
167 argv.push_back("--");
168 }
169
170 argv.insert(argv.end(), positional_args.begin(), positional_args.end());
171 }
172
173 return argv;
174}
175
176} // namespace fml
const char * options
const std::string & argv0() const
CommandLine & operator=(const CommandLine &from)
const std::vector< Option > & options() const
std::vector< std::string_view > GetOptionValues(std::string_view name) const
const std::vector< std::string > & positional_args() const
std::string GetOptionValueWithDefault(std::string_view name, std::string_view default_value) const
bool HasOption(std::string_view name, size_t *index=nullptr) const
bool GetOptionValue(std::string_view name, std::string *value) const
bool has_argv0() const
bool ProcessArg(const std::string &arg)
uint8_t value
const char * name
Definition fuchsia.cc:50
char ** argv
Definition library.h:9
constexpr std::size_t size(T(&array)[N])
Definition size.h:13
std::vector< std::string > CommandLineToArgv(const CommandLine &command_line)