Factor out logic for 'a string option which is one of a set of choices' from CompactOsStringOption as StringChoiceOption.
v2: Allow different behaviour for option without a choice, and option absent. Future work: This doesn't say anything other that "Error during option processing" if you've given an invalid choice string, or left it out when it's required, because libgetopt++ doesn't output anything, just returns success or failure after processing the command line arguments. --- io_stream_cygfile.cc | 52 +++++------------- libgetopt++/Makefile.am | 3 +- .../include/getopt++/StringChoiceOption.h | 41 ++++++++++++++ libgetopt++/src/StringChoiceOption.cc | 54 +++++++++++++++++++ 4 files changed, 109 insertions(+), 41 deletions(-) create mode 100644 libgetopt++/include/getopt++/StringChoiceOption.h create mode 100644 libgetopt++/src/StringChoiceOption.cc diff --git a/io_stream_cygfile.cc b/io_stream_cygfile.cc index a9150e7..52ef735 100644 --- a/io_stream_cygfile.cc +++ b/io_stream_cygfile.cc @@ -20,7 +20,7 @@ #include "mount.h" #include "compactos.h" -#include "getopt++/StringOption.h" +#include "getopt++/StringChoiceOption.h" #include <stdlib.h> #include <errno.h> @@ -30,45 +30,17 @@ #include "IOStreamProvider.h" #include "LogSingleton.h" -/* Option '--compact-os ALGORITHM' */ -class CompactOsStringOption : public StringOption -{ -public: - CompactOsStringOption (); - virtual Result Process (char const *optarg, int prefixIndex) /* override */; - operator int () const { return intval; } -private: - int intval; -}; - -CompactOsStringOption::CompactOsStringOption () -: StringOption ("", '\0', "compact-os", - "Compress installed files with Compact OS " - "(xpress4k, xpress8k, xpress16k, lzx)", false), - intval (-1) -{ -} - -Option::Result CompactOsStringOption::Process (char const *optarg, int prefixIndex) -{ - Result res = StringOption::Process (optarg, prefixIndex); - if (res != Ok) - return res; - const std::string& strval = *this; - if (strval == "xpress4k") - intval = FILE_PROVIDER_COMPRESSION_XPRESS4K; - else if (strval == "xpress8k") - intval = FILE_PROVIDER_COMPRESSION_XPRESS8K; - else if (strval == "xpress16k") - intval = FILE_PROVIDER_COMPRESSION_XPRESS16K; - else if (strval == "lzx") - intval = FILE_PROVIDER_COMPRESSION_LZX; - else - return Failed; - return Ok; -} - -static CompactOsStringOption CompactOsOption; +static StringChoiceOption::StringChoices algs({ + {"xpress4k", FILE_PROVIDER_COMPRESSION_XPRESS4K}, + {"xpress8k", FILE_PROVIDER_COMPRESSION_XPRESS8K}, + {"xpress16k", FILE_PROVIDER_COMPRESSION_XPRESS16K}, + {"lzx", FILE_PROVIDER_COMPRESSION_LZX}, + }); + +static StringChoiceOption CompactOsOption(algs, + '\0', "compact-os", + "Compress installed files with Compact OS (xpress4k, xpress8k, xpress16k, lzx)", + true, -1, FILE_PROVIDER_COMPRESSION_LZX); /* completely private iostream registration class */ class CygFileProvider : public IOStreamProvider diff --git a/libgetopt++/Makefile.am b/libgetopt++/Makefile.am index 34dc6fd..c20c17d 100644 --- a/libgetopt++/Makefile.am +++ b/libgetopt++/Makefile.am @@ -26,7 +26,7 @@ TESTS = tests/OptionSet tests/optioniterator tests/BoolOptionTest libgetopt___la_SOURCES = src/GetOption.cc src/Option.cc src/BoolOption.cc \ src/OptionSet.cc \ - src/StringArrayOption.cc src/StringOption.cc + src/StringArrayOption.cc src/StringChoiceOption.cc src/StringOption.cc libgetopt___la_LDFLAGS = -version-info 1:1:0 -no-undefined @@ -36,6 +36,7 @@ getoptinclude_HEADERS = include/getopt++/Option.h \ include/getopt++/GetOption.h \ include/getopt++/OptionSet.h \ include/getopt++/StringArrayOption.h \ + include/getopt++/StringChoiceOption.h \ include/getopt++/StringOption.h tests_testoption_SOURCES = tests/testoption.cc diff --git a/libgetopt++/include/getopt++/StringChoiceOption.h b/libgetopt++/include/getopt++/StringChoiceOption.h new file mode 100644 index 0000000..8800712 --- /dev/null +++ b/libgetopt++/include/getopt++/StringChoiceOption.h @@ -0,0 +1,41 @@ +/* + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * A copy of the GNU General Public License can be found at + * http://www.gnu.org/ + * + */ + +#ifndef _STRINGCHOICEOPTION_H_ +#define _STRINGCHOICEOPTION_H_ + +#include <vector> +#include <getopt++/StringOption.h> + +class StringChoiceOption : public StringOption +{ +public: + typedef std::vector<std::pair<const char *, int>> StringChoices; + + StringChoiceOption(StringChoices choices, + char shortopt, char const *longopt = 0, + std::string const &shorthelp = std::string(), + bool const optional = true, // option without choice string is permitted + int const defaultvalue = -1, // value when option is absent + int const impliedvalue = -1); // value when option is present without choice string + + virtual ~ StringChoiceOption (); + virtual Result Process (char const *, int); + operator int () const { return intval; } + +private: + StringChoices choices; + int intval; + int _impliedvalue; +}; + +#endif // _STRINGCHOICEOPTION_H_ diff --git a/libgetopt++/src/StringChoiceOption.cc b/libgetopt++/src/StringChoiceOption.cc new file mode 100644 index 0000000..185d56a --- /dev/null +++ b/libgetopt++/src/StringChoiceOption.cc @@ -0,0 +1,54 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * A copy of the GNU General Public License can be found at + * http://www.gnu.org/ + * + */ + +#include <getopt++/StringChoiceOption.h> + +StringChoiceOption::StringChoiceOption (StringChoices _choices, + char shortopt, + char const *longopt, + std::string const &shorthelp, + bool const optional, + int const defaultvalue, + int const impliedvalue) : + StringOption ("", shortopt, longopt, shorthelp, optional), + choices(_choices), intval (defaultvalue), _impliedvalue(impliedvalue) +{ +}; + +StringChoiceOption::~ StringChoiceOption () {}; + +Option::Result +StringChoiceOption::Process (char const *optarg, int prefixIndex) +{ + Result res = StringOption::Process (optarg, prefixIndex); + if (res != Ok) + return res; + + const std::string& strval = *this; + if (strval.empty()) + { + intval = _impliedvalue; + return Ok; + } + + for (StringChoiceOption::StringChoices::const_iterator i = choices.begin(); + i != choices.end(); + i++) + { + if (strval == i->first) + { + intval = i->second; + return Ok; + } + } + + return Failed; +} -- 2.32.0