You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							180 lines
						
					
					
						
							5.8 KiB
						
					
					
				
			
		
		
	
	
							180 lines
						
					
					
						
							5.8 KiB
						
					
					
				| /**
 | |
|  * 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
 |