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 #include <algorithm>
12 
13 extern "C" {
14 #include <unistd.h>
15 }
16 
17 namespace meow {
30 class Usage {
31 private:
32  typedef std::string String;
33  typedef std::vector<String> Strings;
35  class Value {
36  private:
37  String value_;
38  String description_;
39  public:
40  Value() {
41  }
42  Value(String const& value, String const& description) {
43  value_ = value;
44  description_ = stringReplace(description, "<value>", value);
45  }
46  String usage() const {
47  return stringPrintf("%8s%s : %s\n",
48  " ", value_.c_str(), description_.c_str());
49  }
50  String value() const {
51  return value_;
52  }
53  bool operator==(Value const& b) const {
54  return (value_ == b.value_);
55  }
56  };
57  typedef std::vector<Value> Values;
59  class Option {
60  private:
61  Strings values_;
62  Values values_accept_;
63  String value_default_;
64  String value_type_;
65  String description_;
66  bool has_value_;
67  bool has_setup_;
68  bool must_setup_;
69  public:
70  Option() {
71  }
72  Option(String const& description) {
73  has_setup_ = false;
74  has_value_ = false;
75  description_ = description;
76  must_setup_ = false;
77  }
78  Option(String const& description,
79  String const& type,
80  String const& default_value,
81  bool must) {
82  has_setup_ = false;
83  has_value_ = true;
84  description_ = description;
85  value_type_ = type;
86  value_default_ = default_value;
87  must_setup_ = must;
88  }
89  Strings const& values() const {
90  return values_;
91  }
92  String value(size_t index) const {
93  if (!has_value_) return "";
94  if (!has_setup_ || index >= values_.size()) return value_default_;
95  return values_[index];
96  }
97  ssize_t valueAdd(String const& value) {
98  if (!has_value_) {
99  has_setup_ = true;
100  return 0;
101  }
102  if (values_accept_.size() > 0 &&
103  std::find(values_accept_.begin(), values_accept_.end(),
104  Value(value, "")) == values_accept_.end())
105  return -1;
106  values_.push_back(value);
107  has_setup_ = true;
108  return values_.size() - 1;
109  }
110  bool valueAcceptAdd(String const& value, String const& description) {
111  if (!has_value_) return false;
112  if (std::find(values_accept_.begin(), values_accept_.end(),
113  Value(value, "")) == values_accept_.end()){
114  values_accept_.push_back(Value(value, description));
115  }
116  return true;
117  }
118  bool valueAcceptChk(String const& value){
119  if (!has_value_) return false;
120  if (values_accept_.size() == 0) return true;
121  return (std::find(values_accept_.begin(), values_accept_.end(),
122  Value(value, "")) != values_accept_.end());
123  }
124  bool hasSetup() const{ return has_setup_; }
125  bool hasValue() const{ return has_value_; }
126  bool chkSetup() const{ return !(must_setup_ && !has_setup_); }
127 
128  String usage(unsigned char opt, bool detail) const {
129  String ret(stringPrintf("-%c ", opt));
130  if (!detail) {
131  if (has_value_) ret += value_type_;
132  if (!must_setup_) ret = "[" + ret + "]";
133  } else {
134  if (has_value_) {
135  ret += value_type_ + " ";
136  String default_string("");
137  if (value_default_ != "")
138  default_string = "defalut='" + value_default_ + "'";
139  String optional_string("");
140  if (!must_setup_)
141  optional_string = "optional";
142  String tmp;
143  if (default_string.size() + optional_string.size() > 0) {
144  if (default_string.size() > 0 && optional_string.size() > 0) {
145  ret += "(" + optional_string + ", " + default_string + ")";
146  } else {
147  ret += "(" + optional_string + default_string + ")";
148  }
149  }
150  }
151  ret += "\n";
152  String accept_string;
153  for (size_t i = 0; i < values_accept_.size(); i++) {
154  if (i > 0)
155  accept_string += (i + 1 < values_accept_.size()
156  ? ", " : " or ");
157  accept_string += "'" + values_accept_[i].value() + "'";
158  }
159  if (accept_string.size() == 0) accept_string = "... (anything)";
160  ret += " " + stringReplace(stringReplace(description_,
161  "<type>",
162  value_type_),
163  "<values>",
164  accept_string) + "\n";
165  for (size_t i = 0; i < values_accept_.size(); i++) {
166  ret += values_accept_[i].usage();
167  }
168  ret += "\n";
169  }
170  return ret;
171  }
172  };
173  typedef std::map<unsigned char, Option> Options;
174  typedef Options::const_iterator OptionsIterator;
175  String name_;
176  Options options_;
177  Strings usage_begin_;
178  Strings usage_end_;
179  Strings proc_arguments_;
180 public:
186  Usage() {
187  }
188 
194  Usage(String const& name) {
195  name_ = name;
196  }
197 
198 
204  Usage(Usage const& usage) {
205  name_ = usage.name_;
206  options_ = usage.options_;
207  usage_begin_ = usage.usage_begin_;
208  usage_end_ = usage.usage_end_;
209  proc_arguments_ = usage.proc_arguments_;
210  }
211 
218  bool import(Usage const& usage) {
219  for (OptionsIterator
220  it = usage.options_.begin(); it != usage.options_.end(); ++it) {
221  if (options_.find(it->first) != options_.end())
222  return false;
223  }
224  for (OptionsIterator
225  it = usage.options_.begin(); it != usage.options_.end(); ++it) {
226  options_[it->first] = it->second;
227  }
228  for (size_t i = 0; i < usage.usage_begin_.size(); ++i)
229  usage_begin_.push_back(usage.usage_begin_[i]);
230  for (size_t i = 0; i < usage.usage_end_.size(); ++i)
231  usage_end_.push_back(usage.usage_end_[i]);
232  return true;
233  }
234 
241  bool update(Usage const& usage) {
242  for (OptionsIterator
243  it = usage.options_.begin(); it != usage.options_.end(); ++it) {
244  if (options_.find(it->first) == options_.end()) continue;
245  for(size_t i = 0, I = it->second.values().size(); i < I; i++){
246  options_[it->first].valueAdd(it->second.value(i));
247  }
248  }
249  return true;
250  }
251 
259  bool optionAdd(unsigned char opt, String const& des) {
260  if (options_.find(opt) != options_.end()) return false;
261  options_[opt] = Option(des);
262  return true;
263  }
264 
275  bool optionAdd(unsigned char opt, String const& des,
276  String const& val_type,
277  String const& val_default,
278  bool must) {
279  if (options_.find(opt) != options_.end()) return false;
280  options_[opt] = Option(des, val_type, val_default, must);
281  return true;
282  }
283 
292  bool optionValueAcceptAdd(unsigned char opt,
293  String const& val,
294  String const& des) {
295  if (options_.find(opt) == options_.end()) return false;
296  return options_[opt].valueAcceptAdd(val, des);
297  }
298 
305  bool hasOptionSetup(unsigned char opt) const {
306  return (options_.find(opt) != options_.end() &&
307  options_.find(opt)->second.hasSetup());
308  }
309 
316  size_t optionValuesSize(unsigned char opt) const {
317  if(options_.find(opt) == options_.end()) return 0;
318  return options_.find(opt)->second.values().size();
319  }
320 
328  String optionValue(unsigned char opt, size_t index) const {
329  if (options_.find(opt) == options_.end()) {
330  return String();
331  }
332  return options_.find(opt)->second.value(index);
333  }
334 
340  size_t procArgsSize() const {
341  return proc_arguments_.size();
342  }
343 
350  String procArg(size_t index) const {
351  if (index >= proc_arguments_.size()) {
352  return String();
353  }
354  return proc_arguments_[index];
355  }
356 
362  Strings const& procArgs() const{
363  return proc_arguments_;
364  }
365 
371  void usageBeginAdd(String const& des) {
372  usage_begin_.push_back(stringReplace(des, "<name>", name_));
373  }
374 
380  void usageEndAdd(String const& des) {
381  usage_end_.push_back(stringReplace(des, "<name>", name_));
382  }
383 
389  String usage() const{
390  Usage::String out = stringPrintf("USAGE\n %s", name_.c_str());
391  for (OptionsIterator
392  it = options_.begin(); it != options_.end(); ++it)
393  out += " " + it->second.usage(it->first, false);
394  out += "\n\nDESCRIPTION\n";
395  for (size_t i = 0; i < usage_begin_.size(); ++i) {
396  out += " " + usage_begin_[i] + "\n\n";
397  }
398  for (OptionsIterator
399  it = options_.begin(); it != options_.end(); ++it) {
400  out += it->second.usage(it->first, true);
401  }
402  for (size_t i = 0; i < usage_end_.size(); ++i) {
403  out += " " + usage_end_[i] + "\n\n";
404  }
405  return out;
406  }
407 
415  bool arguments(int argc, char** argv, String* errmsg){
416  opterr = 0;
417  String s;
418  OptionsIterator it;
419  String zzz;
420  String& err = (errmsg == NULL ? zzz : *errmsg);
421  for (it = options_.begin(); it != options_.end(); ++it) {
422  s += (char)(it->first);
423  if (it->second.hasValue()) s += ":";
424  }
425  bool succ = true;
426  for (int opt; (opt = getopt(argc, argv, s.c_str())) != -1; ) {
427  if (options_.find(opt) == options_.end()) {
428  if(options_.find(optopt) == options_.end()){
429  err += stringPrintf("Unknown option '-%c'\n", optopt);
430  }else{
431  err += stringPrintf("No specify argument to '-%c'\n",
432  optopt);
433  }
434  succ = false;
435  continue;
436  }
437  if (options_[opt].valueAdd(optarg == NULL ? "" : optarg) < 0) {
438  err += stringPrintf("Option argument '%s' to '-%c' is not allowed\n"
439  , optarg, opt);
440  succ = false;
441  continue;
442  }
443  }
444  for (it = options_.begin(); it != options_.end(); it++) {
445  if (it->second.chkSetup() == false) {
446  err += stringPrintf("No specify argument to '-%c'\n",
447  it->first);
448  succ = false;
449  continue;
450  }
451  }
452  for (int i = optind; i < argc; i++) {
453  proc_arguments_.push_back(String(argv[i]));
454  }
455  return succ;
456  }
457 };
458 
459 } // meow
460 
461 #endif // MEOW_USAGE_H__