#pragma once #include "last_getopt_opts.h" #include "last_getopt_easy_setup.h" #include "last_getopt_parse_result.h" #include #include /// 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::HandleOpt #include "last_getopt_parser.h" namespace NLastGetopt { /// Handler to split option value by delimiter into a target container and allow ranges. template 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(mutableValue.NextTok(RangesDelim), parser->CurOpt()); TValue last = mutableValue ? NPrivate::OptFromString(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 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(val, parser->CurOpt())); }); } } private: TContainer* Target; char Delim; }; template struct TOptKVHandler: public IOptHandler { public: using TKey = typename TFunctionArgs::template TGet<0>; using TValue = typename TFunctionArgs::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(key, curOpt), NPrivate::OptFromString(value, curOpt)); } } private: TpFunc Func; char KVDelim; }; namespace NPrivate { template void THandlerFunctor1::HandleOpt(const TOptsParser* parser) { const TStringBuf curval = parser->CurValOrDef(!HasDef_); const TpArg& arg = curval.IsInited() ? OptFromString(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(); } } } }