diff options
Diffstat (limited to 'meowpp/Usage.h')
-rw-r--r-- | meowpp/Usage.h | 200 |
1 files changed, 106 insertions, 94 deletions
diff --git a/meowpp/Usage.h b/meowpp/Usage.h index 4537202..f0d2fc5 100644 --- a/meowpp/Usage.h +++ b/meowpp/Usage.h @@ -5,18 +5,14 @@ #include <cstdlib> +#include <algorithm> #include <string> #include <vector> #include <map> -#include <algorithm> - -extern "C" { -#include <unistd.h> -} namespace meow { /*! - * @brief 管理參數設置, 自訂usage document, 分析argc, argv + * @brief 管理參數設置, 自訂usage document, 分析argc, argv * * \b Usage 是用來分析argc, argv和輸出usage document的class. \n * argc, argv的部份, 有以下規則 @@ -34,11 +30,10 @@ private: //! 存 (value, description) class Value { private: - String value_; + String value_; String description_; public: - Value() { - } + Value() { } Value(String const& value, String const& description) { value_ = value; description_ = stringReplace(description, "<value>", value); @@ -70,12 +65,12 @@ private: Option() { } Option(String const& description) { - has_setup_ = false; - has_value_ = false; + has_setup_ = false; + has_value_ = false; description_ = description; - must_setup_ = false; + must_setup_ = false; } - Option(String const& description, + Option(String const& description, String const& type, String const& default_value, bool must) { @@ -110,31 +105,32 @@ private: bool valueAcceptAdd(String const& value, String const& description) { if (!has_value_) return false; if (std::find(values_accept_.begin(), values_accept_.end(), - Value(value, "")) == values_accept_.end()){ + Value(value, "")) == values_accept_.end()) { values_accept_.push_back(Value(value, description)); } return true; } - bool valueAcceptChk(String const& value){ + bool valueAcceptChk(String const& value) { if (!has_value_) return false; - if (values_accept_.size() == 0) return true; - return (std::find(values_accept_.begin(), values_accept_.end(), + return (values_accept_.empty() || + std::find(values_accept_.begin(), values_accept_.end(), Value(value, "")) != values_accept_.end()); } bool hasSetup() const{ return has_setup_; } bool hasValue() const{ return has_value_; } bool chkSetup() const{ return !(must_setup_ && !has_setup_); } - String usage(unsigned char opt, bool detail) const { - String ret(stringPrintf("-%c ", opt)); + String usage(String opt, bool detail) const { + String ret(stringPrintf("%s%s ", (opt.size()>1 ? "--":"-"), opt.c_str())); if (!detail) { if (has_value_) ret += value_type_; if (!must_setup_) ret = "[" + ret + "]"; - } else { + } + else { if (has_value_) { ret += value_type_ + " "; String default_string(""); - if (value_default_ != "") + if (value_default_ != "") default_string = "defalut='" + value_default_ + "'"; String optional_string(""); if (!must_setup_) @@ -143,7 +139,8 @@ private: if (default_string.size() + optional_string.size() > 0) { if (default_string.size() > 0 && optional_string.size() > 0) { ret += "(" + optional_string + ", " + default_string + ")"; - } else { + } + else { ret += "(" + optional_string + default_string + ")"; } } @@ -152,8 +149,7 @@ private: String accept_string; for (size_t i = 0; i < values_accept_.size(); i++) { if (i > 0) - accept_string += (i + 1 < values_accept_.size() - ? ", " : " or "); + accept_string += (i + 1 < values_accept_.size() ? ", " : " or "); accept_string += "'" + values_accept_[i].value() + "'"; } if (accept_string.size() == 0) accept_string = "... (anything)"; @@ -170,12 +166,14 @@ private: return ret; } }; - typedef std::map<unsigned char, Option> Options; - typedef Options::const_iterator OptionsIterator; - String name_; - Options options_; - Strings usage_begin_; - Strings usage_end_; + typedef std::map<String, Option> Options; + typedef Options:: iterator OptionsIterator; + typedef Options::const_iterator OptionsIteratorK; + + String name_; + Options options_; + Strings usage_begin_; + Strings usage_end_; Strings proc_arguments_; public: /*! @@ -216,14 +214,14 @@ public: * @return \c true/false 表示 \b 是否成功 */ bool import(Usage const& usage) { - for (OptionsIterator + for (OptionsIteratorK it = usage.options_.begin(); it != usage.options_.end(); ++it) { if (options_.find(it->first) != options_.end()) return false; } - for (OptionsIterator + for (OptionsIteratorK it = usage.options_.begin(); it != usage.options_.end(); ++it) { - options_[it->first] = it->second; + options_.insert(std::pair<String, Option>(it->first, it->second)); } for (size_t i = 0; i < usage.usage_begin_.size(); ++i) usage_begin_.push_back(usage.usage_begin_[i]); @@ -239,11 +237,12 @@ public: * @return \c true/false 表 \b 是否成功 */ bool update(Usage const& usage) { - for (OptionsIterator + for (OptionsIteratorK it = usage.options_.begin(); it != usage.options_.end(); ++it) { - if (options_.find(it->first) == options_.end()) continue; - for(size_t i = 0, I = it->second.values().size(); i < I; i++){ - options_[it->first].valueAdd(it->second.value(i)); + OptionsIterator my = options_.find(it->first); + if (my == options_.end()) continue; + for (size_t i = 0, I = it->second.values().size(); i < I; ++i) { + my->second.valueAdd(it->second.value(i)); } } return true; @@ -256,9 +255,9 @@ public: * @param [in] des 即description, 用來解釋這個選項的意義用的 * @return \c true/false 表 \b 是否成功 */ - bool optionAdd(unsigned char opt, String const& des) { + bool optionAdd(String opt, String const& des) { if (options_.find(opt) != options_.end()) return false; - options_[opt] = Option(des); + options_.insert(std::pair<String, Option>(opt, Option(des))); return true; } @@ -272,12 +271,13 @@ public: * @param [in] must 表示是否一定要設定 * @return \c true/false 表 \b 是否成功 */ - bool optionAdd(unsigned char opt, String const& des, + bool optionAdd(String opt, String const& des, String const& val_type, String const& val_default, bool must) { if (options_.find(opt) != options_.end()) return false; - options_[opt] = Option(des, val_type, val_default, must); + options_.insert(std::pair<String, Option>( + opt, Option(des, val_type, val_default, must))); return true; } @@ -289,11 +289,10 @@ public: * @param [in] des 關於此額外選項的說明 * @return \c true/false 表 \b 是否成功 */ - bool optionValueAcceptAdd(unsigned char opt, - String const& val, - String const& des) { - if (options_.find(opt) == options_.end()) return false; - return options_[opt].valueAcceptAdd(val, des); + bool optionValueAcceptAdd(String opt, String const& val, String const& des) { + OptionsIterator o = options_.find(opt); + if (o == options_.end()) return false; + return o->second.valueAcceptAdd(val, des); } /*! @@ -302,9 +301,9 @@ public: * @param [in] opt 指定字符 * @return \c true/false 表 \b 是否有設定此選項 */ - bool hasOptionSetup(unsigned char opt) const { - return (options_.find(opt) != options_.end() && - options_.find(opt)->second.hasSetup()); + bool hasOptionSetup(String opt) const { + OptionsIteratorK o = options_.find(opt); + return (o != options_.end() && o->second.hasSetup()); } /*! @@ -313,9 +312,10 @@ public: * @param [in] opt 指定字符 * @return 回傳次數 */ - size_t optionValuesSize(unsigned char opt) const { - if(options_.find(opt) == options_.end()) return 0; - return options_.find(opt)->second.values().size(); + size_t optionValuesSize(String opt) const { + OptionsIteratorK o = options_.find(opt); + if (o == options_.end()) return 0; + return o->second.values().size(); } /*! @@ -325,11 +325,10 @@ public: * @param [in] index 第幾個 * @return 回傳參數 \b -(opt) 的第 \b index 個額外選項 */ - String optionValue(unsigned char opt, size_t index) const { - if (options_.find(opt) == options_.end()) { - return String(); - } - return options_.find(opt)->second.value(index); + String optionValue(String opt, size_t index) const { + OptionsIteratorK o = options_.find(opt); + if (o == options_.end()) return String(); + return o->second.value(index); } /*! @@ -386,16 +385,16 @@ public: * * @return \b usage \b string */ - String usage() const{ + String usage() const { Usage::String out = stringPrintf("USAGE\n %s", name_.c_str()); - for (OptionsIterator + for (OptionsIteratorK it = options_.begin(); it != options_.end(); ++it) out += " " + it->second.usage(it->first, false); out += "\n\nDESCRIPTION\n"; for (size_t i = 0; i < usage_begin_.size(); ++i) { out += " " + usage_begin_[i] + "\n\n"; } - for (OptionsIterator + for (OptionsIteratorK it = options_.begin(); it != options_.end(); ++it) { out += it->second.usage(it->first, true); } @@ -407,52 +406,65 @@ public: /*! * @brief 給定argc, argv, 將各參數設置 - * @param [in] argc,argv + * @param [in] argc,argv * @param [out] errmsg 將錯誤訊息寫到這裡 * (若給定NULL pointer, 則會把錯誤訊息忽略) * @return \c true/false \b 成功與否 (否的話代表有錯誤的設定值在其中) */ - bool arguments(int argc, char** argv, String* errmsg){ - opterr = 0; - String s; - OptionsIterator it; - String zzz; + bool arguments(int argc, char** argv, String* errmsg) { + String zzz; String& err = (errmsg == NULL ? zzz : *errmsg); - for (it = options_.begin(); it != options_.end(); ++it) { - s += (char)(it->first); - if (it->second.hasValue()) s += ":"; - } - bool succ = true; - 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); + for (int i = 0; i < argc; ++i) { + if (argv[i][0] == '-') { + String opt; + if (argv[i][1] == '-') { // long option + if (argv[i][2] == '\0' || argv[i][3] == '\0') { + err = stringPrintf("Invalid option '%s'", argv[i]); + return false; + } + opt = String(argv[i] + 2); + } + else { // short option + if (argv[i][1] == '\0' || argv[i][2] != '\0') { + err = stringPrintf("Invalid option '%s'", argv[i]); + return false; + } + opt = String(argv[i] + 1); + } + OptionsIterator o = options_.find(opt); + if (o == options_.end()) { + err = stringPrintf("Unknown option '%s'", argv[i]); + return false; + } + if (o->second.hasValue()) { + if (i + 1 >= argc) { + err = stringPrintf("Option '%s' need a value", argv[i]); + return false; + } + if (o->second.valueAdd(argv[i + 1]) < 0) { + err = stringPrintf("Invalid value '%s' of options '%s'", + argv[i + 1], argv[i]); + return false; + } + ++i; + } + else { + o->second.valueAdd(""); } - succ = false; - continue; } - if (options_[opt].valueAdd(optarg == NULL ? "" : optarg) < 0) { - err += stringPrintf("Option argument '%s' to '-%c' is not allowed\n" - , optarg, opt); - succ = false; - continue; + else { + proc_arguments_.push_back(String(argv[i] + (argv[i][0]=='\\' ? 1:0))); } } - for (it = options_.begin(); it != options_.end(); it++) { + for (OptionsIteratorK it = options_.begin(); it != options_.end(); ++it) { if (it->second.chkSetup() == false) { - err += stringPrintf("No specify argument to '-%c'\n", - it->first); - succ = false; - continue; + err += stringPrintf("No specify argument to '%s%s'\n", + (it->first.size() > 1 ? "--" : "-"), + it->first.c_str()); + return false; } } - for (int i = optind; i < argc; i++) { - proc_arguments_.push_back(String(argv[i])); - } - return succ; + return true; } }; |