From 6bcf419d2e8f739b432d4790d1ba9d48ab65365b Mon Sep 17 00:00:00 2001 From: fcolin Date: Fri, 18 Nov 2011 12:14:12 +0000 Subject: --- ARMFCaptureD3D/options.h | 496 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 496 insertions(+) create mode 100644 ARMFCaptureD3D/options.h (limited to 'ARMFCaptureD3D/options.h') diff --git a/ARMFCaptureD3D/options.h b/ARMFCaptureD3D/options.h new file mode 100644 index 0000000..cc15976 --- /dev/null +++ b/ARMFCaptureD3D/options.h @@ -0,0 +1,496 @@ +// **************************************************************************** +// ^FILE: options.h - option parsing classes +// +// ^DESCRIPTION: +// This file defines classes used to parse command-line options. +// Options may be parsed from an array of strings, or from any structure +// for which a corresponding option-iterator exists. +// +// ^HISTORY: +// 03/06/92 Brad Appleton Created +// +// 03/23/93 Brad Appleton +// - Added OptIstreamIter class +// +// 03/08/94 Brad Appleton +// - Added Options::reset() member function +// +// 07/31/97 Brad Appleton +// - Added PARSE_POS control flag and POSITIONAL return value +// ^^************************************************************************** + +#ifndef _options_h +#define _options_h + +#ifdef USE_STDIO +# include +#else +# include +using std::istream; +using std::ostream; +#endif + +// Abstract class to iterate through options/arguments +// +class OptIter { +public: + OptIter(void) {} + virtual ~OptIter(void); + + // curr() returns the current item in the iterator without + // advancing on to the next item. If we are at the end of items + // then NULL is returned. + virtual const char * + curr(void) = 0; + + // next() advances to the next item. + virtual void + next(void) = 0; + + // operator() returns the current item in the iterator and then + // advances on to the next item. If we are at the end of items + // then NULL is returned. + virtual const char * + operator()(void); +} ; + +// Abstract class for a rewindable OptIter +// +class OptIterRwd : public OptIter { +public: + OptIterRwd(void); + + virtual ~OptIterRwd(void); + + virtual const char * + curr(void) = 0; + + virtual void + next(void) = 0; + + virtual const char * + operator()(void) = 0; + + // rewind() resets the "current-element" to the first one in the "list" + virtual void + rewind(void) = 0; +} ; + +// Class to iterate through an array of tokens. The array may be terminated +// by NULL or a count containing the number of tokens may be given. +// +class OptArgvIter : public OptIterRwd { +private: + int ndx; // index of current arg + int ac; // arg count + const char * const * av; // arg vector + +public: + OptArgvIter(const char * const argv[]) + : ndx(0), ac(-1), av(argv) {} + + OptArgvIter(int argc, const char * const argv[]) + : ndx(0), ac(argc), av(argv) {} + + virtual + ~OptArgvIter(void); + + virtual const char * + curr(void); + + virtual void + next(void); + + virtual const char * + operator()(void); + + virtual void + rewind(void); + + // index returns the current index to use for argv[] + int index(void) { return ndx; } +} ; + + +// Class to iterate through a string containing delimiter-separated tokens +// +class OptStrTokIter : public OptIterRwd { +private: + unsigned len; // length of token-string + const char * str; // the token-string + const char * seps; // delimiter-set (separator-characters) + const char * cur; // current token + char * tokstr; // our copy of the token-string + + static const char * default_delims; // default delimiters = whitespace + +public: + OptStrTokIter(const char * tokens, const char * delimiters =0); + + virtual + ~OptStrTokIter(void); + + virtual const char * + curr(void); + + virtual void + next(void); + + virtual const char * + operator()(void); + + virtual void + rewind(void); + + // delimiters() with NO arguments returns the current set of delimiters, + // If an argument is given then it is used as the new set of delimiters. + const char * + delimiters(void) { return seps; } + + void + delimiters(const char * delims) { + seps = (delims) ? delims : default_delims ; + } +} ; + + + // OptIstreamIter is a class for iterating over arguments that come + // from an input stream. Each line of the input stream is considered + // to be a set of white-space separated tokens. If the the first + // non-white character on a line is '#' ('!' for VMS systems) then + // the line is considered a comment and is ignored. + // + // *Note:: If a line is more than 1022 characters in length then we + // treat it as if it were several lines of length 1022 or less. + // + // *Note:: The string tokens returned by this iterator are pointers + // to temporary buffers which may not necessarily stick around + // for too long after the call to curr() or operator(), hence + // if you need the string value to persist - you will need to + // make a copy. + // +class OptIstreamIter : public OptIter { +private: + istream & is ; + OptStrTokIter * tok_iter ; + + void + fill(void); + +public: + static const unsigned MAX_LINE_LEN ; + + OptIstreamIter(istream & input); + + virtual + ~OptIstreamIter(void); + + virtual const char * + curr(void); + + virtual void + next(void); + + virtual const char * + operator()(void); +} ; + + +// Now we are ready to define a class to declare and parse command-options +// +// +// CLASS +// ===== +// Options -- parse command-line options +// +// SYNOPSIS +// ======== +// #include +// +// Options opts(cmdname, optv); +// char cmdname[], *optv[]; +// +// DESCRIPTION +// =========== +// The Options constructor expects a command-name (usually argv[0]) and +// a pointer to an array of strings. The last element in this array MUST +// be NULL. Each non-NULL string in the array must have the following format: +// +// The 1st character must be the option-name ('c' for a -c option). +// +// The 2nd character must be one of '|', '?', ':', '*', or '+'. +// '|' -- indicates that the option takes NO argument; +// '?' -- indicates that the option takes an OPTIONAL argument; +// ':' -- indicates that the option takes a REQUIRED argument; +// '*' -- indicates that the option takes 0 or more arguments; +// '+' -- indicates that the option takes 1 or more arguments; +// +// The remainder of the string must be the long-option name. +// +// If desired, the long-option name may be followed by one or more +// spaces and then by the name of the option value. This name will +// be used when printing usage messages. If the option-value-name +// is not given then the string "" will be used in usage +// messages. +// +// One may use a space to indicate that a particular option does not +// have a corresponding long-option. For example, "c: " (or "c:") +// means the -c option takes a value & has NO corresponding long-option. +// +// To specify a long-option that has no corresponding single-character +// option is a bit trickier: Options::operator() still needs an "option- +// character" to return when that option is matched. One may use a whitespace +// character or a non-printable character as the single-character option +// in such a case. (hence " |hello" would only match "--hello"). +// +// EXCEPTIONS TO THE ABOVE: +// ------------------------ +// If the 1st character of the string is '-', then the rest of the +// string must correspond to the above format, and the option is +// considered to be a hidden-option. This means it will be parsed +// when actually matching options from the command-line, but will +// NOT show-up if a usage message is printed using the usage() member +// function. Such an example might be "-h|hidden". If you want to +// use any "dummy" options (options that are not parsed, but that +// to show up in the usage message), you can specify them along with +// any positional parameters to the usage() member function. +// +// If the 2nd character of the string is '\0' then it is assumed +// that there is no corresponding long-option and that the option +// takes no argument (hence "f", and "f| " are equivalent). +// +// Examples: +// const char * optv[] = { +// "c:count ", +// "s?str ", +// "x", +// " |hello", +// "g+groups ", +// NULL +// } ; +// +// optv[] now corresponds to the following: +// +// usage: cmdname [-c|--count ] [-s|--str []] +// [-x] [--hello] [-g|--groups ...] +// +// Long-option names are matched case-insensitive and only a unique prefix +// of the name needs to be specified. +// +// Option-name characters are case-sensitive! +// +// CAVEAT +// ====== +// Because of the way in which multi-valued options and options with optional +// values are handled, it is NOT possible to supply a value to an option in +// a separate argument (different argv[] element) if the value is OPTIONAL +// and begins with a '-'. What this means is that if an option "-s" takes an +// optional value value and you wish to supply a value of "-foo" then you must +// specify this on the command-line as "-s-foo" instead of "-s -foo" because +// "-s -foo" will be considered to be two separate sets of options. +// +// A multi-valued option is terminated by another option or by the end-of +// options. The following are all equivalent (if "-l" is a multi-valued +// option and "-x" is an option that takes no value): +// +// cmdname -x -l item1 item2 item3 -- arg1 arg2 arg3 +// cmdname -x -litem1 -litem2 -litem3 -- arg1 arg2 arg3 +// cmdname -l item1 item2 item3 -x arg1 arg2 arg3 +// +// +// EXAMPLE +// ======= +// #include +// +// static const char * optv[] = { +// "H|help", +// "c:count ", +// "s?str ", +// "x", +// " |hello", +// "g+groups ", +// NULL +// } ; +// +// main(int argc, char * argv[]) { +// int optchar; +// const char * optarg; +// const char * str = "default_string"; +// int count = 0, xflag = 0, hello = 0; +// int errors = 0, ngroups = 0; +// +// Options opts(*argv, optv); +// OptArgvIter iter(--argc, ++argv); +// +// while( optchar = opts(iter, optarg) ) { +// switch (optchar) { +// case 'H' : +// opts.usage(cout, "files ..."); +// exit(0); +// break; +// case 'g' : +// ++ngroups; break; // the groupname is in "optarg" +// case 's' : +// str = optarg; break; +// case 'x' : +// ++xflag; break; +// case ' ' : +// ++hello; break; +// case 'c' : +// if (optarg == NULL) ++errors; +// else count = (int) atol(optarg); +// break; +// default : ++errors; break; +// } //switch +// } +// +// if (errors || (iter.index() == argc)) { +// if (! errors) { +// cerr << opts.name() << ": no filenames given." << endl ; +// } +// opts.usage(cerr, "files ..."); +// exit(1); +// } +// +// cout << "xflag=" << ((xflag) ? "ON" : "OFF") << endl +// << "hello=" << ((hello) ? "YES" : "NO") << endl +// << "count=" << count << endl +// << "str=\"" << ((str) ? str : "No value given!") << "\"" << endl +// << "ngroups=" << ngroups << endl ; +// +// if (iter.index() < argc) { +// cout << "files=" ; +// for (int i = iter.index() ; i < argc ; i++) { +// cout << "\"" << argv[i] << "\" " ; +// } +// cout << endl ; +// } +// } +// +class Options { +private: + unsigned explicit_end : 1; // were we terminated because of "--"? + unsigned optctrls : 7; // control settings (a set of OptCtrl masks) + const char * const * optvec; // vector of option-specifications (last=NULL) + const char * nextchar; // next option-character to process + const char * listopt; // last list-option we matched + const char * cmdname; // name of the command + + void + check_syntax(void) const; + + const char * + match_opt(char opt, int ignore_case =0) const; + + const char * + match_longopt(const char * opt, size_t len, int & ambiguous) const; + + int + parse_opt(OptIter & iter, const char * & optarg); + + int + parse_longopt(OptIter & iter, const char * & optarg); + +public: + enum OptCtrl { + DEFAULT = 0x00, // Default setting + ANYCASE = 0x01, // Ignore case when matching short-options + QUIET = 0x02, // Dont print error messages + PLUS = 0x04, // Allow "+" as a long-option prefix + SHORT_ONLY = 0x08, // Dont accept long-options + LONG_ONLY = 0x10, // Dont accept short-options + // (also allows "-" as a long-option prefix). + NOGUESSING = 0x20, // Normally, when we see a short (long) option + // on the command line that doesnt match any + // known short (long) options, then we try to + // "guess" by seeing if it will match any known + // long (short) option. Setting this mask prevents + // this "guessing" from occurring. + PARSE_POS = 0x40 // By default, Options will not present positional + // command-line arguments to the user and will + // instead stop parsing when the first positonal + // argument has been encountered. If this flag + // is given, Options will present positional + // arguments to the user with a return code of + // POSITIONAL; ENDOPTS will be returned only + // when the end of the argument list is reached. + } ; + + // Error return values for operator() + // + enum OptRC { + ENDOPTS = 0, + BADCHAR = -1, + BADKWD = -2, + AMBIGUOUS = -3, + POSITIONAL = -4 + } ; + + Options(const char * name, const char * const optv[]); + + virtual + ~Options(void); + + // name() returns the command name + const char * + name(void) const { return cmdname; } + + // ctrls() (with no arguments) returns the existing control settings + unsigned + ctrls(void) const { return optctrls; } + + // ctrls() (with 1 argument) sets new control settings + void + ctrls(unsigned newctrls) { optctrls = newctrls; } + + // reset for another pass to parse for options + void + reset(void) { nextchar = listopt = NULL; } + + // usage() prints options usage (followed by any positional arguments + // listed in the parameter "positionals") on the given outstream + void + usage(ostream & os, const char * positionals) const ; + + // operator() iterates through the arguments as necessary (using the + // given iterator) and returns the character value of the option + // (or long-option) that it matched. If the option has a value + // then the value given may be found in optarg (otherwise optarg + // will be NULL). + // + // 0 is returned upon end-of-options. At this point, "iter" may + // be used to process any remaining positional parameters. If the + // PARSE_POS control-flag is set then 0 is returned only when all + // arguments in "iter" have been exhausted. + // + // If an invalid option is found then BADCHAR is returned and *optarg + // is the unrecognized option character. + // + // If an invalid long-option is found then BADKWD is returned and optarg + // points to the bad long-option. + // + // If an ambiguous long-option is found then AMBIGUOUS is returned and + // optarg points to the ambiguous long-option. + // + // If the PARSE_POS control-flag is set then POSITIONAL is returned + // when a positional argument is encountered and optarg points to + // the positonal argument (and "iter" is advanced to the next argument + // in the iterator). + // + // Unless Options::QUIET is used, missing option-arguments and + // invalid options (and the like) will automatically cause error + // messages to be issued to cerr. + int + operator()(OptIter & iter, const char * & optarg) ; + + // Call this member function after operator() has returned 0 + // if you want to know whether or not options were explicitly + // terminated because "--" appeared on the command-line. + // + int + explicit_endopts() const { return explicit_end; } +} ; + +#endif /* _options_h */ + + -- cgit v1.1