#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/yexception.h>
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
: public IOptHandler {
TpFunc Func_;
public:
THandlerFunctor0(TpFunc func)
: Func_(func)
{
}
void HandleOpt(const TOptsParser*) override {
Func_();
}
};
template <typename TpFunc, typename TpArg = const TOptsParser*>
class THandlerFunctor1
: public IOptHandler {
TpFunc Func_;
const TpArg Def_;
const bool HasDef_;
public:
THandlerFunctor1(TpFunc func)
: Func_(func)
, Def_()
, HasDef_(false)
{
}
template <typename T>
THandlerFunctor1(const TpFunc& func, const T& def)
: Func_(func)
, Def_(def)
, HasDef_(true)
{
}
void HandleOpt(const TOptsParser* parser) override;
};
template <typename TpFunc>
class THandlerFunctor1<TpFunc, const TOptsParser*>
: public IOptHandler {
TpFunc Func_;
public:
THandlerFunctor1(TpFunc func)
: Func_(func)
{
}
void HandleOpt(const TOptsParser* parser) override {
Func_(parser);
}
};
template <typename T, typename TpVal = T>
class TStoreResultFunctor {
private:
T* Target_;
public:
TStoreResultFunctor(T* target)
: Target_(target)
{
}
void operator()(const TpVal& val) {
*Target_ = val;
}
};
template <typename TpTarget, typename TpFunc, typename TpVal = TpTarget>
class TStoreMappedResultFunctor {
private:
TpTarget* Target_;
const TpFunc Func_;
public:
TStoreMappedResultFunctor(TpTarget* target, const TpFunc& func)
: Target_(target)
, Func_(func)
{
}
void operator()(const TpVal& val) {
*Target_ = Func_(val);
}
};
template <typename T, typename TpVal = T>
class TStoreValueFunctor {
T* Target;
const TpVal Value;
public:
template <typename TpArg>
TStoreValueFunctor(T* target, const TpArg& value)
: Target(target)
, Value(value)
{
}
void operator()(const TOptsParser*) {
*Target = Value;
}
};
TString OptToString(char c);
TString OptToString(const TString& longOption);
TString OptToString(const TOpt* opt);
template <typename T>
inline T OptFromStringImpl(const TStringBuf& value) {
return FromString<T>(value);
}
template <>
inline TStringBuf OptFromStringImpl<TStringBuf>(const TStringBuf& value) {
return value;
}
template <>
inline const char* OptFromStringImpl<const char*>(const TStringBuf& value) {
return value.data();
}
template <typename T, typename TSomeOpt>
T OptFromString(const TStringBuf& value, const TSomeOpt opt) {
try {
return OptFromStringImpl<T>(value);
} catch (...) {
throw TUsageException() << "failed to parse opt " << OptToString(opt) << " value " << TString(value).Quote() << ": " << CurrentExceptionMessage();
}
}
// wrapper of FromString<T> that prints nice message about option used
template <typename T, typename TSomeOpt>
T OptFromString(const TStringBuf& value, const TSomeOpt opt);
}
}