diff options
author | cathook <b01902109@csie.ntu.edu.tw> | 2014-04-19 16:21:17 +0800 |
---|---|---|
committer | cathook <b01902109@csie.ntu.edu.tw> | 2014-04-19 16:21:17 +0800 |
commit | e9a16c4ef0ea782d7db8d788c455ea946eaab039 (patch) | |
tree | 5728aa2076a13079f0ff7f162cfd4cab95e1db91 /meowpp/Usage.hpp | |
download | meow-e9a16c4ef0ea782d7db8d788c455ea946eaab039.tar meow-e9a16c4ef0ea782d7db8d788c455ea946eaab039.tar.gz meow-e9a16c4ef0ea782d7db8d788c455ea946eaab039.tar.bz2 meow-e9a16c4ef0ea782d7db8d788c455ea946eaab039.tar.lz meow-e9a16c4ef0ea782d7db8d788c455ea946eaab039.tar.xz meow-e9a16c4ef0ea782d7db8d788c455ea946eaab039.tar.zst meow-e9a16c4ef0ea782d7db8d788c455ea946eaab039.zip |
init
Diffstat (limited to 'meowpp/Usage.hpp')
-rw-r--r-- | meowpp/Usage.hpp | 297 |
1 files changed, 297 insertions, 0 deletions
diff --git a/meowpp/Usage.hpp b/meowpp/Usage.hpp new file mode 100644 index 0000000..40b933f --- /dev/null +++ b/meowpp/Usage.hpp @@ -0,0 +1,297 @@ +#include <string> +#include <vector> +#include <map> +#include <algorithm> +#include <cstdlib> + +#include "utility.h" + +extern "C"{ +#include <unistd.h> +} + +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>", name)); + } + inline void Usage::addUsageEnd(Usage::String const& des){ + usage_end.push_back(stringReplace(des, "<name>", 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, "<value>", v); + } + inline Usage::String Usage::Value::getUsage() const { + if(description.length() > 0) + return stringPrintf("%8s%s : %s\n", + " ", value.c_str(), description.c_str()); + else + return ""; + } + 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, "<type>", 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, "<values>", vs); + ret += " " + tmp + "\n"; + for(size_t i = 0; i < values_accept.size(); i++){ + ret += values_accept[i].getUsage(); + } + ret += "\n"; + } + return ret; + } +} + |