/** * 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 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> 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 value = Option(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(flagItem.substr(pos + 1)); } keyValues.insert(std::pair>(key, value)); } Option ret = Option(InnerParseFlags(&keyValues)); if (ret.IsSome()) { return Option(ret.Get()); } return Option(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 FlagParser::InnerParseFlags(std::multimap> *keyValues) { MS_ASSERT(keyValues != nullptr); for (auto it = keyValues->begin(); it != keyValues->end(); ++it) { std::string flagName; bool opaque = GetRealFlagName((*it).first, &flagName); Option flagValue = (*it).second; auto item = flags.find(flagName); if (item == flags.end()) { return Option(std::string(flagName + " is not a valid flag")); } FlagInfo *flag = &(item->second); if (flag == nullptr) { return Option("Failed: flag is nullptr"); } if (flag->isParsed) { return Option("Failed: already parsed flag: " + flagName); } std::string tmpValue; if (!flag->isBoolean) { if (opaque) { return Option(flagName + " is not a boolean type"); } if (flagValue.IsNone()) { return Option("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("Boolean flag can not have non-empty value")); } } // begin to parse value Option ret = flag->parse(this, tmpValue); if (ret.IsNone()) { return Option("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("Error, value of '" + flag.first + "' not provided"); } } return Option(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 &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