28 typedef std::string String;
29 typedef std::vector<String> Strings;
37 Value(String
const& value, String
const& description) {
41 String
usage()
const {
43 " ", value_.c_str(), description_.c_str());
45 String value()
const {
48 bool operator==(Value
const& b)
const {
49 return (value_ == b.value_);
52 typedef std::vector<Value> Values;
57 Values values_accept_;
58 String value_default_;
67 Option(String
const& description) {
70 description_ = description;
73 Option(String
const& description,
75 String
const& default_value,
79 description_ = description;
81 value_default_ = default_value;
84 Strings
const& values()
const {
87 String value(
size_t index)
const {
88 if (!has_value_)
return "";
89 if (!has_setup_ || index >= values_.size())
return value_default_;
90 return values_[index];
92 ssize_t valueAdd(String
const& value) {
97 if (values_accept_.size() > 0 &&
98 std::find(values_accept_.begin(), values_accept_.end(),
99 Value(value,
"")) == values_accept_.end())
101 values_.push_back(value);
103 return values_.size() - 1;
105 bool valueAcceptAdd(String
const& value, String
const& description) {
106 if (!has_value_)
return false;
107 if (std::find(values_accept_.begin(), values_accept_.end(),
108 Value(value,
"")) == values_accept_.end()) {
109 values_accept_.push_back(Value(value, description));
113 bool valueAcceptChk(String
const& value) {
114 if (!has_value_)
return false;
115 return (values_accept_.empty() ||
116 std::find(values_accept_.begin(), values_accept_.end(),
117 Value(value,
"")) != values_accept_.end());
119 bool hasSetup()
const{
return has_setup_; }
120 bool hasValue()
const{
return has_value_; }
121 bool chkSetup()
const{
return !(must_setup_ && !has_setup_); }
123 String
usage(String opt,
bool detail)
const {
124 String ret(
stringPrintf(
"%s%s ", (opt.size()>1 ?
"--":
"-"), opt.c_str()));
126 if (has_value_) ret += value_type_;
127 if (!must_setup_) ret =
"[" + ret +
"]";
131 ret += value_type_ +
" ";
132 String default_string(
"");
133 if (value_default_ !=
"")
134 default_string =
"defalut='" + value_default_ +
"'";
135 String optional_string(
"");
137 optional_string =
"optional";
139 if (default_string.size() + optional_string.size() > 0) {
140 if (default_string.size() > 0 && optional_string.size() > 0) {
141 ret +=
"(" + optional_string +
", " + default_string +
")";
144 ret +=
"(" + optional_string + default_string +
")";
149 String accept_string;
150 for (
size_t i = 0; i < values_accept_.size(); i++) {
152 accept_string += (i + 1 < values_accept_.size() ?
", " :
" or ");
153 accept_string +=
"'" + values_accept_[i].value() +
"'";
155 if (accept_string.size() == 0) accept_string =
"... (anything)";
160 accept_string) +
"\n";
161 for (
size_t i = 0; i < values_accept_.size(); i++) {
162 ret += values_accept_[i].usage();
169 typedef std::map<String, Option> Options;
170 typedef Options:: iterator OptionsIterator;
171 typedef Options::const_iterator OptionsIteratorK;
175 Strings usage_begin_;
177 Strings proc_arguments_;
204 options_ = usage.options_;
205 usage_begin_ = usage.usage_begin_;
206 usage_end_ = usage.usage_end_;
207 proc_arguments_ = usage.proc_arguments_;
217 for (OptionsIteratorK
218 it =
usage.options_.begin(); it !=
usage.options_.end(); ++it) {
219 if (options_.find(it->first) != options_.end())
222 for (OptionsIteratorK
223 it =
usage.options_.begin(); it !=
usage.options_.end(); ++it) {
224 options_.insert(std::pair<String, Option>(it->first, it->second));
226 for (
size_t i = 0; i <
usage.usage_begin_.size(); ++i)
227 usage_begin_.push_back(
usage.usage_begin_[i]);
228 for (
size_t i = 0; i <
usage.usage_end_.size(); ++i)
229 usage_end_.push_back(
usage.usage_end_[i]);
240 for (OptionsIteratorK
241 it = usage.options_.begin(); it != usage.options_.end(); ++it) {
242 OptionsIterator my = options_.find(it->first);
243 if (my == options_.end())
continue;
244 for (
size_t i = 0, I = it->second.values().size(); i < I; ++i) {
245 my->second.valueAdd(it->second.value(i));
259 if (options_.find(opt) != options_.end())
return false;
260 options_.insert(std::pair<String, Option>(opt, Option(des)));
275 String
const& val_type,
276 String
const& val_default,
278 if (options_.find(opt) != options_.end())
return false;
279 options_.insert(std::pair<String, Option>(
280 opt, Option(des, val_type, val_default, must)));
293 OptionsIterator o = options_.find(opt);
294 if (o == options_.end())
return false;
295 return o->second.valueAcceptAdd(val, des);
305 OptionsIteratorK o = options_.find(opt);
306 return (o != options_.end() && o->second.hasSetup());
316 OptionsIteratorK o = options_.find(opt);
317 if (o == options_.end())
return 0;
318 return o->second.values().size();
329 OptionsIteratorK o = options_.find(opt);
330 if (o == options_.end())
return String();
331 return o->second.value(index);
340 return proc_arguments_.size();
350 if (index >= proc_arguments_.size()) {
353 return proc_arguments_[index];
362 return proc_arguments_;
389 Usage::String out =
stringPrintf(
"USAGE\n %s", name_.c_str());
390 for (OptionsIteratorK
391 it = options_.begin(); it != options_.end(); ++it)
392 out +=
" " + it->second.usage(it->first,
false);
393 out +=
"\n\nDESCRIPTION\n";
394 for (
size_t i = 0; i < usage_begin_.size(); ++i) {
395 out +=
" " + usage_begin_[i] +
"\n\n";
397 for (OptionsIteratorK
398 it = options_.begin(); it != options_.end(); ++it) {
399 out += it->second.usage(it->first,
true);
401 for (
size_t i = 0; i < usage_end_.size(); ++i) {
402 out +=
" " + usage_end_[i] +
"\n\n";
416 String& err = (errmsg == NULL ? zzz : *errmsg);
417 for (
int i = 0; i < argc; ++i) {
418 if (argv[i][0] ==
'-') {
420 if (argv[i][1] ==
'-') {
421 if (argv[i][2] ==
'\0' || argv[i][3] ==
'\0') {
425 opt = String(argv[i] + 2);
428 if (argv[i][1] ==
'\0' || argv[i][2] !=
'\0') {
432 opt = String(argv[i] + 1);
434 OptionsIterator o = options_.find(opt);
435 if (o == options_.end()) {
439 if (o->second.hasValue()) {
441 err =
stringPrintf(
"Option '%s' need a value", argv[i]);
444 if (o->second.valueAdd(argv[i + 1]) < 0) {
445 err =
stringPrintf(
"Invalid value '%s' of options '%s'",
446 argv[i + 1], argv[i]);
452 o->second.valueAdd(
"");
456 proc_arguments_.push_back(String(argv[i] + (argv[i][0]==
'\\' ? 1:0)));
459 for (OptionsIteratorK it = options_.begin(); it != options_.end(); ++it) {
460 if (it->second.chkSetup() ==
false) {
462 (it->first.size() > 1 ?
"--" :
"-"),
473 #endif // MEOW_USAGE_H__
bool optionAdd(String opt, String const &des)
新增一個沒有額外選項的選項
bool arguments(int argc, char **argv, String *errmsg)
給定argc, argv, 將各參數設置
size_t procArgsSize() const
取得有幾個process arguments
String procArg(size_t index) const
取得第i個process argument
size_t optionValuesSize(String opt) const
回傳參數 -(opt) 被設置幾次
void usageBeginAdd(String const &des)
新增一段usage document於每個選項逐條說明之前
Strings const & procArgs() const
取得process arguments array
bool optionValueAcceptAdd(String opt, String const &val, String const &des)
針對-(opt)新增一個可接受的額外選項
bool hasOptionSetup(String opt) const
回傳是否有設定此選項
Usage(String const &name)
constructor
String usage() const
回傳usage string
Usage(Usage const &usage)
constructor
std::string stringReplace(std::string str, std::string const &from, std::string const &to)
將輸入字串中的某個pattern取代成另一個pattern
管理參數設置, 自訂usage document, 分析argc, argv
void usageEndAdd(String const &des)
新增一段usage document於每個選項逐條說明之後
bool optionAdd(String opt, String const &des, String const &val_type, String const &val_default, bool must)
新增一個有額外選項的選項
bool update(Usage const &usage)
將另一個usage的選項設置加進來
String optionValue(String opt, size_t index) const
回傳參數 -(opt) 的第 index 個額外選項
std::string stringPrintf(char const *fmt,...)
類似C的printf, 不過是將格式化的字串丟到 std::string 裡回傳