123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132 |
- #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();
- }
- }
- }
- }
|