util/OptionParser: pass array of OptionDefs to constructor
This commit is contained in:
@@ -76,24 +76,29 @@
|
|||||||
#define USER_CONFIG_FILE_LOCATION_XDG PATH_LITERAL("mpd/mpd.conf")
|
#define USER_CONFIG_FILE_LOCATION_XDG PATH_LITERAL("mpd/mpd.conf")
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static constexpr OptionDef opt_kill(
|
enum Option {
|
||||||
"kill", "kill the currently running mpd session");
|
OPTION_KILL,
|
||||||
static constexpr OptionDef opt_no_config(
|
OPTION_NO_CONFIG,
|
||||||
"no-config", "don't read from config");
|
OPTION_NO_DAEMON,
|
||||||
static constexpr OptionDef opt_no_daemon(
|
OPTION_STDOUT,
|
||||||
"no-daemon", "don't detach from console");
|
OPTION_STDERR,
|
||||||
static constexpr OptionDef opt_stdout(
|
OPTION_VERBOSE,
|
||||||
"stdout", nullptr); // hidden, compatibility with old versions
|
OPTION_VERSION,
|
||||||
static constexpr OptionDef opt_stderr(
|
OPTION_HELP,
|
||||||
"stderr", "print messages to stderr");
|
OPTION_HELP2,
|
||||||
static constexpr OptionDef opt_verbose(
|
};
|
||||||
"verbose", 'v', "verbose logging");
|
|
||||||
static constexpr OptionDef opt_version(
|
static constexpr OptionDef option_defs[] = {
|
||||||
"version", 'V', "print version number");
|
{"kill", "kill the currently running mpd session"},
|
||||||
static constexpr OptionDef opt_help(
|
{"no-config", "don't read from config"},
|
||||||
"help", 'h', "show help options");
|
{"no-daemon", "don't detach from console"},
|
||||||
static constexpr OptionDef opt_help_alt(
|
{"stdout", nullptr}, // hidden, compatibility with old versions
|
||||||
nullptr, '?', nullptr); // hidden, standard alias for --help
|
{"stderr", "print messages to stderr"},
|
||||||
|
{"verbose", 'v', "verbose logging"},
|
||||||
|
{"version", 'V', "print version number"},
|
||||||
|
{"help", 'h', "show help options"},
|
||||||
|
{nullptr, '?', nullptr}, // hidden, standard alias for --help
|
||||||
|
};
|
||||||
|
|
||||||
static constexpr Domain cmdline_domain("cmdline");
|
static constexpr Domain cmdline_domain("cmdline");
|
||||||
|
|
||||||
@@ -265,13 +270,8 @@ static void help(void)
|
|||||||
"\n"
|
"\n"
|
||||||
"Options:\n");
|
"Options:\n");
|
||||||
|
|
||||||
PrintOption(opt_help);
|
for (const auto &i : option_defs)
|
||||||
PrintOption(opt_kill);
|
PrintOption(i);
|
||||||
PrintOption(opt_no_config);
|
|
||||||
PrintOption(opt_no_daemon);
|
|
||||||
PrintOption(opt_stderr);
|
|
||||||
PrintOption(opt_verbose);
|
|
||||||
PrintOption(opt_version);
|
|
||||||
|
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
@@ -312,35 +312,38 @@ ParseCommandLine(int argc, char **argv, struct options *options)
|
|||||||
options->verbose = false;
|
options->verbose = false;
|
||||||
|
|
||||||
// First pass: handle command line options
|
// First pass: handle command line options
|
||||||
OptionParser parser(argc, argv);
|
OptionParser parser(option_defs, argc, argv);
|
||||||
while (parser.ParseNext()) {
|
int option_index;
|
||||||
if (parser.CheckOption(opt_kill)) {
|
while ((option_index = parser.Next()) >= 0) {
|
||||||
|
switch (Option(option_index)) {
|
||||||
|
case OPTION_KILL:
|
||||||
options->kill = true;
|
options->kill = true;
|
||||||
continue;
|
break;
|
||||||
}
|
|
||||||
if (parser.CheckOption(opt_no_config)) {
|
|
||||||
use_config_file = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (parser.CheckOption(opt_no_daemon)) {
|
|
||||||
options->daemon = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (parser.CheckOption(opt_stderr, opt_stdout)) {
|
|
||||||
options->log_stderr = true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (parser.CheckOption(opt_verbose)) {
|
|
||||||
options->verbose = true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (parser.CheckOption(opt_version))
|
|
||||||
version();
|
|
||||||
if (parser.CheckOption(opt_help, opt_help_alt))
|
|
||||||
help();
|
|
||||||
|
|
||||||
throw FormatRuntimeError("invalid option: %s",
|
case OPTION_NO_CONFIG:
|
||||||
parser.GetOption());
|
use_config_file = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OPTION_NO_DAEMON:
|
||||||
|
options->daemon = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OPTION_STDOUT:
|
||||||
|
case OPTION_STDERR:
|
||||||
|
options->log_stderr = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OPTION_VERBOSE:
|
||||||
|
options->verbose = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OPTION_VERSION:
|
||||||
|
version();
|
||||||
|
|
||||||
|
case OPTION_HELP:
|
||||||
|
case OPTION_HELP2:
|
||||||
|
help();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* initialize the logging library, so the configuration file
|
/* initialize the logging library, so the configuration file
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003-2017 The Music Player Daemon Project
|
* Copyright 2003-2018 The Music Player Daemon Project
|
||||||
* http://www.musicpd.org
|
* http://www.musicpd.org
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@@ -19,43 +19,41 @@
|
|||||||
|
|
||||||
#include "OptionParser.hxx"
|
#include "OptionParser.hxx"
|
||||||
#include "OptionDef.hxx"
|
#include "OptionDef.hxx"
|
||||||
|
#include "util/RuntimeError.hxx"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
bool
|
inline unsigned
|
||||||
OptionParser::CheckOption(const OptionDef &opt) const noexcept
|
OptionParser::IdentifyOption(const char *s) const
|
||||||
{
|
{
|
||||||
assert(option != nullptr);
|
assert(s != nullptr);
|
||||||
|
assert(*s == '-');
|
||||||
|
|
||||||
if (is_long)
|
if (s[1] == '-') {
|
||||||
return opt.HasLongOption() &&
|
for (const auto &i : options)
|
||||||
strcmp(option, opt.GetLongOption()) == 0;
|
if (i.HasLongOption() &&
|
||||||
|
strcmp(s + 2, i.GetLongOption()) == 0)
|
||||||
|
return &i - options.data;
|
||||||
|
} else if (s[1] != 0 && s[2] == 0) {
|
||||||
|
const char ch = s[1];
|
||||||
|
for (const auto &i : options)
|
||||||
|
if (i.HasShortOption() && ch == i.GetShortOption())
|
||||||
|
return &i - options.data;
|
||||||
|
}
|
||||||
|
|
||||||
return opt.HasShortOption() &&
|
throw FormatRuntimeError("Unknown option: %s", s);
|
||||||
option[0] == opt.GetShortOption() &&
|
|
||||||
option[1] == '\0';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
int
|
||||||
OptionParser::ParseNext() noexcept
|
OptionParser::Next()
|
||||||
{
|
{
|
||||||
while (!args.empty()) {
|
while (!args.empty()) {
|
||||||
const char *arg = args.shift();
|
const char *arg = args.shift();
|
||||||
if (arg[0] == '-') {
|
if (arg[0] == '-')
|
||||||
if (arg[1] == '-') {
|
return IdentifyOption(arg);
|
||||||
option = arg + 2;
|
|
||||||
is_long = true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
option = arg + 1;
|
|
||||||
is_long = false;
|
|
||||||
}
|
|
||||||
option_raw = arg;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
*remaining_tail++ = arg;
|
*remaining_tail++ = arg;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003-2017 The Music Player Daemon Project
|
* Copyright 2003-2018 The Music Player Daemon Project
|
||||||
* http://www.musicpd.org
|
* http://www.musicpd.org
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@@ -29,10 +29,9 @@ class OptionDef;
|
|||||||
*/
|
*/
|
||||||
class OptionParser
|
class OptionParser
|
||||||
{
|
{
|
||||||
|
ConstBuffer<OptionDef> options;
|
||||||
|
|
||||||
ConstBuffer<const char *> args;
|
ConstBuffer<const char *> args;
|
||||||
const char *option;
|
|
||||||
const char *option_raw;
|
|
||||||
bool is_long = false;
|
|
||||||
|
|
||||||
const char **const remaining_head, **remaining_tail;
|
const char **const remaining_head, **remaining_tail;
|
||||||
|
|
||||||
@@ -40,41 +39,23 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Constructs #OptionParser.
|
* Constructs #OptionParser.
|
||||||
*/
|
*/
|
||||||
OptionParser(int _argc, char **_argv) noexcept
|
OptionParser(ConstBuffer<OptionDef> _options,
|
||||||
:args(_argv + 1, _argc - 1),
|
int _argc, char **_argv) noexcept
|
||||||
|
:options(_options), args(_argv + 1, _argc - 1),
|
||||||
remaining_head(const_cast<const char **>(_argv + 1)),
|
remaining_head(const_cast<const char **>(_argv + 1)),
|
||||||
remaining_tail(remaining_head) {}
|
remaining_tail(remaining_head) {}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the last parsed option.
|
|
||||||
*/
|
|
||||||
const char *GetOption() noexcept {
|
|
||||||
return option_raw;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if current option is a specified option.
|
|
||||||
*/
|
|
||||||
bool CheckOption(const OptionDef &opt) const noexcept;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if current option is a specified option
|
|
||||||
* or specified alternative option.
|
|
||||||
*/
|
|
||||||
bool CheckOption(const OptionDef &opt,
|
|
||||||
const OptionDef &alt_opt) const noexcept {
|
|
||||||
return CheckOption(opt) || CheckOption(alt_opt);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses current command line entry.
|
* Parses current command line entry.
|
||||||
* Regardless of result, advances current position to the next
|
* Regardless of result, advances current position to the next
|
||||||
* command line entry.
|
* command line entry.
|
||||||
*
|
*
|
||||||
* @return true if an option was found, false if there are no
|
* Throws on error.
|
||||||
* more options
|
*
|
||||||
|
* @return the index if an option was found, -1 if there are
|
||||||
|
* no more options
|
||||||
*/
|
*/
|
||||||
bool ParseNext() noexcept;
|
int Next();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the remaining non-option arguments.
|
* Returns the remaining non-option arguments.
|
||||||
@@ -82,6 +63,9 @@ public:
|
|||||||
ConstBuffer<const char *> GetRemaining() const noexcept {
|
ConstBuffer<const char *> GetRemaining() const noexcept {
|
||||||
return {remaining_head, remaining_tail};
|
return {remaining_head, remaining_tail};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
unsigned IdentifyOption(const char *s) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Reference in New Issue
Block a user