1 | // |
2 | // OptionProcessor.cpp |
3 | // |
4 | // Library: Util |
5 | // Package: Options |
6 | // Module: OptionProcessor |
7 | // |
8 | // Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. |
9 | // and Contributors. |
10 | // |
11 | // SPDX-License-Identifier: BSL-1.0 |
12 | // |
13 | |
14 | |
15 | #include "Poco/Util/OptionProcessor.h" |
16 | #include "Poco/Util/OptionSet.h" |
17 | #include "Poco/Util/Option.h" |
18 | #include "Poco/Util/OptionException.h" |
19 | |
20 | |
21 | namespace Poco { |
22 | namespace Util { |
23 | |
24 | |
25 | OptionProcessor::OptionProcessor(const OptionSet& options): |
26 | _options(options), |
27 | _unixStyle(true), |
28 | _ignore(false) |
29 | { |
30 | } |
31 | |
32 | |
33 | OptionProcessor::~OptionProcessor() |
34 | { |
35 | } |
36 | |
37 | |
38 | void OptionProcessor::setUnixStyle(bool flag) |
39 | { |
40 | _unixStyle = flag; |
41 | } |
42 | |
43 | |
44 | bool OptionProcessor::process(const std::string& argument, std::string& optionName, std::string& optionArg) |
45 | { |
46 | optionName.clear(); |
47 | optionArg.clear(); |
48 | if (!_ignore) |
49 | { |
50 | if (!_deferredOption.empty()) |
51 | return processCommon(argument, false, optionName, optionArg); |
52 | else if (_unixStyle) |
53 | return processUnix(argument, optionName, optionArg); |
54 | else |
55 | return processDefault(argument, optionName, optionArg); |
56 | } |
57 | return false; |
58 | } |
59 | |
60 | |
61 | void OptionProcessor::checkRequired() const |
62 | { |
63 | for (OptionSet::Iterator it = _options.begin(); it != _options.end(); ++it) |
64 | { |
65 | if (it->required() && _specifiedOptions.find(it->fullName()) == _specifiedOptions.end()) |
66 | throw MissingOptionException(it->fullName()); |
67 | } |
68 | if (!_deferredOption.empty()) |
69 | { |
70 | std::string optionArg; |
71 | const Option& option = _options.getOption(_deferredOption, false); |
72 | option.process(_deferredOption, optionArg); // will throw MissingArgumentException |
73 | } |
74 | } |
75 | |
76 | |
77 | bool OptionProcessor::processUnix(const std::string& argument, std::string& optionName, std::string& optionArg) |
78 | { |
79 | std::string::const_iterator it = argument.begin(); |
80 | std::string::const_iterator end = argument.end(); |
81 | if (it != end) |
82 | { |
83 | if (*it == '-') |
84 | { |
85 | ++it; |
86 | if (it != end) |
87 | { |
88 | if (*it == '-') |
89 | { |
90 | ++it; |
91 | if (it == end) |
92 | { |
93 | _ignore = true; |
94 | return true; |
95 | } |
96 | else return processCommon(std::string(it, end), false, optionName, optionArg); |
97 | } |
98 | else return processCommon(std::string(it, end), true, optionName, optionArg); |
99 | } |
100 | } |
101 | } |
102 | return false; |
103 | } |
104 | |
105 | |
106 | bool OptionProcessor::processDefault(const std::string& argument, std::string& optionName, std::string& optionArg) |
107 | { |
108 | std::string::const_iterator it = argument.begin(); |
109 | std::string::const_iterator end = argument.end(); |
110 | if (it != end) |
111 | { |
112 | if (*it == '/') |
113 | { |
114 | ++it; |
115 | return processCommon(std::string(it, end), false, optionName, optionArg); |
116 | } |
117 | } |
118 | return false; |
119 | } |
120 | |
121 | |
122 | bool OptionProcessor::processCommon(const std::string& optionStr, bool isShort, std::string& optionName, std::string& optionArg) |
123 | { |
124 | if (!_deferredOption.empty()) |
125 | { |
126 | const Option& option = _options.getOption(_deferredOption, false); |
127 | std::string optionWithArg(_deferredOption); |
128 | _deferredOption.clear(); |
129 | optionWithArg += '='; |
130 | optionWithArg += optionStr; |
131 | option.process(optionWithArg, optionArg); |
132 | optionName = option.fullName(); |
133 | return true; |
134 | } |
135 | if (optionStr.empty()) throw EmptyOptionException(); |
136 | const Option& option = _options.getOption(optionStr, isShort); |
137 | const std::string& group = option.group(); |
138 | if (!group.empty()) |
139 | { |
140 | if (_groups.find(group) != _groups.end()) |
141 | throw IncompatibleOptionsException(option.fullName()); |
142 | else |
143 | _groups.insert(group); |
144 | } |
145 | if (_specifiedOptions.find(option.fullName()) != _specifiedOptions.end() && !option.repeatable()) |
146 | throw DuplicateOptionException(option.fullName()); |
147 | _specifiedOptions.insert(option.fullName()); |
148 | if (option.argumentRequired() && ((!isShort && optionStr.find_first_of(":=" ) == std::string::npos) || (isShort && optionStr.length() == option.shortName().length()))) |
149 | { |
150 | _deferredOption = option.fullName(); |
151 | return true; |
152 | } |
153 | option.process(optionStr, optionArg); |
154 | optionName = option.fullName(); |
155 | return true; |
156 | } |
157 | |
158 | |
159 | } } // namespace Poco::Util |
160 | |