diff options
-rw-r--r-- | libbutl/builtin-options.cxx | 33 | ||||
-rw-r--r-- | libbutl/builtin-options.hxx | 39 | ||||
-rw-r--r-- | libbutl/builtin-options.ixx | 32 |
3 files changed, 90 insertions, 14 deletions
diff --git a/libbutl/builtin-options.cxx b/libbutl/builtin-options.cxx index 536f97d..5a243e5 100644 --- a/libbutl/builtin-options.cxx +++ b/libbutl/builtin-options.cxx @@ -15,6 +15,7 @@ #include <set> #include <string> #include <vector> +#include <utility> #include <ostream> #include <sstream> @@ -158,6 +159,7 @@ namespace butl else ++i_; + ++start_position_; return r; } else @@ -168,11 +170,20 @@ namespace butl skip () { if (i_ < argc_) + { ++i_; + ++start_position_; + } else throw eos_reached (); } + std::size_t argv_scanner:: + position () + { + return start_position_; + } + // vector_scanner // bool vector_scanner:: @@ -208,6 +219,12 @@ namespace butl throw eos_reached (); } + std::size_t vector_scanner:: + position () + { + return start_position_ + i_; + } + template <typename X> struct parser { @@ -260,6 +277,17 @@ namespace butl }; template <typename X> + struct parser<std::pair<X, std::size_t> > + { + static void + parse (std::pair<X, std::size_t>& x, bool& xs, scanner& s) + { + x.second = s.position (); + parser<X>::parse (x.first, xs, s); + } + }; + + template <typename X> struct parser<std::vector<X> > { static void @@ -297,6 +325,7 @@ namespace butl if (s.more ()) { + std::size_t pos (s.position ()); std::string ov (s.next ()); std::string::size_type p = ov.find ('='); @@ -316,14 +345,14 @@ namespace butl if (!kstr.empty ()) { av[1] = const_cast<char*> (kstr.c_str ()); - argv_scanner s (0, ac, av); + argv_scanner s (0, ac, av, false, pos); parser<K>::parse (k, dummy, s); } if (!vstr.empty ()) { av[1] = const_cast<char*> (vstr.c_str ()); - argv_scanner s (0, ac, av); + argv_scanner s (0, ac, av, false, pos); parser<V>::parse (v, dummy, s); } diff --git a/libbutl/builtin-options.hxx b/libbutl/builtin-options.hxx index b389298..6288e54 100644 --- a/libbutl/builtin-options.hxx +++ b/libbutl/builtin-options.hxx @@ -174,6 +174,14 @@ namespace butl // 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: @@ -191,13 +199,24 @@ namespace butl 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; @@ -214,7 +233,11 @@ namespace butl virtual void skip (); - private: + virtual std::size_t + position (); + + protected: + std::size_t start_position_; int i_; int& argc_; char** argv_; @@ -224,13 +247,15 @@ namespace butl class vector_scanner: public scanner { public: - vector_scanner (const std::vector<std::string>&, std::size_t start = 0); + vector_scanner (const std::vector<std::string>&, + std::size_t start = 0, + std::size_t start_position = 0); std::size_t end () const; void - reset (std::size_t start = 0); + reset (std::size_t start = 0, std::size_t start_position = 0); virtual bool more (); @@ -244,7 +269,11 @@ namespace butl virtual void skip (); + virtual std::size_t + position (); + private: + std::size_t start_position_; const std::vector<std::string>& v_; std::size_t i_; }; diff --git a/libbutl/builtin-options.ixx b/libbutl/builtin-options.ixx index f10f82d..b977f16 100644 --- a/libbutl/builtin-options.ixx +++ b/libbutl/builtin-options.ixx @@ -107,14 +107,29 @@ namespace butl // 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<std::size_t> (start)), + i_ (start), + argc_ (argc), + argv_ (argv), + erase_ (erase) { } @@ -127,8 +142,10 @@ namespace butl // vector_scanner // inline vector_scanner:: - vector_scanner (const std::vector<std::string>& v, std::size_t i) - : v_ (v), i_ (i) + vector_scanner (const std::vector<std::string>& v, + std::size_t i, + std::size_t sp) + : start_position_ (sp), v_ (v), i_ (i) { } @@ -139,9 +156,10 @@ namespace butl } inline void vector_scanner:: - reset (std::size_t i) + reset (std::size_t i, std::size_t sp) { i_ = i; + start_position_ = sp; } } } |