DNS Lookup: Change local function to return struct instead of enum

This let's us get rid of an out-parameter.

Task-number: QTBUG-108873
Pick-to: 6.5
Change-Id: Ifc08d3905932f28ecdfdf3a7de1499700cc7e606
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
This commit is contained in:
Mårten Nordheim 2023-02-27 17:36:01 +01:00
parent 83dac21813
commit af95f97466
2 changed files with 46 additions and 42 deletions

View File

@ -13,6 +13,8 @@
#include <stdio.h> #include <stdio.h>
using namespace Qt::StringLiterals;
static std::optional<QDnsLookup::Type> typeFromParameter(QStringView type) static std::optional<QDnsLookup::Type> typeFromParameter(QStringView type)
{ {
if (type.compare(u"a", Qt::CaseInsensitive) == 0) if (type.compare(u"a", Qt::CaseInsensitive) == 0)
@ -38,16 +40,22 @@ static std::optional<QDnsLookup::Type> typeFromParameter(QStringView type)
//! [0] //! [0]
enum CommandLineParseResult struct CommandLineParseResult
{ {
CommandLineOk, enum class Status {
CommandLineError, Ok,
CommandLineVersionRequested, Error,
CommandLineHelpRequested VersionRequested,
HelpRequested
};
Status statusCode = Status::Ok;
std::optional<QString> errorString = std::nullopt;
}; };
CommandLineParseResult parseCommandLine(QCommandLineParser &parser, DnsQuery *query, QString *errorMessage) CommandLineParseResult parseCommandLine(QCommandLineParser &parser, DnsQuery *query)
{ {
using Status = CommandLineParseResult::Status;
parser.setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions); parser.setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions);
const QCommandLineOption nameServerOption("n", "The name server to use.", "nameserver"); const QCommandLineOption nameServerOption("n", "The name server to use.", "nameserver");
parser.addOption(nameServerOption); parser.addOption(nameServerOption);
@ -57,48 +65,41 @@ CommandLineParseResult parseCommandLine(QCommandLineParser &parser, DnsQuery *qu
const QCommandLineOption helpOption = parser.addHelpOption(); const QCommandLineOption helpOption = parser.addHelpOption();
const QCommandLineOption versionOption = parser.addVersionOption(); const QCommandLineOption versionOption = parser.addVersionOption();
if (!parser.parse(QCoreApplication::arguments())) { if (!parser.parse(QCoreApplication::arguments()))
*errorMessage = parser.errorText(); return { Status::Error, parser.errorText() };
return CommandLineError;
}
if (parser.isSet(versionOption)) if (parser.isSet(versionOption))
return CommandLineVersionRequested; return { Status::VersionRequested };
if (parser.isSet(helpOption)) if (parser.isSet(helpOption))
return CommandLineHelpRequested; return { Status::HelpRequested };
if (parser.isSet(nameServerOption)) { if (parser.isSet(nameServerOption)) {
const QString nameserver = parser.value(nameServerOption); const QString nameserver = parser.value(nameServerOption);
query->nameServer = QHostAddress(nameserver); query->nameServer = QHostAddress(nameserver);
if (query->nameServer.isNull() || query->nameServer.protocol() == QAbstractSocket::UnknownNetworkLayerProtocol) { if (query->nameServer.isNull()
*errorMessage = "Bad nameserver address: " + nameserver; || query->nameServer.protocol() == QAbstractSocket::UnknownNetworkLayerProtocol) {
return CommandLineError; return { Status::Error,
u"Bad nameserver address: %1"_qs.arg(nameserver) };
} }
} }
if (parser.isSet(typeOption)) { if (parser.isSet(typeOption)) {
const QString typeParameter = parser.value(typeOption); const QString typeParameter = parser.value(typeOption);
if (std::optional<QDnsLookup::Type> type = typeFromParameter(typeParameter)) { if (std::optional<QDnsLookup::Type> type = typeFromParameter(typeParameter))
query->type = *type; query->type = *type;
} else { else
*errorMessage = "Bad record type: " + typeParameter; return { Status::Error, u"Bad record type: %1"_qs.arg(typeParameter) };
return CommandLineError;
}
} }
const QStringList positionalArguments = parser.positionalArguments(); const QStringList positionalArguments = parser.positionalArguments();
if (positionalArguments.isEmpty()) { if (positionalArguments.isEmpty())
*errorMessage = "Argument 'name' missing."; return { Status::Error, u"Argument 'name' missing."_qs };
return CommandLineError; if (positionalArguments.size() > 1)
} return { Status::Error, u"Several 'name' arguments specified."_qs };
if (positionalArguments.size() > 1) {
*errorMessage = "Several 'name' arguments specified.";
return CommandLineError;
}
query->name = positionalArguments.first(); query->name = positionalArguments.first();
return CommandLineOk; return { Status::Ok };
} }
//! [0] //! [0]
@ -195,19 +196,20 @@ int main(int argc, char *argv[])
"An example demonstrating the " "An example demonstrating the "
"class QDnsLookup.")); "class QDnsLookup."));
DnsQuery query; DnsQuery query;
QString errorMessage; using Status = CommandLineParseResult::Status;
switch (parseCommandLine(parser, &query, &errorMessage)) { CommandLineParseResult parseResult = parseCommandLine(parser, &query);
case CommandLineOk: switch (parseResult.statusCode) {
case Status::Ok:
break; break;
case CommandLineError: case Status::Error:
fputs(qPrintable(errorMessage), stderr); fputs(qPrintable(parseResult.errorString.value_or(u"Unknown error occurred"_qs)), stderr);
fputs("\n\n", stderr); fputs("\n\n", stderr);
fputs(qPrintable(parser.helpText()), stderr); fputs(qPrintable(parser.helpText()), stderr);
return 1; return 1;
case CommandLineVersionRequested: case Status::VersionRequested:
parser.showVersion(); parser.showVersion();
Q_UNREACHABLE_RETURN(0); Q_UNREACHABLE_RETURN(0);
case CommandLineHelpRequested: case Status::HelpRequested:
parser.showHelp(); parser.showHelp();
Q_UNREACHABLE_RETURN(0); Q_UNREACHABLE_RETURN(0);
} }

View File

@ -176,7 +176,7 @@ QStringList QCommandLineParserPrivate::aliases(const QString &optionName) const
It is then advisable to introduce a function to do the command line parsing It is then advisable to introduce a function to do the command line parsing
which takes a struct or class receiving the option values returning an which takes a struct or class receiving the option values returning an
enumeration representing the result. The dnslookup example of the QtNetwork object representing the result. The dnslookup example of the QtNetwork
module illustrates this: module illustrates this:
\snippet dnslookup.h 0 \snippet dnslookup.h 0
@ -204,20 +204,22 @@ QStringList QCommandLineParserPrivate::aliases(const QString &optionName) const
\code \code
switch (parseCommandLine(parser, &query, &errorMessage)) { switch (parseResult.statusCode) {
case CommandLineOk: case Status::Ok:
break; break;
case CommandLineError: case Status::Error: {
QString errorMessage = parseResult.errorString.value_or(u"Unknown error occurred"_qs);
QMessageBox::warning(0, QGuiApplication::applicationDisplayName(), QMessageBox::warning(0, QGuiApplication::applicationDisplayName(),
"<html><head/><body><h2>" + errorMessage + "</h2><pre>" "<html><head/><body><h2>" + errorMessage + "</h2><pre>"
+ parser.helpText() + "</pre></body></html>"); + parser.helpText() + "</pre></body></html>");
return 1; return 1;
case CommandLineVersionRequested: }
case Status::VersionRequested:
QMessageBox::information(0, QGuiApplication::applicationDisplayName(), QMessageBox::information(0, QGuiApplication::applicationDisplayName(),
QGuiApplication::applicationDisplayName() + ' ' QGuiApplication::applicationDisplayName() + ' '
+ QCoreApplication::applicationVersion()); + QCoreApplication::applicationVersion());
return 0; return 0;
case CommandLineHelpRequested: case Status::HelpRequested:
QMessageBox::warning(0, QGuiApplication::applicationDisplayName(), QMessageBox::warning(0, QGuiApplication::applicationDisplayName(),
"<html><head/><body><pre>" "<html><head/><body><pre>"
+ parser.helpText() + "</pre></body></html>"); + parser.helpText() + "</pre></body></html>");