00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <iostream>
00024 #include <iomanip>
00025 #include <sstream>
00026 #include <set>
00027 #include <vector>
00028
00029
00035 template <typename T>
00036 void str2val(const std::string& str, T& v)
00037 {
00038 std::stringstream s(str);
00039 if (str[0] == '0') {
00040 if (str[1] == 'x' || str[1] == 'X') s >> std::hex >> v;
00041 else s >> std::oct >> v;
00042 }
00043 else
00044 s >> v;
00045 }
00046
00047
00053 template <typename T>
00054 void str2val(const char* str, T& v)
00055 {
00056 str2val<T>(std::string(str), v);
00057 }
00058
00059
00060
00065 struct OptionBase
00066 {
00072 OptionBase(char s, const char* l, const char* h, bool arg)
00073 : fShort(s),
00074 fLong(l),
00075 fHelp(h),
00076 fNeedArg(arg),
00077 fSet(false)
00078 {}
00080 virtual ~OptionBase() {}
00082 bool IsSet() const { return fSet; }
00084 bool NeedArg() const { return fNeedArg; }
00086 virtual char Short() const { return fShort; }
00088 virtual const std::string& Long() const { return fLong; }
00094 virtual bool Handle(char s, const char* arg) = 0;
00100 virtual bool Handle(const std::string& l, const std::string& arg) = 0;
00102 virtual void Help() const
00103 {
00104 std::cout << "\t-" << fShort << ",--" << fLong
00105 << (fNeedArg ? "=ARG" : "") << "\t" << fHelp;
00106 }
00107 protected:
00109 char fShort;
00111 std::string fLong;
00113 std::string fHelp;
00115 bool fNeedArg;
00117 bool fSet;
00118 };
00119
00120 namespace std
00121 {
00125 template <>
00126 struct less<OptionBase*>
00127 {
00130 bool operator()(OptionBase* const & lhs, OptionBase* const & rhs)
00131 {
00132 if (lhs->Short() == '\0' && rhs->Short())
00133 return lhs->Long() < rhs->Long();
00134 return lhs->Short() < rhs->Short();
00135 }
00136 };
00137 }
00138
00139
00143 template <typename T>
00144 struct Option : public OptionBase
00145 {
00152 Option(char s, const char* l, const char* h, const T& v=T(), bool arg=true)
00153 : OptionBase(s, l, h, arg),
00154 fValue(v)
00155 {}
00161 bool Handle(char s, const char* arg)
00162 {
00163 if (s != fShort) return false;
00164 if (!fNeedArg) {
00165 std::stringstream s;
00166 s << true;
00167 s >> fValue;
00168 return fSet = true;
00169 }
00170 if (!arg) return true;
00171 str2val(arg, fValue);
00172 return fSet = true;
00173 }
00179 bool Handle(const std::string& l, const std::string& arg)
00180 {
00181 if (l != fLong) return false;
00182 if (!fNeedArg) {
00183 std::stringstream s;
00184 s << true;
00185 s >> fValue;
00186 return fSet = true;
00187 }
00188 str2val(arg, fValue);
00189 return fSet = true;
00190 }
00192 const T& Value() const { return fValue; }
00194 void Help() const
00195 {
00196 OptionBase::Help();
00197 if (NeedArg()) {
00198 std::cout << "\t[";
00199 if (!IsSet()) std::cout << "default: ";
00200 std::cout << fValue << "]";
00201 }
00202 std::cout << std::endl;
00203 }
00206 const T* operator->() const { return &fValue; }
00209 operator const T&() const { return fValue; }
00213 Option<T>& operator=(const T& v) { fValue = v; return *this; }
00214 private:
00216 T fValue;
00217 };
00218
00219
00224 struct CommandLine
00225 {
00228 CommandLine(const char* args="") : fArg(args) {}
00233 bool Process(int argc, char** argv)
00234 {
00235 fProg = argv[0];
00236 int ret = 0;
00237 for (int i = 1; i < argc; i++) {
00238 if (argv[i][0] == '-') {
00239 if (argv[i][1] == '-') {
00240 std::string opt, val;
00241 GetLong(argv[i], opt, val);
00242 ret = CheckOptions(opt, val);
00243 }
00244 else
00245 ret = CheckOptions(argv[i][1], argv[i+1]);
00246 if (ret < 0) {
00247 std::cerr << fProg << ": Unknown option '" << argv[i]
00248 << "', try '" << fProg << " --help'"
00249 << std::endl;
00250 return false;
00251 }
00252 if (ret > 0) {
00253 ret = 0;
00254 i++;
00255 }
00256 }
00257 else fRemain.push_back(argv[i]);
00258 }
00259 return true;
00260 }
00262 std::vector<std::string>& Remain() { return fRemain; }
00265 void Add(OptionBase& option)
00266 {
00267 fList.insert(&option);
00268 }
00270 void Help() const
00271 {
00272 std::cout << "Usage: " << fProg << " [OPTIONS] " << fArg << "\n\n"
00273 << "Options:" << std::endl;
00274 for (OptionList::const_iterator i = fList.begin(); i != fList.end(); i++)
00275 (*i)->Help();
00276 std::cout << std::endl;
00277 }
00278 protected:
00283 void GetLong(const char* str, std::string& opt, std::string& val)
00284 {
00285 std::string arg(str);
00286 size_t eq = arg.find("=");
00287 if (eq != std::string::npos) {
00288 opt = arg.substr(0, eq);
00289 val = arg.substr(eq+1, arg.size() - eq);
00290 }
00291 else
00292 opt = arg;
00293 opt.erase(0,2);
00294 }
00302 int CheckOptions(const std::string& opt, const std::string& arg)
00303 {
00304 for (OptionList::iterator i = fList.begin(); i != fList.end(); i++)
00305 if ((*i)->Handle(opt, arg)) return 0;
00306 return -1;
00307 }
00315 int CheckOptions(char s, const char* arg)
00316 {
00317 for (OptionList::iterator i = fList.begin(); i != fList.end(); i++) {
00318 if ((*i)->Handle(s, arg)) {
00319 if ((*i)->NeedArg()) return 1;
00320 return 0;
00321 }
00322 }
00323 return -1;
00324 }
00326 std::string fArg;
00328 std::string fProg;
00330 typedef std::set<OptionBase*> OptionList;
00332 OptionList fList;
00334 std::vector<std::string> fRemain;
00335 };
00336
00337
00338
00339
00340