From 68f660dbcce025b2e95e46d193ca69269c56ee69 Mon Sep 17 00:00:00 2001
From: Max Kellermann <max@musicpd.org>
Date: Tue, 16 Jan 2018 11:03:04 +0100
Subject: [PATCH] util/OptionParser: collect remaining arguments

Allow the caller to use a simple "for" loop without checking
arguments.
---
 src/CommandLine.cxx       |  6 ++----
 src/util/OptionParser.cxx |  2 ++
 src/util/OptionParser.hxx | 15 +++++++++------
 3 files changed, 13 insertions(+), 10 deletions(-)

diff --git a/src/CommandLine.cxx b/src/CommandLine.cxx
index 0d0484686..238ec7a34 100644
--- a/src/CommandLine.cxx
+++ b/src/CommandLine.cxx
@@ -357,11 +357,9 @@ ParseCommandLine(int argc, char **argv, struct options *options)
 
 	// Second pass: find non-option parameters (i.e. config file)
 	const char *config_file = nullptr;
-	for (int i = 1; i < argc; ++i) {
-		if (OptionParser::IsOption(argv[i]))
-			continue;
+	for (const char *i : parser.GetRemaining()) {
 		if (config_file == nullptr) {
-			config_file = argv[i];
+			config_file = i;
 			continue;
 		}
 
diff --git a/src/util/OptionParser.cxx b/src/util/OptionParser.cxx
index e51b215f4..5b7d7fc85 100644
--- a/src/util/OptionParser.cxx
+++ b/src/util/OptionParser.cxx
@@ -53,7 +53,9 @@ OptionParser::ParseNext() noexcept
 		option_raw = arg;
 		return true;
 	}
+
 	option = nullptr;
 	option_raw = nullptr;
+	*remaining_tail++ = arg;
 	return false;
 }
diff --git a/src/util/OptionParser.hxx b/src/util/OptionParser.hxx
index a6169eeeb..84a4f0e4f 100644
--- a/src/util/OptionParser.hxx
+++ b/src/util/OptionParser.hxx
@@ -36,12 +36,16 @@ class OptionParser
 	const char *option_raw = nullptr;
 	bool is_long = false;
 
+	const char **const remaining_head, **remaining_tail;
+
 public:
 	/**
 	 * Constructs #OptionParser.
 	 */
-	constexpr OptionParser(int _argc, char *const*_argv) noexcept
-		:args(_argv + 1, _argc - 1) {}
+	constexpr OptionParser(int _argc, char **_argv) noexcept
+		:args(_argv + 1, _argc - 1),
+		 remaining_head(const_cast<const char **>(_argv + 1)),
+		 remaining_tail(remaining_head) {}
 
 	/**
 	 * Checks if there are command line entries to process.
@@ -81,11 +85,10 @@ public:
 	bool ParseNext() noexcept;
 
 	/**
-	 * Checks if specified string is a command line option.
+	 * Returns the remaining non-option arguments.
 	 */
-	static bool IsOption(const char *s) noexcept {
-		assert(s != nullptr);
-		return s[0] == '-';
+	ConstBuffer<const char *> GetRemaining() const noexcept {
+		return {remaining_head, remaining_tail};
 	}
 };