Templates -- Meow  1.1.2
不能,也不應該先編譯成obj-file的templates
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 <string>
9 #include <vector>
10 #include <map>
11 
12 namespace meow {
25 class Usage {
26 private:
27  typedef std::string String;
28  typedef std::vector<String> Strings;
30  class Value {
31  private:
32  String value_;
33  String description_;
34  public:
35  Value() { }
36  Value(String const& value, String const& description) {
37  value_ = value;
38  description_ = stringReplace(description, "<value>", value);
39  }
40  String usage() const {
41  return stringPrintf("%8s%s : %s\n",
42  " ", value_.c_str(), description_.c_str());
43  }
44  String value() const {
45  return value_;
46  }
47  bool operator==(Value const& b) const {
48  return (value_ == b.value_);
49  }
50  };
51  typedef std::vector<Value> Values;
53  class Option {
54  private:
55  Strings values_;
56  Values values_accept_;
57  String value_default_;
58  String value_type_;
59  String description_;
60  bool has_value_;
61  bool has_setup_;
62  bool must_setup_;
63  public:
64  Option() {
65  }
66  Option(String const& description) {
67  has_setup_ = false;
68  has_value_ = false;
69  description_ = description;
70  must_setup_ = false;
71  }
72  Option(String const& description,
73  String const& type,
74  String const& default_value,
75  bool must) {
76  has_setup_ = false;
77  has_value_ = true;
78  description_ = description;
79  value_type_ = type;
80  value_default_ = default_value;
81  must_setup_ = must;
82  }
83  Strings const& values() const {
84  return values_;
85  }
86  String value(size_t index) const {
87  if (!has_value_) return "";
88  if (!has_setup_ || index >= values_.size()) return value_default_;
89  return values_[index];
90  }
91  ssize_t valueAdd(String const& value) {
92  if (!has_value_) {
93  has_setup_ = true;
94  return 0;
95  }
96  if (values_accept_.size() > 0 &&
97  std::find(values_accept_.begin(), values_accept_.end(),
98  Value(value, "")) == values_accept_.end())
99  return -1;
100  values_.push_back(value);
101  has_setup_ = true;
102  return values_.size() - 1;
103  }
104  bool valueAcceptAdd(String const& value, String const& description) {
105  if (!has_value_) return false;
106  if (std::find(values_accept_.begin(), values_accept_.end(),
107  Value(value, "")) == values_accept_.end()) {
108  values_accept_.push_back(Value(value, description));
109  }
110  return true;
111  }
112  bool valueAcceptChk(String const& value) {
113  if (!has_value_) return false;
114  return (values_accept_.empty() ||
115  std::find(values_accept_.begin(), values_accept_.end(),
116  Value(value, "")) != values_accept_.end());
117  }
118  bool hasSetup() const{ return has_setup_; }
119  bool hasValue() const{ return has_value_; }
120  bool chkSetup() const{ return !(must_setup_ && !has_setup_); }
121 
122  String usage(String opt, bool detail) const {
123  String ret(stringPrintf("%s%s ", (opt.size() > 1 ? "--" : "-"), opt));
124  if (!detail) {
125  if (has_value_) ret += value_type_;
126  if (!must_setup_) ret = "[" + ret + "]";
127  }
128  else {
129  if (has_value_) {
130  ret += value_type_ + " ";
131  String default_string("");
132  if (value_default_ != "")
133  default_string = "defalut='" + value_default_ + "'";
134  String optional_string("");
135  if (!must_setup_)
136  optional_string = "optional";
137  String tmp;
138  if (default_string.size() + optional_string.size() > 0) {
139  if (default_string.size() > 0 && optional_string.size() > 0) {
140  ret += "(" + optional_string + ", " + default_string + ")";
141  }
142  else {
143  ret += "(" + optional_string + default_string + ")";
144  }
145  }
146  }
147  ret += "\n";
148  String accept_string;
149  for (size_t i = 0; i < values_accept_.size(); i++) {
150  if (i > 0)
151  accept_string += (i + 1 < values_accept_.size() ? ", " : " or ");
152  accept_string += "'" + values_accept_[i].value() + "'";
153  }
154  if (accept_string.size() == 0) accept_string = "... (anything)";
155  ret += " " + stringReplace(stringReplace(description_,
156  "<type>",
157  value_type_),
158  "<values>",
159  accept_string) + "\n";
160  for (size_t i = 0; i < values_accept_.size(); i++) {
161  ret += values_accept_[i].usage();
162  }
163  ret += "\n";
164  }
165  return ret;
166  }
167  };
168  typedef std::map<String, Option> Options;
169  typedef Options:: iterator OptionsIterator;
170  typedef Options::const_iterator OptionsIteratorK;
171 
172  String name_;
173  Options options_;
174  Strings usage_begin_;
175  Strings usage_end_;
176  Strings proc_arguments_;
177 public:
183  Usage() {
184  }
185 
191  Usage(String const& name) {
192  name_ = name;
193  }
194 
195 
201  Usage(Usage const& usage) {
202  name_ = usage.name_;
203  options_ = usage.options_;
204  longOptions_ = usage.long_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_defalut, 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 (OptionsIterator
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]) == false) {
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 ? "--" : "-"), it->first);
463  return false;
464  }
465  }
466  return true;
467  }
468 };
469 
470 } // meow
471 
472 #endif // MEOW_USAGE_H__