1 //
2 // Option.cpp
3 //
4 // Library: Util
5 // Package: Options
6 // Module:  Option
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/Option.h"
16 #include "Poco/Util/OptionException.h"
17 #include "Poco/Util/Validator.h"
18 #include "Poco/Util/AbstractConfiguration.h"
19 #include "Poco/String.h"
20 #include <algorithm>
21 
22 
23 using Poco::icompare;
24 
25 
26 namespace Poco {
27 namespace Util {
28 
29 
Option()30 Option::Option():
31 	_required(false),
32 	_repeatable(false),
33 	_argRequired(false),
34 	_pValidator(0),
35 	_pCallback(0),
36 	_pConfig(0)
37 {
38 }
39 
40 
Option(const Option & option)41 Option::Option(const Option& option):
42 	_shortName(option._shortName),
43 	_fullName(option._fullName),
44 	_description(option._description),
45 	_required(option._required),
46 	_repeatable(option._repeatable),
47 	_argName(option._argName),
48 	_argRequired(option._argRequired),
49 	_group(option._group),
50 	_binding(option._binding),
51 	_pValidator(option._pValidator),
52 	_pCallback(option._pCallback),
53 	_pConfig(option._pConfig)
54 {
55 	if (_pValidator) _pValidator->duplicate();
56 	if (_pCallback) _pCallback = _pCallback->clone();
57 	if (_pConfig) _pConfig->duplicate();
58 }
59 
60 
Option(const std::string & fullName,const std::string & shortName)61 Option::Option(const std::string& fullName, const std::string& shortName):
62 	_shortName(shortName),
63 	_fullName(fullName),
64 	_required(false),
65 	_repeatable(false),
66 	_argRequired(false),
67 	_pValidator(0),
68 	_pCallback(0),
69 	_pConfig(0)
70 {
71 }
72 
73 
Option(const std::string & fullName,const std::string & shortName,const std::string & description,bool required)74 Option::Option(const std::string& fullName, const std::string& shortName, const std::string& description, bool required):
75 	_shortName(shortName),
76 	_fullName(fullName),
77 	_description(description),
78 	_required(required),
79 	_repeatable(false),
80 	_argRequired(false),
81 	_pValidator(0),
82 	_pCallback(0),
83 	_pConfig(0)
84 {
85 }
86 
87 
Option(const std::string & fullName,const std::string & shortName,const std::string & description,bool required,const std::string & argName,bool argRequired)88 Option::Option(const std::string& fullName, const std::string& shortName, const std::string& description, bool required, const std::string& argName, bool argRequired):
89 	_shortName(shortName),
90 	_fullName(fullName),
91 	_description(description),
92 	_required(required),
93 	_repeatable(false),
94 	_argName(argName),
95 	_argRequired(argRequired),
96 	_pValidator(0),
97 	_pCallback(0),
98 	_pConfig(0)
99 {
100 }
101 
102 
~Option()103 Option::~Option()
104 {
105 	if (_pValidator) _pValidator->release();
106 	if (_pConfig) _pConfig->release();
107 	delete _pCallback;
108 }
109 
110 
operator =(const Option & option)111 Option& Option::operator = (const Option& option)
112 {
113 	if (&option != this)
114 	{
115 		Option tmp(option);
116 		swap(tmp);
117 	}
118 	return *this;
119 }
120 
121 
swap(Option & option)122 void Option::swap(Option& option)
123 {
124 	std::swap(_shortName, option._shortName);
125 	std::swap(_fullName, option._fullName);
126 	std::swap(_description, option._description);
127 	std::swap(_required, option._required);
128 	std::swap(_repeatable, option._repeatable);
129 	std::swap(_argName, option._argName);
130 	std::swap(_argRequired, option._argRequired);
131 	std::swap(_group, option._group);
132 	std::swap(_binding, option._binding);
133 	std::swap(_pValidator, option._pValidator);
134 	std::swap(_pCallback, option._pCallback);
135 	std::swap(_pConfig, option._pConfig);
136 }
137 
138 
shortName(const std::string & name)139 Option& Option::shortName(const std::string& name)
140 {
141 	_shortName = name;
142 	return *this;
143 }
144 
145 
fullName(const std::string & name)146 Option& Option::fullName(const std::string& name)
147 {
148 	_fullName = name;
149 	return *this;
150 }
151 
152 
description(const std::string & text)153 Option& Option::description(const std::string& text)
154 {
155 	_description = text;
156 	return *this;
157 }
158 
159 
required(bool flag)160 Option& Option::required(bool flag)
161 {
162 	_required = flag;
163 	return *this;
164 }
165 
166 
repeatable(bool flag)167 Option& Option::repeatable(bool flag)
168 {
169 	_repeatable = flag;
170 	return *this;
171 }
172 
173 
argument(const std::string & name,bool required)174 Option& Option::argument(const std::string& name, bool required)
175 {
176 	_argName     = name;
177 	_argRequired = required;
178 	return *this;
179 }
180 
181 
noArgument()182 Option& Option::noArgument()
183 {
184 	_argName.clear();
185 	_argRequired = false;
186 	return *this;
187 }
188 
189 
group(const std::string & group)190 Option& Option::group(const std::string& group)
191 {
192 	_group = group;
193 	return *this;
194 }
195 
196 
binding(const std::string & propertyName)197 Option& Option::binding(const std::string& propertyName)
198 {
199 	return binding(propertyName, 0);
200 }
201 
202 
binding(const std::string & propertyName,AbstractConfiguration * pConfig)203 Option& Option::binding(const std::string& propertyName, AbstractConfiguration* pConfig)
204 {
205 	_binding = propertyName;
206 	if (_pConfig) _pConfig->release();
207 	_pConfig = pConfig;
208 	if (_pConfig) _pConfig->duplicate();
209 	return *this;
210 }
211 
212 
callback(const AbstractOptionCallback & cb)213 Option& Option::callback(const AbstractOptionCallback& cb)
214 {
215 	_pCallback = cb.clone();
216 	return *this;
217 }
218 
219 
validator(Validator * pValidator)220 Option& Option::validator(Validator* pValidator)
221 {
222 	if (_pValidator) _pValidator->release();
223 	_pValidator = pValidator;
224 	return *this;
225 }
226 
227 
matchesShort(const std::string & option) const228 bool Option::matchesShort(const std::string& option) const
229 {
230 	return option.length() > 0
231 		&& !_shortName.empty() && option.compare(0, _shortName.length(), _shortName) == 0;
232 }
233 
234 
matchesFull(const std::string & option) const235 bool Option::matchesFull(const std::string& option) const
236 {
237 	std::string::size_type pos = option.find_first_of(":=");
238 	std::string::size_type len = pos == std::string::npos ? option.length() : pos;
239 	return len == _fullName.length()
240 		&& icompare(option, 0, len, _fullName, 0, len) == 0;
241 }
242 
243 
matchesPartial(const std::string & option) const244 bool Option::matchesPartial(const std::string& option) const
245 {
246 	std::string::size_type pos = option.find_first_of(":=");
247 	std::string::size_type len = pos == std::string::npos ? option.length() : pos;
248 	return option.length() > 0
249 		&& icompare(option, 0, len, _fullName, 0, len) == 0;
250 }
251 
252 
process(const std::string & option,std::string & arg) const253 void Option::process(const std::string& option, std::string& arg) const
254 {
255 	std::string::size_type pos = option.find_first_of(":=");
256 	std::string::size_type len = pos == std::string::npos ? option.length() : pos;
257 	if (icompare(option, 0, len, _fullName, 0, len) == 0)
258 	{
259 		if (takesArgument())
260 		{
261 			if (argumentRequired() && pos == std::string::npos)
262 				throw MissingArgumentException(_fullName + " requires " + argumentName());
263 			if (pos != std::string::npos)
264 				arg.assign(option, pos + 1, option.length() - pos - 1);
265 			else
266 				arg.clear();
267 		}
268 		else if (pos != std::string::npos)
269 		{
270 			throw UnexpectedArgumentException(option);
271 		}
272 		else arg.clear();
273 	}
274 	else if (!_shortName.empty() && option.compare(0, _shortName.length(), _shortName) == 0)
275 	{
276 		if (takesArgument())
277 		{
278 			if (argumentRequired() && option.length() == _shortName.length())
279 				throw MissingArgumentException(_shortName + " requires " + argumentName());
280 			arg.assign(option, _shortName.length(), option.length() - _shortName.length());
281 		}
282 		else if (option.length() != _shortName.length())
283 		{
284 			throw UnexpectedArgumentException(option);
285 		}
286 		else arg.clear();
287 	}
288 	else throw UnknownOptionException(option);
289 }
290 
291 
292 } } // namespace Poco::Util
293