You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
286 lines
7.3 KiB
286 lines
7.3 KiB
// Copyright 2014 The Chromium OS 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 "brillo/flag_helper.h"
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <sysexits.h>
|
|
|
|
#include <memory>
|
|
#include <string>
|
|
#include <utility>
|
|
|
|
#include <base/base_switches.h>
|
|
#include <base/command_line.h>
|
|
#include <base/logging.h>
|
|
#include <base/strings/stringprintf.h>
|
|
#include <base/strings/string_number_conversions.h>
|
|
|
|
namespace brillo {
|
|
|
|
Flag::Flag(const char* name,
|
|
const char* default_value,
|
|
const char* help,
|
|
bool visible)
|
|
: name_(name),
|
|
default_value_(default_value),
|
|
help_(help),
|
|
visible_(visible) {
|
|
}
|
|
|
|
class HelpFlag : public brillo::Flag {
|
|
public:
|
|
HelpFlag() : Flag("help", "false", "Show this help message", true) {}
|
|
|
|
bool SetValue(const std::string& /* value */) override { return true; };
|
|
const char* GetType() const override { return "bool"; }
|
|
};
|
|
|
|
BoolFlag::BoolFlag(const char* name,
|
|
bool* value,
|
|
bool* no_value,
|
|
const char* default_value,
|
|
const char* help,
|
|
bool visible)
|
|
: Flag(name, default_value, help, visible),
|
|
value_(value),
|
|
no_value_(no_value) {
|
|
}
|
|
|
|
bool BoolFlag::SetValue(const std::string& value) {
|
|
if (value.empty()) {
|
|
*value_ = true;
|
|
} else {
|
|
if (!value.compare("true"))
|
|
*value_ = true;
|
|
else if (!value.compare("false"))
|
|
*value_ = false;
|
|
else
|
|
return false;
|
|
}
|
|
|
|
*no_value_ = !*value_;
|
|
|
|
return true;
|
|
}
|
|
|
|
const char* BoolFlag::GetType() const {
|
|
return "bool";
|
|
}
|
|
|
|
Int32Flag::Int32Flag(const char* name,
|
|
int* value,
|
|
const char* default_value,
|
|
const char* help,
|
|
bool visible)
|
|
: Flag(name, default_value, help, visible), value_(value) {
|
|
}
|
|
|
|
bool Int32Flag::SetValue(const std::string& value) {
|
|
return base::StringToInt(value, value_);
|
|
}
|
|
|
|
const char* Int32Flag::GetType() const {
|
|
return "int";
|
|
}
|
|
|
|
UInt32Flag::UInt32Flag(const char* name,
|
|
uint32_t* value,
|
|
const char* default_value,
|
|
const char* help,
|
|
bool visible)
|
|
: Flag(name, default_value, help, visible), value_(value) {
|
|
}
|
|
|
|
bool UInt32Flag::SetValue(const std::string& value) {
|
|
return base::StringToUint(value, value_);
|
|
}
|
|
|
|
const char* UInt32Flag::GetType() const {
|
|
return "uint32";
|
|
}
|
|
|
|
Int64Flag::Int64Flag(const char* name,
|
|
int64_t* value,
|
|
const char* default_value,
|
|
const char* help,
|
|
bool visible)
|
|
: Flag(name, default_value, help, visible), value_(value) {
|
|
}
|
|
|
|
bool Int64Flag::SetValue(const std::string& value) {
|
|
return base::StringToInt64(value, value_);
|
|
}
|
|
|
|
const char* Int64Flag::GetType() const {
|
|
return "int64";
|
|
}
|
|
|
|
UInt64Flag::UInt64Flag(const char* name,
|
|
uint64_t* value,
|
|
const char* default_value,
|
|
const char* help,
|
|
bool visible)
|
|
: Flag(name, default_value, help, visible), value_(value) {
|
|
}
|
|
|
|
bool UInt64Flag::SetValue(const std::string& value) {
|
|
return base::StringToUint64(value, value_);
|
|
}
|
|
|
|
const char* UInt64Flag::GetType() const {
|
|
return "uint64";
|
|
}
|
|
|
|
DoubleFlag::DoubleFlag(const char* name,
|
|
double* value,
|
|
const char* default_value,
|
|
const char* help,
|
|
bool visible)
|
|
: Flag(name, default_value, help, visible), value_(value) {
|
|
}
|
|
|
|
bool DoubleFlag::SetValue(const std::string& value) {
|
|
return base::StringToDouble(value, value_);
|
|
}
|
|
|
|
const char* DoubleFlag::GetType() const {
|
|
return "double";
|
|
}
|
|
|
|
StringFlag::StringFlag(const char* name,
|
|
std::string* value,
|
|
const char* default_value,
|
|
const char* help,
|
|
bool visible)
|
|
: Flag(name, default_value, help, visible), value_(value) {
|
|
}
|
|
|
|
bool StringFlag::SetValue(const std::string& value) {
|
|
value_->assign(value);
|
|
|
|
return true;
|
|
}
|
|
|
|
const char* StringFlag::GetType() const {
|
|
return "string";
|
|
}
|
|
|
|
namespace {
|
|
brillo::FlagHelper* instance_ = nullptr;
|
|
} // namespace
|
|
|
|
FlagHelper::FlagHelper() : command_line_(nullptr) {
|
|
AddFlag(std::unique_ptr<Flag>(new HelpFlag()));
|
|
}
|
|
|
|
FlagHelper::~FlagHelper() {
|
|
}
|
|
|
|
brillo::FlagHelper* FlagHelper::GetInstance() {
|
|
if (!instance_)
|
|
instance_ = new FlagHelper();
|
|
|
|
return instance_;
|
|
}
|
|
|
|
void FlagHelper::ResetForTesting() {
|
|
delete instance_;
|
|
instance_ = nullptr;
|
|
}
|
|
|
|
void FlagHelper::Init(int argc,
|
|
const char* const* argv,
|
|
std::string help_usage) {
|
|
brillo::FlagHelper* helper = GetInstance();
|
|
if (!helper->command_line_) {
|
|
if (!base::CommandLine::InitializedForCurrentProcess())
|
|
base::CommandLine::Init(argc, argv);
|
|
helper->command_line_ = base::CommandLine::ForCurrentProcess();
|
|
}
|
|
|
|
GetInstance()->SetUsageMessage(help_usage);
|
|
|
|
GetInstance()->UpdateFlagValues();
|
|
}
|
|
|
|
void FlagHelper::UpdateFlagValues() {
|
|
std::string error_msg;
|
|
int error_code = EX_OK;
|
|
|
|
// Check that base::CommandLine has been initialized.
|
|
CHECK(base::CommandLine::InitializedForCurrentProcess());
|
|
|
|
// If the --help flag exists, print out help message and exit.
|
|
if (command_line_->HasSwitch("help")) {
|
|
puts(GetHelpMessage().c_str());
|
|
exit(EX_OK);
|
|
}
|
|
|
|
// Iterate over the base::CommandLine switches. Update the value
|
|
// of the corresponding Flag if it exists, or output an error message
|
|
// if the flag wasn't defined.
|
|
const base::CommandLine::SwitchMap& switch_map = command_line_->GetSwitches();
|
|
|
|
for (const auto& pair : switch_map) {
|
|
const std::string& key = pair.first;
|
|
// Make sure we allow the standard logging switches (--v and --vmodule).
|
|
if (key == switches::kV || key == switches::kVModule)
|
|
continue;
|
|
|
|
const std::string& value = pair.second;
|
|
|
|
auto df_it = defined_flags_.find(key);
|
|
if (df_it != defined_flags_.end()) {
|
|
Flag* flag = df_it->second.get();
|
|
if (!flag->SetValue(value)) {
|
|
base::StringAppendF(
|
|
&error_msg,
|
|
"ERROR: illegal value '%s' specified for %s flag '%s'\n",
|
|
value.c_str(),
|
|
flag->GetType(),
|
|
flag->name_);
|
|
error_code = EX_DATAERR;
|
|
}
|
|
} else {
|
|
base::StringAppendF(
|
|
&error_msg, "ERROR: unknown command line flag '%s'\n", key.c_str());
|
|
error_code = EX_USAGE;
|
|
}
|
|
}
|
|
|
|
if (error_code != EX_OK) {
|
|
puts(error_msg.c_str());
|
|
exit(error_code);
|
|
}
|
|
}
|
|
|
|
void FlagHelper::AddFlag(std::unique_ptr<Flag> flag) {
|
|
defined_flags_.emplace(flag->name_, std::move(flag));
|
|
}
|
|
|
|
void FlagHelper::SetUsageMessage(std::string help_usage) {
|
|
help_usage_.assign(std::move(help_usage));
|
|
}
|
|
|
|
std::string FlagHelper::GetHelpMessage() const {
|
|
std::string help = help_usage_;
|
|
help.append("\n\n");
|
|
for (const auto& pair : defined_flags_) {
|
|
const Flag* flag = pair.second.get();
|
|
if (flag->visible_) {
|
|
base::StringAppendF(&help,
|
|
" --%s (%s) type: %s default: %s\n",
|
|
flag->name_,
|
|
flag->help_,
|
|
flag->GetType(),
|
|
flag->default_value_);
|
|
}
|
|
}
|
|
return help;
|
|
}
|
|
|
|
} // namespace brillo
|