#pragma once #include "last_getopt_opts.h" #include #include #include namespace NLastGetopt { /** * NLastGetopt::TOptsParser is an implementation of parsing * argv/argv into TOptsParseResult by rules of TOpts. * * The class allows to make complicated handlers. * Note, that if PERMUTE mode is on, then data, pointed by argv can be changed. */ class TOptsParser { enum EIsOpt { EIO_NONE, //is not an option name EIO_SDASH, //single-dashed ('-c') option name EIO_DDASH, //double-dashed ("--opt") option name EIO_PLUS, //plus prefix ("+opt") option name }; public: // TODO: make private const TOpts* Opts_; //rules of parsing // argc/argv pair size_t Argc_; const char** Argv_; private: //the storage of last unkown options. TODO: can be moved to local-method scope TCopyPtr TempCurrentOpt_; public: //storage of argv[0] TString ProgramName_; //state of parsing: size_t Pos_; // current element withing argv size_t Sop_; // current char within arg bool Stopped_; bool GotMinusMinus_; //true if "--" have been seen in argv protected: const TOpt* CurrentOpt_; // ptr on the last meeted option TStringBuf CurrentValue_; // the value of the last met argument (corresponding to CurrentOpt_) private: typedef THashSet TdOptSet; TdOptSet OptsSeen_; //the set of options that have been met during parsing TList OptsDefault_; private: void Init(const TOpts* options, int argc, const char* argv[]); void Init(const TOpts* options, int argc, char* argv[]); bool CommitEndOfOptions(size_t pos); bool Commit(const TOpt* currentOption, const TStringBuf& currentValue, size_t pos, size_t sop); bool ParseShortOptArg(size_t pos); bool ParseOptArg(size_t pos); bool ParseOptParam(const TOpt* opt, size_t pos); bool ParseUnknownShortOptWithinArg(size_t pos, size_t sop); bool ParseShortOptWithinArg(size_t pos, size_t sop); bool ParseWithPermutation(); bool DoNext(); void Finish(); EIsOpt IsOpt(const TStringBuf& arg) const; void Swap(TOptsParser& that); public: TOptsParser(const TOpts* options, int argc, const char* argv[]) { Init(options, argc, argv); } TOptsParser(const TOpts* options, int argc, char* argv[]) { Init(options, argc, argv); } /// fetch next argument, false if no more arguments left bool Next(); bool Seen(const TOpt* opt) const { return OptsSeen_.contains(opt); } bool Seen(TStringBuf name) const { if (auto opt = Opts_->FindLongOption(name)) { return Seen(opt); } else { return false; } } bool Seen(char name) const { if (auto opt = Opts_->FindCharOption(name)) { return Seen(opt); } else { return false; } } const TOpt* CurOpt() const { return CurrentOpt_; } const char* CurVal() const { return CurrentValue_.data(); } const TStringBuf& CurValStr() const { return CurrentValue_; } TStringBuf CurValOrOpt() const { TStringBuf val(CurValStr()); if (!val.IsInited() && CurOpt()->HasOptionalValue()) val = CurOpt()->GetOptionalValue(); return val; } TStringBuf CurValOrDef(bool useDef = true) const { TStringBuf val(CurValOrOpt()); if (!val.IsInited() && useDef && CurOpt()->HasDefaultValue()) val = CurOpt()->GetDefaultValue(); return val; } // true if this option was actually specified by the user bool IsExplicit() const { return nullptr == CurrentOpt_ || !OptsSeen_.empty(); } bool CurrentIs(const TString& name) const { return CurOpt()->NameIs(name); } const TString& ProgramName() const { return ProgramName_; } void PrintUsage(IOutputStream& os = Cout) const; void PrintUsage(IOutputStream& os, const NColorizer::TColors& colors) const; }; } //namespace NLastGetopt