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
21namespace Poco {
22namespace Util {
23
24
25OptionProcessor::OptionProcessor(const OptionSet& options):
26 _options(options),
27 _unixStyle(true),
28 _ignore(false)
29{
30}
31
32
33OptionProcessor::~OptionProcessor()
34{
35}
36
37
38void OptionProcessor::setUnixStyle(bool flag)
39{
40 _unixStyle = flag;
41}
42
43
44bool 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
61void 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
77bool 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
106bool 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
122bool 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