last_getopt_parser.h 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. #pragma once
  2. #include "last_getopt_opts.h"
  3. #include <library/cpp/colorizer/fwd.h>
  4. #include <util/generic/hash_set.h>
  5. #include <util/generic/list.h>
  6. namespace NLastGetopt {
  7. /**
  8. * NLastGetopt::TOptsParser is an implementation of parsing
  9. * argv/argv into TOptsParseResult by rules of TOpts.
  10. *
  11. * The class allows to make complicated handlers.
  12. * Note, that if PERMUTE mode is on, then data, pointed by argv can be changed.
  13. */
  14. class TOptsParser {
  15. enum EIsOpt {
  16. EIO_NONE, //is not an option name
  17. EIO_SDASH, //single-dashed ('-c') option name
  18. EIO_DDASH, //double-dashed ("--opt") option name
  19. EIO_PLUS, //plus prefix ("+opt") option name
  20. };
  21. public: // TODO: make private
  22. const TOpts* Opts_; //rules of parsing
  23. // argc/argv pair
  24. size_t Argc_;
  25. const char** Argv_;
  26. private:
  27. //the storage of last unkown options. TODO: can be moved to local-method scope
  28. TCopyPtr<TOpt> TempCurrentOpt_;
  29. public:
  30. //storage of argv[0]
  31. TString ProgramName_;
  32. //state of parsing:
  33. size_t Pos_; // current element withing argv
  34. size_t Sop_; // current char within arg
  35. bool Stopped_;
  36. bool GotMinusMinus_; //true if "--" have been seen in argv
  37. protected:
  38. const TOpt* CurrentOpt_; // ptr on the last meeted option
  39. TStringBuf CurrentValue_; // the value of the last met argument (corresponding to CurrentOpt_)
  40. private:
  41. typedef THashSet<const TOpt*> TdOptSet;
  42. TdOptSet OptsSeen_; //the set of options that have been met during parsing
  43. TList<const TOpt*> OptsDefault_;
  44. private:
  45. void Init(const TOpts* options, int argc, const char* argv[]);
  46. void Init(const TOpts* options, int argc, char* argv[]);
  47. bool CommitEndOfOptions(size_t pos);
  48. bool Commit(const TOpt* currentOption, const TStringBuf& currentValue, size_t pos, size_t sop);
  49. bool ParseShortOptArg(size_t pos);
  50. bool ParseOptArg(size_t pos);
  51. bool ParseOptParam(const TOpt* opt, size_t pos);
  52. bool ParseUnknownShortOptWithinArg(size_t pos, size_t sop);
  53. bool ParseShortOptWithinArg(size_t pos, size_t sop);
  54. bool ParseWithPermutation();
  55. bool DoNext();
  56. void Finish();
  57. EIsOpt IsOpt(const TStringBuf& arg) const;
  58. void Swap(TOptsParser& that);
  59. public:
  60. TOptsParser(const TOpts* options, int argc, const char* argv[]) {
  61. Init(options, argc, argv);
  62. }
  63. TOptsParser(const TOpts* options, int argc, char* argv[]) {
  64. Init(options, argc, argv);
  65. }
  66. /// fetch next argument, false if no more arguments left
  67. bool Next();
  68. bool Seen(const TOpt* opt) const {
  69. return OptsSeen_.contains(opt);
  70. }
  71. bool Seen(TStringBuf name) const {
  72. if (auto opt = Opts_->FindLongOption(name)) {
  73. return Seen(opt);
  74. } else {
  75. return false;
  76. }
  77. }
  78. bool Seen(char name) const {
  79. if (auto opt = Opts_->FindCharOption(name)) {
  80. return Seen(opt);
  81. } else {
  82. return false;
  83. }
  84. }
  85. const TOpt* CurOpt() const {
  86. return CurrentOpt_;
  87. }
  88. const char* CurVal() const {
  89. return CurrentValue_.data();
  90. }
  91. const TStringBuf& CurValStr() const {
  92. return CurrentValue_;
  93. }
  94. TStringBuf CurValOrOpt() const {
  95. TStringBuf val(CurValStr());
  96. if (!val.IsInited() && CurOpt()->HasOptionalValue())
  97. val = CurOpt()->GetOptionalValue();
  98. return val;
  99. }
  100. TStringBuf CurValOrDef(bool useDef = true) const {
  101. TStringBuf val(CurValOrOpt());
  102. if (!val.IsInited() && useDef && CurOpt()->HasDefaultValue())
  103. val = CurOpt()->GetDefaultValue();
  104. return val;
  105. }
  106. // true if this option was actually specified by the user
  107. bool IsExplicit() const {
  108. return nullptr == CurrentOpt_ || !OptsSeen_.empty();
  109. }
  110. bool CurrentIs(const TString& name) const {
  111. return CurOpt()->NameIs(name);
  112. }
  113. const TString& ProgramName() const {
  114. return ProgramName_;
  115. }
  116. void PrintUsage(IOutputStream& os = Cout) const;
  117. void PrintUsage(IOutputStream& os, const NColorizer::TColors& colors) const;
  118. };
  119. } //namespace NLastGetopt