summaryrefslogblamecommitdiffstatshomepage
path: root/src/lib/netlist/plib/poptions.cpp
blob: 910660acb3de82f5526b7d04e4257a2557cd040d (plain) (tree)
1
2
3
4
5
6
7
8
9
10









                               



                                                                            

                                                               



                                             



                                   







                                         
                                                                                                       

                                                                    


         



                         
                                                      




                                 
                                                            









                                                                 
                                                       




                             
                                                         





                                                 






                                                       
                                                      





                                          

                          
















                                               
                                                       





                                                  
                                                        


                                       
                                                            





                                                   
                                                                   

                                                               





                                                                                   


                                                     

                                                                     
                                    
                                                     

                                                             
                                                                
                                 

                            
                         
                                         
                         





                                                  
                                                                        




                                                                                
                                                                                                






                                                             
                                                  





                            

                                                                                        
         
                                                    



                                          
                                                                               
                                                      
                         
                                                                       

                                                           
                                                                             








                                                                 
                                                        



                                                                        
                                                               
 
                                              
                 
                                                                       
                         



                                                                         
                                 





                                                                       
                                         


                                                                                                             
                                                 



                                                                                   
                                                                                            
                                                 

                                                                        
                                         
                                 
                                                                         
                                                           






                                                                                                      
                         
                                                                                  
                         

                                                                                                                
                         









                                                                                            
                                    

                                                        





                                                  
                                             
                 

                                                                   





                                                 
                                             
                 

                                                                   





                                           
 
// license:GPL-2.0+
// copyright-holders:Couriersud
/*
 * poptions.cpp
 *
 */

#include "poptions.h"

namespace plib {
/***************************************************************************
    Options
***************************************************************************/

	option_base::option_base(options &parent, pstring help)
	: m_help(help)
	{
		parent.register_option(this);
	}

	option_base::~option_base()
	{
	}

	option_group::~option_group()
	{
	}

	option_example::~option_example()
	{
	}

	option::option(options &parent, pstring ashort, pstring along, pstring help, bool has_argument)
	: option_base(parent, help), m_short(ashort), m_long(along),
	  m_has_argument(has_argument), m_specified(false)
	{
	}

	option::~option()
	{
	}

	int option_str::parse(const pstring &argument)
	{
		m_val = argument;
		return 0;
	}

	int option_str_limit::parse(const pstring &argument)
	{
		if (plib::container::contains(m_limit, argument))
		{
			m_val = argument;
			return 0;
		}
		else
			return 1;
	}

	int option_bool::parse(const pstring &argument)
	{
		m_val = true;
		return 0;
	}

	int option_double::parse(const pstring &argument)
	{
		bool err = false;
		m_val = argument.as_double(&err);
		return (err ? 1 : 0);
	}

	int option_long::parse(const pstring &argument)
	{
		bool err = false;
		m_val = argument.as_long(&err);
		return (err ? 1 : 0);
	}

	int option_vec::parse(const pstring &argument)
	{
		bool err = false;
		m_val.push_back(argument);
		return (err ? 1 : 0);
	}

	options::options()
	{
	}

	options::options(option *o[])
	{
		int i=0;
		while (o[i] != nullptr)
		{
			m_opts.push_back(o[i]);
			i++;
		}
	}

	options::~options()
	{
		m_opts.clear();
	}

	void options::register_option(option_base *opt)
	{
		m_opts.push_back(opt);
	}

	int options::parse(int argc, char *argv[])
	{
		m_app = pstring(argv[0], pstring::UTF8);

		for (int i=1; i<argc; )
		{
			pstring arg(argv[i], pstring::UTF8);
			option *opt = nullptr;
			pstring opt_arg;
			bool has_equal_arg = false;

			if (arg.startsWith("--"))
			{
				auto v = psplit(arg.substr(2),"=");
				opt = getopt_long(v[0]);
				has_equal_arg = (v.size() > 1);
				if (has_equal_arg)
				{
					for (unsigned j = 1; j < v.size() - 1; j++)
						opt_arg = opt_arg + v[j] + "=";
					opt_arg += v[v.size()-1];
				}
			}
			else if (arg.startsWith("-"))
			{
				std::size_t p = 1;
				opt = getopt_short(arg.substr(p, 1));
				++p;
				if (p < arg.length())
				{
					has_equal_arg = true;
					opt_arg = arg.substr(p);
				}
			}
			else
			{
				return i;
			}
			if (opt == nullptr)
				return i;
			if (opt->has_argument())
			{
				if (has_equal_arg)
				{
					if (opt->do_parse(opt_arg) != 0)
						return i;
				}
				else
				{
					i++; // FIXME: are there more arguments?
					if (opt->do_parse(pstring(argv[i], pstring::UTF8)) != 0)
						return i - 1;
				}
			}
			else
			{
				if (has_equal_arg)
					return i;
				opt->do_parse("");
			}
			i++;
		}
		return argc;
	}

	pstring options::split_paragraphs(pstring text, unsigned width, unsigned indent,
			unsigned firstline_indent)
	{
		auto paragraphs = psplit(text,"\n");
		pstring ret("");

		for (auto &p : paragraphs)
		{
			pstring line = pstring("").rpad(" ", firstline_indent);
			for (auto &s : psplit(p, " "))
			{
				if (line.length() + s.length() > width)
				{
					ret += line + "\n";
					line = pstring("").rpad(" ", indent);
				}
				line += s + " ";
			}
			ret += line + "\n";
		}
		return ret;
	}

	pstring options::help(pstring description, pstring usage,
			unsigned width, unsigned indent)
	{
		pstring ret;

		ret = split_paragraphs(description, width, 0, 0) + "\n";
		ret += "Usage:\t" + usage + "\n\nOptions:\n\n";

		for (auto & optbase : m_opts )
		{
			if (auto opt = dynamic_cast<option *>(optbase))
			{
				pstring line = "";
				if (opt->short_opt() != "")
					line += "  -" + opt->short_opt();
				if (opt->long_opt() != "")
				{
					if (line != "")
						line += ", ";
					else
						line = "      ";
					line += "--" + opt->long_opt();
					if (opt->has_argument())
					{
						line += "=";
						option_str_limit *ol = dynamic_cast<option_str_limit *>(opt);
						if (ol)
						{
							for (auto &v : ol->limit())
							{
								line += v + "|";
							}
							line = line.left(line.length() - 1);
						}
						else
							line += "Value";
					}
				}
				line = line.rpad(" ", indent - 2) + "  ";
				if (line.length() > indent)
				{
					//ret += "TestGroup abc\n  def gef\nxyz\n\n" ;
					ret += line + "\n";
					ret += split_paragraphs(opt->help(), width, indent, indent);
				}
				else
					ret += split_paragraphs(line + opt->help(), width, indent, 0);
			}
			else if (auto grp = dynamic_cast<option_group *>(optbase))
			{
				ret += "\n" + grp->group() + ":\n";
				if (grp->help() != "") ret += split_paragraphs(grp->help(), width, 4, 4) + "\n";
			}
		}
		pstring ex("");
		for (auto & optbase : m_opts )
		{
			if (auto example = dynamic_cast<option_example *>(optbase))
			{
				ex += "> " + example->example()+"\n\n";
				ex += split_paragraphs(example->help(), width, 4, 4) + "\n";
			}
		}
		if (ex.length() > 0)
		{
			ret += "\n\nExamples:\n\n" + ex;
		}
		return ret;
	}

	option *options::getopt_short(pstring arg)
	{
		for (auto & optbase : m_opts)
		{
			auto opt = dynamic_cast<option *>(optbase);
			if (opt && opt->short_opt() == arg)
				return opt;
		}
		return nullptr;
	}
	option *options::getopt_long(pstring arg)
	{
		for (auto & optbase : m_opts)
		{
			auto opt = dynamic_cast<option *>(optbase);
			if (opt && opt->long_opt() == arg)
				return opt;
		}
		return nullptr;
	}

} // namespace plib