Skip to content

Commit 0ec70bb

Browse files
committed
[main] use early continue in Parse loop
1 parent e152e04 commit 0ec70bb

1 file changed

Lines changed: 95 additions & 94 deletions

File tree

main/src/optparse.hxx

Lines changed: 95 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -428,124 +428,125 @@ public:
428428
if (!isFlag) {
429429
// positional argument
430430
fArgs.push_back(arg);
431-
} else {
431+
continue;
432+
}
433+
434+
++arg;
435+
// Parse long or short flag and its argument into `argStr` / `nxtArgStr`.
436+
// Note that `argStr` may contain multiple flags in case of grouped short flags (in which case nxtArgStr
437+
// refers only to the last one).
438+
argStr.clear();
439+
std::string_view nxtArgStr;
440+
// If this is false `nxtArgStr` *must* refer to the next arg, otherwise it might or might not be.
441+
bool nxtArgIsTentative = true;
442+
if (arg[0] == '-') {
443+
// long flag
432444
++arg;
433-
// Parse long or short flag and its argument into `argStr` / `nxtArgStr`.
434-
// Note that `argStr` may contain multiple flags in case of grouped short flags (in which case nxtArgStr
435-
// refers only to the last one).
436-
argStr.clear();
437-
std::string_view nxtArgStr;
438-
// If this is false `nxtArgStr` *must* refer to the next arg, otherwise it might or might not be.
439-
bool nxtArgIsTentative = true;
440-
if (arg[0] == '-') {
441-
// long flag
442-
++arg;
443-
const char *eq = strchr(arg, '=');
444-
if (eq) {
445-
argStr.push_back(std::string_view(arg, eq - arg));
446-
nxtArgStr = std::string_view(eq + 1);
447-
nxtArgIsTentative = false;
448-
} else {
449-
argStr.push_back(std::string_view(arg));
450-
if (i < nArgs - 1 && args[i + 1][0] != '-') {
451-
nxtArgStr = args[i + 1];
452-
++i;
453-
}
454-
}
445+
const char *eq = strchr(arg, '=');
446+
if (eq) {
447+
argStr.push_back(std::string_view(arg, eq - arg));
448+
nxtArgStr = std::string_view(eq + 1);
449+
nxtArgIsTentative = false;
455450
} else {
456-
// short flag.
457-
// If flag grouping is active, all flags except the last one will have an implicitly empty argument.
458-
auto argLen = strlen(arg);
459-
while (fSettings.fFlagTreatment == EFlagTreatment::kGrouped && argLen > 1) {
460-
argStr.push_back(std::string_view{arg, 1});
461-
++arg, --argLen;
462-
}
463-
464451
argStr.push_back(std::string_view(arg));
465452
if (i < nArgs - 1 && args[i + 1][0] != '-') {
466453
nxtArgStr = args[i + 1];
467454
++i;
468455
}
469456
}
457+
} else {
458+
// short flag.
459+
// If flag grouping is active, all flags except the last one will have an implicitly empty argument.
460+
auto argLen = strlen(arg);
461+
while (fSettings.fFlagTreatment == EFlagTreatment::kGrouped && argLen > 1) {
462+
argStr.push_back(std::string_view{arg, 1});
463+
++arg, --argLen;
464+
}
465+
466+
argStr.push_back(std::string_view(arg));
467+
if (i < nArgs - 1 && args[i + 1][0] != '-') {
468+
nxtArgStr = args[i + 1];
469+
++i;
470+
}
471+
}
472+
473+
for (auto j = 0u; j < argStr.size(); ++j) {
474+
std::string_view argS = argStr[j];
470475

471-
for (auto j = 0u; j < argStr.size(); ++j) {
472-
std::string_view argS = argStr[j];
476+
const auto *exp = GetExpectedFlag(argS);
477+
if (!exp) {
478+
fErrors.push_back(std::string("Unknown flag: ") + argOrig);
479+
break;
480+
}
473481

474-
const auto *exp = GetExpectedFlag(argS);
475-
if (!exp) {
482+
// In Prefix mode, check if the returned expected flag is shorter than `argS`. This can mean two things:
483+
// - if `nxtArgIsTentative == false` then this flag was followed by an equal sign, and in that case
484+
// the intention is interpreted as "I want this flag's argument to be whatever follows the equal sign",
485+
// which means we treat this as an unknown flag;
486+
// - otherwise, we use the rest of `argS` as the argument to the flag.
487+
// More concretely: if the user added flag "-D" and argS is "-Dfoo=bar", we parse it as
488+
// {flag: "-Dfoo", arg: "bar"}, rather than {flag: "-D", arg: "foo=bar"}.
489+
if ((exp->fOpts & kFlagPrefixArg) && argS.size() > exp->fName.size()) {
490+
if (nxtArgIsTentative) {
491+
i -= !nxtArgStr.empty(); // if we had already picked a candidate next arg, undo that.
492+
nxtArgStr = argS.substr(exp->fName.size());
493+
nxtArgIsTentative = false;
494+
} else {
476495
fErrors.push_back(std::string("Unknown flag: ") + argOrig);
477496
break;
478497
}
498+
} else {
499+
assert(exp->fName.size() == argS.size());
500+
}
479501

480-
// In Prefix mode, check if the returned expected flag is shorter than `argS`. This can mean two things:
481-
// - if `nxtArgIsTentative == false` then this flag was followed by an equal sign, and in that case
482-
// the intention is interpreted as "I want this flag's argument to be whatever follows the equal sign",
483-
// which means we treat this as an unknown flag;
484-
// - otherwise, we use the rest of `argS` as the argument to the flag.
485-
// More concretely: if the user added flag "-D" and argS is "-Dfoo=bar", we parse it as
486-
// {flag: "-Dfoo", arg: "bar"}, rather than {flag: "-D", arg: "foo=bar"}.
487-
if ((exp->fOpts & kFlagPrefixArg) && argS.size() > exp->fName.size()) {
488-
if (nxtArgIsTentative) {
489-
i -= !nxtArgStr.empty(); // if we had already picked a candidate next arg, undo that.
490-
nxtArgStr = argS.substr(exp->fName.size());
491-
nxtArgIsTentative = false;
492-
} else {
493-
fErrors.push_back(std::string("Unknown flag: ") + argOrig);
494-
break;
495-
}
496-
} else {
497-
assert(exp->fName.size() == argS.size());
498-
}
502+
std::string_view nxtArg = (j == argStr.size() - 1) ? nxtArgStr : "";
499503

500-
std::string_view nxtArg = (j == argStr.size() - 1) ? nxtArgStr : "";
501-
502-
RCmdLineOpts::RFlag flag;
503-
flag.fHelp = exp->fHelp;
504-
// If the flag is an alias (e.g. long version of a short one), save its name as the aliased one, so we
505-
// can fetch the value later by using any of the aliases.
506-
if (exp->fAlias < 0)
507-
flag.fName = exp->fName;
508-
else
509-
flag.fName = fExpectedFlags[exp->fAlias].fName;
510-
511-
// Check for duplicate flags
512-
if (!(exp->fOpts & kFlagAllowMultiple)) {
513-
auto existingIt = std::find_if(fFlags.begin(), fFlags.end(),
514-
[&flag](const auto &f) { return f.fName == flag.fName; });
515-
if (existingIt != fFlags.end()) {
516-
std::string err = std::string("Flag ") + exp->AsStr() + " appeared more than once";
517-
if (exp->fFlagType == RCmdLineOpts::EFlagType::kWithArg)
518-
err += " with the value: " + existingIt->fValue;
519-
fErrors.push_back(err);
520-
break;
521-
}
504+
RCmdLineOpts::RFlag flag;
505+
flag.fHelp = exp->fHelp;
506+
// If the flag is an alias (e.g. long version of a short one), save its name as the aliased one, so we
507+
// can fetch the value later by using any of the aliases.
508+
if (exp->fAlias < 0)
509+
flag.fName = exp->fName;
510+
else
511+
flag.fName = fExpectedFlags[exp->fAlias].fName;
512+
513+
// Check for duplicate flags
514+
if (!(exp->fOpts & kFlagAllowMultiple)) {
515+
auto existingIt =
516+
std::find_if(fFlags.begin(), fFlags.end(), [&flag](const auto &f) { return f.fName == flag.fName; });
517+
if (existingIt != fFlags.end()) {
518+
std::string err = std::string("Flag ") + exp->AsStr() + " appeared more than once";
519+
if (exp->fFlagType == RCmdLineOpts::EFlagType::kWithArg)
520+
err += " with the value: " + existingIt->fValue;
521+
fErrors.push_back(err);
522+
break;
522523
}
524+
}
523525

524-
// Check that arguments are what we expect.
525-
if (exp->fFlagType == RCmdLineOpts::EFlagType::kWithArg) {
526-
if (!nxtArg.empty()) {
527-
flag.fValue = nxtArg;
528-
} else {
529-
fErrors.push_back("Missing argument for flag " + exp->AsStr());
530-
}
526+
// Check that arguments are what we expect.
527+
if (exp->fFlagType == RCmdLineOpts::EFlagType::kWithArg) {
528+
if (!nxtArg.empty()) {
529+
flag.fValue = nxtArg;
531530
} else {
532-
if (!nxtArg.empty()) {
533-
if (nxtArgIsTentative)
534-
--i;
535-
else
536-
fErrors.push_back("Flag " + exp->AsStr() + " does not expect an argument");
537-
}
531+
fErrors.push_back("Missing argument for flag " + exp->AsStr());
532+
}
533+
} else {
534+
if (!nxtArg.empty()) {
535+
if (nxtArgIsTentative)
536+
--i;
537+
else
538+
fErrors.push_back("Flag " + exp->AsStr() + " does not expect an argument");
538539
}
539-
540-
if (!fErrors.empty())
541-
break;
542-
543-
fFlags.push_back(flag);
544540
}
545541

546542
if (!fErrors.empty())
547543
break;
544+
545+
fFlags.push_back(flag);
548546
}
547+
548+
if (!fErrors.empty())
549+
break;
549550
}
550551
}
551552
};

0 commit comments

Comments
 (0)