Flutter Engine
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 
7 namespace fml {
8 
9 // CommandLine -----------------------------------------------------------------
10 
11 CommandLine::Option::Option(const std::string& name) : name(name) {}
12 
13 CommandLine::Option::Option(const std::string& name, const std::string& value)
14  : name(name), value(value) {}
15 
16 CommandLine::CommandLine() = default;
17 
18 CommandLine::CommandLine(const CommandLine& from) = default;
19 
20 CommandLine::CommandLine(CommandLine&& from) = default;
21 
22 CommandLine::CommandLine(const std::string& argv0,
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 
34 CommandLine::~CommandLine() = default;
35 
36 CommandLine& CommandLine::operator=(const CommandLine& from) = default;
37 
39 
40 bool 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 
51 bool 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 
61 std::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 
84 namespace internal {
85 
86 CommandLineBuilder::CommandLineBuilder() {}
87 CommandLineBuilder::~CommandLineBuilder() {}
88 
89 bool 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 
132 CommandLine CommandLineBuilder::Build() const {
133  if (!has_argv0_) {
134  return CommandLine();
135  }
136  return CommandLine(argv0_, options_, positional_args_);
137 }
138 
139 } // namespace internal
140 
141 std::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
bool has_argv0() const
Definition: command_line.h:92
std::vector< std::string > CommandLineToArgv(const CommandLine &command_line)
bool GetOptionValue(std::string_view name, std::string *value) const
Definition: command_line.cc:51
constexpr std::size_t size(T(&array)[N])
Definition: size.h:13
Definition: ascii_trie.cc:9
CommandLine & operator=(const CommandLine &from)
const std::vector< Option > & options() const
Definition: command_line.h:94
const std::string & argv0() const
Definition: command_line.h:93
uint8_t value
const std::vector< std::string > & positional_args() const
Definition: command_line.h:95
std::vector< std::string_view > GetOptionValues(std::string_view name) const
Definition: command_line.cc:61
const char * name
Definition: fuchsia.cc:50
std::string GetOptionValueWithDefault(std::string_view name, std::string_view default_value) const
Definition: command_line.cc:72
bool HasOption(std::string_view name, size_t *index=nullptr) const
Definition: command_line.cc:40