1 /****************************************************************************
2 **
3 ** Copyright (C) 2013 Laszlo Papp <lpapp@kde.org>
4 ** Copyright (C) 2013 David Faure <faure@kde.org>
5 ** Contact: https://www.qt.io/licensing/
6 **
7 ** This file is part of the QtCore module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** Commercial License Usage
11 ** Licensees holding valid commercial Qt licenses may use this file in
12 ** accordance with the commercial license agreement provided with the
13 ** Software or, alternatively, in accordance with the terms contained in
14 ** a written agreement between you and The Qt Company. For licensing terms
15 ** and conditions see https://www.qt.io/terms-conditions. For further
16 ** information use the contact form at https://www.qt.io/contact-us.
17 **
18 ** GNU Lesser General Public License Usage
19 ** Alternatively, this file may be used under the terms of the GNU Lesser
20 ** General Public License version 3 as published by the Free Software
21 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
22 ** packaging of this file. Please review the following information to
23 ** ensure the GNU Lesser General Public License version 3 requirements
24 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
25 **
26 ** GNU General Public License Usage
27 ** Alternatively, this file may be used under the terms of the GNU
28 ** General Public License version 2.0 or (at your option) the GNU General
29 ** Public license version 3 or any later version approved by the KDE Free
30 ** Qt Foundation. The licenses are as published by the Free Software
31 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
32 ** included in the packaging of this file. Please review the following
33 ** information to ensure the GNU General Public License requirements will
34 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
35 ** https://www.gnu.org/licenses/gpl-3.0.html.
36 **
37 ** $QT_END_LICENSE$
38 **
39 ****************************************************************************/
40 
41 #include "qcommandlineoption.h"
42 
43 #include "qset.h"
44 
45 QT_BEGIN_NAMESPACE
46 
47 class QCommandLineOptionPrivate : public QSharedData
48 {
49 public:
50     Q_NEVER_INLINE
QCommandLineOptionPrivate(const QString & name)51     explicit QCommandLineOptionPrivate(const QString &name)
52         : names(removeInvalidNames(QStringList(name)))
53     { }
54 
55     Q_NEVER_INLINE
QCommandLineOptionPrivate(const QStringList & names)56     explicit QCommandLineOptionPrivate(const QStringList &names)
57         : names(removeInvalidNames(names))
58     { }
59 
60     static QStringList removeInvalidNames(QStringList nameList);
61 
62     //! The list of names used for this option.
63     QStringList names;
64 
65     //! The documentation name for the value, if one is expected
66     //! Example: "-o <file>" means valueName == "file"
67     QString valueName;
68 
69     //! The description used for this option.
70     QString description;
71 
72     //! The list of default values used for this option.
73     QStringList defaultValues;
74 
75     QCommandLineOption::Flags flags;
76 };
77 
78 /*!
79     \since 5.2
80     \class QCommandLineOption
81     \brief The QCommandLineOption class defines a possible command-line option.
82     \inmodule QtCore
83     \ingroup shared
84     \ingroup tools
85 
86     This class is used to describe an option on the command line. It allows
87     different ways of defining the same option with multiple aliases possible.
88     It is also used to describe how the option is used - it may be a flag (e.g. \c{-v})
89     or take a value (e.g. \c{-o file}).
90 
91     Examples:
92     \snippet code/src_corelib_tools_qcommandlineoption.cpp 0
93 
94     \sa QCommandLineParser
95 */
96 
97 /*!
98     \fn QCommandLineOption &QCommandLineOption::operator=(QCommandLineOption &&other)
99 
100     Move-assigns \a other to this QCommandLineOption instance.
101 
102     \since 5.2
103 */
104 
105 /*!
106     Constructs a command line option object with the name \a name.
107 
108     The name can be either short or long. If the name is one character in
109     length, it is considered a short name. Option names must not be empty,
110     must not start with a dash or a slash character, must not contain a \c{=}
111     and cannot be repeated.
112 
113     \sa setDescription(), setValueName(), setDefaultValues()
114 */
QCommandLineOption(const QString & name)115 QCommandLineOption::QCommandLineOption(const QString &name)
116     : d(new QCommandLineOptionPrivate(name))
117 {
118 }
119 
120 /*!
121     Constructs a command line option object with the names \a names.
122 
123     This overload allows to set multiple names for the option, for instance
124     \c{o} and \c{output}.
125 
126     The names can be either short or long. Any name in the list that is one
127     character in length is a short name. Option names must not be empty,
128     must not start with a dash or a slash character, must not contain a \c{=}
129     and cannot be repeated.
130 
131     \sa setDescription(), setValueName(), setDefaultValues()
132 */
QCommandLineOption(const QStringList & names)133 QCommandLineOption::QCommandLineOption(const QStringList &names)
134     : d(new QCommandLineOptionPrivate(names))
135 {
136 }
137 
138 /*!
139     Constructs a command line option object with the given arguments.
140 
141     The name of the option is set to \a name.
142     The name can be either short or long. If the name is one character in
143     length, it is considered a short name. Option names must not be empty,
144     must not start with a dash or a slash character, must not contain a \c{=}
145     and cannot be repeated.
146 
147     The description is set to \a description. It is customary to add a "."
148     at the end of the description.
149 
150     In addition, the \a valueName needs to be set if the option expects a value.
151     The default value for the option is set to \a defaultValue.
152 
153     In Qt versions before 5.4, this constructor was \c explicit. In Qt 5.4
154     and later, it no longer is and can be used for C++11-style uniform
155     initialization:
156 
157     \snippet code/src_corelib_tools_qcommandlineoption.cpp cxx11-init
158 
159     \sa setDescription(), setValueName(), setDefaultValues()
160 */
QCommandLineOption(const QString & name,const QString & description,const QString & valueName,const QString & defaultValue)161 QCommandLineOption::QCommandLineOption(const QString &name, const QString &description,
162                                        const QString &valueName,
163                                        const QString &defaultValue)
164     : d(new QCommandLineOptionPrivate(name))
165 {
166     setValueName(valueName);
167     setDescription(description);
168     setDefaultValue(defaultValue);
169 }
170 
171 /*!
172     Constructs a command line option object with the given arguments.
173 
174     This overload allows to set multiple names for the option, for instance
175     \c{o} and \c{output}.
176 
177     The names of the option are set to \a names.
178     The names can be either short or long. Any name in the list that is one
179     character in length is a short name. Option names must not be empty,
180     must not start with a dash or a slash character, must not contain a \c{=}
181     and cannot be repeated.
182 
183     The description is set to \a description. It is customary to add a "."
184     at the end of the description.
185 
186     In addition, the \a valueName needs to be set if the option expects a value.
187     The default value for the option is set to \a defaultValue.
188 
189     In Qt versions before 5.4, this constructor was \c explicit. In Qt 5.4
190     and later, it no longer is and can be used for C++11-style uniform
191     initialization:
192 
193     \snippet code/src_corelib_tools_qcommandlineoption.cpp cxx11-init-list
194 
195     \sa setDescription(), setValueName(), setDefaultValues()
196 */
QCommandLineOption(const QStringList & names,const QString & description,const QString & valueName,const QString & defaultValue)197 QCommandLineOption::QCommandLineOption(const QStringList &names, const QString &description,
198                                        const QString &valueName,
199                                        const QString &defaultValue)
200     : d(new QCommandLineOptionPrivate(names))
201 {
202     setValueName(valueName);
203     setDescription(description);
204     setDefaultValue(defaultValue);
205 }
206 
207 /*!
208     Constructs a QCommandLineOption object that is a copy of the QCommandLineOption
209     object \a other.
210 
211     \sa operator=()
212 */
QCommandLineOption(const QCommandLineOption & other)213 QCommandLineOption::QCommandLineOption(const QCommandLineOption &other)
214     : d(other.d)
215 {
216 }
217 
218 /*!
219     Destroys the command line option object.
220 */
~QCommandLineOption()221 QCommandLineOption::~QCommandLineOption()
222 {
223 }
224 
225 /*!
226     Makes a copy of the \a other object and assigns it to this QCommandLineOption
227     object.
228 */
operator =(const QCommandLineOption & other)229 QCommandLineOption &QCommandLineOption::operator=(const QCommandLineOption &other)
230 {
231     d = other.d;
232     return *this;
233 }
234 
235 /*!
236     \fn void QCommandLineOption::swap(QCommandLineOption &other)
237 
238     Swaps option \a other with this option. This operation is very
239     fast and never fails.
240 */
241 
242 /*!
243     Returns the names set for this option.
244  */
names() const245 QStringList QCommandLineOption::names() const
246 {
247     return d->names;
248 }
249 
250 namespace {
251     struct IsInvalidName
252     {
253         typedef bool result_type;
254         typedef QString argument_type;
255 
256         Q_NEVER_INLINE
operator ()__anona51ba5f00111::IsInvalidName257         result_type operator()(const QString &name) const noexcept
258         {
259             if (Q_UNLIKELY(name.isEmpty()))
260                 return warn("be empty");
261 
262             const QChar c = name.at(0);
263             if (Q_UNLIKELY(c == QLatin1Char('-')))
264                 return warn("start with a '-'");
265             if (Q_UNLIKELY(c == QLatin1Char('/')))
266                 return warn("start with a '/'");
267             if (Q_UNLIKELY(name.contains(QLatin1Char('='))))
268                 return warn("contain a '='");
269 
270             return false;
271         }
272 
273         Q_NEVER_INLINE
warn__anona51ba5f00111::IsInvalidName274         static bool warn(const char *what) noexcept
275         {
276             qWarning("QCommandLineOption: Option names cannot %s", what);
277             return true;
278         }
279     };
280 } // unnamed namespace
281 
282 // static
removeInvalidNames(QStringList nameList)283 QStringList QCommandLineOptionPrivate::removeInvalidNames(QStringList nameList)
284 {
285     if (Q_UNLIKELY(nameList.isEmpty()))
286         qWarning("QCommandLineOption: Options must have at least one name");
287     else
288         nameList.erase(std::remove_if(nameList.begin(), nameList.end(), IsInvalidName()),
289                        nameList.end());
290     return nameList;
291 }
292 
293 /*!
294     Sets the name of the expected value, for the documentation, to \a valueName.
295 
296     Options without a value assigned have a boolean-like behavior:
297     either the user specifies --option or they don't.
298 
299     Options with a value assigned need to set a name for the expected value,
300     for the documentation of the option in the help output. An option with names \c{o} and \c{output},
301     and a value name of \c{file} will appear as \c{-o, --output <file>}.
302 
303     Call QCommandLineParser::value() if you expect the option to be present
304     only once, and QCommandLineParser::values() if you expect that option
305     to be present multiple times.
306 
307     \sa valueName()
308  */
setValueName(const QString & valueName)309 void QCommandLineOption::setValueName(const QString &valueName)
310 {
311     d->valueName = valueName;
312 }
313 
314 /*!
315     Returns the name of the expected value.
316 
317     If empty, the option doesn't take a value.
318 
319     \sa setValueName()
320  */
valueName() const321 QString QCommandLineOption::valueName() const
322 {
323     return d->valueName;
324 }
325 
326 /*!
327     Sets the description used for this option to \a description.
328 
329     It is customary to add a "." at the end of the description.
330 
331     The description is used by QCommandLineParser::showHelp().
332 
333     \sa description()
334  */
setDescription(const QString & description)335 void QCommandLineOption::setDescription(const QString &description)
336 {
337     d->description = description;
338 }
339 
340 /*!
341     Returns the description set for this option.
342 
343     \sa setDescription()
344  */
description() const345 QString QCommandLineOption::description() const
346 {
347     return d->description;
348 }
349 
350 /*!
351     Sets the default value used for this option to \a defaultValue.
352 
353     The default value is used if the user of the application does not specify
354     the option on the command line.
355 
356     If \a defaultValue is empty, the option has no default values.
357 
358     \sa defaultValues() setDefaultValues()
359  */
setDefaultValue(const QString & defaultValue)360 void QCommandLineOption::setDefaultValue(const QString &defaultValue)
361 {
362     QStringList newDefaultValues;
363     if (!defaultValue.isEmpty()) {
364         newDefaultValues.reserve(1);
365         newDefaultValues << defaultValue;
366     }
367     // commit:
368     d->defaultValues.swap(newDefaultValues);
369 }
370 
371 /*!
372     Sets the list of default values used for this option to \a defaultValues.
373 
374     The default values are used if the user of the application does not specify
375     the option on the command line.
376 
377     \sa defaultValues() setDefaultValue()
378  */
setDefaultValues(const QStringList & defaultValues)379 void QCommandLineOption::setDefaultValues(const QStringList &defaultValues)
380 {
381     d->defaultValues = defaultValues;
382 }
383 
384 /*!
385     Returns the default values set for this option.
386 
387     \sa setDefaultValues()
388  */
defaultValues() const389 QStringList QCommandLineOption::defaultValues() const
390 {
391     return d->defaultValues;
392 }
393 
394 #if QT_DEPRECATED_SINCE(5, 8)
395 /*!
396     Sets whether to hide this option in the user-visible help output.
397 
398     All options are visible by default. Setting \a hide to true for
399     a particular option makes it internal, i.e. not listed in the help output.
400 
401     \since 5.6
402     \obsolete Use setFlags(QCommandLineOption::HiddenFromHelp), QCommandLineOption::HiddenFromHelp
403     \sa isHidden
404  */
setHidden(bool hide)405 void QCommandLineOption::setHidden(bool hide)
406 {
407     d->flags.setFlag(HiddenFromHelp, hide);
408 }
409 
410 /*!
411     Returns true if this option is omitted from the help output,
412     false if the option is listed.
413 
414     \since 5.6
415     \obsolete Use flags() & QCommandLineOption::HiddenFromHelp
416     \sa setHidden(), QCommandLineOption::HiddenFromHelp
417  */
isHidden() const418 bool QCommandLineOption::isHidden() const
419 {
420     return d->flags & HiddenFromHelp;
421 }
422 #endif
423 
424 /*!
425     Returns a set of flags that affect this command-line option.
426 
427     \since 5.8
428     \sa setFlags(), QCommandLineOption::Flags
429  */
flags() const430 QCommandLineOption::Flags QCommandLineOption::flags() const
431 {
432     return d->flags;
433 }
434 
435 /*!
436     Set the set of flags that affect this command-line option to \a flags.
437 
438     \since 5.8
439     \sa flags(), QCommandLineOption::Flags
440  */
setFlags(Flags flags)441 void QCommandLineOption::setFlags(Flags flags)
442 {
443     d->flags = flags;
444 }
445 
446 /*!
447     \enum QCommandLineOption::Flag
448 
449     \value HiddenFromHelp Hide this option in the user-visible help output. All
450     options are visible by default. Setting this flag for a particular
451     option makes it internal, i.e. not listed in the help output.
452 
453     \value ShortOptionStyle The option will always be understood as a short
454     option, regardless of what was set by
455     QCommandLineParser::setSingleDashWordOptionMode.
456     This allows flags such as \c{-DDEFINE=VALUE} or \c{-I/include/path} to be
457     interpreted as short flags even when the parser is in
458     QCommandLineParser::ParseAsLongOptions mode.
459 
460     \sa QCommandLineOption::setFlags(), QCommandLineOption::flags()
461 */
462 
463 QT_END_NAMESPACE
464