This repository was archived by the owner on Feb 3, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathoptions.cpp
More file actions
135 lines (110 loc) · 3.73 KB
/
options.cpp
File metadata and controls
135 lines (110 loc) · 3.73 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/**
* Copyright (C) 2020 Tristan. All Rights Reserved.
* This file is licensed under the BSD 2-Clause license.
* See the COPYING file for licensing information.
*/
#include "options.hpp"
#include <algorithm>
#include <array>
#include <iostream>
#include <iterator>
#include <optional>
#include <string>
#include <string_view>
#include <utility>
#include <vector>
#include <strings.h>
namespace CommandLineParser {
struct Input {
std::string name;
bool optionHasValue;
};
struct Output {
std::string name;
std::optional<std::string> value;
inline Output(std::string name, std::optional<std::string> value)
: name(std::move(name)), value(std::move(value)) {
}
};
std::vector<Output> outputs;
std::vector<std::string> textOutput;
} // namespace CommandLineParser
Options::OptionLookupResult
Options::GetCommandLineParameter(const std::string &name) {
auto result = std::find_if(std::begin(CommandLineParser::outputs), std::end(CommandLineParser::outputs),
[name](const auto &entry) -> bool { return strcasecmp(name.c_str(), entry.name.c_str()) == 0; });
if (result != std::end(CommandLineParser::outputs)) {
return {true, result->value};
}
return {false, {}};
}
bool
ParseEqualsOption(const std::string_view &strview, std::optional<std::string_view> *prevName, bool isLastOption) {
static const std::array<CommandLineParser::Input, 4> inputs = {{
{"copyright", false},
{"credits", false},
{"test", true},
}};
std::string name(std::begin(strview) + 2);
const auto *result = std::find_if(std::begin(inputs), std::end(inputs),
[name](const auto &entry) -> bool { return strcasecmp(name.c_str(), entry.name.c_str()) == 0; });
if (result != std::end(inputs) && result->optionHasValue) {
if (isLastOption) {
std::cerr << "Invalid command line option: " << result->name << " (required option value)" << std::endl;
return false;
}
*prevName = strview;
} else {
CommandLineParser::outputs.emplace_back(std::string(std::begin(strview) + 2, std::end(strview)), std::string());
}
return true;
}
bool
Options::ParseCommandLine(int argc, const char **argv) {
if (argc == 0 || argc == 1) {
return true;
}
std::optional<std::string_view> prevName;
for (std::size_t i = 1; i < static_cast<std::size_t>(argc); i++) {
std::string_view strview(argv[i]);
if (argv[i][0] == '\0')
continue;
if (strview[0] == '-' && strview[1] == '-') {
if (prevName.has_value()) {
std::cerr << "Invalid command line option: " << prevName.value() << " (required option value)"
<< std::endl;
return false;
}
/* Option name is empty */
auto equals = strview.find('=');
if (strview.length() == 2 || equals == 2) {
std::cerr << "Invalid command line option: " << strview << " (option name is empty)" << std::endl;
return false;
}
if (equals == std::string::npos) {
if (!ParseEqualsOption(strview, &prevName, i == static_cast<std::size_t>(argc) - 1))
return false;
} else {
if (strview.size() > equals + 1) {
CommandLineParser::outputs.emplace_back(std::string(std::begin(strview) + 2, equals - 2),
std::string(std::begin(strview) + equals + 1));
} else {
CommandLineParser::outputs.emplace_back(
std::string(std::begin(strview) + 2, equals - 2), std::optional<std::string>());
}
}
} else if (prevName.has_value()) {
if (strview.empty())
CommandLineParser::outputs.emplace_back(
std::string(std::begin(prevName.value()) + 2, std::end(prevName.value())),
std::optional<std::string>());
else
CommandLineParser::outputs.emplace_back(
std::string(std::begin(prevName.value()) + 2, std::end(prevName.value())), std::string(strview));
prevName.reset();
} else {
CommandLineParser::textOutput.emplace_back(strview);
}
}
return true;
}