diff options
author | Devtools Arcadia <arcadia-devtools@yandex-team.ru> | 2022-02-07 18:08:42 +0300 |
---|---|---|
committer | Devtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net> | 2022-02-07 18:08:42 +0300 |
commit | 1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch) | |
tree | e26c9fed0de5d9873cce7e00bc214573dc2195b7 /library/cpp/getopt/small/last_getopt.h | |
download | ydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz |
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'library/cpp/getopt/small/last_getopt.h')
-rw-r--r-- | library/cpp/getopt/small/last_getopt.h | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/library/cpp/getopt/small/last_getopt.h b/library/cpp/getopt/small/last_getopt.h new file mode 100644 index 0000000000..07687bc914 --- /dev/null +++ b/library/cpp/getopt/small/last_getopt.h @@ -0,0 +1,132 @@ +#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 { + /// Handler to split option value by delimiter into a target container and allow ranges. + template <class Container> + struct TOptRangeSplitHandler: public IOptHandler { + public: + using TContainer = Container; + using TValue = typename TContainer::value_type; + + explicit TOptRangeSplitHandler(TContainer* target, const char elementsDelim, const char rangesDelim) + : Target(target) + , ElementsDelim(elementsDelim) + , RangesDelim(rangesDelim) + { + } + + void HandleOpt(const TOptsParser* parser) override { + const TStringBuf curval(parser->CurValOrDef()); + 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; + char RangesDelim; + }; + + template <class Container> + struct TOptSplitHandler: public IOptHandler { + public: + using TContainer = Container; + using TValue = typename TContainer::value_type; + + explicit TOptSplitHandler(TContainer* target, const char delim) + : Target(target) + , Delim(delim) + { + } + + void HandleOpt(const TOptsParser* parser) override { + const TStringBuf curval(parser->CurValOrDef()); + if (curval.IsInited()) { + StringSplitter(curval).Split(Delim).Consume([&](const TStringBuf& val) { + Target->insert(Target->end(), NPrivate::OptFromString<TValue>(val, parser->CurOpt())); + }); + } + } + + private: + TContainer* Target; + char Delim; + }; + + template <class TpFunc> + struct TOptKVHandler: public IOptHandler { + public: + using TKey = typename TFunctionArgs<TpFunc>::template TGet<0>; + using TValue = typename TFunctionArgs<TpFunc>::template TGet<1>; + + explicit TOptKVHandler(TpFunc func, const char kvdelim = '=') + : Func(func) + , KVDelim(kvdelim) + { + } + + void HandleOpt(const TOptsParser* parser) override { + const TStringBuf curval(parser->CurValOrDef()); + const TOpt* curOpt(parser->CurOpt()); + if (curval.IsInited()) { + TStringBuf key, value; + if (!curval.TrySplit(KVDelim, key, value)) { + throw TUsageException() << "failed to parse opt " << NPrivate::OptToString(curOpt) + << " value " << TString(curval).Quote() << ": expected key" << KVDelim << "value format"; + } + Func(NPrivate::OptFromString<TKey>(key, curOpt), NPrivate::OptFromString<TValue>(value, curOpt)); + } + } + + private: + TpFunc Func; + char KVDelim; + }; + + namespace NPrivate { + template <typename TpFunc, typename TpArg> + void THandlerFunctor1<TpFunc, TpArg>::HandleOpt(const TOptsParser* parser) { + const TStringBuf curval = parser->CurValOrDef(!HasDef_); + const TpArg& arg = curval.IsInited() ? OptFromString<TpArg>(curval, parser->CurOpt()) : Def_; + try { + Func_(arg); + } catch (const TUsageException&) { + throw; + } catch (...) { + throw TUsageException() << "failed to handle opt " << OptToString(parser->CurOpt()) + << " value " << TString(curval).Quote() << ": " << CurrentExceptionMessage(); + } + } + + } + +} |