forked from OSSInnovation/mindspore
180 lines
5.8 KiB
C++
180 lines
5.8 KiB
C++
|
/**
|
||
|
* Copyright 2019 Huawei Technologies Co., Ltd
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*/
|
||
|
|
||
|
#include "common/flag_parser.h"
|
||
|
|
||
|
namespace mindspore {
|
||
|
namespace predict {
|
||
|
// parse flags read from command line
|
||
|
Option<std::string> FlagParser::ParseFlags(int argc, const char *const *argv, bool supportUnknown,
|
||
|
bool supportDuplicate) {
|
||
|
MS_ASSERT(argv != nullptr);
|
||
|
const int FLAG_PREFIX_LEN = 2;
|
||
|
// Get binary name
|
||
|
binName = GetFileName(argv[0]);
|
||
|
|
||
|
std::multimap<std::string, Option<std::string>> keyValues;
|
||
|
for (int i = 1; i < argc; i++) {
|
||
|
std::string tmp = argv[i];
|
||
|
Trim(&tmp);
|
||
|
const std::string flagItem(tmp);
|
||
|
|
||
|
if (flagItem == "--") {
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (flagItem.find("--") == std::string::npos) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
std::string key;
|
||
|
Option<std::string> value = Option<std::string>(None());
|
||
|
|
||
|
size_t pos = flagItem.find_first_of("=");
|
||
|
if (pos == std::string::npos && flagItem.find("--no-") != std::string::npos) {
|
||
|
key = flagItem.substr(FLAG_PREFIX_LEN);
|
||
|
} else if (pos == std::string::npos) {
|
||
|
key = flagItem.substr(FLAG_PREFIX_LEN);
|
||
|
} else {
|
||
|
key = flagItem.substr(FLAG_PREFIX_LEN, pos - FLAG_PREFIX_LEN);
|
||
|
value = Option<std::string>(flagItem.substr(pos + 1));
|
||
|
}
|
||
|
|
||
|
keyValues.insert(std::pair<std::string, Option<std::string>>(key, value));
|
||
|
}
|
||
|
|
||
|
Option<std::string> ret = Option<std::string>(InnerParseFlags(&keyValues));
|
||
|
if (ret.IsSome()) {
|
||
|
return Option<std::string>(ret.Get());
|
||
|
}
|
||
|
|
||
|
return Option<std::string>(None());
|
||
|
}
|
||
|
|
||
|
bool FlagParser::GetRealFlagName(const std::string &oriFlagName, std::string *flagName) {
|
||
|
MS_ASSERT(flagName != nullptr);
|
||
|
const int BOOL_TYPE_FLAG_PREFIX_LEN = 3;
|
||
|
bool opaque = false;
|
||
|
if (StartsWithPrefix(oriFlagName, "no-")) {
|
||
|
*flagName = oriFlagName.substr(BOOL_TYPE_FLAG_PREFIX_LEN);
|
||
|
opaque = true;
|
||
|
} else {
|
||
|
*flagName = oriFlagName;
|
||
|
}
|
||
|
return opaque;
|
||
|
}
|
||
|
|
||
|
// Inner parse function
|
||
|
Option<std::string> FlagParser::InnerParseFlags(std::multimap<std::string, Option<std::string>> *keyValues) {
|
||
|
MS_ASSERT(keyValues != nullptr);
|
||
|
for (auto it = keyValues->begin(); it != keyValues->end(); ++it) {
|
||
|
std::string flagName;
|
||
|
bool opaque = GetRealFlagName((*it).first, &flagName);
|
||
|
Option<std::string> flagValue = (*it).second;
|
||
|
|
||
|
auto item = flags.find(flagName);
|
||
|
if (item == flags.end()) {
|
||
|
return Option<std::string>(std::string(flagName + " is not a valid flag"));
|
||
|
}
|
||
|
FlagInfo *flag = &(item->second);
|
||
|
if (flag == nullptr) {
|
||
|
return Option<std::string>("Failed: flag is nullptr");
|
||
|
}
|
||
|
if (flag->isParsed) {
|
||
|
return Option<std::string>("Failed: already parsed flag: " + flagName);
|
||
|
}
|
||
|
std::string tmpValue;
|
||
|
if (!flag->isBoolean) {
|
||
|
if (opaque) {
|
||
|
return Option<std::string>(flagName + " is not a boolean type");
|
||
|
}
|
||
|
if (flagValue.IsNone()) {
|
||
|
return Option<std::string>("No value provided for non-boolean type: " + flagName);
|
||
|
}
|
||
|
tmpValue = flagValue.Get();
|
||
|
} else {
|
||
|
if (flagValue.IsNone() || flagValue.Get().empty()) {
|
||
|
tmpValue = !opaque ? "true" : "false";
|
||
|
} else if (!opaque) {
|
||
|
tmpValue = flagValue.Get();
|
||
|
} else {
|
||
|
return Option<std::string>(std::string("Boolean flag can not have non-empty value"));
|
||
|
}
|
||
|
}
|
||
|
// begin to parse value
|
||
|
Option<Nothing> ret = flag->parse(this, tmpValue);
|
||
|
if (ret.IsNone()) {
|
||
|
return Option<std::string>("Failed to parse value for: " + flag->flagName);
|
||
|
}
|
||
|
flag->isParsed = true;
|
||
|
}
|
||
|
|
||
|
// to check flags not given in command line but added as in constructor
|
||
|
for (auto &flag : flags) {
|
||
|
if (flag.second.isRequired && !flag.second.isParsed) {
|
||
|
return Option<std::string>("Error, value of '" + flag.first + "' not provided");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return Option<std::string>(None());
|
||
|
}
|
||
|
|
||
|
void Replaceall(std::string *str, const std::string &oldValue, const std::string &newValue) {
|
||
|
if (str == nullptr) {
|
||
|
MS_LOGE("Input str is nullptr");
|
||
|
return;
|
||
|
}
|
||
|
while (true) {
|
||
|
std::string::size_type pos(0);
|
||
|
if ((pos = str->find(oldValue)) != std::string::npos) {
|
||
|
str->replace(pos, oldValue.length(), newValue);
|
||
|
} else {
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
std::string FlagParser::Usage(const Option<std::string> &usgMsg) const {
|
||
|
// first line, brief of the usage
|
||
|
std::string usageString = usgMsg.IsSome() ? usgMsg.Get() + "\n" : "";
|
||
|
// usage of bin name
|
||
|
usageString += usageMsg.IsNone() ? "usage: " + binName + " [options]\n" : usageMsg.Get() + "\n";
|
||
|
// help line of help message, usageLine:message of parametors
|
||
|
std::string helpLine = "";
|
||
|
std::string usageLine = "";
|
||
|
uint32_t i = 0;
|
||
|
for (auto flag = flags.begin(); flag != flags.end(); flag++) {
|
||
|
std::string flagName = flag->second.flagName;
|
||
|
std::string helpInfo = flag->second.helpInfo;
|
||
|
// parameter line
|
||
|
std::string thisLine = flag->second.isBoolean ? " --[no-]" + flagName : " --" + flagName + "=VALUE";
|
||
|
if (++i < flags.size()) {
|
||
|
// add paramter help message of each line
|
||
|
thisLine += " " + helpInfo;
|
||
|
Replaceall(&helpInfo, "\n\r", "\n");
|
||
|
usageLine += thisLine + "\n";
|
||
|
} else {
|
||
|
// brief help message
|
||
|
helpLine = thisLine + " " + helpInfo + "\n";
|
||
|
}
|
||
|
}
|
||
|
// total usage is brief of usage+ brief of bin + help message + brief of
|
||
|
// paramters
|
||
|
return usageString + helpLine + usageLine;
|
||
|
}
|
||
|
} // namespace predict
|
||
|
} // namespace mindspore
|