Templates -- Meow  1.1.4
A C++ template which is unable and also not allowed to compile to obj-file first.
Usage.h
Go to the documentation of this file.
1 #ifndef MEOW_USAGE_H__
2 #define MEOW_USAGE_H__
3 
4 #include "utility.h"
5 
6 #include <cstdlib>
7 
8 #include <algorithm>
9 #include <string>
10 #include <vector>
11 #include <map>
12 
13 namespace meow {
26 class Usage {
27 private:
28  typedef std::string String;
29  typedef std::vector<String> Strings;
31  class Value {
32  private:
33  String value_;
34  String description_;
35  public:
36  Value() { }
37  Value(String const& value, String const& description) {
38  value_ = value;
39  description_ = stringReplace(description, "<value>", value);
40  }
41  String usage() const {
42  return stringPrintf("%8s%s : %s\n",
43  " ", value_.c_str(), description_.c_str());
44  }
45  String value() const {
46  return value_;
47  }
48  bool operator==(Value const& b) const {
49  return (value_ == b.value_);
50  }
51  };
52  typedef std::vector<Value> Values;
54  class Option {
55  private:
56  Strings values_;
57  Values values_accept_;
58  String value_default_;
59  String value_type_;
60  String description_;
61  bool has_value_;
62  bool has_setup_;
63  bool must_setup_;
64  public:
65  Option() {
66  }
67  Option(String const& description) {
68  has_setup_ = false;
69  has_value_ = false;
70  description_ = description;
71  must_setup_ = false;
72  }
73  Option(String const& description,
74  String const& type,
75  String const& default_value,
76  bool must) {
77  has_setup_ = false;
78  has_value_ = true;
79  description_ = description;
80  value_type_ = type;
81  value_default_ = default_value;
82  must_setup_ = must;
83  }
84  Strings const& values() const {
85  return values_;
86  }
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];
91  }
92  ssize_t valueAdd(String const& value) {
93  if (!has_value_) {
94  has_setup_ = true;
95  return 0;
96  }
97  if (values_accept_.size() > 0 &&
98  std::find(values_accept_.begin(), values_accept_.end(),
99  Value(value, "")) == values_accept_.end())
100  return -1;
101  values_.push_back(value);
102  has_setup_ = true;
103  return values_.size() - 1;
104  }
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));
110  }
111  return true;
112  }
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());
118  }
119  bool hasSetup() const{ return has_setup_; }
120  bool hasValue() const{ return has_value_; }
121  bool chkSetup() const{ return !(must_setup_ && !has_setup_); }
122 
123  String usage(String opt, bool detail) const {
124  String ret(stringPrintf("%s%s ", (opt.size()>1 ? "--":"-"), opt.c_str()));
125  if (!detail) {
126  if (has_value_) ret += value_type_;
127  if (!must_setup_) ret = "[" + ret + "]";
128  }
129  else {
130  if (has_value_) {
131  ret += value_type_ + " ";
132  String default_string("");
133  if (value_default_ != "")
134  default_string = "defalut='" + value_default_ + "'";
135  String optional_string("");
136  if (!must_setup_)
137  optional_string = "optional";
138  String tmp;
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 + ")";
142  }
143  else {
144  ret += "(" + optional_string + default_string + ")";
145  }
146  }
147  }
148  ret += "\n";
149  String accept_string;
150  for (size_t i = 0; i < values_accept_.size(); i++) {
151  if (i > 0)
152  accept_string += (i + 1 < values_accept_.size() ? ", " : " or ");
153  accept_string += "'" + values_accept_[i].value() + "'";
154  }
155  if (accept_string.size() == 0) accept_string = "... (anything)";
156  ret += " " + stringReplace(stringReplace(description_,
157  "<type>",
158  value_type_),
159  "<values>",
160  accept_string) + "\n";
161  for (size_t i = 0; i < values_accept_.size(); i++) {
162  ret += values_accept_[i].usage();
163  }
164  ret += "\n";
165  }
166  return ret;
167  }
168  };
169  typedef std::map<String, Option> Options;
170  typedef Options:: iterator OptionsIterator;
171  typedef Options::const_iterator OptionsIteratorK;
172 
173  String name_;
174  Options options_;
175  Strings usage_begin_;
176  Strings usage_end_;
177  Strings proc_arguments_;
178 public:
184  Usage() {
185  }
186 
192  Usage(String const& name) {
193  name_ = name;
194  }
195 
196 
202  Usage(Usage const& usage) {
203  name_ = usage.name_;
204  options_ = usage.options_;
205  usage_begin_ = usage.usage_begin_;
206  usage_end_ = usage.usage_end_;
207  proc_arguments_ = usage.proc_arguments_;
208  }
209 
216  bool import(Usage const& usage) {
217  for (OptionsIteratorK
218  it = usage.options_.begin(); it != usage.options_.end(); ++it) {
219  if (options_.find(it->first) != options_.end())
220  return false;
221  }
222  for (OptionsIteratorK
223  it = usage.options_.begin(); it != usage.options_.end(); ++it) {
224  options_.insert(std::pair<String, Option>(it->first, it->second));
225  }
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]);
230  return true;
231  }
232 
239  bool update(Usage const& usage) {
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));
246  }
247  }
248  return true;
249  }
250 
258  bool optionAdd(String opt, String const& des) {
259  if (options_.find(opt) != options_.end()) return false;
260  options_.insert(std::pair<String, Option>(opt, Option(des)));
261  return true;
262  }
263 
274  bool optionAdd(String opt, String const& des,
275  String const& val_type,
276  String const& val_default,
277  bool must) {
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)));
281  return true;
282  }
283 
292  bool optionValueAcceptAdd(String opt, String const& val, String const& des) {
293  OptionsIterator o = options_.find(opt);
294  if (o == options_.end()) return false;
295  return o->second.valueAcceptAdd(val, des);
296  }
297 
304  bool hasOptionSetup(String opt) const {
305  OptionsIteratorK o = options_.find(opt);
306  return (o != options_.end() && o->second.hasSetup());
307  }
308 
315  size_t optionValuesSize(String opt) const {
316  OptionsIteratorK o = options_.find(opt);
317  if (o == options_.end()) return 0;
318  return o->second.values().size();
319  }
320 
328  String optionValue(String opt, size_t index) const {
329  OptionsIteratorK o = options_.find(opt);
330  if (o == options_.end()) return String();
331  return o->second.value(index);
332  }
333 
339  size_t procArgsSize() const {
340  return proc_arguments_.size();
341  }
342 
349  String procArg(size_t index) const {
350  if (index >= proc_arguments_.size()) {
351  return String();
352  }
353  return proc_arguments_[index];
354  }
355 
361  Strings const& procArgs() const{
362  return proc_arguments_;
363  }
364 
370  void usageBeginAdd(String const& des) {
371  usage_begin_.push_back(stringReplace(des, "<name>", name_));
372  }
373 
379  void usageEndAdd(String const& des) {
380  usage_end_.push_back(stringReplace(des, "<name>", name_));
381  }
382 
388  String usage() const {
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";
396  }
397  for (OptionsIteratorK
398  it = options_.begin(); it != options_.end(); ++it) {
399  out += it->second.usage(it->first, true);
400  }
401  for (size_t i = 0; i < usage_end_.size(); ++i) {
402  out += " " + usage_end_[i] + "\n\n";
403  }
404  return out;
405  }
406 
414  bool arguments(int argc, char** argv, String* errmsg) {
415  String zzz;
416  String& err = (errmsg == NULL ? zzz : *errmsg);
417  for (int i = 0; i < argc; ++i) {
418  if (argv[i][0] == '-') {
419  String opt;
420  if (argv[i][1] == '-') { // long option
421  if (argv[i][2] == '\0' || argv[i][3] == '\0') {
422  err = stringPrintf("Invalid option '%s'", argv[i]);
423  return false;
424  }
425  opt = String(argv[i] + 2);
426  }
427  else { // short option
428  if (argv[i][1] == '\0' || argv[i][2] != '\0') {
429  err = stringPrintf("Invalid option '%s'", argv[i]);
430  return false;
431  }
432  opt = String(argv[i] + 1);
433  }
434  OptionsIterator o = options_.find(opt);
435  if (o == options_.end()) {
436  err = stringPrintf("Unknown option '%s'", argv[i]);
437  return false;
438  }
439  if (o->second.hasValue()) {
440  if (i + 1 >= argc) {
441  err = stringPrintf("Option '%s' need a value", argv[i]);
442  return false;
443  }
444  if (o->second.valueAdd(argv[i + 1]) < 0) {
445  err = stringPrintf("Invalid value '%s' of options '%s'",
446  argv[i + 1], argv[i]);
447  return false;
448  }
449  ++i;
450  }
451  else {
452  o->second.valueAdd("");
453  }
454  }
455  else {
456  proc_arguments_.push_back(String(argv[i] + (argv[i][0]=='\\' ? 1:0)));
457  }
458  }
459  for (OptionsIteratorK it = options_.begin(); it != options_.end(); ++it) {
460  if (it->second.chkSetup() == false) {
461  err += stringPrintf("No specify argument to '%s%s'\n",
462  (it->first.size() > 1 ? "--" : "-"),
463  it->first.c_str());
464  return false;
465  }
466  }
467  return true;
468  }
469 };
470 
471 } // meow
472 
473 #endif // MEOW_USAGE_H__
bool optionAdd(String opt, String const &des)
新增一個沒有額外選項的選項
Definition: Usage.h:258
bool arguments(int argc, char **argv, String *errmsg)
給定argc, argv, 將各參數設置
Definition: Usage.h:414
size_t procArgsSize() const
取得有幾個process arguments
Definition: Usage.h:339
String procArg(size_t index) const
取得第i個process argument
Definition: Usage.h:349
size_t optionValuesSize(String opt) const
回傳參數 -(opt) 被設置幾次
Definition: Usage.h:315
void usageBeginAdd(String const &des)
新增一段usage document於每個選項逐條說明之前
Definition: Usage.h:370
Strings const & procArgs() const
取得process arguments array
Definition: Usage.h:361
bool optionValueAcceptAdd(String opt, String const &val, String const &des)
針對-(opt)新增一個可接受的額外選項
Definition: Usage.h:292
bool hasOptionSetup(String opt) const
回傳是否有設定此選項
Definition: Usage.h:304
Usage(String const &name)
constructor
Definition: Usage.h:192
String usage() const
回傳usage string
Definition: Usage.h:388
Usage()
constructor
Definition: Usage.h:184
Usage(Usage const &usage)
constructor
Definition: Usage.h:202
std::string stringReplace(std::string str, std::string const &from, std::string const &to)
將輸入字串中的某個pattern取代成另一個pattern
Definition: utility.h:60
管理參數設置, 自訂usage document, 分析argc, argv
Definition: Usage.h:26
void usageEndAdd(String const &des)
新增一段usage document於每個選項逐條說明之後
Definition: Usage.h:379
bool optionAdd(String opt, String const &des, String const &val_type, String const &val_default, bool must)
新增一個有額外選項的選項
Definition: Usage.h:274
bool update(Usage const &usage)
將另一個usage的選項設置加進來
Definition: Usage.h:239
String optionValue(String opt, size_t index) const
回傳參數 -(opt) 的第 index 個額外選項
Definition: Usage.h:328
std::string stringPrintf(char const *fmt,...)
類似C的printf, 不過是將格式化的字串丟到 std::string 裡回傳
Definition: utility.h:42