mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
167 lines
4.9 KiB
C++
167 lines
4.9 KiB
C++
// Copyright 2013 The Flutter Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include "flutter/fml/command_line.h"
|
|
|
|
namespace fml {
|
|
|
|
// CommandLine -----------------------------------------------------------------
|
|
|
|
CommandLine::Option::Option(const std::string& name) : name(name) {}
|
|
|
|
CommandLine::Option::Option(const std::string& name, const std::string& value)
|
|
: name(name), value(value) {}
|
|
|
|
CommandLine::CommandLine() = default;
|
|
|
|
CommandLine::CommandLine(const CommandLine& from) = default;
|
|
|
|
CommandLine::CommandLine(CommandLine&& from) = default;
|
|
|
|
CommandLine::CommandLine(const std::string& argv0,
|
|
const std::vector<Option>& options,
|
|
const std::vector<std::string>& positional_args)
|
|
: has_argv0_(true),
|
|
argv0_(argv0),
|
|
options_(options),
|
|
positional_args_(positional_args) {
|
|
for (size_t i = 0; i < options_.size(); i++)
|
|
option_index_[options_[i].name] = i;
|
|
}
|
|
|
|
CommandLine::~CommandLine() = default;
|
|
|
|
CommandLine& CommandLine::operator=(const CommandLine& from) = default;
|
|
|
|
CommandLine& CommandLine::operator=(CommandLine&& from) = default;
|
|
|
|
bool CommandLine::HasOption(std::string_view name, size_t* index) const {
|
|
auto it = option_index_.find(name.data());
|
|
if (it == option_index_.end())
|
|
return false;
|
|
if (index)
|
|
*index = it->second;
|
|
return true;
|
|
}
|
|
|
|
bool CommandLine::GetOptionValue(std::string_view name,
|
|
std::string* value) const {
|
|
size_t index;
|
|
if (!HasOption(name, &index))
|
|
return false;
|
|
*value = options_[index].value;
|
|
return true;
|
|
}
|
|
|
|
std::vector<std::string_view> CommandLine::GetOptionValues(
|
|
std::string_view name) const {
|
|
std::vector<std::string_view> ret;
|
|
for (const auto& option : options_) {
|
|
if (option.name == name)
|
|
ret.push_back(option.value);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
std::string CommandLine::GetOptionValueWithDefault(
|
|
std::string_view name,
|
|
std::string_view default_value) const {
|
|
size_t index;
|
|
if (!HasOption(name, &index))
|
|
return {default_value.data(), default_value.size()};
|
|
return options_[index].value;
|
|
}
|
|
|
|
// Factory functions (etc.) ----------------------------------------------------
|
|
|
|
namespace internal {
|
|
|
|
CommandLineBuilder::CommandLineBuilder() {}
|
|
CommandLineBuilder::~CommandLineBuilder() {}
|
|
|
|
bool CommandLineBuilder::ProcessArg(const std::string& arg) {
|
|
if (!has_argv0_) {
|
|
has_argv0_ = true;
|
|
argv0_ = arg;
|
|
return false;
|
|
}
|
|
|
|
// If we've seen a positional argument, then the remaining arguments are also
|
|
// positional.
|
|
if (started_positional_args_) {
|
|
bool rv = positional_args_.empty();
|
|
positional_args_.push_back(arg);
|
|
return rv;
|
|
}
|
|
|
|
// Anything that doesn't start with "--" is a positional argument.
|
|
if (arg.size() < 2u || arg[0] != '-' || arg[1] != '-') {
|
|
bool rv = positional_args_.empty();
|
|
started_positional_args_ = true;
|
|
positional_args_.push_back(arg);
|
|
return rv;
|
|
}
|
|
|
|
// "--" ends option processing, but isn't stored as a positional argument.
|
|
if (arg.size() == 2u) {
|
|
started_positional_args_ = true;
|
|
return false;
|
|
}
|
|
|
|
// Note: The option name *must* be at least one character, so start at
|
|
// position 3 -- "--=foo" will yield a name of "=foo" and no value. (Passing a
|
|
// starting |pos| that's "too big" is OK.)
|
|
size_t equals_pos = arg.find('=', 3u);
|
|
if (equals_pos == std::string::npos) {
|
|
options_.push_back(CommandLine::Option(arg.substr(2u)));
|
|
return false;
|
|
}
|
|
|
|
options_.push_back(CommandLine::Option(arg.substr(2u, equals_pos - 2u),
|
|
arg.substr(equals_pos + 1u)));
|
|
return false;
|
|
}
|
|
|
|
CommandLine CommandLineBuilder::Build() const {
|
|
if (!has_argv0_)
|
|
return CommandLine();
|
|
return CommandLine(argv0_, options_, positional_args_);
|
|
}
|
|
|
|
} // namespace internal
|
|
|
|
std::vector<std::string> CommandLineToArgv(const CommandLine& command_line) {
|
|
if (!command_line.has_argv0())
|
|
return std::vector<std::string>();
|
|
|
|
std::vector<std::string> argv;
|
|
const std::vector<CommandLine::Option>& options = command_line.options();
|
|
const std::vector<std::string>& positional_args =
|
|
command_line.positional_args();
|
|
// Reserve space for argv[0], options, maybe a "--" (if needed), and the
|
|
// positional arguments.
|
|
argv.reserve(1u + options.size() + 1u + positional_args.size());
|
|
|
|
argv.push_back(command_line.argv0());
|
|
for (const auto& option : options) {
|
|
if (option.value.empty())
|
|
argv.push_back("--" + option.name);
|
|
else
|
|
argv.push_back("--" + option.name + "=" + option.value);
|
|
}
|
|
|
|
if (!positional_args.empty()) {
|
|
// Insert a "--" if necessary.
|
|
if (positional_args[0].size() >= 2u && positional_args[0][0] == '-' &&
|
|
positional_args[0][1] == '-')
|
|
argv.push_back("--");
|
|
|
|
argv.insert(argv.end(), positional_args.begin(), positional_args.end());
|
|
}
|
|
|
|
return argv;
|
|
}
|
|
|
|
} // namespace fml
|