aboutsummaryrefslogtreecommitdiffstats
path: root/meowpp/Usage.h
diff options
context:
space:
mode:
Diffstat (limited to 'meowpp/Usage.h')
-rw-r--r--meowpp/Usage.h200
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;
}
};