aboutsummaryrefslogtreecommitdiffstats
path: root/meowpp/Usage.hpp
diff options
context:
space:
mode:
authorcathook <b01902109@csie.ntu.edu.tw>2014-04-19 16:21:17 +0800
committercathook <b01902109@csie.ntu.edu.tw>2014-04-19 16:21:17 +0800
commite9a16c4ef0ea782d7db8d788c455ea946eaab039 (patch)
tree5728aa2076a13079f0ff7f162cfd4cab95e1db91 /meowpp/Usage.hpp
downloadmeow-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.hpp297
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;
+ }
+}
+