|  |  | @ -3,423 +3,429 @@ | 
			
		
	
		
		
			
				
					
					|  |  |  | namespace program_options { |  |  |  | namespace program_options { | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | // class ParseError
 |  |  |  | // class ParseError
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | //定义了一个名为ParseError的类
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | ParseError::ParseError(const std::string& msg) : _msg(msg) {} |  |  |  | //ParseError类是一个用于处理命令行解析错误的异常类。
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | ParseError::ParseError(const std::string& msg) : _msg(msg) {}//是ParseError类的构造函数
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | const char* ParseError::what() const throw() { |  |  |  | //它接受一个字符串作为参数,并将这个字符串赋值给成员变量_msg。
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   std::string msg; |  |  |  | const char* ParseError::what() const throw() {//是一个成员函数,它返回一个描述错误的字符串
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   msg.append("Command line parse error: ").append(_msg).push_back('.'); |  |  |  |   std::string msg;//首先创建一个新的字符串
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   return msg.c_str(); |  |  |  |   msg.append("Command line parse error: ").append(_msg).push_back('.');//添加一个错误消息前缀,接着添加成员变量_msg,最后添加一个句点。
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   return msg.c_str();//返回这个字符串的C风格字符串。
 | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | ParseError::~ParseError() throw() {} |  |  |  | ParseError::~ParseError() throw() {}// 是ParseError类的析构函数
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | // class Generator
 |  |  |  | // class Generator
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | //定义了一个名为Generator的类,该类用于生成和管理命令行选项解析器和子程序。
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | Generator::Generator() : parser_(nullptr) { |  |  |  | Generator::Generator() : parser_(nullptr) {//Generator类的构造函数
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   current_subroutine_ = Subroutine::get_default_name(); |  |  |  |   current_subroutine_ = Subroutine::get_default_name();//初始化parser_为nullptr,设置当前子程序为默认子程序
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   add_subroutine(current_subroutine_.c_str()); |  |  |  |   add_subroutine(current_subroutine_.c_str());//添加这个子程序。
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | Generator::~Generator() { |  |  |  | Generator::~Generator() {//Generator类的析构函数
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |   if (parser_) { |  |  |  |   if (parser_) { | 
			
		
	
		
		
			
				
					
					|  |  |  |     delete parser_; |  |  |  |     delete parser_; | 
			
		
	
		
		
			
				
					
					|  |  |  |     parser_ = nullptr; |  |  |  |     parser_ = nullptr; | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |   }//它删除parser_和所有的子程序
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |   for (auto it = subroutines_.begin(); it != subroutines_.end(); ++it) { |  |  |  |   for (auto it = subroutines_.begin(); it != subroutines_.end(); ++it) { | 
			
		
	
		
		
			
				
					
					|  |  |  |     if (it->second) { |  |  |  |     if (it->second) { | 
			
		
	
		
		
			
				
					
					|  |  |  |       delete it->second; |  |  |  |       delete it->second;//它删除所有的子程序,
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |       it->second = nullptr; |  |  |  |       it->second = nullptr;//并将parser_和所有的子程序设置为nullptr。
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | Generator& Generator::make_usage(const char* first_line) { |  |  |  | Generator& Generator::make_usage(const char* first_line) {//是一个成员函数
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   get_subroutine()->set_first_line(first_line); |  |  |  |   get_subroutine()->set_first_line(first_line);//它设置当前子程序的第一行
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   return *this; |  |  |  |   return *this;//并返回this指针。
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | Parser* Generator::make_parser() { |  |  |  | Parser* Generator::make_parser() {//是一个成员函数
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |   if (parser_) delete parser_; |  |  |  |   if (parser_) delete parser_; | 
			
		
	
		
		
			
				
					
					|  |  |  |   parser_ = new Parser; |  |  |  |   parser_ = new Parser;//它创建一个新的Parser对象
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   parser_->set_usage_subroutines(&subroutines_); |  |  |  |   parser_->set_usage_subroutines(&subroutines_);//设置其使用的子程序
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   return parser_; |  |  |  |   return parser_;//并返回这个Parser对象。
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | Generator& Generator::add_subroutine(const char* name) { |  |  |  | Generator& Generator::add_subroutine(const char* name) {//是成员函数
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   add_subroutine(name, ""); |  |  |  |   add_subroutine(name, "");//它们添加一个新的子程序。
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |   return *this; |  |  |  |   return *this; | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | Generator& Generator::add_subroutine(const char* name, |  |  |  | Generator& Generator::add_subroutine(const char* name, | 
			
		
	
		
		
			
				
					
					|  |  |  |                                      const char* description) { |  |  |  |                                      const char* description) {//成员函数
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   if (subroutines_.find(name) == subroutines_.end()) { |  |  |  |   if (subroutines_.find(name) == subroutines_.end()) {//如果子程序已经存在,它们不会添加。
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     // a new subroutine
 |  |  |  |     // a new subroutine
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     current_subroutine_ = name; |  |  |  |     current_subroutine_ = name;//设立新名字
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     Subroutine* routine = new Subroutine(name, description); |  |  |  |     Subroutine* routine = new Subroutine(name, description);//新建一个子程序。
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     subroutines_.insert({current_subroutine_, routine}); |  |  |  |     subroutines_.insert({current_subroutine_, routine});//添加一个新的子程序。
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  |   return *this; |  |  |  |   return *this; | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | std::map<std::string, std::string> Generator::get_subroutine_list() { |  |  |  | std::map<std::string, std::string> Generator::get_subroutine_list() {//是一个成员函数,它返回一个包含所有子程序名称和描述的映射。
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |   std::map<std::string, std::string> kv; |  |  |  |   std::map<std::string, std::string> kv; | 
			
		
	
		
		
			
				
					
					|  |  |  |   for (auto pr : subroutines_) { |  |  |  |   for (auto pr : subroutines_) {//遍历所有的子程序
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     Subroutine* subroutine = pr.second; |  |  |  |     Subroutine* subroutine = pr.second;//遍历所有的子程序
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     if (subroutine->get_name() != Subroutine::get_default_name()) |  |  |  |     if (subroutine->get_name() != Subroutine::get_default_name())//如果子程序的名称不是默认名称
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |       kv[subroutine->get_name()] = subroutine->get_description(); |  |  |  |       kv[subroutine->get_name()] = subroutine->get_description();//将子程序的名称和描述添加到映射中。
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  |   return std::move(kv); |  |  |  |   return std::move(kv);//返回一个包含所有子程序名称和描述的映射
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | bool Generator::add_usage_line(const char* option, const char* default_value, |  |  |  | bool Generator::add_usage_line(const char* option, const char* default_value, | 
			
		
	
		
		
			
				
					
					|  |  |  |                                const char* description) { |  |  |  |                                const char* description) {// 是一个成员函数,它添加一个使用行到当前子程序。
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |   std::string option_str(option); |  |  |  |   std::string option_str(option); | 
			
		
	
		
		
			
				
					
					|  |  |  |   auto delimiter_pos = option_str.find(kDelimiter); |  |  |  |   auto delimiter_pos = option_str.find(kDelimiter); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | //定义新变量,将选项字符串赋给新变量
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |   std::string option_short; |  |  |  |   std::string option_short; | 
			
		
	
		
		
			
				
					
					|  |  |  |   std::string option_long; |  |  |  |   std::string option_long; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | //将选项字符串分割为短选项和长选项
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |   if (delimiter_pos != std::string::npos) { |  |  |  |   if (delimiter_pos != std::string::npos) { | 
			
		
	
		
		
			
				
					
					|  |  |  |     option_short.assign(std::move(option_str.substr(0, delimiter_pos))); |  |  |  |     option_short.assign(std::move(option_str.substr(0, delimiter_pos))); | 
			
		
	
		
		
			
				
					
					|  |  |  |     option_long.assign(std::move(option_str.substr(delimiter_pos + 1))); |  |  |  |     option_long.assign(std::move(option_str.substr(delimiter_pos + 1))); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     Row row; |  |  |  |     Row row;//创建一个Row对象,
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     row.oshort(option_short); |  |  |  |     row.oshort(option_short); | 
			
		
	
		
		
			
				
					
					|  |  |  |     row.olong(option_long); |  |  |  |     row.olong(option_long); | 
			
		
	
		
		
			
				
					
					|  |  |  |     row.value(default_value); |  |  |  |     row.value(default_value); | 
			
		
	
		
		
			
				
					
					|  |  |  |     row.desc(description); |  |  |  |     row.desc(description); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | ////设置其短选项、长选项、默认值和描述
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     get_subroutine()->add_usage_line(row); |  |  |  |     get_subroutine()->add_usage_line(row);//将这个Row对象添加到当前子程序的使用行中。
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     return true; |  |  |  |     return true; | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  |   return false; |  |  |  |   return false; | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | std::ostream& operator<<(std::ostream& out, Generator& generator) { |  |  |  | std::ostream& operator<<(std::ostream& out, Generator& generator) {// 是一个输出运算符重载函数,它打印所有子程序的名称和描述。
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   for (auto pr : generator.subroutines_) { |  |  |  |   for (auto pr : generator.subroutines_) {//遍历所有的子程序
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     Subroutine* subroutine = pr.second; |  |  |  |     Subroutine* subroutine = pr.second; | 
			
		
	
		
		
			
				
					
					|  |  |  |     if (subroutine->get_name() != Subroutine::get_default_name()) { |  |  |  |     if (subroutine->get_name() != Subroutine::get_default_name()) { | 
			
		
	
		
		
			
				
					
					|  |  |  |       out << subroutine->get_name() << "\t"; |  |  |  |       out << subroutine->get_name() << "\t"; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     }//如果子程序的名称不是默认名称,就打印子程序的名称
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     out << subroutine->get_description();//打印子程序的描述
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     if (!subroutine->get_usage().empty()) {//如果子程序的使用信息不为空,就打印一个换行符
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       out << std::endl;//打印一个换行符
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |     out << subroutine->get_description(); |  |  |  |     out << *subroutine;//打印子程序的使用信息。
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     if (!subroutine->get_usage().empty()) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |       out << std::endl; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     out << *subroutine; |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  |   return out; |  |  |  |   return out; | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | // class ParseItem
 |  |  |  | // class ParseItem
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | ParseItem::ParseItem(const std::string& value) : value_(value) {} |  |  |  | ParseItem::ParseItem(const std::string& value) : value_(value) {}//ParseItem 类的构造函数
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | //它接受一个 std::string 类型的参数 value。在构造函数体中,将传入的 value 直接赋值给类的成员变量 value_。
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | //这个构造函数用于创建一个 ParseItem 对象,并初始化其 value_ 成员变量。
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | // class Parser
 |  |  |  | // class Parser
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | ParseItem* Parser::get(const std::string& key) { |  |  |  | ParseItem* Parser::get(const std::string& key) {//Parser 类的 get 方法,它接受一个 std::string 类型的参数 key。
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   if (pr_->find(key) != pr_->end()) { |  |  |  |   if (pr_->find(key) != pr_->end()) {//如果 key 在 pr_ 中存在
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     return (*pr_)[key]; |  |  |  |     return (*pr_)[key];//那么返回对应的 ParseItem 指针
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  |   return nullptr; |  |  |  |   return nullptr;//返回 nullptr
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | Parser::Parser() : subroutines_(nullptr), pr_(nullptr) {} |  |  |  | Parser::Parser() : subroutines_(nullptr), pr_(nullptr) {}//
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | //Parser 类的构造函数,它使用初始化列表将 subroutines_ 和 pr_ 成员变量初始化为 nullptr。
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | Parser::~Parser() { this->cleanup(); } |  |  |  | Parser::~Parser() { this->cleanup(); } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | //这是 Parser 类的析构函数,它调用 cleanup 方法来清理资源。
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | Parser::ParseResult* Parser::parse(const int argc, const char** argv) { |  |  |  | Parser::ParseResult* Parser::parse(const int argc, const char** argv) {//Parser 类的 parse 方法,它接受命令行参数的数量 argc 和参数值 argv
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   if (!this->init(argc, argv)) { |  |  |  |   if (!this->init(argc, argv)) {//它调用 init 方法来初始化解析过程
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     return nullptr; |  |  |  |     return nullptr;//如果初始化失败,那么返回 nullptr
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  |   auto ibegin = args_.begin() + 1;  // ignore the first cmd name
 |  |  |  |   auto ibegin = args_.begin() + 1;  // 忽略第一个命令名
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |   auto iend = args_.end(); |  |  |  |   auto iend = args_.end(); | 
			
		
	
		
		
			
				
					
					|  |  |  |   auto it = ibegin; |  |  |  |   auto it = ibegin;//定义开始变量名
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   if (argc >= 2 && args_[1][0] != '-') { |  |  |  |   if (argc >= 2 && args_[1][0] != '-') { | 
			
		
	
		
		
			
				
					
					|  |  |  |     // the second block may be a subroutine name
 |  |  |  |     // 第二个块可能是一个子程序名
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     // e.g., ./exec pull --option
 |  |  |  |     // e.g., ./exec pull --option
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     if (subroutines_ && (subroutines_->find(args_[1]) != subroutines_->end())) { |  |  |  |     if (subroutines_ && (subroutines_->find(args_[1]) != subroutines_->end())) { | 
			
		
	
		
		
			
				
					
					|  |  |  |       subroutine_name_ = args_[1]; |  |  |  |       subroutine_name_ = args_[1]; | 
			
		
	
		
		
			
				
					
					|  |  |  |       it++;  // ignore the subroutine name
 |  |  |  |       it++;   // 忽略子程序名
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     } else { |  |  |  |     } else { | 
			
		
	
		
		
			
				
					
					|  |  |  |       subroutine_name_ = args_[1]; |  |  |  |       subroutine_name_ = args_[1]; | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |   } else { |  |  |  |   } else { | 
			
		
	
		
		
			
				
					
					|  |  |  |     // there is no options as well as subroutine name
 |  |  |  |     // 没有选项以及子程序名
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     // e.g., ./exec
 |  |  |  |     // 例如,./exec
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     subroutine_name_ = Subroutine::get_default_name(); |  |  |  |     subroutine_name_ = Subroutine::get_default_name(); | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   std::string block; |  |  |  |   std::string block;//声明变量
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   std::string previous(*ibegin); |  |  |  |   std::string previous(*ibegin);//声明变量
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   for (; it != iend; ++it) { |  |  |  |   for (; it != iend; ++it) {// 遍历所有的命令行参数
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     block.assign(*it); |  |  |  |     block.assign(*it);// 将当前参数赋值给 block
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     switch (block.size()) { |  |  |  |     switch (block.size()) {//// 根据 block 的大小进行不同的处理
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |       case 1: |  |  |  |       case 1://// 如果 block 的大小为 1
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         if (block == "-") { |  |  |  |         if (block == "-") {//// 如果 block 是一个单独的 "-"
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |           throw ParseError("single '-' is not allowed"); |  |  |  |           throw ParseError("single '-' is not allowed");//// 抛出异常,因为单独的 "-" 是不允许的
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         } |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |         break; |  |  |  |         break; | 
			
		
	
		
		
			
				
					
					|  |  |  |       case 2: |  |  |  |       case 2:// // 如果 block 的大小为 2
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         if (block[0] == '-') { |  |  |  |         if (block[0] == '-') {//// 如果 block 的第一个字符是 "-"
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |           if (block[1] == '-') { |  |  |  |           if (block[1] == '-') {//// 如果 block 的第二个字符也是 "-"
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |             throw ParseError("option '--' is incomplete"); |  |  |  |             throw ParseError("option '--' is incomplete");//// 抛出异常,因为 "--" 是不完整的选项
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |           } else if (block[1] == '=') { |  |  |  | 
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |             throw ParseError("option '-=' is invalid"); |  |  |  |           } else if (block[1] == '=') {//// 如果 block 的第二个字符是 "="
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             throw ParseError("option '-=' is invalid");//// 抛出异常,因为 "-=" 是无效的选项
 | 
			
		
	
		
		
			
				
					
					|  |  |  |           } else { |  |  |  |           } else { | 
			
		
	
		
		
			
				
					
					|  |  |  |             // single option
 |  |  |  |             // 单个选项
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |             // e.g., ./exec -s
 |  |  |  |             // e.g., ./exec -s
 | 
			
		
	
		
		
			
				
					
					|  |  |  |             (*pr_)[block.substr(1)] = nullptr; |  |  |  |             (*pr_)[block.substr(1)] = nullptr; | 
			
		
	
		
		
			
				
					
					|  |  |  |           } |  |  |  |           } | 
			
		
	
		
		
			
				
					
					|  |  |  |         } |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |         break; |  |  |  |         break; | 
			
		
	
		
		
			
				
					
					|  |  |  |       default:  // >=3
 |  |  |  |       default:  // >=3
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         if (block[0] == '-') { |  |  |  |         if (block[0] == '-') {//// 如果 block 的第一个字符是 "-"
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |           if (block[1] == '-') { |  |  |  |           if (block[1] == '-') {//// 如果 block 的第二个字符也是 "-"
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |             size_t pos_equal = block.find('='); |  |  |  |             size_t pos_equal = block.find('=');//// 查找 "=" 在 block 中的位置
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |             if (pos_equal == std::string::npos) { |  |  |  |             if (pos_equal == std::string::npos) {//// 如果没有找到 "="
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |               // a long format option
 |  |  |  |               // 长格式选项
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |               // e.g., ./exec --option
 |  |  |  |               // e.g., ./exec --option
 | 
			
		
	
		
		
			
				
					
					|  |  |  |               (*pr_)[block.substr(2)] = nullptr; |  |  |  |               (*pr_)[block.substr(2)] = nullptr;//// 将选项添加到 pr_ 中,值为 nullptr
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |             } else { |  |  |  |             } else { | 
			
		
	
		
		
			
				
					
					|  |  |  |               if (pos_equal > 3) { |  |  |  |               if (pos_equal > 3) {// 如果 "=" 的位置大于 3
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |                 // e.g, ./exec --op[..=]value
 |  |  |  |                 // e.g, ./exec --op[..=]value
 | 
			
		
	
		
		
			
				
					
					|  |  |  |                 std::string key(block.substr(2, pos_equal - 2)); |  |  |  |                 std::string key(block.substr(2, pos_equal - 2));// 获取选项名
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |                 if (block.size() > 5) |  |  |  |                 if (block.size() > 5)//// 如果 block 的大小大于 5
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |                   // e.g, ./exec --op=v
 |  |  |  |                   // e.g, ./exec --op=v
 | 
			
		
	
		
		
			
				
					
					|  |  |  |                   (*pr_)[key] = new ParseItem(block.substr(pos_equal + 1)); |  |  |  |                   (*pr_)[key] = new ParseItem(block.substr(pos_equal + 1));// 将选项和值添加到 pr_ 中
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |                 else |  |  |  |                 else | 
			
		
	
		
		
			
				
					
					|  |  |  |                   (*pr_)[key] = nullptr; |  |  |  |                   (*pr_)[key] = nullptr;// 将选项添加到 pr_ 中,值为 nullptr
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |               } else { |  |  |  |               } else { | 
			
		
	
		
		
			
				
					
					|  |  |  |                 // a long format option but = is illegal
 |  |  |  |                 // 长格式选项但 = 是非法的
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |                 // e.g., ./exec --o=[...]
 |  |  |  |                 // e.g., ./exec --o=[...]
 | 
			
		
	
		
		
			
				
					
					|  |  |  |                 (*pr_)[block.substr(2)] = nullptr; |  |  |  |                 (*pr_)[block.substr(2)] = nullptr;//// 将选项添加到 pr_ 中,值为 nullptr
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |               } |  |  |  |               } | 
			
		
	
		
		
			
				
					
					|  |  |  |             } |  |  |  |             } | 
			
		
	
		
		
			
				
					
					|  |  |  |           } else if (block[2] == '=') { |  |  |  |           } else if (block[2] == '=') {// // 如果 block 的第三个字符是 "="
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |             // a single option with =
 |  |  |  |             // 单个选项带有 =
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |             // e.g., ./exec -o=[...]
 |  |  |  |             // e.g., ./exec -o=[...]
 | 
			
		
	
		
		
			
				
					
					|  |  |  |             std::string key; |  |  |  |             std::string key; | 
			
		
	
		
		
			
				
					
					|  |  |  |             key.push_back(block[1]); |  |  |  |             key.push_back(block[1]);// 获取选项名
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |             if (block.size() > 3) |  |  |  |             if (block.size() > 3)// 如果 block 的大小大于 3
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |               (*pr_)[key] = new ParseItem(block.substr(3)); |  |  |  |               (*pr_)[key] = new ParseItem(block.substr(3));//// 将选项和值添加到 pr_ 中
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |             else |  |  |  |             else | 
			
		
	
		
		
			
				
					
					|  |  |  |               (*pr_)[key] = nullptr; |  |  |  |               (*pr_)[key] = nullptr;// 将选项添加到 pr_ 中,值为 nullptr
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |           } else { |  |  |  |           } else { | 
			
		
	
		
		
			
				
					
					|  |  |  |             // a combination options
 |  |  |  |             // 组合选项
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |             // e.g., ./exec -ab[...]
 |  |  |  |             // e.g., ./exec -ab[...]
 | 
			
		
	
		
		
			
				
					
					|  |  |  |             auto tbegin = block.begin() + 1;  // ignore the first '-'
 |  |  |  |             auto tbegin = block.begin() + 1;  // 忽略第一个 '-'
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |             auto tend = block.end(); |  |  |  |             auto tend = block.end(); | 
			
		
	
		
		
			
				
					
					|  |  |  |             auto t = tbegin; |  |  |  |             auto t = tbegin; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |             for (; t != tend; ++t) { |  |  |  |             for (; t != tend; ++t) { // 遍历 block 中的每个字符
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |               std::string key; |  |  |  |               std::string key; | 
			
		
	
		
		
			
				
					
					|  |  |  |               key.push_back(*t); |  |  |  |               key.push_back(*t);// // 获取选项名
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |               (*pr_)[key] = nullptr; |  |  |  |               (*pr_)[key] = nullptr; // 将选项添加到 pr_ 中,值为 nullptr
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |             } |  |  |  |             } | 
			
		
	
		
		
			
				
					
					|  |  |  |           } |  |  |  |           } | 
			
		
	
		
		
			
				
					
					|  |  |  |         } |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |         break; |  |  |  |         break; | 
			
		
	
		
		
			
				
					
					|  |  |  |     }  // switch
 |  |  |  |     }  // switch
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     if (block[0] != '-' && previous != block  // not the first option
 |  |  |  |     if (block[0] != '-' && previous != block  // 如果 block 不是选项(不以 "-" 开头)并且不是第一个选项
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         ) { |  |  |  |         ) { | 
			
		
	
		
		
			
				
					
					|  |  |  |       if (previous[0] != '-') { |  |  |  |       if (previous[0] != '-') {//// 如果 previous 不是选项
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         // previous is not an option, error occur
 |  |  |  |         // previous 不是一个选项,发生错误
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         // e.g., ./exec abc def
 |  |  |  |         // e.g., ./exec abc def
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         throw ParseError("'" + block + "' is not allowed here"); |  |  |  |         throw ParseError("'" + block + "' is not allowed here");//抛出异常,因为在这里不允许非选项
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |       } |  |  |  |       } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |       std::string key; |  |  |  |       std::string key; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |       if (previous[0] == '-' && previous[1] == '-') { |  |  |  |       if (previous[0] == '-' && previous[1] == '-') {//// 如果 previous 是一个长格式选项
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         // previous is a long format option.
 |  |  |  |         // previous is a long format option.
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         // e.g., ./exec --option value
 |  |  |  |         // e.g., ./exec --option value
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         key = previous.substr(2); |  |  |  |         key = previous.substr(2);//// 获取选项名
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |       } else { |  |  |  |       } else { | 
			
		
	
		
		
			
				
					
					|  |  |  |         // it's the value of previous option.
 |  |  |  |         // 它是前一个选项的值。
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         // e.g., ./exec -o   [...]
 |  |  |  |         // e.g., ./exec -o   [...]
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         // e.g., ./exec -opq [...]
 |  |  |  |         // e.g., ./exec -opq [...]
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         key.push_back(*(previous.end() - 1)); |  |  |  |         key.push_back(*(previous.end() - 1));// // 获取选项名
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |       } |  |  |  |       } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |       if (pr_->find(key) != pr_->end()) { |  |  |  |       if (pr_->find(key) != pr_->end()) {//// 如果选项在 pr_ 中存在
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         (*pr_)[key] = new ParseItem(block); |  |  |  |         (*pr_)[key] = new ParseItem(block); // 将选项和值添加到 pr_ 中
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |       } |  |  |  |       } | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     previous = block; |  |  |  |     previous = block;//// 更新 previous 为当前的 block
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |   }  // for
 |  |  |  |   }  // for
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   if (subroutines_) { |  |  |  |   if (subroutines_) { | 
			
		
	
		
		
			
				
					
					|  |  |  |     this->set_addition(); |  |  |  |     this->set_addition();// 如果存在子程序,调用 set_addition 方法处理额外的选项
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   return pr_; |  |  |  |   return pr_;//返回解析结果 pr_
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | Parser::ParseResult* Parser::parse(const char* command_line) { |  |  |  | Parser::ParseResult* Parser::parse(const char* command_line) {//Parser 类的 parse 方法
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   int i = 0; |  |  |  |   int i = 0;//初始化计数器
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   std::string block; |  |  |  |   std::string block;//用于存储单个命令行参数
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   std::vector<std::string> blocks; |  |  |  |   std::vector<std::string> blocks;//声明用于存储所有命令行参数
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   char c; |  |  |  |   char c;//声明用于存储当前字符
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   while ((c = command_line[i++]) != '\0') { |  |  |  |   while ((c = command_line[i++]) != '\0') {// 遍历命令行字符串
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     if (c != ' ') { |  |  |  |     if (c != ' ') {// 如果当前字符不是空格
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |       block.push_back(c); |  |  |  |       block.push_back(c);//// 将当前字符添加到 block
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     } else { |  |  |  |     } else { | 
			
		
	
		
		
			
				
					
					|  |  |  |       if (!block.empty()) { |  |  |  |       if (!block.empty()) {// 如果 block 不为空
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         blocks.push_back(block); |  |  |  |         blocks.push_back(block);// 将 block 添加到 blocks
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |       } |  |  |  |       } | 
			
		
	
		
		
			
				
					
					|  |  |  |       block.clear(); |  |  |  |       block.clear();//清空 block
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  |   if (!block.empty()) { |  |  |  |   if (!block.empty()) {// 如果最后一个 block 不为空
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     blocks.push_back(block); |  |  |  |     blocks.push_back(block);// 将 block 添加到 blocks
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  |   size_t size = blocks.size();  // argc
 |  |  |  |   size_t size = blocks.size();  // argc
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   char** argv = new char*[size]; |  |  |  |   char** argv = new char*[size];// 创建一个新的 char* 数组
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |   i = 0; |  |  |  |   i = 0; | 
			
		
	
		
		
			
				
					
					|  |  |  |   std::for_each(blocks.begin(), blocks.end(), [argv, &i](const std::string& b) { |  |  |  |   std::for_each(blocks.begin(), blocks.end(), [argv, &i](const std::string& b) {// 遍历 blocks
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     argv[i++] = const_cast<char*>(b.c_str()); |  |  |  |     argv[i++] = const_cast<char*>(b.c_str());// 将每个 block 转换为 char* 并存储在 argv 中
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |   }); |  |  |  |   }); | 
			
		
	
		
		
			
				
					
					|  |  |  |   auto pr = |  |  |  |   auto pr = | 
			
		
	
		
		
			
				
					
					|  |  |  |       this->parse(static_cast<const int>(size), const_cast<const char**>(argv)); |  |  |  |       this->parse(static_cast<const int>(size), const_cast<const char**>(argv)); // 调用 parse 方法解析命令行参数
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   delete[] argv; |  |  |  |   delete[] argv;// 删除 argv
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |   argv = nullptr; |  |  |  |   argv = nullptr; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   return pr; |  |  |  |   return pr;// 返回解析结果
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | bool Parser::has(const char* key) { |  |  |  | bool Parser::has(const char* key) {//Parser 类的 has 方法,它接受一个 char 指针 key,并检查 key 是否在 pr_ 中存在。
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   std::string skey(key); |  |  |  |   std::string skey(key);// 将 key 转换为 std::string
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   if (pr_ && !pr_->empty() && !skey.empty()) { |  |  |  |   if (pr_ && !pr_->empty() && !skey.empty()) {//判断是否存在
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     if (skey[0] == '-') { |  |  |  |     if (skey[0] == '-') { | 
			
		
	
		
		
			
				
					
					|  |  |  |       // check combination options, e.g., Parser::has("-xyz")
 |  |  |  |        // 如果 skey 是一个组合选项,例如 "-xyz"
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |       for (size_t i = 1; i < skey.size(); ++i) { |  |  |  |       for (size_t i = 1; i < skey.size(); ++i) {// 遍历 skey 的每个字符
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         std::string tkey; |  |  |  |         std::string tkey; | 
			
		
	
		
		
			
				
					
					|  |  |  |         tkey.push_back(skey[i]); |  |  |  |         tkey.push_back(skey[i]);// 获取选项名
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         if (pr_->find(tkey) == pr_->end()) { |  |  |  |         if (pr_->find(tkey) == pr_->end()) { // 如果选项名在 pr_ 中不存在
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |           return false; |  |  |  |           return false; | 
			
		
	
		
		
			
				
					
					|  |  |  |         } |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |       } |  |  |  |       } | 
			
		
	
		
		
			
				
					
					|  |  |  |       return true; |  |  |  |       return true; | 
			
		
	
		
		
			
				
					
					|  |  |  |     } else { |  |  |  |     } else { | 
			
		
	
		
		
			
				
					
					|  |  |  |       // check single option, e.g., Parser::has("x")
 |  |  |  |       // 如果 skey 是一个单个选项,例如 "x"
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |       return pr_->find(skey) != pr_->end(); |  |  |  |       return pr_->find(skey) != pr_->end();// 检查选项是否在 pr_ 中存在
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  |   return false; |  |  |  |   return false;// 如果 pr_ 为空或 skey 为空,返回 false
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | //parser 类的 has_or 方法,它接受一个初始化列表 options,并检查 options 中的任何一个 key 是否在 pr_ 中存在。
 | 
			
		
	
		
		
			
				
					
					|  |  |  | bool Parser::has_or(std::initializer_list<const char*> options) { |  |  |  | bool Parser::has_or(std::initializer_list<const char*> options) { | 
			
		
	
		
		
			
				
					
					|  |  |  |   if (options.size() == 0) { |  |  |  |   if (options.size() == 0) {// 如果 options 为空
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     return false; |  |  |  |     return false; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   }4 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   for (auto key : options) {// 遍历 options 中的每个选项
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     if (this->has(key)) return true;// 如果选项在 pr_ 中存在,返回 true
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  |   for (auto key : options) { |  |  |  |   return false;// 如果 options 中的所有选项都不存在,返回 false
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     if (this->has(key)) return true; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   return false; |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | bool Parser::has_and(std::initializer_list<const char*> options) { |  |  |  | bool Parser::has_and(std::initializer_list<const char*> options) { // Parser 类的 has_and 方法,接受一个初始化列表 options
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   if (options.size() == 0) { |  |  |  |   if (options.size() == 0) {// 如果 options 为空
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     return false; |  |  |  |     return false; | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  |   for (auto key : options) { |  |  |  |   for (auto key : options) {// 遍历 options 中的每个选项
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     if (!this->has(key)) return false; |  |  |  |     if (!this->has(key)) return false;// 如果选项在 pr_ 中不存在,返回 false
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  |   return true; |  |  |  |   return true;// 如果 options 中的所有选项都存在,返回 true
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | bool Parser::init(const int argc, const char** argv) { |  |  |  | bool Parser::init(const int argc, const char** argv) { | 
			
		
	
		
		
			
				
					
					|  |  |  |   argc_ = argc; |  |  |  |   argc_ = argc;// 保存参数数量
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |   // argv_ = argv;
 |  |  |  |   // argv_ = argv;
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   // don't save it, point to a local var in parse(const char* command_line).
 |  |  |  |   // don't save it, point to a local var in parse(const char* command_line).
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   // use member var args_ instead.
 |  |  |  |   // use member var args_ instead.
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   if (argc > 0) { |  |  |  |   if (argc > 0) {// 如果参数数量大于 0
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     this->cleanup(); |  |  |  |     this->cleanup(); // 清理之前的解析结果
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     args_.reserve(static_cast<size_t>(argc_)); |  |  |  |     args_.reserve(static_cast<size_t>(argc_));// 为 args_ 预留空间
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     for (int i = 0; i < argc_; ++i) { |  |  |  |     for (int i = 0; i < argc_; ++i) {// 遍历所有的命令行参数
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |       args_.push_back(argv[i]); |  |  |  |       args_.push_back(argv[i]);// 将参数添加到 args_
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     pr_ = new Parser::ParseResult; |  |  |  |     pr_ = new Parser::ParseResult;// 创建新的解析结果
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     return true; |  |  |  |     return true; | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  |   return false; |  |  |  |   return false;// 如果参数数量为 0,返回 false
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | void Parser::cleanup() { |  |  |  | void Parser::cleanup() {// Parser 类的 cleanup 方法,用于清理解析结果
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   args_.clear(); |  |  |  |   args_.clear();// 清空 args_
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   if (pr_) { |  |  |  |   if (pr_) {// 如果 pr_ 不为空
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     auto ibegin = pr_->begin(); |  |  |  |     auto ibegin = pr_->begin(); | 
			
		
	
		
		
			
				
					
					|  |  |  |     auto iend = pr_->end(); |  |  |  |     auto iend = pr_->end(); | 
			
		
	
		
		
			
				
					
					|  |  |  |     auto it = ibegin; |  |  |  |     auto it = ibegin; | 
			
		
	
		
		
			
				
					
					|  |  |  |     for (; it != iend; ++it) { |  |  |  |     for (; it != iend; ++it) {// 遍历 pr_ 中的每个元素
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |       ParseItem* item = it->second; |  |  |  |       ParseItem* item = it->second; | 
			
		
	
		
		
			
				
					
					|  |  |  |       if (item) delete item; |  |  |  |       if (item) delete item;// 删除元素
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |     delete pr_; |  |  |  |     delete pr_;// 删除 pr_
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     pr_ = nullptr; |  |  |  |     pr_ = nullptr; | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | void Parser::set_addition() { |  |  |  | void Parser::set_addition() {// Parser 类的 set_addition 方法,用于处理额外的选项
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   if (subroutines_->find(subroutine_name_) != subroutines_->end()) { |  |  |  |   if (subroutines_->find(subroutine_name_) != subroutines_->end()) {// 如果子程序名在 subroutines_ 中存在
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     for (const Row& row : *(subroutines_->at(subroutine_name_))) { |  |  |  |     for (const Row& row : *(subroutines_->at(subroutine_name_))) {// 遍历子程序中的每一行
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |       // assume both -o and --option are allowed,
 |  |  |  |       // assume both -o and --option are allowed,
 | 
			
		
	
		
		
			
				
					
					|  |  |  |       // but only provide -o,
 |  |  |  |       // but only provide -o,
 | 
			
		
	
		
		
			
				
					
					|  |  |  |       // then set the another --option.
 |  |  |  |       // then set the another --option.
 | 
			
		
	
		
		
			
				
					
					|  |  |  |       // vice versa.
 |  |  |  |       // vice versa.
 | 
			
		
	
		
		
			
				
					
					|  |  |  |       const std::string& def = row.value(); |  |  |  |       const std::string& def = row.value();// 获取默认值
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |       const std::string& ops = row.oshort(); |  |  |  |       const std::string& ops = row.oshort();// 获取短选项
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |       const std::string& opl = row.olong(); |  |  |  |       const std::string& opl = row.olong();// 获取长选项
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |       ParseResult& pr = *pr_; |  |  |  |       ParseResult& pr = *pr_; // 获取解析结果
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |       bool has_short = this->has(ops.c_str()); |  |  |  |       bool has_short = this->has(ops.c_str());// 检查短选项是否存在
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |       bool has_long = this->has(opl.c_str()); |  |  |  |       bool has_long = this->has(opl.c_str());// 检查长选项是否存在
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |       // assume -o [ --option ] arg = 1
 |  |  |  |       // assume -o [ --option ] arg = 1
 | 
			
		
	
		
		
			
				
					
					|  |  |  |       // but not provide option value,
 |  |  |  |       // but not provide option value,
 | 
			
		
	
		
		
			
				
					
					|  |  |  |       // then set to default 1.
 |  |  |  |       // then set to default 1.
 | 
			
		
	
		
		
			
				
					
					|  |  |  |       // otherwise, both set to user defined value
 |  |  |  |       // otherwise, both set to user defined value
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |       if (!ops.empty()) { |  |  |  |       if (!ops.empty()) {// 如果短选项不为空
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         if (has_short) { |  |  |  |         if (has_short) {// 如果短选项存在
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |           if (pr[ops] != nullptr && !opl.empty()) { |  |  |  |           if (pr[ops] != nullptr && !opl.empty()) {// 如果短选项有值且长选项不为空
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |             pr[opl] = new ParseItem(std::move(pr[ops]->val())); |  |  |  |             pr[opl] = new ParseItem(std::move(pr[ops]->val()));// 将短选项的值赋给长选项
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |           } else if (pr[ops] == nullptr && !def.empty()) { |  |  |  |           } else if (pr[ops] == nullptr && !def.empty()) {// 如果短选项没有值且默认值不为空
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |             pr[ops] = new ParseItem(std::move(def)); |  |  |  |             pr[ops] = new ParseItem(std::move(def));// 将默认值赋给短选项
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |             if (!opl.empty()) pr[opl] = new ParseItem(std::move(def)); |  |  |  |             if (!opl.empty()) pr[opl] = new ParseItem(std::move(def));// 如果长选项不为空,也将默认值赋给长选项
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |           } else { |  |  |  |           } else { | 
			
		
	
		
		
			
				
					
					|  |  |  |             pr[opl] = nullptr; |  |  |  |             pr[opl] = nullptr;// 将长选项的值设为 nullptr
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |           } |  |  |  |           } | 
			
		
	
		
		
			
				
					
					|  |  |  |         } |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |       } |  |  |  |       } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |       if (!opl.empty()) { |  |  |  |       if (!opl.empty()) {// 如果长选项不为空
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         if (has_long) { |  |  |  |         if (has_long) { // 如果长选项存在
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |           if (pr[opl] != nullptr && !ops.empty()) { |  |  |  |           if (pr[opl] != nullptr && !ops.empty()) { // 如果长选项有值且短选项不为空
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |             pr[ops] = new ParseItem(std::move(pr[opl]->val())); |  |  |  |             pr[ops] = new ParseItem(std::move(pr[opl]->val()));// 将长选项的值赋给短选项
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |           } else if (pr[opl] == nullptr && !def.empty()) { |  |  |  |           } else if (pr[opl] == nullptr && !def.empty()) {// 如果长选项没有值且默认值不为空
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |             if (!ops.empty()) pr[ops] = new ParseItem(std::move(def)); |  |  |  |             if (!ops.empty()) pr[ops] = new ParseItem(std::move(def));// 如果短选项不为空,将默认值赋给短选项
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |             pr[opl] = new ParseItem(std::move(def)); |  |  |  |             pr[opl] = new ParseItem(std::move(def));// 将默认值赋给长选项
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |           } else { |  |  |  |           } else { | 
			
		
	
		
		
			
				
					
					|  |  |  |             pr[ops] = nullptr; |  |  |  |             pr[ops] = nullptr;// 将短选项的值设为 nullptr
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |           } |  |  |  |           } | 
			
		
	
		
		
			
				
					
					|  |  |  |         } |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |       } |  |  |  |       } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |       if (!has_long && !has_short && !def.empty()) { |  |  |  |       if (!has_long && !has_short && !def.empty()) {// 如果长选项和短选项都不存在且默认值不为
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         if (!opl.empty()) pr[opl] = new ParseItem(std::move(def)); |  |  |  |         if (!opl.empty()) pr[opl] = new ParseItem(std::move(def));// 如果长选项不为空,将默认值赋给长选项
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         if (!ops.empty()) pr[ops] = new ParseItem(std::move(def)); |  |  |  |         if (!ops.empty()) pr[ops] = new ParseItem(std::move(def));// 如果短选项不为空,将默认值赋给短选项
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |       } |  |  |  |       } | 
			
		
	
		
		
			
				
					
					|  |  |  |     }  // for
 |  |  |  |     }  // for
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   }    // if
 |  |  |  |   }    // if
 | 
			
		
	
	
		
		
			
				
					|  |  | @ -427,114 +433,115 @@ void Parser::set_addition() { | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | // class Row
 |  |  |  | // class Row
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | Row::Row() : require_value(true) {} |  |  |  | Row::Row() : require_value(true) {} // Row 类的构造函数,初始化 require_value 为 true
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | // class Subroutine
 |  |  |  | // class Subroutine
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | Subroutine::Subroutine() : first_line_("") {} |  |  |  | Subroutine::Subroutine() : first_line_("") {}// Subroutine 类的默认构造函数,初始化 first_line_ 为空字符串
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | Subroutine::Subroutine(const char* name, const char* description) |  |  |  | Subroutine::Subroutine(const char* name, const char* description) | 
			
		
	
		
		
			
				
					
					|  |  |  |     : first_line_(""), description_(description), name_(name) { |  |  |  |     : first_line_(""), description_(description), name_(name) { // Subroutine 类的构造函数,接受子程序名和描述作为参数
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   usages_.reserve(5); |  |  |  |   usages_.reserve(5);// 为 usages_ 预留空间
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | void Subroutine::print_with_row(std::ostream& out) { |  |  |  | void Subroutine::print_with_row(std::ostream& out) {// Subroutine 类的 print_with_row 方法,接受一个输出流作为参数
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |   // print the subroutine name and its description
 |  |  |  |   // print the subroutine name and its description
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   if (strcmp(get_first_line(), "") != 0) { |  |  |  |   // 打印子程序名和描述
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   if (strcmp(get_first_line(), "") != 0) {// 如果 first_line_ 不为空
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     // print the first line
 |  |  |  |     // print the first line
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     out << get_first_line(); |  |  |  |     out << get_first_line(); | 
			
		
	
		
		
			
				
					
					|  |  |  |     if (!usages_.empty()) { |  |  |  |     if (!usages_.empty()) {// 如果 usages_ 不为空
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |       out << std::endl; |  |  |  |       out << std::endl;// 打印换行符
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  |   auto begin = usages_.begin(); |  |  |  |   auto begin = usages_.begin(); // 获取 usages_ 的开始迭代器
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   auto end = usages_.end(); |  |  |  |   auto end = usages_.end();// 获取 usages_ 的结束迭代器
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   std::vector<std::string> row_list; |  |  |  |   std::vector<std::string> row_list;// 创建一个字符串向量用于存储行
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   row_list.reserve(usages_.size()); |  |  |  |   row_list.reserve(usages_.size());// 为 row_list 预留空间
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   // build usage rows without description field,
 |  |  |  |   // build usage rows without description field,
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   // find the max-len row at the same time.
 |  |  |  |   // find the max-len row at the same time.
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   size_t max_len = 0; |  |  |  |   size_t max_len = 0; | 
			
		
	
		
		
			
				
					
					|  |  |  |   std::for_each(begin, end, [&max_len, &row_list](const Row& row) { |  |  |  |   std::for_each(begin, end, [&max_len, &row_list](const Row& row) {// 遍历 usages_
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     std::stringstream ss; |  |  |  |     std::stringstream ss;// 创建一个字符串流
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     ss << "  "; |  |  |  |     ss << "  ";// 向字符串流中添加两个空格
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     if (!row.oshort().empty()) { |  |  |  |     if (!row.oshort().empty()) {// 如果短选项不为空
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |       ss << "-" << row.oshort() << " "; |  |  |  |       ss << "-" << row.oshort() << " "; // 添加短选项
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |     if (!row.olong().empty()) { |  |  |  |     if (!row.olong().empty()) {// 如果长选项不为空
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |       if (!row.oshort().empty()) |  |  |  |       if (!row.oshort().empty()) | 
			
		
	
		
		
			
				
					
					|  |  |  |         ss << "[ --" << row.olong() << " ] "; |  |  |  |         ss << "[ --" << row.olong() << " ] ";// 添加长选项
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |       else |  |  |  |       else | 
			
		
	
		
		
			
				
					
					|  |  |  |         ss << "--" << row.olong() << " "; |  |  |  |         ss << "--" << row.olong() << " "; // 添加长选项
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     if (row.required()) { |  |  |  |     if (row.required()) {// 如果选项是必需的
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |       ss << "arg "; |  |  |  |       ss << "arg "; // 添加 "arg "
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |       if (!row.value().empty()) { |  |  |  |       if (!row.value().empty()) {// 如果选项值不为空
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         ss << "= " << row.value() << " "; |  |  |  |         ss << "= " << row.value() << " ";// 添加选项值
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |       } |  |  |  |       } | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     max_len = std::max(max_len, ss.str().size()); |  |  |  |     max_len = std::max(max_len, ss.str().size());// 更新最大长度
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     row_list.push_back(std::move(ss.str())); |  |  |  |     row_list.push_back(std::move(ss.str()));// 将字符串流的内容添加到 row_list
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |   }); |  |  |  |   }); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   // show all rows and align description field
 |  |  |  |   // show all rows and align description field
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   size_t row_count = usages_.size(); |  |  |  |   size_t row_count = usages_.size();// 获取 usages_ 的大小
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   for (size_t i = 0; i < row_count; ++i) { |  |  |  |   for (size_t i = 0; i < row_count; ++i) {// 遍历 usages_
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     std::string str_row(std::move(row_list[i])); |  |  |  |     std::string str_row(std::move(row_list[i]));// 获取当前行
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     // print row without description
 |  |  |  |     // print row without description
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     out << str_row; |  |  |  |     out << str_row;// 打印当前行
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     // print spaces
 |  |  |  |     // print spaces
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     size_t spaces = 0; |  |  |  |     size_t spaces = 0;// 打印空格
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     size_t len = str_row.size(); |  |  |  |     size_t len = str_row.size();// 获取当前行的长度
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     if (max_len > len) spaces = max_len - len; |  |  |  |     if (max_len > len) spaces = max_len - len;// 计算需要打印的空格数量
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     while (spaces--) { |  |  |  |     while (spaces--) {// 打印空格
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |       out << " "; |  |  |  |       out << " "; | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |     // print description
 |  |  |  |     // print description
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     out << usages_.at(i).desc() << std::endl; |  |  |  |     out << usages_.at(i).desc() << std::endl;// 打印描述
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | void Subroutine::print_with_template(std::ostream& out) { |  |  |  | void Subroutine::print_with_template(std::ostream& out) {// Subroutine 类的 print_with_template 方法,接受一个输出流作为参数
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   for (auto usage : usages_) { |  |  |  |   for (auto usage : usages_) {// 遍历 usages_
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     size_t i = 0; |  |  |  |     size_t i = 0; | 
			
		
	
		
		
			
				
					
					|  |  |  |     for (auto t = template_str_.begin(); t != template_str_.end(); ++t) { |  |  |  |     for (auto t = template_str_.begin(); t != template_str_.end(); ++t) {// 遍历模板字符串
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |       if (*t == '%') { |  |  |  |       if (*t == '%') {// 如果当前字符是 '%'
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         switch (*(order_.begin() + i)) { |  |  |  |         switch (*(order_.begin() + i)) { // 根据 order_ 中的值决定打印哪个字段
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |           case Row::kShort: |  |  |  |           case Row::kShort: | 
			
		
	
		
		
			
				
					
					|  |  |  |             out << usage.oshort(); |  |  |  |             out << usage.oshort();// 打印短选项
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |             break; |  |  |  |             break; | 
			
		
	
		
		
			
				
					
					|  |  |  |           case Row::kLong: |  |  |  |           case Row::kLong: | 
			
		
	
		
		
			
				
					
					|  |  |  |             out << usage.olong(); |  |  |  |             out << usage.olong();// 打印长选项
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |             break; |  |  |  |             break; | 
			
		
	
		
		
			
				
					
					|  |  |  |           case Row::kDefault: |  |  |  |           case Row::kDefault: | 
			
		
	
		
		
			
				
					
					|  |  |  |             out << usage.value(); |  |  |  |             out << usage.value();// 打印默认值
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |             break; |  |  |  |             break; | 
			
		
	
		
		
			
				
					
					|  |  |  |           case Row::kDescription: |  |  |  |           case Row::kDescription: | 
			
		
	
		
		
			
				
					
					|  |  |  |             out << usage.desc(); |  |  |  |             out << usage.desc();// 打印描述
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |             break; |  |  |  |             break; | 
			
		
	
		
		
			
				
					
					|  |  |  |           default: |  |  |  |           default: | 
			
		
	
		
		
			
				
					
					|  |  |  |             break; |  |  |  |             break; | 
			
		
	
		
		
			
				
					
					|  |  |  |         } |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |         ++i; |  |  |  |         ++i; | 
			
		
	
		
		
			
				
					
					|  |  |  |       } else { |  |  |  |       } else { | 
			
		
	
		
		
			
				
					
					|  |  |  |         out << *t; |  |  |  |         out << *t;// 如果当前字符不是 '%',直接打印
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |       }  // if %
 |  |  |  |       }  // if %
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     }    // for template_str_
 |  |  |  |     }    // for template_str_
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     out << std::endl; |  |  |  |     out << std::endl;// 打印换行符
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |   }  // for usages_
 |  |  |  |   }  // for usages_
 | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | std::ostream& operator<<(std::ostream& out, Subroutine& subroutine) { |  |  |  | std::ostream& operator<<(std::ostream& out, Subroutine& subroutine) {// 重载 << 运算符,接受一个输出流和一个 Subroutine 对象作为参数
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   if (subroutine.template_str_.empty()) { |  |  |  |   if (subroutine.template_str_.empty()) {// 如果模板字符串为空
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     subroutine.print_with_row(out); |  |  |  |     subroutine.print_with_row(out);// 使用 print_with_row 方法打印
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |   } else { |  |  |  |   } else { | 
			
		
	
		
		
			
				
					
					|  |  |  |     subroutine.print_with_template(out); |  |  |  |     subroutine.print_with_template(out);// 使用 print_with_template 方法打印
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  |   return out; |  |  |  |   return out;// 返回输出流
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } |