From 969c18af00d98a6bd96fe042fd870896edf9873f Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 5 Aug 2021 12:29:17 +0200 Subject: Regenerate options parsing code --- odb/options.cxx | 37 +++++++++++++++++++++++++++++++++++-- odb/options.hxx | 50 +++++++++++++++++++++++++++++++++++++++++--------- odb/options.ixx | 53 +++++++++++++++++++++++++++++++++++++---------------- 3 files changed, 113 insertions(+), 27 deletions(-) diff --git a/odb/options.cxx b/odb/options.cxx index 9065abc..d5af128 100644 --- a/odb/options.cxx +++ b/odb/options.cxx @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -197,6 +198,7 @@ namespace cli else ++i_; + ++start_position_; return r; } else @@ -207,11 +209,20 @@ namespace cli skip () { if (i_ < argc_) + { ++i_; + ++start_position_; + } else throw eos_reached (); } + std::size_t argv_scanner:: + position () + { + return start_position_; + } + // argv_file_scanner // int argv_file_scanner::zero_argc_ = 0; @@ -322,6 +333,7 @@ namespace cli { hold_[i_ == 0 ? ++i_ : --i_].swap (args_.front ().value); args_.pop_front (); + ++start_position_; return hold_[i_].c_str (); } } @@ -335,7 +347,10 @@ namespace cli if (args_.empty ()) return base::skip (); else + { args_.pop_front (); + ++start_position_; + } } const argv_file_scanner::option_info* argv_file_scanner:: @@ -348,6 +363,12 @@ namespace cli return 0; } + std::size_t argv_file_scanner:: + position () + { + return start_position_; + } + void argv_file_scanner:: load (const std::string& file) { @@ -559,6 +580,17 @@ namespace cli }; template + struct parser > + { + static void + parse (std::pair& x, bool& xs, scanner& s) + { + x.second = s.position (); + parser::parse (x.first, xs, s); + } + }; + + template struct parser > { static void @@ -596,6 +628,7 @@ namespace cli if (s.more ()) { + std::size_t pos (s.position ()); std::string ov (s.next ()); std::string::size_type p = ov.find ('='); @@ -615,14 +648,14 @@ namespace cli if (!kstr.empty ()) { av[1] = const_cast (kstr.c_str ()); - argv_scanner s (0, ac, av); + argv_scanner s (0, ac, av, false, pos); parser::parse (k, dummy, s); } if (!vstr.empty ()) { av[1] = const_cast (vstr.c_str ()); - argv_scanner s (0, ac, av); + argv_scanner s (0, ac, av, false, pos); parser::parse (v, dummy, s); } diff --git a/odb/options.hxx b/odb/options.hxx index dce0fe0..74406a0 100644 --- a/odb/options.hxx +++ b/odb/options.hxx @@ -238,6 +238,14 @@ namespace cli // for the two previous arguments up until a call to a third // peek() or next(). // + // The position() function returns a monotonically-increasing + // number which, if stored, can later be used to determine the + // relative position of the argument returned by the following + // call to next(). Note that if multiple scanners are used to + // extract arguments from multiple sources, then the end + // position of the previous scanner should be used as the + // start position of the next. + // class scanner { public: @@ -255,13 +263,24 @@ namespace cli virtual void skip () = 0; + + virtual std::size_t + position () = 0; }; class argv_scanner: public scanner { public: - argv_scanner (int& argc, char** argv, bool erase = false); - argv_scanner (int start, int& argc, char** argv, bool erase = false); + argv_scanner (int& argc, + char** argv, + bool erase = false, + std::size_t start_position = 0); + + argv_scanner (int start, + int& argc, + char** argv, + bool erase = false, + std::size_t start_position = 0); int end () const; @@ -278,7 +297,11 @@ namespace cli virtual void skip (); - private: + virtual std::size_t + position (); + + protected: + std::size_t start_position_; int i_; int& argc_; char** argv_; @@ -291,16 +314,19 @@ namespace cli argv_file_scanner (int& argc, char** argv, const std::string& option, - bool erase = false); + bool erase = false, + std::size_t start_position = 0); argv_file_scanner (int start, int& argc, char** argv, const std::string& option, - bool erase = false); + bool erase = false, + std::size_t start_position = 0); argv_file_scanner (const std::string& file, - const std::string& option); + const std::string& option, + std::size_t start_position = 0); struct option_info { @@ -317,18 +343,21 @@ namespace cli char** argv, const option_info* options, std::size_t options_count, - bool erase = false); + bool erase = false, + std::size_t start_position = 0); argv_file_scanner (int start, int& argc, char** argv, const option_info* options, std::size_t options_count, - bool erase = false); + bool erase = false, + std::size_t start_position = 0); argv_file_scanner (const std::string& file, const option_info* options = 0, - std::size_t options_count = 0); + std::size_t options_count = 0, + std::size_t start_position = 0); virtual bool more (); @@ -342,6 +371,9 @@ namespace cli virtual void skip (); + virtual std::size_t + position (); + // Return the file path if the peeked at argument came from a file and // the empty string otherwise. The reference is guaranteed to be valid // till the end of the scanner lifetime. diff --git a/odb/options.ixx b/odb/options.ixx index f52fbb4..9a78a2e 100644 --- a/odb/options.ixx +++ b/odb/options.ixx @@ -141,14 +141,29 @@ namespace cli // argv_scanner // inline argv_scanner:: - argv_scanner (int& argc, char** argv, bool erase) - : i_ (1), argc_ (argc), argv_ (argv), erase_ (erase) + argv_scanner (int& argc, + char** argv, + bool erase, + std::size_t sp) + : start_position_ (sp + 1), + i_ (1), + argc_ (argc), + argv_ (argv), + erase_ (erase) { } inline argv_scanner:: - argv_scanner (int start, int& argc, char** argv, bool erase) - : i_ (start), argc_ (argc), argv_ (argv), erase_ (erase) + argv_scanner (int start, + int& argc, + char** argv, + bool erase, + std::size_t sp) + : start_position_ (sp + static_cast (start)), + i_ (start), + argc_ (argc), + argv_ (argv), + erase_ (erase) { } @@ -164,8 +179,9 @@ namespace cli argv_file_scanner (int& argc, char** argv, const std::string& option, - bool erase) - : argv_scanner (argc, argv, erase), + bool erase, + std::size_t sp) + : argv_scanner (argc, argv, erase, sp), option_ (option), options_ (&option_info_), options_count_ (1), @@ -181,8 +197,9 @@ namespace cli int& argc, char** argv, const std::string& option, - bool erase) - : argv_scanner (start, argc, argv, erase), + bool erase, + std::size_t sp) + : argv_scanner (start, argc, argv, erase, sp), option_ (option), options_ (&option_info_), options_count_ (1), @@ -195,8 +212,9 @@ namespace cli inline argv_file_scanner:: argv_file_scanner (const std::string& file, - const std::string& option) - : argv_scanner (0, zero_argc_, 0), + const std::string& option, + std::size_t sp) + : argv_scanner (0, zero_argc_, 0, sp), option_ (option), options_ (&option_info_), options_count_ (1), @@ -214,8 +232,9 @@ namespace cli char** argv, const option_info* options, std::size_t options_count, - bool erase) - : argv_scanner (argc, argv, erase), + bool erase, + std::size_t sp) + : argv_scanner (argc, argv, erase, sp), options_ (options), options_count_ (options_count), i_ (1), @@ -229,8 +248,9 @@ namespace cli char** argv, const option_info* options, std::size_t options_count, - bool erase) - : argv_scanner (start, argc, argv, erase), + bool erase, + std::size_t sp) + : argv_scanner (start, argc, argv, erase, sp), options_ (options), options_count_ (options_count), i_ (1), @@ -241,8 +261,9 @@ namespace cli inline argv_file_scanner:: argv_file_scanner (const std::string& file, const option_info* options, - std::size_t options_count) - : argv_scanner (0, zero_argc_, 0), + std::size_t options_count, + std::size_t sp) + : argv_scanner (0, zero_argc_, 0, sp), options_ (options), options_count_ (options_count), i_ (1), -- cgit v1.1