Skip to content

Commit 821a4f7

Browse files
authored
Merge pull request #3878 from hannes-steffenhagen-diffblue/feature-command_line_iterator
Add cmdlinet::option_names
2 parents 8daa27e + 3e0e19b commit 821a4f7

File tree

3 files changed

+147
-1
lines changed

3 files changed

+147
-1
lines changed

src/util/cmdline.cpp

+79
Original file line numberDiff line numberDiff line change
@@ -247,3 +247,82 @@ bool cmdlinet::parse(int argc, const char **argv, const char *optstring)
247247

248248
return false;
249249
}
250+
251+
cmdlinet::option_namest cmdlinet::option_names() const
252+
{
253+
return option_namest{*this};
254+
}
255+
256+
cmdlinet::option_namest::option_names_iteratort::option_names_iteratort(
257+
const cmdlinet *command_line,
258+
std::size_t index)
259+
: command_line(command_line), index(index)
260+
{
261+
goto_next_valid_index();
262+
}
263+
264+
cmdlinet::option_namest::option_names_iteratort &
265+
cmdlinet::option_namest::option_names_iteratort::operator++()
266+
{
267+
PRECONDITION(command_line != nullptr);
268+
++index;
269+
goto_next_valid_index();
270+
return *this;
271+
}
272+
bool cmdlinet::option_namest::option_names_iteratort::is_valid_index() const
273+
{
274+
PRECONDITION(command_line != nullptr);
275+
auto const &options = command_line->options;
276+
return index < options.size() && options[index].isset &&
277+
options[index].islong;
278+
}
279+
280+
void cmdlinet::option_namest::option_names_iteratort::goto_next_valid_index()
281+
{
282+
PRECONDITION(command_line != nullptr);
283+
while(index < command_line->options.size() && !is_valid_index())
284+
{
285+
++index;
286+
}
287+
}
288+
289+
const cmdlinet::option_namest::option_names_iteratort
290+
cmdlinet::option_namest::option_names_iteratort::operator++(int dummy)
291+
{
292+
return ++option_names_iteratort(*this);
293+
}
294+
295+
const std::string &cmdlinet::option_namest::option_names_iteratort::operator*()
296+
{
297+
PRECONDITION(command_line != nullptr);
298+
return command_line->options.at(index).optstring;
299+
}
300+
301+
bool cmdlinet::option_namest::option_names_iteratort::
302+
operator==(const cmdlinet::option_namest::option_names_iteratort &other)
303+
{
304+
PRECONDITION(command_line != nullptr && command_line == other.command_line);
305+
return index == other.index;
306+
}
307+
308+
bool cmdlinet::option_namest::option_names_iteratort::
309+
operator!=(const cmdlinet::option_namest::option_names_iteratort &other)
310+
{
311+
PRECONDITION(command_line != nullptr && command_line == other.command_line);
312+
return index != other.index;
313+
}
314+
315+
cmdlinet::option_namest::option_namest(const cmdlinet &command_line)
316+
: command_line(command_line)
317+
{
318+
}
319+
320+
cmdlinet::option_namest::option_names_iteratort cmdlinet::option_namest::begin()
321+
{
322+
return option_names_iteratort(&command_line, 0);
323+
}
324+
325+
cmdlinet::option_namest::option_names_iteratort cmdlinet::option_namest::end()
326+
{
327+
return option_names_iteratort(&command_line, command_line.options.size());
328+
}

src/util/cmdline.h

+42-1
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@ Author: Daniel Kroening, [email protected]
1010
#ifndef CPROVER_UTIL_CMDLINE_H
1111
#define CPROVER_UTIL_CMDLINE_H
1212

13-
#include <vector>
13+
#include <limits>
1414
#include <list>
1515
#include <string>
16+
#include <vector>
1617

1718
#include "optional.h"
1819

@@ -40,6 +41,46 @@ class cmdlinet
4041
return getoptnr(option).has_value();
4142
}
4243

44+
struct option_namest
45+
{
46+
explicit option_namest(const cmdlinet &command_line);
47+
struct option_names_iteratort
48+
: public std::iterator<std::forward_iterator_tag, std::string>
49+
{
50+
option_names_iteratort() = default;
51+
explicit option_names_iteratort(
52+
const cmdlinet *command_line,
53+
std::size_t index);
54+
option_names_iteratort(const option_names_iteratort &other) = default;
55+
option_names_iteratort(option_names_iteratort &&other) = default;
56+
option_names_iteratort &
57+
operator=(const option_names_iteratort &) = default;
58+
option_names_iteratort &operator=(option_names_iteratort &&) = default;
59+
60+
option_names_iteratort &operator++();
61+
const option_names_iteratort operator++(int);
62+
const std::string &operator*();
63+
64+
bool operator==(const option_names_iteratort &other);
65+
bool operator!=(const option_names_iteratort &other);
66+
67+
private:
68+
const cmdlinet *command_line = nullptr;
69+
std::size_t index = std::numeric_limits<std::size_t>::max();
70+
bool is_valid_index() const;
71+
void goto_next_valid_index();
72+
};
73+
option_names_iteratort begin();
74+
option_names_iteratort end();
75+
76+
private:
77+
const cmdlinet &command_line;
78+
};
79+
80+
/// Pseudo-object that can be used to iterate over
81+
/// options in this cmdlinet (should not outlive this)
82+
option_namest option_names() const;
83+
4384
typedef std::vector<std::string> argst;
4485
argst args;
4586
std::string unknown_arg;

unit/util/cmdline.cpp

+26
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ Author: Diffblue Ltd.
66
77
\*******************************************************************/
88

9+
#include <array>
910
#include <testing-utils/use_catch.h>
1011
#include <util/cmdline.h>
1112

@@ -17,3 +18,28 @@ TEST_CASE("cmdlinet::has_option", "[core][util][cmdline]")
1718
REQUIRE(cmdline.has_option("b"));
1819
REQUIRE(!cmdline.has_option("c"));
1920
}
21+
22+
TEST_CASE("cmdline::option_names", "[core][util][cmdline]")
23+
{
24+
cmdlinet cmdline;
25+
std::array<const char *, 5> args = {
26+
{"-f", "--a", "--b", "--c-with-arg", "c-arg"}};
27+
REQUIRE(!cmdline.parse(
28+
args.size(),
29+
args.data(),
30+
"?f"
31+
"(a)"
32+
"(b)"
33+
"(c-with-arg):"
34+
"(notset)"));
35+
auto option_names = std::vector<std::string>{};
36+
for(auto const &option_name : cmdline.option_names())
37+
{
38+
option_names.push_back(option_name);
39+
}
40+
REQUIRE(option_names.size() == 3);
41+
REQUIRE(option_names[0] == "a");
42+
REQUIRE(option_names[1] == "b");
43+
REQUIRE(option_names[2] == "c-with-arg");
44+
REQUIRE(cmdline.get_value(option_names[2].c_str()) == "c-arg");
45+
}

0 commit comments

Comments
 (0)