#include #include #include #include #include #include "utility.h" extern "C"{ #include } namespace meow{ inline Usage::Usage(): name("nobody") { } inline Usage::Usage(Usage::String const& _name): name(_name){ } inline bool Usage::import(Usage const& usage){ OptionsIterator it; for(it = usage.options.begin(); it != usage.options.end(); it++){ unsigned char const& chr = it->first; Option const& opt = it->second; if(options.find(chr) == options.end()){ options[chr] = opt; }else{ return false; } } for(size_t i = 0; i < usage.usage_begin.size(); i++){ usage_begin.push_back(usage.usage_begin[i]); } for(size_t i = 0; i < usage.usage_end.size(); i++){ usage_end.push_back(usage.usage_end[i]); } return true; } inline bool Usage::update(Usage const& usage){ OptionsIterator it; for(it = usage.options.begin(); it != usage.options.end(); it++){ unsigned char const& chr = it->first; if(options.find(chr) == options.end()){ continue; } options[chr] = it->second; } return true; } inline bool Usage::addOption(unsigned char opt, Usage::String const& des){ if(options.find(opt) != options.end()){ return false; } options[opt] = Option(des); return true; } inline bool Usage::addOption(unsigned char opt, Usage::String const& des, Usage::String const& val_type, Usage::String const& val_default, bool must){ if(options.find(opt) != options.end()){ return false; } options[opt] = Option(des, val_type, val_default, must); return true; } inline bool Usage::addOptionValueAccept(unsigned char opt, Usage::String const& val, Usage::String const& des){ if(options.find(opt) == options.end()){ return false; } return options[opt].addValueAccept(val, des); } inline bool Usage::hasOptionSetup(unsigned char opt) const { return (options.find(opt) != options.end() && options.find(opt)->second.hasSetup()); } inline size_t Usage::getOptionValuesCount(unsigned char opt) const { if(options.find(opt) == options.end()){ return 0; } return options.find(opt)->second.getValuesCount(); } inline Usage::String Usage::getOptionValue(unsigned char opt, size_t index) const { if(options.find(opt) == options.end()){ return Usage::String(); } return options.find(opt)->second.getValue(index); } inline size_t Usage::getProcArgsCount() const{ return proc_arguments.size(); } inline Usage::String Usage::getProcArg(size_t index) const { if(index >= proc_arguments.size()){ return Usage::String(); } return proc_arguments[index]; } inline Usage::Strings Usage::getProcArgs() const { return proc_arguments; } inline void Usage::addUsageBegin(Usage::String const& des){ usage_begin.push_back(stringReplace(des, "", name)); } inline void Usage::addUsageEnd(Usage::String const& des){ usage_end.push_back(stringReplace(des, "", name)); } inline Usage::String Usage::getUsage() const { Usage::String out = stringPrintf("USAGE\n %s", name.c_str()); OptionsIterator it; for(it = options.begin(); it != options.end(); it++){ out += " " + it->second.getUsage(it->first, false); } out += "\n\nDESCRIPTION\n"; for(size_t i = 0; i < usage_begin.size(); i++){ out += " " + usage_begin[i] + "\n\n"; } for(it = options.begin(); it != options.end(); it++){ out += it->second.getUsage(it->first, true); } for(size_t i = 0; i < usage_end.size(); i++){ out += " " + usage_end[i] + "\n\n"; } return out; } inline bool Usage::setArguments(int argc, char** argv, Usage::String *errmsg){ opterr = 0; Usage::String s; OptionsIterator it; Usage::String zzz; Usage::String& err = (errmsg == NULL ? zzz : *errmsg); for(it = options.begin(); it != options.end(); it++){ s += (char)(it->first); if(it->second.hasValue()){ s += ":"; } } for(int opt; (opt = getopt(argc, argv, s.c_str())) != -1; ){ if(options.find(opt) == options.end()){ if(options.find(optopt) == options.end()){ err += stringPrintf("Unknown option '-%c'\n", optopt); }else{ err += stringPrintf("No specify argument to '-%c'\n", optopt); } opt = optopt; return false; } if(options[opt].setValue(optarg == NULL ? "" : optarg) == false){ err += stringPrintf( "Option argument '%s' to '-%c' is not allowed\n" , optarg, opt); return false; } } for(it = options.begin(); it != options.end(); it++){ if(it->second.chkSetup() == false){ err += stringPrintf("No specify argument to '-%c'\n", it->first); return false; } } for(int i = optind; i < argc; i++){ proc_arguments.push_back(Usage::String(argv[i])); } return true; } // inline Usage::Value::Value(){ } inline Usage::Value::Value(Usage::String const& v){ value = v; description = ""; } inline Usage::Value::Value(Usage::String const& v, Usage::String const& d){ value = v; description = stringReplace(d, "", v); } inline Usage::String Usage::Value::getUsage() const { return stringPrintf("%8s%s : %s\n", " ", value.c_str(), description.c_str()); } inline Usage::String Usage::Value::getValue() const { return value; } inline bool Usage::Value::operator==(Value const& b) const { return (value == b.value); } // inline Usage::Option::Option(){ } inline Usage::Option::Option(Usage::String const& des){ has_setup = false; has_value = false; description = des; must_setup = false; } inline Usage::Option::Option(Usage::String const& des, Usage::String const& typ, Usage::String const& def, bool must){ has_setup = false; has_value = true; description = des; value_type = typ; value_default = def; must_setup = must; } inline bool Usage::Option::setValue(Usage::String const& str){ if(has_value){ if(values_accept.size() > 0 && std::find(values_accept.begin(), values_accept.end(), Value(str, "")) == values_accept.end()){ return false; } values.push_back(str); } has_setup = true; return true; } inline size_t Usage::Option::getValuesCount()const{return values.size();} inline Usage::String Usage::Option::getValue(size_t index) const{ if(!has_value){ return ""; } if(!has_setup || index >= values.size()){ return value_default; } return values[index]; } inline bool Usage::Option::addValueAccept(Usage::String const& val, Usage::String const& des){ if(!has_value){ return false; } if(std::find(values_accept.begin(), values_accept.end(), Value(val)) == values_accept.end()){ values_accept.push_back(Value(val, des)); } return true; } inline bool Usage::Option::hasSetup() const { return has_setup; } inline bool Usage::Option::hasValue() const { return has_value; } inline bool Usage::Option::chkSetup() const { return !(must_setup && !has_setup); } inline Usage::String Usage::Option::getUsage(unsigned char opt, bool detail) const { Usage::String ret; if(!detail){ if(!has_value){ ret = stringPrintf("-%c", opt); }else{ ret = stringPrintf("-%c %s", opt, value_type.c_str()); } if(!must_setup){ ret = stringPrintf("[%s]", ret.c_str()); } }else{ Usage::String tmp; if(has_value){ Usage::String tmp2; if(value_default != ""){ tmp2=stringPrintf("defuault='%s'",value_default.c_str()); } Usage::String tmp3 = must_setup ? "" : "optional"; if(tmp2.length() + tmp3.length() > 0){ if(tmp2.length() > 0 && tmp3.length() > 0){ tmp = "(" + tmp3 + ", " + tmp2 + ")"; }else{ tmp = "(" + tmp3 + tmp2 + ")"; } } tmp = value_type + " " + tmp; } ret = stringPrintf(" -%c %s\n", opt, tmp.c_str()); tmp = stringReplace(description, "", value_type); Usage::String vs; for(size_t i = 0; i < values_accept.size(); i++){ if(i > 0){ vs += (i + 1 < values_accept.size() ? ", " : " or "); } vs += "'" + values_accept[i].getValue() + "'"; } if(vs.length() == 0){ vs = "... (anything)"; } tmp = stringReplace(tmp, "", vs); ret += " " + tmp + "\n"; for(size_t i = 0; i < values_accept.size(); i++){ ret += values_accept[i].getUsage(); } ret += "\n"; } return ret; } }