aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/getopt/small/last_getopt.h
diff options
context:
space:
mode:
authorDevtools Arcadia <arcadia-devtools@yandex-team.ru>2022-02-07 18:08:42 +0300
committerDevtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net>2022-02-07 18:08:42 +0300
commit1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch)
treee26c9fed0de5d9873cce7e00bc214573dc2195b7 /library/cpp/getopt/small/last_getopt.h
downloadydb-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.h132
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();
+ }
+ }
+
+ }
+
+}