File indexing completed on 2024-04-06 11:56:21
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095 #ifndef CMDLINE_HH_
0096 #define CMDLINE_HH_
0097
0098 #include <cstdio>
0099 #include <cstring>
0100 #include <memory>
0101 #include <list>
0102 #include <sstream>
0103 #include <utility>
0104
0105
0106 class CmdLineError {
0107 public:
0108 inline CmdLineError(const char *msg = 0) : os_(new std::ostringstream()) {
0109 if (msg)
0110 *os_ << msg;
0111 }
0112
0113 template <typename T>
0114 inline CmdLineError &operator<<(const T &obj) {
0115 *os_ << obj;
0116 return *this;
0117 }
0118
0119 inline std::string str() const { return os_->str(); }
0120
0121 private:
0122 std::shared_ptr<std::ostringstream> os_;
0123 };
0124
0125 template <typename T>
0126 inline void OneShotExtract(std::istringstream &is, T &obj) {
0127 is >> obj;
0128 }
0129
0130 template <>
0131 inline void OneShotExtract<std::string>(std::istringstream &is, std::string &obj) {
0132 obj = is.str();
0133 is.seekg(0, std::ios_base::end);
0134 }
0135
0136 class OneShotIStream {
0137 public:
0138 inline OneShotIStream() : valid_(false), readout_(false) {}
0139
0140 inline OneShotIStream(const std::string &s) : str_(s), valid_(true), readout_(false) {}
0141
0142 inline operator void *() const { return valid_ && !readout_ ? (void *)this : (void *)0; }
0143
0144 template <typename T>
0145 inline bool operator>>(T &obj) {
0146 if (readout_)
0147 throw CmdLineError() << "can't reuse command line argument \"" << str_ << '"';
0148 readout_ = true;
0149 if (valid_) {
0150 std::istringstream is(str_);
0151 OneShotExtract(is, obj);
0152 if (is.bad() || is.fail())
0153 throw CmdLineError() << "failed to parse command line argument \"" << str_ << '"';
0154 if (is.peek() != EOF)
0155 throw CmdLineError() << "extra characters in command line argument \"" << str_ << '"';
0156 }
0157 return valid_;
0158 }
0159
0160 inline bool isValid() const { return valid_; }
0161
0162 private:
0163 std::string str_;
0164 bool valid_;
0165 bool readout_;
0166 };
0167
0168 class CmdLine {
0169
0170
0171
0172
0173
0174 typedef std::pair<std::string, int> Pair;
0175 typedef std::list<Pair> Optlist;
0176
0177 inline Optlist::iterator find(const char *shortOpt, const char *longOpt) {
0178 Optlist::iterator iend = args_.end();
0179 for (Optlist::iterator it = args_.begin(); it != iend; ++it) {
0180 if (shortOpt && it->second == 1 && it->first == shortOpt)
0181 return it;
0182 if (longOpt && it->second == 2 && it->first == longOpt)
0183 return it;
0184 }
0185 return iend;
0186 }
0187
0188 public:
0189 inline CmdLine(const unsigned argc, const char *const argv[]) : nprogargs_(0) {
0190
0191 const char *progname = std::strrchr(argv[0], '/');
0192 if (progname)
0193 ++progname;
0194 else
0195 progname = argv[0];
0196
0197
0198 if (strncmp(progname, "lt-", 3) == 0)
0199 progname += 3;
0200 progname_ = progname;
0201
0202
0203
0204 bool previousIsOpt = false;
0205 bool nextIsArg = false;
0206 for (unsigned i = 1; i < argc; ++i) {
0207 if (nextIsArg) {
0208 args_.push_back(Pair(argv[i], previousIsOpt ? 0 : 3));
0209 previousIsOpt = false;
0210 ++nprogargs_;
0211 nextIsArg = false;
0212 } else if (strcmp(argv[i], "-") == 0)
0213 nextIsArg = true;
0214 else if (strcmp(argv[i], "--") == 0) {
0215
0216 for (unsigned k = i + 1; k < argc; ++k) {
0217 args_.push_back(Pair(argv[k], 3));
0218 ++nprogargs_;
0219 }
0220 return;
0221 } else if (strncmp(argv[i], "--", 2) == 0) {
0222 args_.push_back(Pair(argv[i], 2));
0223 previousIsOpt = true;
0224 } else if (argv[i][0] == '-') {
0225 const unsigned len = strlen(argv[i]);
0226 for (unsigned k = 1; k < len; ++k) {
0227 std::string dummy("-");
0228 dummy += argv[i][k];
0229 args_.push_back(Pair(dummy, 1));
0230 previousIsOpt = true;
0231 }
0232 } else {
0233 args_.push_back(Pair(argv[i], previousIsOpt ? 0 : 3));
0234 previousIsOpt = false;
0235 ++nprogargs_;
0236 }
0237 }
0238 }
0239
0240 inline const char *progname() const { return progname_.c_str(); }
0241
0242 inline bool has(const char *shortOpt, const char *longOpt = 0) {
0243 bool found = false;
0244 for (Optlist::iterator it = find(shortOpt, longOpt); it != args_.end(); it = find(shortOpt, longOpt)) {
0245 found = true;
0246 Optlist::iterator it0(it);
0247 if (++it != args_.end())
0248 if (it->second == 0)
0249 it->second = 3;
0250 args_.erase(it0);
0251 }
0252 return found;
0253 }
0254
0255 inline OneShotIStream option(const char *shortOpt, const char *longOpt = 0) {
0256 OneShotIStream result;
0257 for (Optlist::iterator it = find(shortOpt, longOpt); it != args_.end(); it = find(shortOpt, longOpt)) {
0258 Optlist::iterator it0(it);
0259 if (++it != args_.end())
0260 if (it->second == 0) {
0261 result = OneShotIStream(it->first);
0262 args_.erase(it0, ++it);
0263 --nprogargs_;
0264 continue;
0265 }
0266 throw CmdLineError() << "missing command line argument for option \"" << it0->first << '"';
0267 }
0268 return result;
0269 }
0270
0271 inline OneShotIStream require(const char *shortOpt, const char *longOpt = 0) {
0272 const OneShotIStream &is(option(shortOpt, longOpt));
0273 if (!is.isValid()) {
0274 const char empty[] = "";
0275 const char *s = shortOpt ? shortOpt : (longOpt ? longOpt : empty);
0276 throw CmdLineError() << "required command line option \"" << s << "\" is missing";
0277 }
0278 return is;
0279 }
0280
0281 inline void optend() const {
0282 for (Optlist::const_iterator it = args_.begin(); it != args_.end(); ++it)
0283 if (it->second == 1 || it->second == 2)
0284 throw CmdLineError("invalid command line option \"") << it->first << '"';
0285 }
0286
0287 inline operator void *() const { return (void *)(static_cast<unsigned long>(nprogargs_)); }
0288
0289 inline unsigned argc() const { return nprogargs_; }
0290
0291 template <typename T>
0292 inline CmdLine &operator>>(T &obj) {
0293 if (!nprogargs_)
0294 throw CmdLineError("no more input available on the command line");
0295 Optlist::iterator it = args_.begin();
0296 for (; it != args_.end(); ++it)
0297 if (it->second == 0 || it->second == 3)
0298 break;
0299 OneShotIStream is(it->first);
0300 args_.erase(it);
0301 --nprogargs_;
0302 is >> obj;
0303 return *this;
0304 }
0305
0306 private:
0307 CmdLine();
0308
0309 std::string progname_;
0310 Optlist args_;
0311 unsigned nprogargs_;
0312 };
0313
0314 #endif