diff options
author | nga <nga@yandex-team.ru> | 2022-02-10 16:48:09 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:48:09 +0300 |
commit | 1f553f46fb4f3c5eec631352cdd900a0709016af (patch) | |
tree | a231fba2c03b440becaea6c86a2702d0bfb0336e /library/cpp/getopt | |
parent | c4de7efdedc25b49cbea74bd589eecb61b55b60a (diff) | |
download | ydb-1f553f46fb4f3c5eec631352cdd900a0709016af.tar.gz |
Restoring authorship annotation for <nga@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'library/cpp/getopt')
-rw-r--r-- | library/cpp/getopt/last_getopt_demo/demo.cpp | 22 | ||||
-rw-r--r-- | library/cpp/getopt/last_getopt_demo/ya.make | 14 | ||||
-rw-r--r-- | library/cpp/getopt/small/last_getopt.cpp | 2 | ||||
-rw-r--r-- | library/cpp/getopt/small/last_getopt.h | 20 | ||||
-rw-r--r-- | library/cpp/getopt/small/last_getopt_support.h | 24 | ||||
-rw-r--r-- | library/cpp/getopt/small/opt.cpp | 120 | ||||
-rw-r--r-- | library/cpp/getopt/small/opt.h | 170 | ||||
-rw-r--r-- | library/cpp/getopt/small/opt2.h | 6 | ||||
-rw-r--r-- | library/cpp/getopt/small/posix_getopt.cpp | 110 | ||||
-rw-r--r-- | library/cpp/getopt/small/posix_getopt.h | 56 | ||||
-rw-r--r-- | library/cpp/getopt/ut/last_getopt_ut.cpp | 700 | ||||
-rw-r--r-- | library/cpp/getopt/ut/opt2_ut.cpp | 30 | ||||
-rw-r--r-- | library/cpp/getopt/ut/opt_ut.cpp | 22 | ||||
-rw-r--r-- | library/cpp/getopt/ut/posix_getopt_ut.cpp | 126 |
14 files changed, 711 insertions, 711 deletions
diff --git a/library/cpp/getopt/last_getopt_demo/demo.cpp b/library/cpp/getopt/last_getopt_demo/demo.cpp index 79426a9cc9..cb31dba733 100644 --- a/library/cpp/getopt/last_getopt_demo/demo.cpp +++ b/library/cpp/getopt/last_getopt_demo/demo.cpp @@ -3,7 +3,7 @@ #include <library/cpp/colorizer/colors.h> // For the sake of this example, let's implement Wget - + Y_COMPLETER(HeaderCompleter) { AddCompletion("Host"); AddCompletion("Referer"); @@ -31,8 +31,8 @@ Y_COMPLETER(HeaderCompleter) { AddCompletion("Content-MD5"); AddCompletion("Content-Range"); } -} - +} + class TMain: public TMainClassArgs { bool Background_; size_t Timeout_; @@ -42,7 +42,7 @@ class TMain: public TMainClassArgs { TMaybe<TString> PostData_; TMaybe<TString> PostFile_; TVector<TString> Headers_; - + protected: void RegisterOptions(NLastGetopt::TOpts& opts) override { // Brief description for the whole program, will appear in the beginning of a help message. @@ -75,7 +75,7 @@ protected: .CompletionArgHelp("timeout (ms)") .StoreResult(&Timeout_) .Completer(NLastGetopt::NComp::Choice({{"1000"}, {"5000"}, {"10000"}, {"60000"}})); - + opts.AddLongOption("method") .RequiredArgument("http-method") .Help("specify HTTP method") @@ -100,7 +100,7 @@ protected: .CompletionHelp("set custom user agent for each HTTP request") .CompletionArgHelp("user agent string") .StoreResult(&UserAgent_); - + opts.AddLongOption("post-data") .RequiredArgument("string") .Help("use POST method and send the specified data in the request body (cannot be used with --post-file)") @@ -121,10 +121,10 @@ protected: ImplicitMethod_ = "POST"; }) .Completer(NLastGetopt::NComp::File()); - + // These two options can't be together. opts.MutuallyExclusive("post-file", "post-data"); - + opts.AddLongOption("header") .RequiredArgument("header-line") .Help("send `header-line` along with the rest of the headers in each HTTP request") @@ -133,9 +133,9 @@ protected: .AppendTo(&Headers_) .AllowMultipleCompletion() .Completer(NLastGetopt::NComp::LaunchSelf(HeaderCompleter)); - + // Setting up free arguments. - + // We are going to have one mandatory argument and unlimited number of optional arguments. opts.SetFreeArgsMin(1); opts.SetFreeArgsMax(NLastGetopt::TOpts::UNLIMITED_ARGS); @@ -239,4 +239,4 @@ protected: int main(int argc, const char** argv) { NLastGetopt::NComp::TCustomCompleter::FireCustomCompleter(argc, argv); TMain().Run(argc, argv); -} +} diff --git a/library/cpp/getopt/last_getopt_demo/ya.make b/library/cpp/getopt/last_getopt_demo/ya.make index 53f1cfc122..275f983051 100644 --- a/library/cpp/getopt/last_getopt_demo/ya.make +++ b/library/cpp/getopt/last_getopt_demo/ya.make @@ -1,13 +1,13 @@ -PROGRAM(last_getopt_demo) - +PROGRAM(last_getopt_demo) + OWNER(amatanhead) PEERDIR( library/cpp/getopt ) -SRCS( - demo.cpp -) - -END() +SRCS( + demo.cpp +) + +END() diff --git a/library/cpp/getopt/small/last_getopt.cpp b/library/cpp/getopt/small/last_getopt.cpp index 30669b2c5a..d76420629d 100644 --- a/library/cpp/getopt/small/last_getopt.cpp +++ b/library/cpp/getopt/small/last_getopt.cpp @@ -6,4 +6,4 @@ namespace NLastGetopt { exit(0); } -} +} diff --git a/library/cpp/getopt/small/last_getopt.h b/library/cpp/getopt/small/last_getopt.h index 07687bc914..4377591fa8 100644 --- a/library/cpp/getopt/small/last_getopt.h +++ b/library/cpp/getopt/small/last_getopt.h @@ -1,21 +1,21 @@ #pragma once - + #include "last_getopt_opts.h" #include "last_getopt_easy_setup.h" #include "last_getopt_parse_result.h" #include <util/generic/function.h> #include <util/string/split.h> - + /// see some documentation in /// https://wiki.yandex-team.ru/development/poisk/arcadia/util/lastgetopt/ /// https://wiki.yandex-team.ru/development/poisk/arcadia/library/getopt/ /// see examples in library/cpp/getopt/last_getopt_demo - + //TODO: in most cases this include is unnecessary, but needed THandlerFunctor1<TpFunc, TpArg>::HandleOpt #include "last_getopt_parser.h" -namespace NLastGetopt { +namespace NLastGetopt { /// Handler to split option value by delimiter into a target container and allow ranges. template <class Container> struct TOptRangeSplitHandler: public IOptHandler { @@ -35,21 +35,21 @@ namespace NLastGetopt { if (curval.IsInited()) { StringSplitter(curval).Split(ElementsDelim).Consume([&](const TStringBuf& val) { TStringBuf mutableValue = val; - + TValue first = NPrivate::OptFromString<TValue>(mutableValue.NextTok(RangesDelim), parser->CurOpt()); TValue last = mutableValue ? NPrivate::OptFromString<TValue>(mutableValue, parser->CurOpt()) : first; - + if (last < first) { throw TUsageException() << "failed to parse opt " << NPrivate::OptToString(parser->CurOpt()) << " value " << TString(val).Quote() << ": the second argument is less than the first one"; } - + for (++last; first < last; ++first) { Target->insert(Target->end(), first); } }); } } - + private: TContainer* Target; char ElementsDelim; @@ -126,7 +126,7 @@ namespace NLastGetopt { << " value " << TString(curval).Quote() << ": " << CurrentExceptionMessage(); } } - - } + + } } diff --git a/library/cpp/getopt/small/last_getopt_support.h b/library/cpp/getopt/small/last_getopt_support.h index 17bed3e614..3ea05733ff 100644 --- a/library/cpp/getopt/small/last_getopt_support.h +++ b/library/cpp/getopt/small/last_getopt_support.h @@ -1,36 +1,36 @@ #pragma once - + #include <util/string/cast.h> #include <util/generic/string.h> #include <util/generic/vector.h> -#include <util/generic/utility.h> +#include <util/generic/utility.h> #include <util/generic/yexception.h> - -namespace NLastGetopt { + +namespace NLastGetopt { class TOpt; class TOpts; class TOptsParser; class TOptsParseResult; - + /// base of all getopt exceptions class TException: public yexception { }; - + /// TOpts configuration is incorrect class TConfException: public TException { }; - + /// User passed incorrect arguments, parsing failed /// Note: use `throw TUsageException()` instead of `ythrow TUsageException()` to prevent appearence of stacktrace /// and location of the `ythrow` statment in error messages. class TUsageException: public TException { }; - + struct IOptHandler { virtual void HandleOpt(const TOptsParser* parser) = 0; virtual ~IOptHandler() = default; }; - + namespace NPrivate { template <typename TpFunc> class THandlerFunctor0 @@ -94,7 +94,7 @@ namespace NLastGetopt { class TStoreResultFunctor { private: T* Target_; - + public: TStoreResultFunctor(T* target) : Target_(target) @@ -128,7 +128,7 @@ namespace NLastGetopt { class TStoreValueFunctor { T* Target; const TpVal Value; - + public: template <typename TpArg> TStoreValueFunctor(T* target, const TpArg& value) @@ -155,7 +155,7 @@ namespace NLastGetopt { inline TStringBuf OptFromStringImpl<TStringBuf>(const TStringBuf& value) { return value; } - + template <> inline const char* OptFromStringImpl<const char*>(const TStringBuf& value) { return value.data(); diff --git a/library/cpp/getopt/small/opt.cpp b/library/cpp/getopt/small/opt.cpp index 744501765c..2752987a55 100644 --- a/library/cpp/getopt/small/opt.cpp +++ b/library/cpp/getopt/small/opt.cpp @@ -1,105 +1,105 @@ #include "opt.h" - + #include <util/system/progname.h> -#include <ctype.h> +#include <ctype.h> -using namespace NLastGetopt; +using namespace NLastGetopt; -namespace { +namespace { struct TOptsNoDefault: public TOpts { TOptsNoDefault(const TStringBuf& optstring = TStringBuf()) : TOpts(optstring) { } - }; - -} - -void Opt::Init(int argc, char* argv[], const char* optString, const Ion* longOptions, bool longOnly, bool isOpen) { - Ions_ = longOptions; - Err = true; - GotError_ = false; + }; + +} + +void Opt::Init(int argc, char* argv[], const char* optString, const Ion* longOptions, bool longOnly, bool isOpen) { + Ions_ = longOptions; + Err = true; + GotError_ = false; Ind = argc; - - Opts_.Reset(new TOptsNoDefault(optString)); + + Opts_.Reset(new TOptsNoDefault(optString)); for (const Ion* o = longOptions; o != nullptr && o->name != nullptr; ++o) { - TOpt* opt; + TOpt* opt; if ((unsigned)o->val < 0x80 && isalnum(o->val)) { - opt = &Opts_->CharOption(char(o->val)); + opt = &Opts_->CharOption(char(o->val)); opt->AddLongName(o->name); - } else { - Opts_->AddLongOption(o->name); - opt = const_cast<TOpt*>(&Opts_->GetLongOption(o->name)); - } - opt->HasArg_ = EHasArg(o->has_arg); + } else { + Opts_->AddLongOption(o->name); + opt = const_cast<TOpt*>(&Opts_->GetLongOption(o->name)); + } + opt->HasArg_ = EHasArg(o->has_arg); opt->UserValue(o); } - Opts_->AllowSingleDashForLong_ = longOnly; - Opts_->AllowPlusForLong_ = true; - Opts_->AllowUnknownCharOptions_ = isOpen; - Opts_->AllowUnknownLongOptions_ = false; - - OptsParser_.Reset(new TOptsParser(Opts_.Get(), argc, argv)); -} + Opts_->AllowSingleDashForLong_ = longOnly; + Opts_->AllowPlusForLong_ = true; + Opts_->AllowUnknownCharOptions_ = isOpen; + Opts_->AllowUnknownLongOptions_ = false; -Opt::Opt(int argc, char* argv[], const char* optString, const Ion* longOptions, bool longOnly, bool isOpen) { - Init(argc, argv, optString, longOptions, longOnly, isOpen); + OptsParser_.Reset(new TOptsParser(Opts_.Get(), argc, argv)); } -Opt::Opt(int argc, const char* argv[], const char* optString, const Ion* longOptions, bool longOnly, bool isOpen) { +Opt::Opt(int argc, char* argv[], const char* optString, const Ion* longOptions, bool longOnly, bool isOpen) { + Init(argc, argv, optString, longOptions, longOnly, isOpen); +} + +Opt::Opt(int argc, const char* argv[], const char* optString, const Ion* longOptions, bool longOnly, bool isOpen) { Init(argc, (char**)argv, optString, longOptions, longOnly, isOpen); -} - -int Opt::Get() { +} + +int Opt::Get() { return Get(nullptr); } -int Opt::Get(int* longOptionIndex) { - if (GotError_) - return EOF; +int Opt::Get(int* longOptionIndex) { + if (GotError_) + return EOF; Arg = nullptr; - try { - bool r = OptsParser_->Next(); + try { + bool r = OptsParser_->Next(); Ind = (int)OptsParser_->Pos_; - if (!r) { + if (!r) { return EOF; - } else { + } else { Arg = (char*)OptsParser_->CurVal(); if (!OptsParser_->CurOpt()) { - // possible if RETURN_IN_ORDER - return 1; - } else { + // possible if RETURN_IN_ORDER + return 1; + } else { const Ion* ion = (const Ion*)OptsParser_->CurOpt()->UserValue(); if (longOptionIndex) { *longOptionIndex = int(ion - Ions_); - } + } char c = OptsParser_->CurOpt()->GetCharOr0(); - return c != 0 ? c : ion->val; + return c != 0 ? c : ion->val; } } - } catch (const NLastGetopt::TException&) { - GotError_ = true; - if (Err) - Cerr << CurrentExceptionMessage() << Endl; - return '?'; + } catch (const NLastGetopt::TException&) { + GotError_ = true; + if (Err) + Cerr << CurrentExceptionMessage() << Endl; + return '?'; } } void Opt::DummyHelp(IOutputStream& os) { Opts_->PrintUsage(GetProgramName(), os); -} - -int Opt::GetArgC() const { +} + +int Opt::GetArgC() const { return (int)OptsParser_->Argc_; -} - -const char** Opt::GetArgV() const { - return OptsParser_->Argv_; -} - +} + +const char** Opt::GetArgV() const { + return OptsParser_->Argv_; +} + int opt_get_number(int& argc, char* argv[]) { int num = -1; for (int a = 1; a < argc; a++) { diff --git a/library/cpp/getopt/small/opt.h b/library/cpp/getopt/small/opt.h index ecb57439bc..80701aa7e9 100644 --- a/library/cpp/getopt/small/opt.h +++ b/library/cpp/getopt/small/opt.h @@ -1,118 +1,118 @@ #pragma once - + #include "last_getopt.h" #include <util/generic/ptr.h> -#include <util/generic/noncopyable.h> - -// implementation of Opt class using last getopt - -/* - short-options syntax: - - opt-letter ::= - [^: ] - - opt-string ::= - '+'|'-'?({opt-letter}':'{0,2})* - - example: "AbCx:y:z::" - {A,b,C} options without argument - {x,y} options with argument - {z} option with optional argument - - 1. shortopts begins with '-' :=> RETURN_IN_ORDER - == non-option forces getopt to return 1 and to place non-option into optarg - - 2. shortopts begins with '+' :=> REQUIRE_ORDER +#include <util/generic/noncopyable.h> + +// implementation of Opt class using last getopt + +/* + short-options syntax: + + opt-letter ::= + [^: ] + + opt-string ::= + '+'|'-'?({opt-letter}':'{0,2})* + + example: "AbCx:y:z::" + {A,b,C} options without argument + {x,y} options with argument + {z} option with optional argument + + 1. shortopts begins with '-' :=> RETURN_IN_ORDER + == non-option forces getopt to return 1 and to place non-option into optarg + + 2. shortopts begins with '+' :=> REQUIRE_ORDER GetEnv(_POSIX_OPTION_ORDER) :=> REQUIRE_ORDER - == 1st non-option forces getopt to return EOF - - 3. default :=> PERMUTE - == exchange options with non-options and place all options first - - 4. '--' command line argument forces getopt to stop parsing and to return EOF - in any case - - long options should begin by '+' sign - or when (_getopt_long_only = 1) by '-' sign - - struct option { - char *name : option name - int has_arg: 0 | 1 | 2 = without | with | optional argument - int *flag : if (flag != 0) then getopt returns 0 and stores val into *flag - int val : if (flag == 0) then getopt returns val - } - - Example: - - struct option my_opts[] = { - { "delete", 0, &deletion_flag, DEL }, -- returns 0, deletion_flag := DEL - { "add", 1, NULL, 'a' }, -- returns 'a', argument in optarg - { NULL } - } -*/ - -#define OPT_RETURN_IN_ORDER "-" + == 1st non-option forces getopt to return EOF + + 3. default :=> PERMUTE + == exchange options with non-options and place all options first + + 4. '--' command line argument forces getopt to stop parsing and to return EOF + in any case + + long options should begin by '+' sign + or when (_getopt_long_only = 1) by '-' sign + + struct option { + char *name : option name + int has_arg: 0 | 1 | 2 = without | with | optional argument + int *flag : if (flag != 0) then getopt returns 0 and stores val into *flag + int val : if (flag == 0) then getopt returns val + } + + Example: + + struct option my_opts[] = { + { "delete", 0, &deletion_flag, DEL }, -- returns 0, deletion_flag := DEL + { "add", 1, NULL, 'a' }, -- returns 'a', argument in optarg + { NULL } + } +*/ + +#define OPT_RETURN_IN_ORDER "-" #define OPT_REQUIRE_ORDER "+" #define OPT_DONT_STORE_ARG ((void*)0) - + class Opt : TNonCopyable { -public: +public: enum HasArg { WithoutArg, WithArg, PossibleArg }; - - struct Ion { + + struct Ion { const char* name; HasArg has_arg; int* flag; int val; - }; - -private: - THolder<NLastGetopt::TOpts> Opts_; - THolder<NLastGetopt::TOptsParser> OptsParser_; - const Ion* Ions_; - bool GotError_; + }; + +private: + THolder<NLastGetopt::TOpts> Opts_; + THolder<NLastGetopt::TOptsParser> OptsParser_; + const Ion* Ions_; + bool GotError_; void Init(int argc, char* argv[], const char* optString, const Ion* longOptions = nullptr, bool longOnly = false, bool isOpen = false); - -public: + +public: Opt(int argc, char* argv[], const char* optString, const Ion* longOptions = nullptr, bool longOnly = false, bool isOpen = false); Opt(int argc, const char* argv[], const char* optString, const Ion* longOptions = nullptr, bool longOnly = false, bool isOpen = false); - - // Get() means next - int Get(); - int Get(int* longOptionIndex); + + // Get() means next + int Get(); + int Get(int* longOptionIndex); int operator()() { - return Get(); - } - + return Get(); + } + const char* GetArg() const { return Arg; } - + TVector<TString> GetFreeArgs() const { return NLastGetopt::TOptsParseResult(&*Opts_, GetArgC(), GetArgV()).GetFreeArgs(); } - // obsolete, use GetArg() instead + // obsolete, use GetArg() instead char* Arg; /* option argument if any or NULL */ - + int Ind; /* command line index */ bool Err; /* flag to print error messages */ - - int GetArgC() const; - const char** GetArgV() const; - + + int GetArgC() const; + const char** GetArgV() const; + void DummyHelp(IOutputStream& os = Cerr); -}; - -// call before getopt. returns non-negative int, removing it from arguments (not found: -1) -// Example: returns 11 for "progname -11abc", -1 for "progname -a11" +}; + +// call before getopt. returns non-negative int, removing it from arguments (not found: -1) +// Example: returns 11 for "progname -11abc", -1 for "progname -a11" int opt_get_number(int& argc, char* argv[]); - + #define OPTION_HANDLING_PROLOG \ { \ int optlet; \ @@ -128,12 +128,12 @@ int opt_get_number(int& argc, char* argv[]); #define OPTION_HANDLE_END \ } \ break; - + #define OPTION_HANDLE(opt, handle) \ OPTION_HANDLE_BEGIN(opt) \ handle; \ OPTION_HANDLE_END - + #define OPTION_HANDLING_EPILOG \ default: \ ythrow yexception() << "unknown optlet"; \ diff --git a/library/cpp/getopt/small/opt2.h b/library/cpp/getopt/small/opt2.h index 4d9d943237..c81cf345a4 100644 --- a/library/cpp/getopt/small/opt2.h +++ b/library/cpp/getopt/small/opt2.h @@ -111,11 +111,11 @@ public: void AddError(const char* message = nullptr); public: - // non-option args + // non-option args TVector<char*> Pos; bool HasErrors; - -private: + +private: bool BadPosCount; char UnknownOption; char* UnknownLongOption; diff --git a/library/cpp/getopt/small/posix_getopt.cpp b/library/cpp/getopt/small/posix_getopt.cpp index bd06f3499f..cae224133a 100644 --- a/library/cpp/getopt/small/posix_getopt.cpp +++ b/library/cpp/getopt/small/posix_getopt.cpp @@ -2,76 +2,76 @@ #include <util/generic/ptr.h> -#include <ctype.h> - -namespace NLastGetopt { - char* optarg; - int optind; - int optopt; - int opterr; - int optreset; - - static THolder<TOpts> Opts; - static THolder<TOptsParser> OptsParser; - +#include <ctype.h> + +namespace NLastGetopt { + char* optarg; + int optind; + int optopt; + int opterr; + int optreset; + + static THolder<TOpts> Opts; + static THolder<TOptsParser> OptsParser; + int getopt_long_impl(int argc, char* const* argv, const char* optstring, const struct option* longopts, int* longindex, bool long_only) { - if (!Opts || optreset == 1) { + if (!Opts || optreset == 1) { optarg = nullptr; - optind = 1; - opterr = 1; - optreset = 0; - Opts.Reset(new TOpts(TOpts::Default(optstring))); - - Opts->AllowSingleDashForLong_ = long_only; - + optind = 1; + opterr = 1; + optreset = 0; + Opts.Reset(new TOpts(TOpts::Default(optstring))); + + Opts->AllowSingleDashForLong_ = long_only; + for (const struct option* o = longopts; o != nullptr && o->name != nullptr; ++o) { - TOpt* opt; + TOpt* opt; if ((unsigned)o->val < 0x80 && isalnum(o->val)) { - opt = &Opts->CharOption(char(o->val)); + opt = &Opts->CharOption(char(o->val)); opt->AddLongName(o->name); - } else { - Opts->AddLongOption(o->name); - opt = const_cast<TOpt*>(&Opts->GetLongOption(o->name)); - } - opt->HasArg_ = EHasArg(o->has_arg); + } else { + Opts->AddLongOption(o->name); + opt = const_cast<TOpt*>(&Opts->GetLongOption(o->name)); + } + opt->HasArg_ = EHasArg(o->has_arg); opt->UserValue(o->flag); - } - + } + OptsParser.Reset(new TOptsParser(&*Opts, argc, (const char**)argv)); - } - + } + optarg = nullptr; - - try { - if (!OptsParser->Next()) { - return -1; - } else { + + try { + if (!OptsParser->Next()) { + return -1; + } else { optarg = (char*)OptsParser->CurVal(); optind = (int)OptsParser->Pos_; if (longindex && OptsParser->CurOpt()) *longindex = (int)Opts->IndexOf(OptsParser->CurOpt()); return OptsParser->CurOpt() ? OptsParser->CurOpt()->GetCharOr0() : 1; - } - } catch (const NLastGetopt::TException&) { - return '?'; - } - } - + } + } catch (const NLastGetopt::TException&) { + return '?'; + } + } + int getopt_long(int argc, char* const* argv, const char* optstring, const struct option* longopts, int* longindex) { - return getopt_long_impl(argc, argv, optstring, longopts, longindex, false); - } - - int getopt_long_only(int argc, char* const* argv, const char* optstring, + return getopt_long_impl(argc, argv, optstring, longopts, longindex, false); + } + + int getopt_long_only(int argc, char* const* argv, const char* optstring, const struct option* longopts, int* longindex) { - return getopt_long_impl(argc, argv, optstring, longopts, longindex, true); - } - - // XXX: leading colon is not supported - // XXX: updating optind by client is not supported - int getopt(int argc, char* const* argv, const char* optstring) { + return getopt_long_impl(argc, argv, optstring, longopts, longindex, true); + } + + // XXX: leading colon is not supported + // XXX: updating optind by client is not supported + int getopt(int argc, char* const* argv, const char* optstring) { return getopt_long(argc, argv, optstring, nullptr, nullptr); - } - -} + } + +} diff --git a/library/cpp/getopt/small/posix_getopt.h b/library/cpp/getopt/small/posix_getopt.h index e6af1e0284..d26fa96641 100644 --- a/library/cpp/getopt/small/posix_getopt.h +++ b/library/cpp/getopt/small/posix_getopt.h @@ -1,32 +1,32 @@ #pragma once - -// implementation of posix getopt using last getopt for demonstration purposes - -#include "last_getopt.h" - -namespace NLastGetopt { - extern char* optarg; - extern int optind; - extern int optopt; - extern int opterr; - extern int optreset; - - enum { - no_argument = NO_ARGUMENT, - required_argument = REQUIRED_ARGUMENT, - optional_argument = OPTIONAL_ARGUMENT, - }; - - struct option { - const char* name; - int has_arg; - int* flag; - int val; - }; - - int getopt(int argc, char* const* argv, const char* optstring); + +// implementation of posix getopt using last getopt for demonstration purposes + +#include "last_getopt.h" + +namespace NLastGetopt { + extern char* optarg; + extern int optind; + extern int optopt; + extern int opterr; + extern int optreset; + + enum { + no_argument = NO_ARGUMENT, + required_argument = REQUIRED_ARGUMENT, + optional_argument = OPTIONAL_ARGUMENT, + }; + + struct option { + const char* name; + int has_arg; + int* flag; + int val; + }; + + int getopt(int argc, char* const* argv, const char* optstring); int getopt_long(int argc, char* const* argv, const char* optstring, const struct option* longopts, int* longindex); - int getopt_long_only(int argc, char* const* argv, const char* optstring, + int getopt_long_only(int argc, char* const* argv, const char* optstring, const struct option* longopts, int* longindex); -} +} diff --git a/library/cpp/getopt/ut/last_getopt_ut.cpp b/library/cpp/getopt/ut/last_getopt_ut.cpp index c99a1d053d..7d6a29f2a5 100644 --- a/library/cpp/getopt/ut/last_getopt_ut.cpp +++ b/library/cpp/getopt/ut/last_getopt_ut.cpp @@ -2,22 +2,22 @@ #include <library/cpp/colorizer/colors.h> #include <library/cpp/testing/unittest/registar.h> - + #include <util/generic/array_size.h> #include <util/string/subst.h> #include <util/string/vector.h> #include <util/string/split.h> -using namespace NLastGetopt; - -namespace { +using namespace NLastGetopt; + +namespace { struct TOptsNoDefault: public TOpts { TOptsNoDefault(const TStringBuf& optstring = TStringBuf()) : TOpts(optstring) { } - }; - + }; + class TOptsParseResultTestWrapper: public TOptsParseResultException { TVector<const char*> Argv_; @@ -30,101 +30,101 @@ namespace { }; using V = TVector<const char*>; -} - -struct TOptsParserTester { - TOptsNoDefault Opts_; +} + +struct TOptsParserTester { + TOptsNoDefault Opts_; TVector<const char*> Argv_; - - THolder<TOptsParser> Parser_; - - void Initialize() { - if (!Parser_) + + THolder<TOptsParser> Parser_; + + void Initialize() { + if (!Parser_) Parser_.Reset(new TOptsParser(&Opts_, (int)Argv_.size(), Argv_.data())); - } - - void Accept() { - Initialize(); - UNIT_ASSERT(Parser_->Next()); - } - - void AcceptOption() { - Accept(); + } + + void Accept() { + Initialize(); + UNIT_ASSERT(Parser_->Next()); + } + + void AcceptOption() { + Accept(); UNIT_ASSERT(!!Parser_->CurOpt()); - } - - void AcceptOption(char c) { - AcceptOption(); + } + + void AcceptOption(char c) { + AcceptOption(); UNIT_ASSERT(Parser_->CurOpt()->CharIs(c)); - } - + } + void AcceptOption(const TString& optName) { - AcceptOption(); + AcceptOption(); UNIT_ASSERT(Parser_->CurOpt()->NameIs(optName)); - } - - template <typename TOpt> + } + + template <typename TOpt> void AcceptOptionWithValue(TOpt optName, const TString& value) { - AcceptOption(optName); + AcceptOption(optName); UNIT_ASSERT_VALUES_EQUAL_C(value, Parser_->CurValStr(), "; option " << optName); - } - - template <typename TOpt> - void AcceptOptionWithoutValue(TOpt optName) { - AcceptOption(optName); + } + + template <typename TOpt> + void AcceptOptionWithoutValue(TOpt optName) { + AcceptOption(optName); UNIT_ASSERT_C(!Parser_->CurVal(), ": opt " << optName << " must have no param"); - } - + } + void AcceptFreeArgInOrder(const TString& expected) { - Accept(); + Accept(); UNIT_ASSERT(!Parser_->CurOpt()); UNIT_ASSERT_VALUES_EQUAL(expected, Parser_->CurValStr()); - } - - size_t Pos_; - - void AcceptEndOfOptions() { - Initialize(); - UNIT_ASSERT(!Parser_->Next()); - Pos_ = Parser_->Pos_; - - // pos must not be changed after last meaningful invocation of Next() - UNIT_ASSERT(!Parser_->Next()); - UNIT_ASSERT_VALUES_EQUAL(Pos_, Parser_->Pos_); - UNIT_ASSERT(!Parser_->Next()); - UNIT_ASSERT_VALUES_EQUAL(Pos_, Parser_->Pos_); - } - - void AcceptError() { - Initialize(); - try { - Parser_->Next(); - UNIT_FAIL("expecting exception"); - } catch (const TUsageException&) { - // expecting - } - } - - void AcceptUnexpectedOption() { - Initialize(); - size_t pos = Parser_->Pos_; - size_t sop = Parser_->Sop_; - AcceptError(); - UNIT_ASSERT_VALUES_EQUAL(pos, Parser_->Pos_); - UNIT_ASSERT_VALUES_EQUAL(sop, Parser_->Sop_); - } - + } + + size_t Pos_; + + void AcceptEndOfOptions() { + Initialize(); + UNIT_ASSERT(!Parser_->Next()); + Pos_ = Parser_->Pos_; + + // pos must not be changed after last meaningful invocation of Next() + UNIT_ASSERT(!Parser_->Next()); + UNIT_ASSERT_VALUES_EQUAL(Pos_, Parser_->Pos_); + UNIT_ASSERT(!Parser_->Next()); + UNIT_ASSERT_VALUES_EQUAL(Pos_, Parser_->Pos_); + } + + void AcceptError() { + Initialize(); + try { + Parser_->Next(); + UNIT_FAIL("expecting exception"); + } catch (const TUsageException&) { + // expecting + } + } + + void AcceptUnexpectedOption() { + Initialize(); + size_t pos = Parser_->Pos_; + size_t sop = Parser_->Sop_; + AcceptError(); + UNIT_ASSERT_VALUES_EQUAL(pos, Parser_->Pos_); + UNIT_ASSERT_VALUES_EQUAL(sop, Parser_->Sop_); + } + void AcceptFreeArg(const TString& expected) { - UNIT_ASSERT(Pos_ < Parser_->Argc_); - UNIT_ASSERT_VALUES_EQUAL(expected, Parser_->Argv_[Pos_]); - ++Pos_; - } - - void AcceptEndOfFreeArgs() { - UNIT_ASSERT_VALUES_EQUAL(Argv_.size(), Pos_); - } -}; - + UNIT_ASSERT(Pos_ < Parser_->Argc_); + UNIT_ASSERT_VALUES_EQUAL(expected, Parser_->Argv_[Pos_]); + ++Pos_; + } + + void AcceptEndOfFreeArgs() { + UNIT_ASSERT_VALUES_EQUAL(Argv_.size(), Pos_); + } +}; + namespace { bool gSimpleFlag = false; void SimpleHander(void) { @@ -134,37 +134,37 @@ namespace { Y_UNIT_TEST_SUITE(TLastGetoptTests) { Y_UNIT_TEST(TestEqual) { - TOptsNoDefault opts; - opts.AddLongOption("from"); - opts.AddLongOption("to"); + TOptsNoDefault opts; + opts.AddLongOption("from"); + opts.AddLongOption("to"); TOptsParseResultTestWrapper r(&opts, V({"copy", "--from=/", "--to=/etc"})); - - UNIT_ASSERT_VALUES_EQUAL("copy", r.GetProgramName()); - UNIT_ASSERT_VALUES_EQUAL("/", r.Get("from")); - UNIT_ASSERT_VALUES_EQUAL("/etc", r.Get("to")); - UNIT_ASSERT_VALUES_EQUAL("/etc", r.GetOrElse("to", "trash")); - UNIT_ASSERT(r.Has("from")); - UNIT_ASSERT(r.Has("to")); + + UNIT_ASSERT_VALUES_EQUAL("copy", r.GetProgramName()); + UNIT_ASSERT_VALUES_EQUAL("/", r.Get("from")); + UNIT_ASSERT_VALUES_EQUAL("/etc", r.Get("to")); + UNIT_ASSERT_VALUES_EQUAL("/etc", r.GetOrElse("to", "trash")); + UNIT_ASSERT(r.Has("from")); + UNIT_ASSERT(r.Has("to")); UNIT_ASSERT_EXCEPTION(r.Get("left"), TException); - } - + } + Y_UNIT_TEST(TestCharOptions) { - TOptsNoDefault opts; - opts.AddCharOption('R', NO_ARGUMENT); - opts.AddCharOption('l', NO_ARGUMENT); - opts.AddCharOption('h', NO_ARGUMENT); + TOptsNoDefault opts; + opts.AddCharOption('R', NO_ARGUMENT); + opts.AddCharOption('l', NO_ARGUMENT); + opts.AddCharOption('h', NO_ARGUMENT); TOptsParseResultTestWrapper r(&opts, V({"cp", "/etc", "-Rl", "/tmp/etc"})); - UNIT_ASSERT(r.Has('R')); - UNIT_ASSERT(r.Has('l')); - UNIT_ASSERT(!r.Has('h')); - + UNIT_ASSERT(r.Has('R')); + UNIT_ASSERT(r.Has('l')); + UNIT_ASSERT(!r.Has('h')); + UNIT_ASSERT_VALUES_EQUAL(2u, r.GetFreeArgs().size()); UNIT_ASSERT_VALUES_EQUAL(2u, r.GetFreeArgCount()); - UNIT_ASSERT_VALUES_EQUAL("/etc", r.GetFreeArgs()[0]); - UNIT_ASSERT_VALUES_EQUAL("/tmp/etc", r.GetFreeArgs()[1]); - } - + UNIT_ASSERT_VALUES_EQUAL("/etc", r.GetFreeArgs()[0]); + UNIT_ASSERT_VALUES_EQUAL("/tmp/etc", r.GetFreeArgs()[1]); + } + Y_UNIT_TEST(TestFreeArgs) { TOptsNoDefault opts; opts.SetFreeArgsNum(1, 3); @@ -185,167 +185,167 @@ Y_UNIT_TEST_SUITE(TLastGetoptTests) { } Y_UNIT_TEST(TestCharOptionsRequiredOptional) { - TOptsNoDefault opts; - opts.AddCharOption('d', REQUIRED_ARGUMENT); - opts.AddCharOption('e', REQUIRED_ARGUMENT); - opts.AddCharOption('x', REQUIRED_ARGUMENT); - opts.AddCharOption('y', REQUIRED_ARGUMENT); - opts.AddCharOption('l', NO_ARGUMENT); + TOptsNoDefault opts; + opts.AddCharOption('d', REQUIRED_ARGUMENT); + opts.AddCharOption('e', REQUIRED_ARGUMENT); + opts.AddCharOption('x', REQUIRED_ARGUMENT); + opts.AddCharOption('y', REQUIRED_ARGUMENT); + opts.AddCharOption('l', NO_ARGUMENT); TOptsParseResultTestWrapper r(&opts, V({"cmd", "-ld11", "-e", "22", "-lllx33", "-y", "44"})); - UNIT_ASSERT_VALUES_EQUAL("11", r.Get('d')); - UNIT_ASSERT_VALUES_EQUAL("22", r.Get('e')); - UNIT_ASSERT_VALUES_EQUAL("33", r.Get('x')); - UNIT_ASSERT_VALUES_EQUAL("44", r.Get('y')); - } - + UNIT_ASSERT_VALUES_EQUAL("11", r.Get('d')); + UNIT_ASSERT_VALUES_EQUAL("22", r.Get('e')); + UNIT_ASSERT_VALUES_EQUAL("33", r.Get('x')); + UNIT_ASSERT_VALUES_EQUAL("44", r.Get('y')); + } + Y_UNIT_TEST(TestReturnInOrder) { - TOptsParserTester tester; - tester.Opts_.AddLongOption('v', "value"); - tester.Opts_.ArgPermutation_ = RETURN_IN_ORDER; - - tester.Argv_.push_back("cmd"); - tester.Argv_.push_back("--value=11"); - tester.Argv_.push_back("xx"); - tester.Argv_.push_back("-v12"); - tester.Argv_.push_back("yy"); - tester.Argv_.push_back("--"); - tester.Argv_.push_back("-v13"); - tester.Argv_.push_back("--"); - - tester.AcceptOptionWithValue("value", "11"); - tester.AcceptFreeArgInOrder("xx"); - tester.AcceptOptionWithValue('v', "12"); - tester.AcceptFreeArgInOrder("yy"); - tester.AcceptFreeArgInOrder("-v13"); - tester.AcceptFreeArgInOrder("--"); - tester.AcceptEndOfOptions(); - tester.AcceptEndOfFreeArgs(); - } - + TOptsParserTester tester; + tester.Opts_.AddLongOption('v', "value"); + tester.Opts_.ArgPermutation_ = RETURN_IN_ORDER; + + tester.Argv_.push_back("cmd"); + tester.Argv_.push_back("--value=11"); + tester.Argv_.push_back("xx"); + tester.Argv_.push_back("-v12"); + tester.Argv_.push_back("yy"); + tester.Argv_.push_back("--"); + tester.Argv_.push_back("-v13"); + tester.Argv_.push_back("--"); + + tester.AcceptOptionWithValue("value", "11"); + tester.AcceptFreeArgInOrder("xx"); + tester.AcceptOptionWithValue('v', "12"); + tester.AcceptFreeArgInOrder("yy"); + tester.AcceptFreeArgInOrder("-v13"); + tester.AcceptFreeArgInOrder("--"); + tester.AcceptEndOfOptions(); + tester.AcceptEndOfFreeArgs(); + } + Y_UNIT_TEST(TestRequireOrder) { - TOptsParserTester tester; - tester.Opts_.ArgPermutation_ = REQUIRE_ORDER; - tester.Opts_.AddLongOption('v', "value"); - - tester.Argv_.push_back("cmd"); - tester.Argv_.push_back("--value=11"); - tester.Argv_.push_back("xx"); - tester.Argv_.push_back("-v12"); - tester.Argv_.push_back("yy"); - - tester.AcceptOptionWithValue("value", "11"); - tester.AcceptEndOfOptions(); - - tester.AcceptFreeArg("xx"); - tester.AcceptFreeArg("-v12"); - tester.AcceptFreeArg("yy"); - tester.AcceptEndOfFreeArgs(); - } - + TOptsParserTester tester; + tester.Opts_.ArgPermutation_ = REQUIRE_ORDER; + tester.Opts_.AddLongOption('v', "value"); + + tester.Argv_.push_back("cmd"); + tester.Argv_.push_back("--value=11"); + tester.Argv_.push_back("xx"); + tester.Argv_.push_back("-v12"); + tester.Argv_.push_back("yy"); + + tester.AcceptOptionWithValue("value", "11"); + tester.AcceptEndOfOptions(); + + tester.AcceptFreeArg("xx"); + tester.AcceptFreeArg("-v12"); + tester.AcceptFreeArg("yy"); + tester.AcceptEndOfFreeArgs(); + } + Y_UNIT_TEST(TestPlusForLongOption) { - TOptsParserTester tester; - tester.Opts_.AddLongOption('v', "value"); - tester.Opts_.AllowPlusForLong_ = true; - tester.Argv_.push_back("cmd"); - tester.Argv_.push_back("+value=11"); - tester.Argv_.push_back("xx"); - tester.Argv_.push_back("-v12"); - tester.Argv_.push_back("yy"); - - tester.AcceptOptionWithValue("value", "11"); - tester.AcceptOptionWithValue("value", "12"); - tester.AcceptEndOfOptions(); - - tester.AcceptFreeArg("xx"); - tester.AcceptFreeArg("yy"); - tester.AcceptEndOfFreeArgs(); - } - + TOptsParserTester tester; + tester.Opts_.AddLongOption('v', "value"); + tester.Opts_.AllowPlusForLong_ = true; + tester.Argv_.push_back("cmd"); + tester.Argv_.push_back("+value=11"); + tester.Argv_.push_back("xx"); + tester.Argv_.push_back("-v12"); + tester.Argv_.push_back("yy"); + + tester.AcceptOptionWithValue("value", "11"); + tester.AcceptOptionWithValue("value", "12"); + tester.AcceptEndOfOptions(); + + tester.AcceptFreeArg("xx"); + tester.AcceptFreeArg("yy"); + tester.AcceptEndOfFreeArgs(); + } + Y_UNIT_TEST(TestBug1) { - TOptsParserTester tester; - tester.Opts_.AddCharOptions("A:b:cd:"); - - tester.Argv_.push_back("cmd"); - tester.Argv_.push_back("-A"); - tester.Argv_.push_back("aaaa"); - tester.Argv_.push_back("zz"); - tester.Argv_.push_back("-c"); - tester.Argv_.push_back("-d8"); - tester.Argv_.push_back("ww"); - - tester.AcceptOptionWithValue('A', "aaaa"); - tester.AcceptOptionWithoutValue('c'); - tester.AcceptOptionWithValue('d', "8"); - tester.AcceptEndOfOptions(); - - tester.AcceptFreeArg("zz"); - tester.AcceptFreeArg("ww"); - tester.AcceptEndOfFreeArgs(); - } - + TOptsParserTester tester; + tester.Opts_.AddCharOptions("A:b:cd:"); + + tester.Argv_.push_back("cmd"); + tester.Argv_.push_back("-A"); + tester.Argv_.push_back("aaaa"); + tester.Argv_.push_back("zz"); + tester.Argv_.push_back("-c"); + tester.Argv_.push_back("-d8"); + tester.Argv_.push_back("ww"); + + tester.AcceptOptionWithValue('A', "aaaa"); + tester.AcceptOptionWithoutValue('c'); + tester.AcceptOptionWithValue('d', "8"); + tester.AcceptEndOfOptions(); + + tester.AcceptFreeArg("zz"); + tester.AcceptFreeArg("ww"); + tester.AcceptEndOfFreeArgs(); + } + Y_UNIT_TEST(TestPermuteComplex) { - TOptsParserTester tester; - - tester.Opts_.AddCharOption('x').NoArgument(); - tester.Opts_.AddCharOption('y').RequiredArgument(); - tester.Opts_.AddCharOption('z').NoArgument(); - tester.Opts_.AddCharOption('w').RequiredArgument(); - tester.Opts_.ArgPermutation_ = PERMUTE; - - tester.Argv_.push_back("cmd"); - tester.Argv_.push_back("-x"); - tester.Argv_.push_back("-y"); - tester.Argv_.push_back("val"); - tester.Argv_.push_back("freearg1"); - tester.Argv_.push_back("-zw"); - tester.Argv_.push_back("val2"); - tester.Argv_.push_back("freearg2"); - - tester.AcceptOptionWithoutValue('x'); - tester.AcceptOptionWithValue('y', "val"); - tester.AcceptOptionWithoutValue('z'); - tester.AcceptOptionWithValue('w', "val2"); - tester.AcceptEndOfOptions(); - tester.AcceptFreeArg("freearg1"); - tester.AcceptFreeArg("freearg2"); - tester.AcceptEndOfFreeArgs(); - } - + TOptsParserTester tester; + + tester.Opts_.AddCharOption('x').NoArgument(); + tester.Opts_.AddCharOption('y').RequiredArgument(); + tester.Opts_.AddCharOption('z').NoArgument(); + tester.Opts_.AddCharOption('w').RequiredArgument(); + tester.Opts_.ArgPermutation_ = PERMUTE; + + tester.Argv_.push_back("cmd"); + tester.Argv_.push_back("-x"); + tester.Argv_.push_back("-y"); + tester.Argv_.push_back("val"); + tester.Argv_.push_back("freearg1"); + tester.Argv_.push_back("-zw"); + tester.Argv_.push_back("val2"); + tester.Argv_.push_back("freearg2"); + + tester.AcceptOptionWithoutValue('x'); + tester.AcceptOptionWithValue('y', "val"); + tester.AcceptOptionWithoutValue('z'); + tester.AcceptOptionWithValue('w', "val2"); + tester.AcceptEndOfOptions(); + tester.AcceptFreeArg("freearg1"); + tester.AcceptFreeArg("freearg2"); + tester.AcceptEndOfFreeArgs(); + } + Y_UNIT_TEST(TestFinalDashDash) { - TOptsParserTester tester; - tester.Opts_.AddLongOption("size"); - - tester.Argv_.push_back("cmd"); - tester.Argv_.push_back("--"); - - tester.AcceptEndOfOptions(); - tester.AcceptEndOfFreeArgs(); - } - + TOptsParserTester tester; + tester.Opts_.AddLongOption("size"); + + tester.Argv_.push_back("cmd"); + tester.Argv_.push_back("--"); + + tester.AcceptEndOfOptions(); + tester.AcceptEndOfFreeArgs(); + } + Y_UNIT_TEST(TestDashDashAfterDashDash) { - TOptsParserTester tester; - tester.Opts_.AddLongOption("size"); - - tester.Argv_.push_back("cmd"); - tester.Argv_.push_back("--"); - tester.Argv_.push_back("--"); - tester.Argv_.push_back("--"); - - tester.AcceptEndOfOptions(); - tester.AcceptFreeArg("--"); - tester.AcceptFreeArg("--"); - tester.AcceptEndOfFreeArgs(); - } - + TOptsParserTester tester; + tester.Opts_.AddLongOption("size"); + + tester.Argv_.push_back("cmd"); + tester.Argv_.push_back("--"); + tester.Argv_.push_back("--"); + tester.Argv_.push_back("--"); + + tester.AcceptEndOfOptions(); + tester.AcceptFreeArg("--"); + tester.AcceptFreeArg("--"); + tester.AcceptEndOfFreeArgs(); + } + Y_UNIT_TEST(TestUnexpectedUnknownOption) { - TOptsParserTester tester; - - tester.Argv_.push_back("cmd"); - tester.Argv_.push_back("-x"); - - tester.AcceptUnexpectedOption(); - } - + TOptsParserTester tester; + + tester.Argv_.push_back("cmd"); + tester.Argv_.push_back("-x"); + + tester.AcceptUnexpectedOption(); + } + Y_UNIT_TEST(TestDuplicatedOptionCrash) { // this test is broken, cause UNIT_ASSERT(false) always throws return; @@ -364,84 +364,84 @@ Y_UNIT_TEST_SUITE(TLastGetoptTests) { } Y_UNIT_TEST(TestPositionWhenNoArgs) { - TOptsParserTester tester; - - tester.Argv_.push_back("cmd"); - - tester.Opts_.AddCharOption('c'); - - tester.AcceptEndOfOptions(); - + TOptsParserTester tester; + + tester.Argv_.push_back("cmd"); + + tester.Opts_.AddCharOption('c'); + + tester.AcceptEndOfOptions(); + UNIT_ASSERT_VALUES_EQUAL(1u, tester.Parser_->Pos_); - } - + } + Y_UNIT_TEST(TestExpectedUnknownCharOption) { - TOptsParserTester tester; - - tester.Argv_.push_back("cmd"); - tester.Argv_.push_back("-x"); - tester.Argv_.push_back("-y"); - tester.Argv_.push_back("val"); - tester.Argv_.push_back("freearg1"); - tester.Argv_.push_back("-zw"); - tester.Argv_.push_back("val2"); - tester.Argv_.push_back("freearg2"); - - tester.Opts_.AllowUnknownCharOptions_ = true; - - tester.AcceptOptionWithoutValue('x'); - tester.AcceptOptionWithValue('y', "val"); - tester.AcceptOptionWithoutValue('z'); - tester.AcceptOptionWithValue('w', "val2"); - tester.AcceptEndOfOptions(); - tester.AcceptFreeArg("freearg1"); - tester.AcceptFreeArg("freearg2"); - tester.AcceptEndOfFreeArgs(); - } - -#if 0 + TOptsParserTester tester; + + tester.Argv_.push_back("cmd"); + tester.Argv_.push_back("-x"); + tester.Argv_.push_back("-y"); + tester.Argv_.push_back("val"); + tester.Argv_.push_back("freearg1"); + tester.Argv_.push_back("-zw"); + tester.Argv_.push_back("val2"); + tester.Argv_.push_back("freearg2"); + + tester.Opts_.AllowUnknownCharOptions_ = true; + + tester.AcceptOptionWithoutValue('x'); + tester.AcceptOptionWithValue('y', "val"); + tester.AcceptOptionWithoutValue('z'); + tester.AcceptOptionWithValue('w', "val2"); + tester.AcceptEndOfOptions(); + tester.AcceptFreeArg("freearg1"); + tester.AcceptFreeArg("freearg2"); + tester.AcceptEndOfFreeArgs(); + } + +#if 0 Y_UNIT_TEST(TestRequiredParams) { - TOptsParserTester tester; - - tester.Argv_.push_back("cmd"); - tester.Argv_.push_back("--port=1231"); - tester.Argv_.push_back("asas"); - - tester.Opts_.AddLongOption("port"); - tester.Opts_.AddLongOption("home").Required(); - - tester.AcceptOptionWithValue("port", "1231"); - tester.AcceptError(); - } -#endif - + TOptsParserTester tester; + + tester.Argv_.push_back("cmd"); + tester.Argv_.push_back("--port=1231"); + tester.Argv_.push_back("asas"); + + tester.Opts_.AddLongOption("port"); + tester.Opts_.AddLongOption("home").Required(); + + tester.AcceptOptionWithValue("port", "1231"); + tester.AcceptError(); + } +#endif + Y_UNIT_TEST(TestStoreResult) { - TOptsNoDefault opts; + TOptsNoDefault opts; TString data; - int number; + int number; TMaybe<TString> optionalString0, optionalString1; TMaybe<int> optionalNumber0, optionalNumber1; - opts.AddLongOption('d', "data").StoreResult(&data); - opts.AddLongOption('n', "number").StoreResult(&number); + opts.AddLongOption('d', "data").StoreResult(&data); + opts.AddLongOption('n', "number").StoreResult(&number); opts.AddLongOption("optional-string-0").StoreResult(&optionalString0); opts.AddLongOption("optional-number-0").StoreResult(&optionalNumber0); opts.AddLongOption("optional-string-1").StoreResult(&optionalString1); opts.AddLongOption("optional-number-1").StoreResult(&optionalNumber1); TOptsParseResultTestWrapper r(&opts, V({"cmd", "--data=jjhh", "-n", "11", "--optional-number-1=8", "--optional-string-1=os1"})); - UNIT_ASSERT_VALUES_EQUAL("jjhh", data); - UNIT_ASSERT_VALUES_EQUAL(11, number); + UNIT_ASSERT_VALUES_EQUAL("jjhh", data); + UNIT_ASSERT_VALUES_EQUAL(11, number); UNIT_ASSERT(!optionalString0.Defined()); UNIT_ASSERT(!optionalNumber0.Defined()); UNIT_ASSERT_VALUES_EQUAL(*optionalString1, "os1"); UNIT_ASSERT_VALUES_EQUAL(*optionalNumber1, 8); - } - + } + Y_UNIT_TEST(TestStoreValue) { int a = 0, b = 0; size_t c = 0; EHasArg e = NO_ARGUMENT; - TOptsNoDefault opts; + TOptsNoDefault opts; opts.AddLongOption('a', "alpha").NoArgument().StoreValue(&a, 42); opts.AddLongOption('b', "beta").NoArgument().StoreValue(&b, 24); opts.AddLongOption('e', "enum").NoArgument().StoreValue(&e, REQUIRED_ARGUMENT).StoreValue(&c, 12345); @@ -472,17 +472,17 @@ Y_UNIT_TEST_SUITE(TLastGetoptTests) { } Y_UNIT_TEST(TestDefaultValue) { - TOptsNoDefault opts; - opts.AddLongOption("path").DefaultValue("/etc"); + TOptsNoDefault opts; + opts.AddLongOption("path").DefaultValue("/etc"); int value = 42; opts.AddLongOption("value").StoreResult(&value).DefaultValue(32); TOptsParseResultTestWrapper r(&opts, V({"cmd", "dfdf"})); - UNIT_ASSERT_VALUES_EQUAL("/etc", r.Get("path")); + UNIT_ASSERT_VALUES_EQUAL("/etc", r.Get("path")); UNIT_ASSERT_VALUES_EQUAL(32, value); - } - + } + Y_UNIT_TEST(TestSplitValue) { - TOptsNoDefault opts; + TOptsNoDefault opts; TVector<TString> vals; opts.AddLongOption('s', "split").SplitHandler(&vals, ','); TOptsParseResultTestWrapper r(&opts, V({"prog", "--split=a,b,c"})); @@ -508,17 +508,17 @@ Y_UNIT_TEST_SUITE(TLastGetoptTests) { } Y_UNIT_TEST(TestParseArgs) { - TOptsNoDefault o("AbCx:y:z::"); - UNIT_ASSERT_EQUAL(o.GetCharOption('A').HasArg_, NO_ARGUMENT); - UNIT_ASSERT_EQUAL(o.GetCharOption('b').HasArg_, NO_ARGUMENT); - UNIT_ASSERT_EQUAL(o.GetCharOption('C').HasArg_, NO_ARGUMENT); - UNIT_ASSERT_EQUAL(o.GetCharOption('x').HasArg_, REQUIRED_ARGUMENT); - UNIT_ASSERT_EQUAL(o.GetCharOption('y').HasArg_, REQUIRED_ARGUMENT); - UNIT_ASSERT_EQUAL(o.GetCharOption('z').HasArg_, OPTIONAL_ARGUMENT); - } - + TOptsNoDefault o("AbCx:y:z::"); + UNIT_ASSERT_EQUAL(o.GetCharOption('A').HasArg_, NO_ARGUMENT); + UNIT_ASSERT_EQUAL(o.GetCharOption('b').HasArg_, NO_ARGUMENT); + UNIT_ASSERT_EQUAL(o.GetCharOption('C').HasArg_, NO_ARGUMENT); + UNIT_ASSERT_EQUAL(o.GetCharOption('x').HasArg_, REQUIRED_ARGUMENT); + UNIT_ASSERT_EQUAL(o.GetCharOption('y').HasArg_, REQUIRED_ARGUMENT); + UNIT_ASSERT_EQUAL(o.GetCharOption('z').HasArg_, OPTIONAL_ARGUMENT); + } + Y_UNIT_TEST(TestRequiredOpts) { - TOptsNoDefault opts; + TOptsNoDefault opts; TOpt& opt_d = opts.AddCharOption('d'); // test 'not required' @@ -549,14 +549,14 @@ Y_UNIT_TEST_SUITE(TLastGetoptTests) { }; Y_UNIT_TEST(TestHandlers) { { - TOptsNoDefault opts; + TOptsNoDefault opts; bool flag = false; opts.AddLongOption("flag").Handler0(HandlerStoreTrue(&flag)).NoArgument(); TOptsParseResultTestWrapper r(&opts, V({"cmd", "--flag"})); UNIT_ASSERT(flag); } { - TOptsNoDefault opts; + TOptsNoDefault opts; unsigned uval = 5; double fval = 0.0; opts.AddLongOption("flag1").RequiredArgument().StoreResult(&uval); @@ -702,17 +702,17 @@ Y_UNIT_TEST_SUITE(TLastGetoptTests) { Y_UNIT_TEST(TestAppendTo) { TVector<int> ints; - - TOptsNoDefault opts; - opts.AddLongOption("size").AppendTo(&ints); - + + TOptsNoDefault opts; + opts.AddLongOption("size").AppendTo(&ints); + TOptsParseResultTestWrapper r(&opts, V({"cmd", "--size=17", "--size=19"})); - - UNIT_ASSERT_VALUES_EQUAL(size_t(2), ints.size()); - UNIT_ASSERT_VALUES_EQUAL(17, ints.at(0)); - UNIT_ASSERT_VALUES_EQUAL(19, ints.at(1)); - } - + + UNIT_ASSERT_VALUES_EQUAL(size_t(2), ints.size()); + UNIT_ASSERT_VALUES_EQUAL(17, ints.at(0)); + UNIT_ASSERT_VALUES_EQUAL(19, ints.at(1)); + } + Y_UNIT_TEST(TestEmplaceTo) { TVector<std::tuple<TString>> richPaths; @@ -791,4 +791,4 @@ Y_UNIT_TEST_SUITE(TLastGetoptTests) { UNIT_ASSERT_VALUES_EQUAL(25, number); UNIT_ASSERT_VALUES_EQUAL(2, r.GetFreeArgCount()); } -} +} diff --git a/library/cpp/getopt/ut/opt2_ut.cpp b/library/cpp/getopt/ut/opt2_ut.cpp index 0e7464747c..facf0a6b0d 100644 --- a/library/cpp/getopt/ut/opt2_ut.cpp +++ b/library/cpp/getopt/ut/opt2_ut.cpp @@ -1,13 +1,13 @@ #include <library/cpp/getopt/opt2.h> #include <library/cpp/testing/unittest/registar.h> - + //using namespace NLastGetopt; - + Y_UNIT_TEST_SUITE(Opt2Test) { Y_UNIT_TEST(TestSimple) { int argc = 8; - char* argv[] = { + char* argv[] = { (char*)"cmd", (char*)"--aaaa=aaaa", (char*)"zz", @@ -16,10 +16,10 @@ Y_UNIT_TEST_SUITE(Opt2Test) { (char*)"-c", (char*)"-d8", (char*)"ww", - }; - + }; + Opt2 opt(argc, argv, "A:b:cd:e:x:", 2, "aaaa=A"); - + const char* edef = "edef"; const char* a = opt.Arg('A', "<var_name> - usage of -A"); int b = opt.Int('b', "<var_name> - usage of -b", 2); @@ -27,21 +27,21 @@ Y_UNIT_TEST_SUITE(Opt2Test) { int d = opt.Int('d', "<var_name> - usage of -d", 13); const char* e = opt.Arg('e', "<unused> - only default is really used", edef); const TVector<const char*>& x = opt.MArg('x', "<var_name> - usage of -x"); - - UNIT_ASSERT(!opt.AutoUsage("<L> <M>")); - UNIT_ASSERT_VALUES_EQUAL("aaaa", a); - UNIT_ASSERT_VALUES_EQUAL(2, b); - UNIT_ASSERT(c); - UNIT_ASSERT_VALUES_EQUAL(8, d); + + UNIT_ASSERT(!opt.AutoUsage("<L> <M>")); + UNIT_ASSERT_VALUES_EQUAL("aaaa", a); + UNIT_ASSERT_VALUES_EQUAL(2, b); + UNIT_ASSERT(c); + UNIT_ASSERT_VALUES_EQUAL(8, d); UNIT_ASSERT_VALUES_EQUAL((void*)edef, e); - + UNIT_ASSERT_VALUES_EQUAL(2u, opt.Pos.size()); UNIT_ASSERT_STRINGS_EQUAL("zz", opt.Pos.at(0)); UNIT_ASSERT_VALUES_EQUAL((void*)argv[2], opt.Pos.at(0)); UNIT_ASSERT_STRINGS_EQUAL("ww", opt.Pos.at(1)); UNIT_ASSERT_STRINGS_EQUAL("1", x.at(0)); UNIT_ASSERT_STRINGS_EQUAL("2", x.at(1)); - } + } Y_UNIT_TEST(TestErrors1) { int argc = 4; @@ -60,4 +60,4 @@ Y_UNIT_TEST_SUITE(Opt2Test) { UNIT_ASSERT(c); UNIT_ASSERT_VALUES_EQUAL((void*)edef, e); } -} +} diff --git a/library/cpp/getopt/ut/opt_ut.cpp b/library/cpp/getopt/ut/opt_ut.cpp index 441aa493a0..66122f6ae3 100644 --- a/library/cpp/getopt/ut/opt_ut.cpp +++ b/library/cpp/getopt/ut/opt_ut.cpp @@ -2,19 +2,19 @@ #include <library/cpp/testing/unittest/registar.h> #include <util/string/vector.h> - + Y_UNIT_TEST_SUITE(OptTest) { Y_UNIT_TEST(TestSimple) { - int argc = 3; - char* argv[] = { + int argc = 3; + char* argv[] = { (char*)"cmd", (char*)"-x"}; - Opt opt(argc, argv, ""); - opt.Err = false; // be quiet - UNIT_ASSERT_VALUES_EQUAL('?', opt.Get()); - UNIT_ASSERT_VALUES_EQUAL(EOF, opt.Get()); - UNIT_ASSERT_VALUES_EQUAL(EOF, opt.Get()); - UNIT_ASSERT_VALUES_EQUAL(EOF, opt.Get()); - } + Opt opt(argc, argv, ""); + opt.Err = false; // be quiet + UNIT_ASSERT_VALUES_EQUAL('?', opt.Get()); + UNIT_ASSERT_VALUES_EQUAL(EOF, opt.Get()); + UNIT_ASSERT_VALUES_EQUAL(EOF, opt.Get()); + UNIT_ASSERT_VALUES_EQUAL(EOF, opt.Get()); + } Y_UNIT_TEST(TestFreeArguments) { Opt::Ion options[] = { @@ -49,4 +49,4 @@ Y_UNIT_TEST_SUITE(OptTest) { UNIT_ASSERT_VALUES_EQUAL(optionValue, "ARG2"); } } -} +} diff --git a/library/cpp/getopt/ut/posix_getopt_ut.cpp b/library/cpp/getopt/ut/posix_getopt_ut.cpp index b6d374bf28..9235e7340d 100644 --- a/library/cpp/getopt/ut/posix_getopt_ut.cpp +++ b/library/cpp/getopt/ut/posix_getopt_ut.cpp @@ -1,119 +1,119 @@ #include <library/cpp/getopt/posix_getopt.h> #include <library/cpp/testing/unittest/registar.h> - -using namespace NLastGetopt; - + +using namespace NLastGetopt; + Y_UNIT_TEST_SUITE(TPosixGetoptTest) { Y_UNIT_TEST(TestSimple) { - int argc = 6; + int argc = 6; const char* argv0[] = {"program", "-b", "-f1", "-f", "2", "zzzz"}; char** const argv = (char**)argv0; - - NLastGetopt::optreset = 1; - UNIT_ASSERT_VALUES_EQUAL('b', NLastGetopt::getopt(argc, argv, "bf:")); - UNIT_ASSERT_VALUES_EQUAL('f', NLastGetopt::getopt(argc, argv, "bf:")); + + NLastGetopt::optreset = 1; + UNIT_ASSERT_VALUES_EQUAL('b', NLastGetopt::getopt(argc, argv, "bf:")); + UNIT_ASSERT_VALUES_EQUAL('f', NLastGetopt::getopt(argc, argv, "bf:")); UNIT_ASSERT_VALUES_EQUAL(NLastGetopt::optarg, TString("1")); - UNIT_ASSERT_VALUES_EQUAL('f', NLastGetopt::getopt(argc, argv, "bf:")); + UNIT_ASSERT_VALUES_EQUAL('f', NLastGetopt::getopt(argc, argv, "bf:")); UNIT_ASSERT_VALUES_EQUAL(NLastGetopt::optarg, TString("2")); - UNIT_ASSERT_VALUES_EQUAL(-1, NLastGetopt::getopt(argc, argv, "bf:")); - - UNIT_ASSERT_VALUES_EQUAL(5, NLastGetopt::optind); - } - + UNIT_ASSERT_VALUES_EQUAL(-1, NLastGetopt::getopt(argc, argv, "bf:")); + + UNIT_ASSERT_VALUES_EQUAL(5, NLastGetopt::optind); + } + Y_UNIT_TEST(TestLong) { - int daggerset = 0; - /* options descriptor */ - const NLastGetopt::option longopts[] = { + int daggerset = 0; + /* options descriptor */ + const NLastGetopt::option longopts[] = { {"buffy", no_argument, nullptr, 'b'}, {"fluoride", required_argument, nullptr, 'f'}, {"daggerset", no_argument, &daggerset, 1}, {nullptr, 0, nullptr, 0}}; - - int argc = 7; + + int argc = 7; const char* argv0[] = {"program", "-b", "--buffy", "-f1", "--fluoride=2", "--daggerset", "zzzz"}; char** const argv = (char**)argv0; - - int longIndex; - - NLastGetopt::optreset = 1; - UNIT_ASSERT_VALUES_EQUAL('b', NLastGetopt::getopt_long(argc, argv, "bf:", longopts, &longIndex)); - UNIT_ASSERT_VALUES_EQUAL(0, longIndex); + + int longIndex; + + NLastGetopt::optreset = 1; + UNIT_ASSERT_VALUES_EQUAL('b', NLastGetopt::getopt_long(argc, argv, "bf:", longopts, &longIndex)); + UNIT_ASSERT_VALUES_EQUAL(0, longIndex); UNIT_ASSERT_VALUES_EQUAL('b', NLastGetopt::getopt_long(argc, argv, "bf:", longopts, nullptr)); - UNIT_ASSERT_VALUES_EQUAL('f', NLastGetopt::getopt_long(argc, argv, "bf:", longopts, &longIndex)); - UNIT_ASSERT_VALUES_EQUAL(1, longIndex); + UNIT_ASSERT_VALUES_EQUAL('f', NLastGetopt::getopt_long(argc, argv, "bf:", longopts, &longIndex)); + UNIT_ASSERT_VALUES_EQUAL(1, longIndex); UNIT_ASSERT_VALUES_EQUAL('f', NLastGetopt::getopt_long(argc, argv, "bf:", longopts, nullptr)); UNIT_ASSERT_VALUES_EQUAL(0, NLastGetopt::getopt_long(argc, argv, "bf:", longopts, nullptr)); UNIT_ASSERT_VALUES_EQUAL(-1, NLastGetopt::getopt_long(argc, argv, "bf:", longopts, nullptr)); - - UNIT_ASSERT_VALUES_EQUAL(6, NLastGetopt::optind); - } - + + UNIT_ASSERT_VALUES_EQUAL(6, NLastGetopt::optind); + } + Y_UNIT_TEST(TestLongPermutation) { - int daggerset = 0; - /* options descriptor */ - const NLastGetopt::option longopts[] = { + int daggerset = 0; + /* options descriptor */ + const NLastGetopt::option longopts[] = { {"buffy", no_argument, nullptr, 'b'}, {"fluoride", required_argument, nullptr, 'f'}, {"daggerset", no_argument, &daggerset, 1}, {nullptr, 0, nullptr, 0}}; - - int argc = 7; + + int argc = 7; const char* argv0[] = {"program", "aa", "-b", "bb", "cc", "--buffy", "dd"}; char** const argv = (char**)argv0; - - NLastGetopt::optreset = 1; + + NLastGetopt::optreset = 1; UNIT_ASSERT_VALUES_EQUAL('b', NLastGetopt::getopt_long(argc, argv, "bf:", longopts, nullptr)); UNIT_ASSERT_VALUES_EQUAL('b', NLastGetopt::getopt_long(argc, argv, "bf:", longopts, nullptr)); UNIT_ASSERT_VALUES_EQUAL(-1, NLastGetopt::getopt_long(argc, argv, "bf:", longopts, nullptr)); - - UNIT_ASSERT_VALUES_EQUAL(3, NLastGetopt::optind); - } - + + UNIT_ASSERT_VALUES_EQUAL(3, NLastGetopt::optind); + } + Y_UNIT_TEST(TestNoOptionsOptionsWithDoubleDash) { - const NLastGetopt::option longopts[] = { + const NLastGetopt::option longopts[] = { {"buffy", no_argument, nullptr, 'b'}, {"fluoride", no_argument, nullptr, 'f'}, {nullptr, 0, nullptr, 0}}; - - int argc = 2; + + int argc = 2; const char* argv0[] = {"program", "--bf"}; char** const argv = (char**)argv0; - - NLastGetopt::optreset = 1; + + NLastGetopt::optreset = 1; UNIT_ASSERT_VALUES_EQUAL('?', NLastGetopt::getopt_long(argc, argv, "bf", longopts, nullptr)); - } - + } + Y_UNIT_TEST(TestLongOnly) { - const NLastGetopt::option longopts[] = { + const NLastGetopt::option longopts[] = { {"foo", no_argument, nullptr, 'F'}, {"fluoride", no_argument, nullptr, 'f'}, {"ogogo", no_argument, nullptr, 'o'}, {nullptr, 0, nullptr, 0}}; - - int argc = 4; + + int argc = 4; const char* argv0[] = {"program", "--foo", "-foo", "-fo"}; char** const argv = (char**)argv0; - - NLastGetopt::optreset = 1; + + NLastGetopt::optreset = 1; UNIT_ASSERT_VALUES_EQUAL('F', NLastGetopt::getopt_long_only(argc, argv, "fo", longopts, nullptr)); UNIT_ASSERT_VALUES_EQUAL('F', NLastGetopt::getopt_long_only(argc, argv, "fo", longopts, nullptr)); UNIT_ASSERT_VALUES_EQUAL('f', NLastGetopt::getopt_long_only(argc, argv, "fo", longopts, nullptr)); UNIT_ASSERT_VALUES_EQUAL('o', NLastGetopt::getopt_long_only(argc, argv, "fo", longopts, nullptr)); UNIT_ASSERT_VALUES_EQUAL(-1, NLastGetopt::getopt_long_only(argc, argv, "fo", longopts, nullptr)); - } - + } + Y_UNIT_TEST(TestLongWithoutOnlySingleDashNowAllowed) { - const NLastGetopt::option longopts[] = { + const NLastGetopt::option longopts[] = { {"foo", no_argument, nullptr, 'F'}, {"zoo", no_argument, nullptr, 'z'}, {nullptr, 0, nullptr, 0}}; - - int argc = 2; + + int argc = 2; const char* argv0[] = {"program", "-foo"}; char** const argv = (char**)argv0; - - NLastGetopt::optreset = 1; + + NLastGetopt::optreset = 1; UNIT_ASSERT_VALUES_EQUAL('?', NLastGetopt::getopt_long(argc, argv, "z", longopts, nullptr)); - } -} + } +} |