ROSE  0.11.22.0
util/Sawyer/CommandLine.h
1 // WARNING: Changes to this file must be contributed back to Sawyer or else they will
2 // be clobbered by the next update from Sawyer. The Sawyer repository is at
3 // https://github.com/matzke1/sawyer.
4 
5 
6 
7 
8 /* Command-line switch parsing. */
9 #ifndef Sawyer_CommandLine_H
10 #define Sawyer_CommandLine_H
11 
12 #include <Sawyer/Assert.h>
13 #include <Sawyer/BitFlags.h>
14 #include <Sawyer/DocumentMarkup.h>
15 #include <Sawyer/IntervalSet.h>
16 #include <Sawyer/Map.h>
17 #include <Sawyer/Message.h>
18 #include <Sawyer/Optional.h>
19 #include <Sawyer/Sawyer.h>
20 #include <Sawyer/Set.h>
21 #include <Sawyer/SharedPointer.h>
22 
23 #include <boost/algorithm/string/case_conv.hpp>
24 #include <boost/any.hpp>
25 #include <boost/cstdint.hpp>
26 #include <boost/foreach.hpp>
27 #include <boost/lexical_cast.hpp>
28 #include <boost/numeric/conversion/cast.hpp>
29 #include <cerrno>
30 #include <ctype.h>
31 #include <list>
32 #include <set>
33 #include <stdexcept>
34 #include <string>
35 #include <vector>
36 
37 namespace Sawyer { // documented in Sawyer.h
38 
163 namespace CommandLine {
164 
165 SAWYER_EXPORT extern const std::string STR_NONE;
166 class Switch;
167 class SwitchGroup;
168 class Parser;
169 class ParserResult;
170 
172 enum SortOrder {
182 };
183 
185 enum Canonical {
190 };
191 
198 };
199 
205 };
206 
208 // Program argument cursor
210 
215 struct SAWYER_EXPORT Location {
216  size_t idx;
217  size_t offset;
221  Location(): idx(0), offset(0) {}
222 
224  Location(size_t idx, size_t offset): idx(idx), offset(offset) {}
225 
228  bool operator==(const Location &other) const { return idx==other.idx && offset==other.offset; }
229 
232  bool operator!=(const Location &other) const { return !(*this==other); }
233 
236  bool operator<(const Location &other) const { return idx<other.idx || (idx==other.idx && offset<other.offset); }
237 
240  bool operator<=(const Location &other) const { return *this<other || *this==other; }
241 };
242 
244 SAWYER_EXPORT std::ostream& operator<<(std::ostream&, const Location&);
245 
249 SAWYER_EXPORT extern const Location NOWHERE;
250 
254 class SAWYER_EXPORT Cursor {
255 #include <Sawyer/WarningsOff.h>
256  std::vector<std::string> strings_;
257  Location loc_;
258 #include <Sawyer/WarningsRestore.h>
259 public:
262  Cursor(const std::vector<std::string> &strings): strings_(strings) { location(Location()); }
263 
266  Cursor(const std::string &string): strings_(1, string) { location(Location()); }
267 
269  Cursor() {}
270 
272  const std::vector<std::string>& strings() const { return strings_; }
273 
291  const Location& location() const { return loc_; }
292  Cursor& location(const Location &loc);
297  bool atArgBegin() const { return loc_.idx<strings_.size() && 0==loc_.offset; }
298 
301  bool atArgEnd() const { return loc_.idx<strings_.size() && loc_.offset>=strings_[loc_.idx].size(); }
302 
307  bool atEnd() const { return atEnd(loc_); }
308  bool atEnd(const Location &location) const { return location.idx >= strings_.size(); }
315  const std::string& arg() const { return arg(loc_); }
316  const std::string& arg(const Location &location) const;
323  std::string rest() const { return rest(loc_); }
324  std::string rest(const Location &location) const;
332  std::string substr(const Location &limit, const std::string &separator=" ") const { return substr(loc_, limit, separator); }
333  std::string substr(const Location &limit1, const Location &limit2, const std::string &separator=" ") const;
338  void replace(const std::vector<std::string>&);
339 
343  void consumeChars(size_t nchars);
344 
349  void consumeArgs(size_t nargs) {
350  loc_.idx = std::min(strings_.size(), loc_.idx+nargs);
351  loc_.offset = 0;
352  }
353  void consumeArg() { consumeArgs(1); }
361  size_t linearDistance() const;
362 };
363 
367  Cursor &cursor_;
368  Location loc_;
369  bool canceled_;
370 public:
373  ExcursionGuard(Cursor &cursor): cursor_(cursor), loc_(cursor.location()), canceled_(false) {} // implicit
374  ~ExcursionGuard() { if (!canceled_) cursor_.location(loc_); }
375 
378  void cancel() { canceled_ = true; }
379 
382  const Location &startingLocation() const { return loc_; }
383 };
384 
385 
387 // Switch value savers
389 
390 // used internally
391 class SAWYER_EXPORT ValueSaver: public SharedObject {
392 protected:
393  ValueSaver() {}
394 public:
396  virtual ~ValueSaver() {}
397  virtual void save(const boost::any&, const std::string &switchKey) = 0;
398 };
399 
400 // used internally
401 template<typename T>
402 class TypedSaver: public ValueSaver {
403  T &storage_;
404 protected:
405  TypedSaver(T &storage): storage_(storage) {}
406 public:
408  static Ptr instance(T &storage) { return Ptr(new TypedSaver(storage)); }
409  virtual void save(const boost::any &value, const std::string &/*switchKey*/) /*override*/ {
410  storage_ = boost::any_cast<T>(value);
411  }
412 };
413 
414 // Partial specialization of TypedSaver, saving a value of any type T into a container of type CONTAINER_TEMPLATE calling the
415 // containers INSERT_METHOD with one argument: the value. The CONTAINER_TEMPLATE is the name of a class template that
416 // takes one argument: type type of value stored by the container.
417 #define SAWYER_COMMANDLINE_SEQUENCE_SAVER(CONTAINER_TEMPLATE, INSERT_METHOD) \
418  template<typename T> \
419  class TypedSaver<CONTAINER_TEMPLATE<T> >: public ValueSaver { \
420  CONTAINER_TEMPLATE<T> &storage_; \
421  protected: \
422  TypedSaver(CONTAINER_TEMPLATE<T> &storage): storage_(storage) {} \
423  public: \
424  static Ptr instance(CONTAINER_TEMPLATE<T> &storage) { return Ptr(new TypedSaver(storage)); } \
425  virtual void save(const boost::any &value, const std::string &/*switchKey*/) /*override*/ { \
426  T typed = boost::any_cast<T>(value); \
427  storage_.INSERT_METHOD(typed); \
428  } \
429  }
430 
431 // Partial specialization of TypedSaver for saving values into map-like containers. The CONTAINER_TEMPLATE should take two
432 // parameters: the key type (always std::string) and the value type (not part of this specialization). The value is stored by
433 // invoking the INSERT_METHOD with two arguments: the key string for the switch whose value is being saved, and the value to
434 // save.
435 #define SAWYER_COMMANDLINE_MAP_SAVER(CONTAINER_TEMPLATE, INSERT_METHOD) \
436  template<typename T> \
437  class TypedSaver<CONTAINER_TEMPLATE<std::string, T> >: public ValueSaver { \
438  CONTAINER_TEMPLATE<std::string, T> &storage_; \
439  protected: \
440  TypedSaver(CONTAINER_TEMPLATE<std::string, T> &storage): storage_(storage) {} \
441  public: \
442  static Ptr instance(CONTAINER_TEMPLATE<std::string, T> &storage) { return Ptr(new TypedSaver(storage)); } \
443  virtual void save(const boost::any &value, const std::string &switchKey) /*override*/ { \
444  T typed = boost::any_cast<T>(value); \
445  storage_.INSERT_METHOD(switchKey, typed); \
446  } \
447  }
448 
449 // Partial specialization of TypedSaver for saving values into set-like containers. The CONTAINER_TEMPLATE should take one
450 // parameter: the value type (not part of this specialization). The value is stored by invoking the INSERT_METHOD with one
451 // argument: the value to save. The value is always an interval.
452 #define SAWYER_COMMANDLINE_INTERVALSET_SAVER(CONTAINER_TEMPLATE, INSERT_METHOD) \
453  template<typename Interval> \
454  class TypedSaver<CONTAINER_TEMPLATE<Interval> >: public ValueSaver { \
455  CONTAINER_TEMPLATE<Interval> &storage_; \
456  protected: \
457  TypedSaver(CONTAINER_TEMPLATE<Interval> &storage): storage_(storage) {} \
458  public: \
459  static Ptr instance(CONTAINER_TEMPLATE<Interval> &storage) { return Ptr(new TypedSaver(storage)); } \
460  virtual void save(const boost::any &value, const std::string &switchKey) /*override*/ { \
461  Interval typed = boost::any_cast<Interval>(value); \
462  storage_.INSERT_METHOD(typed); \
463  } \
464  }
465 
466 // Partial specialization of TypedSaver for saving values into map-like containers using the STL approach where the insert
467 // operator takes an std::pair(key,value) rather than two arguments. The CONTAINER_TEMPLATE should take two parameters: the key
468 // type (always std::string) and the value type (not part of this specialization). The value is stored by invoking the
469 // INSERT_METHOD with two arguments: the key string for the switch whose value is being saved, and the value to save.
470 #define SAWYER_COMMANDLINE_MAP_PAIR_SAVER(CONTAINER_TEMPLATE, INSERT_METHOD) \
471  template<typename T> \
472  class TypedSaver<CONTAINER_TEMPLATE<std::string, T> >: public ValueSaver { \
473  CONTAINER_TEMPLATE<std::string, T> &storage_; \
474  protected: \
475  TypedSaver(CONTAINER_TEMPLATE<std::string, T> &storage): storage_(storage) {} \
476  public: \
477  static Ptr instance(CONTAINER_TEMPLATE<std::string, T> &storage) { return Ptr(new TypedSaver(storage)); } \
478  virtual void save(const boost::any &value, const std::string &switchKey) /*override*/ { \
479  T typed = boost::any_cast<T>(value); \
480  storage_.INSERT_METHOD(std::make_pair(switchKey, typed)); \
481  } \
482  }
483 
484 SAWYER_COMMANDLINE_SEQUENCE_SAVER(std::vector, push_back);
485 SAWYER_COMMANDLINE_SEQUENCE_SAVER(std::list, push_back);
486 SAWYER_COMMANDLINE_SEQUENCE_SAVER(std::set, insert);
487 SAWYER_COMMANDLINE_SEQUENCE_SAVER(Sawyer::Container::Set, insert);
488 SAWYER_COMMANDLINE_SEQUENCE_SAVER(Optional, operator=);
489 SAWYER_COMMANDLINE_SEQUENCE_SAVER(BitFlags, set);
490 SAWYER_COMMANDLINE_MAP_PAIR_SAVER(std::map, insert);
491 SAWYER_COMMANDLINE_MAP_SAVER(Sawyer::Container::Map, insert);
492 SAWYER_COMMANDLINE_INTERVALSET_SAVER(Sawyer::Container::IntervalSet, insert);
493 
495 // Parsed value
497 
504 class SAWYER_EXPORT ParsedValue {
505 #include <Sawyer/WarningsOff.h>
506  boost::any value_;
507  Location valueLocation_;
508  std::string valueString_;
509  std::string switchKey_;
510  Location switchLocation_;
511  std::string switchString_;
512  size_t keySequence_;
513  size_t switchSequence_;
514  ValueSaver::Ptr valueSaver_;
515 #include <Sawyer/WarningsRestore.h>
516 
517 public:
519  ParsedValue(): keySequence_(0), switchSequence_(0) {}
520 
530  ParsedValue(const boost::any value, const Location &loc, const std::string &str, const ValueSaver::Ptr &saver)
531  : value_(value), valueLocation_(loc), valueString_(str), keySequence_(0), switchSequence_(0), valueSaver_(saver) {}
532 
535  ParsedValue& switchInfo(const std::string &key, const Location &loc, const std::string &str) {
536  switchKey_ = key;
537  switchLocation_ = loc;
538  switchString_ = str;
539  return *this;
540  }
541 
542 private:
543  friend class ParserResult;
544  void sequenceInfo(size_t keySequence, size_t switchSequence) {
545  keySequence_ = keySequence;
546  switchSequence_ = switchSequence;
547  }
548 
549 public:
555  const boost::any& value() const { return value_; }
556  void value(const boost::any &v) { value_ = v; }
562  Location valueLocation() const { return valueLocation_; }
563  ParsedValue& valueLocation(const Location &loc) { valueLocation_ = loc; return *this; }
567  const std::string &string() const { return valueString_; }
568 
574  int asInt() const;
575  unsigned asUnsigned() const;
576  long asLong() const;
577  unsigned long asUnsignedLong() const;
578  boost::int64_t asInt64() const;
579  boost::uint64_t asUnsigned64() const;
580  double asDouble() const;
581  float asFloat() const;
582  bool asBool() const;
583  std::string asString() const;
588  template<typename T> T as() const { return boost::any_cast<T>(value_); }
589 
592  ParsedValue& switchKey(const std::string &s) { switchKey_ = s; return *this; }
593  const std::string& switchKey() const { return switchKey_; }
603  const std::string& switchString() const { return switchString_; }
604 
608  Location switchLocation() const { return switchLocation_; }
609 
612  size_t keySequence() const { return keySequence_; }
613 
616  size_t switchSequence() const { return switchSequence_; }
617 
620  const ValueSaver::Ptr valueSaver() const { return valueSaver_; }
621 
624  void save() const;
625 
627  bool isEmpty() const { return value_.empty(); }
628 
630  void print(std::ostream&) const;
631 };
632 
634 SAWYER_EXPORT std::ostream& operator<<(std::ostream&, const ParsedValue&);
635 
637 typedef std::vector<ParsedValue> ParsedValues;
638 
639 
640 
641 
643 // Switch argument parsers
645 
698 class SAWYER_EXPORT ValueParser: public SharedObject, public SharedFromThis<ValueParser> {
699 #include <Sawyer/WarningsOff.h>
700  ValueSaver::Ptr valueSaver_;
701 #include <Sawyer/WarningsRestore.h>
702 protected:
705 
707  explicit ValueParser(const ValueSaver::Ptr &valueSaver): valueSaver_(valueSaver) {}
708 public:
711 
712  virtual ~ValueParser() {}
713 
717  ParsedValue matchString(const std::string&) /*final*/;
718 
723  ParsedValue match(Cursor&) /*final*/;
724 
739  Ptr valueSaver(const ValueSaver::Ptr &f) { valueSaver_ = f; return sharedFromThis(); }
740  const ValueSaver::Ptr valueSaver() const { return valueSaver_; }
743 private:
746  virtual ParsedValue operator()(Cursor&);
747  virtual ParsedValue operator()(const char *input, const char **endptr, const Location&);
749 };
750 
751 // used internally to convert from one type to another via boost::lexical_cast or throw a runtime_error with a decent message.
752 template<typename T>
753 struct LexicalCast {
754  static T convert(const std::string &src) {
755  try {
756  return boost::lexical_cast<T>(src);
757  } catch (const boost::bad_lexical_cast &e) {
758  throw std::runtime_error(e.what());
759  }
760  }
761 };
762 
763 template<>
764 struct LexicalCast<boost::regex> {
765  static boost::regex convert(const std::string &src) {
766  return boost::regex(src);
767  }
768 };
769 
770 template<>
771 struct LexicalCast<boost::any> {
772  static boost::any convert(const std::string &src) {
773  return src;
774  }
775 };
776 
777 template<typename T>
778 struct LexicalCast<Optional<T> > {
779  static T convert(const std::string &src) {
780  return LexicalCast<T>::convert(src);
781  }
782 };
783 
784 template<typename T>
786  static T convert(const std::string &src) {
787  return LexicalCast<T>::convert(src);
788  }
789 };
790 
791 template<typename T>
792 struct LexicalCast<Sawyer::Container::Map<std::string, T> > {
793  static T convert(const std::string &src) {
794  return LexicalCast<T>::convert(src);
795  }
796 };
797 
798 template<typename T>
799 struct LexicalCast<std::vector<T> > {
800  static T convert(const std::string &src) {
801  return LexicalCast<T>::convert(src);
802  }
803 };
804 
805 template<typename T>
806 struct LexicalCast<std::set<T> > {
807  static T convert(const std::string &src) {
808  return LexicalCast<T>::convert(src);
809  }
810 };
811 
812 template<typename T>
813 struct LexicalCast<std::list<T> > {
814  static T convert(const std::string &src) {
815  return LexicalCast<T>::convert(src);
816  }
817 };
818 
819 template<typename T>
820 struct LexicalCast<std::map<std::string, T> > {
821  static T convert(const std::string &src) {
822  return LexicalCast<T>::convert(src);
823  }
824 };
825 
849 template<typename T>
850 class AnyParser: public ValueParser {
851 protected:
854 
857 public:
860 
864  static Ptr instance() { return Ptr(new AnyParser); }
865 
869  static Ptr instance(const ValueSaver::Ptr &valueSaver) { return Ptr(new AnyParser(valueSaver)); }
870 private:
871  virtual ParsedValue operator()(Cursor &cursor) /*override*/ {
872  if (cursor.atEnd())
873  throw std::runtime_error("string expected");
874  Location startLoc = cursor.location();
875  std::string s = cursor.rest();
876  cursor.consumeChars(s.size());
877  return ParsedValue(LexicalCast<T>::convert(s), startLoc, s, valueSaver());
878  }
879 };
880 
881 // used internally to cast one numeric type to another and throw a range_error with a decent message.
882 template<typename Target, typename Source>
883 struct NumericCast {
884  static Target convert(Source from, const std::string &parsed) {
885  try {
886  return boost::numeric_cast<Target>(from);
887  } catch (const boost::numeric::positive_overflow&) {
888  std::string bound = boost::lexical_cast<std::string>(boost::numeric::bounds<Target>::highest());
889  throw std::range_error("parsed string \""+parsed+"\" is greater than "+bound);
890  } catch (const boost::numeric::negative_overflow&) {
891  std::string bound = boost::lexical_cast<std::string>(boost::numeric::bounds<Target>::lowest());
892  throw std::range_error("parsed string \""+parsed+"\" is less than "+bound);
893  } catch (const boost::numeric::bad_numeric_cast&) {
894  throw std::range_error("cannot cast \""+parsed+"\" to destination type");
895  }
896  }
897 };
898 
899 // partial specialization for Sawyer::Optional<Target>
900 template<typename Target, typename Source>
901 struct NumericCast<Optional<Target>, Source> {
902  static Target convert(Source from, const std::string &parsed) {
903  return NumericCast<Target, Source>::convert(from, parsed);
904  }
905 };
906 
907 // partial specialization for std::vector<Target>
908 template<typename Target, typename Source>
909 struct NumericCast<std::vector<Target>, Source> {
910  static Target convert(Source from, const std::string &parsed) {
911  return NumericCast<Target, Source>::convert(from, parsed);
912  }
913 };
914 
915 // partial specialization for std::list<Target>
916 template<typename Target, typename Source>
917 struct NumericCast<std::list<Target>, Source> {
918  static Target convert(Source from, const std::string &parsed) {
919  return NumericCast<Target, Source>::convert(from, parsed);
920  }
921 };
922 
923 // partial specialization for std::set<Target>
924 template<typename Target, typename Source>
925 struct NumericCast<std::set<Target>, Source> {
926  static Target convert(Source from, const std::string &parsed) {
927  return NumericCast<Target, Source>::convert(from, parsed);
928  }
929 };
930 
931 // partial specialization for Sawyer::Container::Set<Target>
932 template<typename Target, typename Source>
933 struct NumericCast<Sawyer::Container::Set<Target>, Source> {
934  static Target convert(Source from, const std::string &parsed) {
935  return NumericCast<Target, Source>::convert(from, parsed);
936  }
937 };
938 
939 // partial specialization for std::map<std::string, Target>
940 template<typename Target, typename Source>
941 struct NumericCast<std::map<std::string, Target>, Source> {
942  static Target convert(Source from, const std::string &parsed) {
943  return NumericCast<Target, Source>::convert(from, parsed);
944  }
945 };
946 
947 // partial specialization for Sawyer::Container::Map<std::string, Target>
948 template<typename Target, typename Source>
949 struct NumericCast<Sawyer::Container::Map<std::string, Target>, Source> {
950  static Target convert(Source from, const std::string &parsed) {
951  return NumericCast<Target, Source>::convert(from, parsed);
952  }
953 };
954 
964 template<typename T>
965 class IntegerParser: public ValueParser {
966 protected:
969 
971  explicit IntegerParser(const ValueSaver::Ptr &valueSaver): ValueParser(valueSaver) {}
972 public:
975 
982  static Ptr instance() { return Ptr(new IntegerParser); }
983 
990  static Ptr instance(const ValueSaver::Ptr &valueSaver) { return Ptr(new IntegerParser(valueSaver)); }
991 private:
992  virtual ParsedValue operator()(const char *input, const char **rest, const Location &loc) /*override*/ {
993  errno = 0;
994  boost::int64_t big = strtoll(input, (char**)rest, 0);
995  if (*rest==input)
996  throw std::runtime_error("integer expected");
997  while (isspace(**rest)) ++*rest;
998  std::string parsed(input, *rest-input);
999  if (ERANGE==errno)
1000  throw std::range_error("integer overflow when parsing \""+parsed+"\"");
1001  return ParsedValue(NumericCast<T, boost::int64_t>::convert(big, parsed), loc, parsed, valueSaver());
1002  }
1003 };
1004 
1015 template<typename T>
1017 protected:
1020 
1023 public:
1026 
1030  static Ptr instance() { return Ptr(new NonNegativeIntegerParser); }
1031 
1035  static Ptr instance(const ValueSaver::Ptr &valueSaver) { return Ptr(new NonNegativeIntegerParser(valueSaver)); }
1036 private:
1037  virtual ParsedValue operator()(const char *input, const char **rest, const Location &loc) /*override*/ {
1038  errno = 0;
1039  while (isspace(*input)) ++input;
1040  if ('+'!=*input && !isdigit(*input))
1041  throw std::runtime_error("unsigned integer expected");
1042  boost::uint64_t big = strtoull(input, (char**)rest, 0);
1043  if (*rest==input)
1044  throw std::runtime_error("unsigned integer expected");
1045  while (isspace(**rest)) ++*rest;
1046  std::string parsed(input, *rest-input);
1047  if (ERANGE==errno)
1048  throw std::range_error("integer overflow when parsing \""+parsed+"\"");
1049  return ParsedValue(NumericCast<T, boost::uint64_t>::convert(big, parsed), loc, parsed, valueSaver());
1050  }
1051 };
1052 
1063 template<typename T>
1065 protected:
1068 
1071 public:
1074 
1078  static Ptr instance() { return Ptr(new PositiveIntegerParser); }
1079 
1083  static Ptr instance(const ValueSaver::Ptr &valueSaver) { return Ptr(new PositiveIntegerParser(valueSaver)); }
1084 private:
1085  virtual ParsedValue operator()(const char *input, const char **rest, const Location &loc) /*override*/ {
1086  errno = 0;
1087  while (isspace(*input)) ++input;
1088  if ('+'!=*input && !isdigit(*input))
1089  throw std::runtime_error("positive integer expected");
1090  boost::uint64_t big = strtoull(input, (char**)rest, 0);
1091  if (*rest==input || big==0)
1092  throw std::runtime_error("positive integer expected");
1093  while (isspace(**rest)) ++*rest;
1094  std::string parsed(input, *rest-input);
1095  if (ERANGE==errno)
1096  throw std::range_error("integer overflow when parsing \""+parsed+"\"");
1097  return ParsedValue(NumericCast<T, boost::uint64_t>::convert(big, parsed), loc, parsed, valueSaver());
1098  }
1099 };
1100 
1110 template<typename T>
1112 protected:
1115 
1118 public:
1121 
1125  static Ptr instance() { return Ptr(new RealNumberParser); }
1126 
1130  static Ptr instance(const ValueSaver::Ptr &valueSaver) { return Ptr(new RealNumberParser(valueSaver)); }
1131 private:
1132  virtual ParsedValue operator()(const char *input, const char **rest, const Location &loc) /*override*/ {
1133  double big = strtod(input, (char**)rest);
1134  if (*rest==input)
1135  throw std::runtime_error("real number expected");
1136  while (isspace(**rest)) ++*rest;
1137  std::string parsed(input, *rest-input);
1138  return ParsedValue(NumericCast<T, double>::convert(big, parsed), loc, parsed, valueSaver());
1139  }
1140 };
1141 
1148 template<typename T>
1150 protected:
1153 
1156 public:
1159 
1163  static Ptr instance() { return Ptr(new BooleanParser); }
1164 
1168  static Ptr instance(const ValueSaver::Ptr &valueSaver) { return Ptr(new BooleanParser(valueSaver)); }
1169 private:
1170  virtual ParsedValue operator()(const char *input, const char **rest, const Location &loc) /*override*/ {
1171  static const char *neg[] = {"false", "off", "no", "0", "f", "n"}; // longest to shortest
1172  static const char *pos[] = {"true", "yes", "on", "1", "t", "y"};
1173  const char *start = input;
1174  while (isspace(*input)) ++input;
1175  for (int negpos=0; negpos<2; ++negpos) {
1176  const char **list = 0==negpos ? neg : pos;
1177  size_t listsz = 0==negpos ? sizeof(neg)/sizeof(*neg) : sizeof(pos)/sizeof(*pos);
1178  for (size_t i=0; i<listsz; ++i) {
1179  if (0==my_strncasecmp(list[i], input, strlen(list[i]))) {
1180  *rest = input + strlen(list[i]);
1181  while (isspace(**rest)) ++*rest;
1182  std::string parsed(start, *rest-start);
1183  return ParsedValue(NumericCast<T, bool>::convert(0!=negpos, parsed), loc, parsed, valueSaver());
1184  }
1185  }
1186  }
1187  throw std::runtime_error("Boolean expected");
1188  }
1189 
1190  // Microsoft doesn't have the POSIX.1-2001 strncasecmp function
1191  int my_strncasecmp(const char *a, const char *b, size_t nchars) {
1192  ASSERT_not_null(a);
1193  ASSERT_not_null(b);
1194  for (size_t i=0; i<nchars; ++i) {
1195  if (!a[i] || !b[i])
1196  return a[i] ? 1 : (b[i] ? -1 : 0);
1197  char achar = (char)tolower(a[i]);
1198  char bchar = (char)tolower(b[i]);
1199  if (achar != bchar)
1200  return achar < bchar ? -1 : 1;
1201  }
1202  return 0;
1203  }
1204 };
1205 
1214 class SAWYER_EXPORT StringSetParser: public ValueParser {
1215 #include <Sawyer/WarningsOff.h>
1216  std::vector<std::string> strings_;
1217 #include <Sawyer/WarningsRestore.h>
1218 protected:
1221 
1223  StringSetParser(const ValueSaver::Ptr &valueSaver): ValueParser(valueSaver) {}
1224 public:
1227 
1231  static Ptr instance() { return Ptr(new StringSetParser); }
1232 
1236  static Ptr instance(const ValueSaver::Ptr &valueSaver) { return Ptr(new StringSetParser(valueSaver)); }
1237 
1240  Ptr with(const std::string &s) { return with(&s, &s+1); }
1241  Ptr with(const std::vector<std::string> sv) { return with(sv.begin(), sv.end()); }
1242  template<class InputIterator>
1243  Ptr with(InputIterator begin, InputIterator end) {
1244  strings_.insert(strings_.end(), begin, end);
1245  return sharedFromThis().dynamicCast<StringSetParser>();
1246  }
1249 private:
1250  virtual ParsedValue operator()(Cursor&) /*override*/;
1251 };
1252 
1260 template<typename T>
1261 class EnumParser: public ValueParser {
1262  StringSetParser::Ptr strParser_;
1264 protected:
1266  EnumParser(): strParser_(StringSetParser::instance()) {}
1267 
1270 public:
1273 
1277  static Ptr instance() { return Ptr(new EnumParser); }
1278 
1282  static Ptr instance(const ValueSaver::Ptr &valueSaver) { return Ptr(new EnumParser(valueSaver)); }
1283 
1285  Ptr with(const std::string &name, T value) {
1286  strParser_->with(name);
1287  members_.insert(name, value);
1288  return sharedFromThis().template dynamicCast<EnumParser>();
1289  }
1290 private:
1291  virtual ParsedValue operator()(Cursor &cursor) /*override*/ {
1292  ParsedValue strVal = strParser_->match(cursor);
1293  return ParsedValue(members_[strVal.string()], strVal.valueLocation(), strVal.string(), valueSaver());
1294  }
1295 };
1296 
1304 class SAWYER_EXPORT ListParser: public ValueParser {
1305  typedef std::pair<ValueParser::Ptr, std::string> ParserSep;
1306 #include <Sawyer/WarningsOff.h>
1307  std::vector<ParserSep> elements_;
1308  size_t minLength_, maxLength_; // limits on the number of values permitted
1309 #include <Sawyer/WarningsRestore.h>
1310 protected:
1312  ListParser(const ValueParser::Ptr &firstElmtType, const std::string &separatorRe)
1313  : minLength_(1), maxLength_((size_t)-1) {
1314  elements_.push_back(ParserSep(firstElmtType, separatorRe));
1315  }
1316 public:
1319 
1321  typedef std::list<ParsedValue> ValueList;
1322 
1330  static Ptr instance(const ValueParser::Ptr &firstElmtType, const std::string &separatorRe="[,;:]\\s*") {
1331  return Ptr(new ListParser(firstElmtType, separatorRe));
1332  }
1333 
1340  Ptr nextMember(const ValueParser::Ptr &elmtType, const std::string &separatorRe="[,;:]\\s*") {
1341  elements_.push_back(ParserSep(elmtType, separatorRe));
1342  return sharedFromThis().dynamicCast<ListParser>();
1343  }
1344 
1351  Ptr limit(size_t minLength, size_t maxLength);
1352  Ptr limit(size_t maxLength) { return limit(std::min(minLength_, maxLength), maxLength); }
1353  Ptr exactly(size_t length) { return limit(length, length); }
1355 private:
1356  virtual ParsedValue operator()(Cursor&) /*override*/;
1357 };
1358 
1414 template<typename T>
1415 typename AnyParser<T>::Ptr anyParser(T &storage) {
1417 }
1418 template<typename T>
1420  return AnyParser<T>::instance();
1421 }
1422 SAWYER_EXPORT AnyParser<std::string>::Ptr anyParser();
1423 
1424 template<typename T>
1425 typename IntegerParser<T>::Ptr integerParser(T &storage) {
1427 }
1428 template<typename T>
1430  return IntegerParser<T>::instance();
1431 }
1432 SAWYER_EXPORT IntegerParser<int>::Ptr integerParser();
1433 
1434 template<typename T>
1437 }
1438 template<typename T>
1441 }
1442 SAWYER_EXPORT NonNegativeIntegerParser<unsigned>::Ptr nonNegativeIntegerParser();
1443 
1444 template<typename T>
1447 }
1448 template<typename T>
1451 }
1452 SAWYER_EXPORT PositiveIntegerParser<unsigned>::Ptr positiveIntegerParser();
1453 
1454 template<typename T>
1457 }
1458 template<typename T>
1461 }
1462 SAWYER_EXPORT RealNumberParser<double>::Ptr realNumberParser();
1463 
1464 template<typename T>
1465 typename BooleanParser<T>::Ptr booleanParser(T &storage) {
1467 }
1468 template<typename T>
1470  return BooleanParser<T>::instance();
1471 }
1472 SAWYER_EXPORT BooleanParser<bool>::Ptr booleanParser();
1473 
1474 template<typename T>
1475 typename EnumParser<T>::Ptr enumParser(T &storage) {
1477 }
1478 template<typename T>
1479 typename EnumParser<T>::Ptr enumParser(std::vector<T> &storage) {
1480  return EnumParser<T>::instance(TypedSaver<std::vector<T> >::instance(storage));
1481 }
1482 template<typename T>
1484  return EnumParser<T>::instance(TypedSaver<Optional<T> >::instance(storage));
1485 }
1486 template<typename T>
1488  return EnumParser<T>::instance(TypedSaver<BitFlags<T> >::instance(storage));
1489 }
1490 template<typename T>
1492  return EnumParser<T>::instance();
1493 }
1494 
1495 SAWYER_EXPORT StringSetParser::Ptr stringSetParser(std::string &storage);
1496 SAWYER_EXPORT StringSetParser::Ptr stringSetParser();
1497 
1498 SAWYER_EXPORT ListParser::Ptr listParser(const ValueParser::Ptr&, const std::string &sepRe="[,;:]\\s*");
1502 // Switch argument descriptors
1505 
1520 class SAWYER_EXPORT SwitchArgument {
1521 #include <Sawyer/WarningsOff.h>
1522  std::string name_; // argument name for synopsis
1523  ValueParser::Ptr parser_; // how to match and parse this argument
1524  ParsedValue defaultValue_; // default value if the argument is optional
1525 #include <Sawyer/WarningsRestore.h>
1526 public:
1529  explicit SwitchArgument(const std::string &name, const ValueParser::Ptr &parser = anyParser())
1530  : name_(name), parser_(parser) {}
1531 
1535  SwitchArgument(const std::string &name, const ValueParser::Ptr &parser, const std::string &defaultValueString)
1536  : name_(name), parser_(parser), defaultValue_(parser->matchString(defaultValueString)) {
1537  defaultValue_.valueLocation(NOWHERE);
1538  }
1539 
1541  bool isRequired() const {
1542  return defaultValue_.isEmpty();
1543  }
1544 
1547  bool isOptional() const {
1548  return !isRequired();
1549  }
1550 
1556  const std::string &name() const { return name_; }
1557 
1559  std::string nameAsText() const;
1560 
1562  const ParsedValue& defaultValue() const {
1563  return defaultValue_;
1564  }
1565 
1569  const std::string& defaultValueString() const {
1570  return defaultValue_.string();
1571  }
1572 
1574  const ValueParser::Ptr& parser() const { return parser_; }
1575 };
1576 
1577 
1579 // Switch actions
1581 
1597 class SAWYER_EXPORT SwitchAction: public SharedObject {
1598 public:
1601  virtual ~SwitchAction() {}
1602 
1604  void run(const ParserResult &parserResult) /*final*/ { (*this)(parserResult); }
1605 protected:
1606  virtual void operator()(const ParserResult&) = 0;
1607 };
1608 
1612 class SAWYER_EXPORT ShowVersion: public SwitchAction {
1613 #include <Sawyer/WarningsOff.h>
1614  std::string versionString_;
1615 #include <Sawyer/WarningsRestore.h>
1616 protected:
1618  explicit ShowVersion(const std::string &versionString): versionString_(versionString) {}
1619 public:
1622 
1627  static Ptr instance(const std::string &versionString) { return Ptr(new ShowVersion(versionString)); }
1628 protected:
1629  virtual void operator()(const ParserResult&) /*overload*/;
1630 };
1631 
1634 class SAWYER_EXPORT ShowVersionAndExit: public ShowVersion {
1635  int exitStatus_;
1636 protected:
1638  explicit ShowVersionAndExit(const std::string &versionString, int exitStatus)
1639  : ShowVersion(versionString), exitStatus_(exitStatus) {}
1640 public:
1643 
1648  static Ptr instance(const std::string &versionString, int exitStatus) {
1649  return Ptr(new ShowVersionAndExit(versionString, exitStatus));
1650  }
1651 protected:
1652  virtual void operator()(const ParserResult&) /*overload*/;
1653 };
1654 
1659 class SAWYER_EXPORT ShowHelp: public SwitchAction {
1660 protected:
1663 public:
1666 
1671  static Ptr instance() { return Ptr(new ShowHelp); }
1672 protected:
1673  virtual void operator()(const ParserResult&) /*override*/;
1674 };
1675 
1678 class SAWYER_EXPORT ShowHelpAndExit: public ShowHelp {
1679  int exitStatus_;
1680 protected:
1682  ShowHelpAndExit(int exitStatus): exitStatus_(exitStatus) {}
1683 public:
1686 
1691  static Ptr instance(int exitStatus) { return Ptr(new ShowHelpAndExit(exitStatus)); }
1692 protected:
1693  virtual void operator()(const ParserResult&) /*override*/;
1694 };
1695 
1711 class SAWYER_EXPORT ConfigureDiagnostics: public SwitchAction {
1712 #include <Sawyer/WarningsOff.h>
1713  std::string switchKey_;
1714  Message::Facilities &facilities_;
1715  bool exitOnHelp_;
1716 #include <Sawyer/WarningsRestore.h>
1717 protected:
1719  ConfigureDiagnostics(const std::string &switchKey, Message::Facilities &facilities, bool exitOnHelp)
1720  : switchKey_(switchKey), facilities_(facilities), exitOnHelp_(exitOnHelp) {}
1721 public:
1724 
1729  static Ptr instance(const std::string &switchKey, Message::Facilities &facilities, bool exitOnHelp=true) {
1730  return Ptr(new ConfigureDiagnostics(switchKey, facilities, exitOnHelp));
1731  }
1732 
1738  bool exitOnHelp() const { return exitOnHelp_; }
1739  void exitOnHelp(bool b) { exitOnHelp_=b; }
1741 protected:
1742  virtual void operator()(const ParserResult&) /*override*/;
1743 };
1744 
1752 class SAWYER_EXPORT ConfigureDiagnosticsQuiet: public SwitchAction {
1753 #include <Sawyer/WarningsOff.h>
1754  Message::Facilities &facilities_;
1755 #include <Sawyer/WarningsRestore.h>
1756 protected:
1758  : facilities_(facilities) {
1759  }
1760 
1761 public:
1764 
1769  static Ptr instance(Message::Facilities &facilities) {
1770  return Ptr(new ConfigureDiagnosticsQuiet(facilities));
1771  }
1772 
1773 protected:
1774  virtual void operator()(const ParserResult&) /*override*/;
1775 };
1776 
1796 template<class Functor>
1797 class UserAction: public SwitchAction {
1798  Functor &functor_;
1799 protected:
1801  UserAction(Functor &f): functor_(f) {}
1802 public:
1805 
1810  static Ptr instance(Functor &f) { return Ptr(new UserAction(f)); }
1811 protected:
1812  virtual void operator()(const ParserResult &parserResult) /*override*/ { (functor_)(parserResult); }
1813 };
1814 
1844 SAWYER_EXPORT ShowVersion::Ptr showVersion(const std::string &versionString);
1845 SAWYER_EXPORT ShowVersionAndExit::Ptr showVersionAndExit(const std::string &versionString, int exitStatus);
1846 
1847 SAWYER_EXPORT ShowHelp::Ptr showHelp();
1848 
1849 SAWYER_EXPORT ShowHelpAndExit::Ptr showHelpAndExit(int exitStatus);
1850 
1851 SAWYER_EXPORT ConfigureDiagnostics::Ptr configureDiagnostics(const std::string&, Message::Facilities&, bool exitOnHelp=true);
1852 
1853 SAWYER_EXPORT ConfigureDiagnosticsQuiet::Ptr configureDiagnosticsQuiet(Message::Facilities&);
1854 
1855 template<class Functor>
1856 typename UserAction<Functor>::Ptr userAction(const Functor &functor) {
1857  return UserAction<Functor>::instance(functor);
1858 }
1863 // Switch value agumenters
1866 
1881 class SAWYER_EXPORT ValueAugmenter: public SharedObject {
1882 public:
1885  virtual ~ValueAugmenter() {}
1886 
1891  virtual ParsedValues operator()(const ParsedValues &savedValues, const ParsedValues &newValues) = 0;
1892 };
1893 
1906 template<typename T>
1907 class Sum: public ValueAugmenter {
1908 protected:
1910  Sum() {}
1911 public:
1914 
1919  static Ptr instance() { return Ptr(new Sum<T>); }
1920 
1921  virtual ParsedValues operator()(const ParsedValues &savedValues, const ParsedValues &newValues) /*override*/ {
1922  ASSERT_forbid(newValues.empty());
1923  T sum = 0;
1924  BOOST_FOREACH (const ParsedValue &pv, savedValues)
1925  sum = sum + boost::any_cast<T>(pv.value());
1926  BOOST_FOREACH (const ParsedValue &pv, newValues)
1927  sum = sum + boost::any_cast<T>(pv.value());
1928  ParsedValue pval = newValues.front(); // so we keep the same location information
1929  pval.value(sum);
1930  ParsedValues pvals;
1931  pvals.push_back(pval);
1932  return pvals;
1933  }
1934 };
1935 
1965 template<typename T>
1966 typename Sum<T>::Ptr sum() {
1967  return Sum<T>::instance();
1968 }
1973 // Switch descriptors
1976 
1977 // Used internally to pass around switch properties that are common among parsers, switch groups, and switches.
1978 struct SAWYER_EXPORT ParsingProperties {
1979 #include <Sawyer/WarningsOff.h>
1980  std::vector<std::string> longPrefixes; // Prefixes for long command-line switches
1981  bool inheritLongPrefixes; // True if this also inherits longPrefixes from a higher layer
1982  std::vector<std::string> shortPrefixes;
1983  bool inheritShortPrefixes;
1984  std::vector<std::string> valueSeparators; // What separates a long switch from its value.
1985  bool inheritValueSeparators;
1986  ShowGroupName showGroupName; // How to show group name in switch synopsis
1987 #include <Sawyer/WarningsRestore.h>
1989  : inheritLongPrefixes(true), inheritShortPrefixes(true), inheritValueSeparators(true),
1990  showGroupName(SHOW_GROUP_INHERIT) {}
1991  ParsingProperties inherit(const ParsingProperties &base) const;
1992 };
1993 
2002 };
2003 
2026 class SAWYER_EXPORT Switch {
2027 private:
2028 #include <Sawyer/WarningsOff.h>
2029  std::vector<std::string> longNames_; // Long name of switch, or empty string.
2030  std::string shortNames_; // Optional short names for this switch.
2031  std::string key_; // Unique key, usually the long name or the first short name.
2032  ParsingProperties properties_; // Properties valid at multiple levels of the hierarchy.
2033  std::string synopsis_; // User-defined synopsis or empty string.
2034  std::string documentation_; // Main documentation for the switch.
2035  std::string documentationKey_; // For sorting documentation.
2036  bool hidden_; // Whether to hide documentation.
2037  std::vector<SwitchArgument> arguments_; // Arguments with optional default values.
2038  SwitchAction::Ptr action_; // Optional action to perform during ParserResult::apply.
2039  WhichValue whichValue_; // Which switch values should be saved.
2040  ValueAugmenter::Ptr valueAugmenter_; // Used if <code>whichValue_==SAVE_AUGMENTED</code>.
2041  ParsedValue intrinsicValue_; // Value for switches that have no declared arguments.
2042  bool explosiveLists_; // Whether to expand ListParser::ValueList into separate values.
2043  SwitchSkipping skipping_; // Whether to skip over this switch without saving or acting.
2044 #include <Sawyer/WarningsRestore.h>
2045 
2046 public:
2059  explicit Switch(const std::string &longName, char shortName='\0')
2060  : hidden_(false), whichValue_(SAVE_LAST), intrinsicValue_(ParsedValue(true, NOWHERE, "true", ValueSaver::Ptr())),
2061  explosiveLists_(false), skipping_(SKIP_NEVER) {
2062  init(longName, shortName);
2063  }
2064 
2065  // FIXME[Robb Matzke 2014-03-03]: test that "--prefix=5" works when names are "pre" and "prefix" in that order
2070  Switch& longName(const std::string &name);
2071  const std::string& longName() const { return longNames_.front(); }
2072  const std::vector<std::string>& longNames() const { return longNames_; }
2080  Switch& shortName(char c) { if (c) shortNames_ += std::string(1, c); return *this; }
2081  const std::string& shortNames() const { return shortNames_; }
2086  std::string preferredName() const { return longNames_.empty() ? std::string(1, shortNames_[0]) : longNames_[0]; }
2087 
2096  Switch& key(const std::string &s) { key_ = s; return *this; }
2097  const std::string &key() const { return key_; }
2131  Switch& synopsis(const std::string &s) { synopsis_ = s; return *this; }
2132  std::string synopsis() const;
2170  Switch& doc(const std::string &s) { documentation_ = s; return *this; }
2171  const std::string& doc() const { return documentation_; }
2178  Switch& docKey(const std::string &s) { documentationKey_ = s; return *this; }
2179  const std::string &docKey() const { return documentationKey_; }
2186  Switch& hidden(bool b) { hidden_ = b; return *this; }
2187  bool hidden() const { return hidden_; }
2201  Switch& skipping(SwitchSkipping how) { skipping_ = how; return *this; }
2202  SwitchSkipping skipping() const { return skipping_; }
2216  Switch& resetLongPrefixes(const std::string &s1=STR_NONE, const std::string &s2=STR_NONE,
2217  const std::string &s3=STR_NONE, const std::string &s4=STR_NONE);
2218  Switch& longPrefix(const std::string &s1) { properties_.longPrefixes.push_back(s1); return *this; }
2219  const std::vector<std::string>& longPrefixes() const { return properties_.longPrefixes; }
2233  Switch& resetShortPrefixes(const std::string &s1=STR_NONE, const std::string &s2=STR_NONE,
2234  const std::string &s3=STR_NONE, const std::string &s4=STR_NONE);
2235  Switch& shortPrefix(const std::string &s1) { properties_.shortPrefixes.push_back(s1); return *this; }
2236  const std::vector<std::string>& shortPrefixes() const { return properties_.shortPrefixes; }
2255  Switch& resetValueSeparators(const std::string &s1=STR_NONE, const std::string &s2=STR_NONE,
2256  const std::string &s3=STR_NONE, const std::string &s4=STR_NONE);
2257  Switch& valueSeparator(const std::string &s1) { properties_.valueSeparators.push_back(s1); return *this; }
2258  const std::vector<std::string>& valueSeparators() const { return properties_.valueSeparators; }
2283  Switch& argument(const std::string &name, const ValueParser::Ptr &parser = anyParser());
2284  Switch& argument(const std::string &name, const ValueParser::Ptr &parser, const std::string &defaultValue);
2285  Switch& argument(const SwitchArgument &arg) { arguments_.push_back(arg); return *this; }
2286  const SwitchArgument& argument(size_t idx) const { return arguments_[idx]; }
2287  const std::vector<SwitchArgument>& arguments() const { return arguments_; }
2291  size_t nArguments() const { return arguments_.size(); }
2292 
2295  size_t nRequiredArguments() const;
2296 
2326  template<typename T>
2327  Switch& intrinsicValue(const T &value, T &storage) {
2328  intrinsicValue_ = ParsedValue(value, NOWHERE, boost::lexical_cast<std::string>(value), TypedSaver<T>::instance(storage));
2329  return *this;
2330  }
2331  Switch& intrinsicValue(const char *value, std::string &storage) {
2332  intrinsicValue_ = ParsedValue(std::string(value), NOWHERE, value, TypedSaver<std::string>::instance(storage));
2333  return *this;
2334  }
2335  Switch& intrinsicValue(const std::string &text, const ValueParser::Ptr &p) {
2336  intrinsicValue_ = p->matchString(text);
2337  intrinsicValue_.valueLocation(NOWHERE);
2338  return *this;
2339  }
2340  Switch& intrinsicValue(const std::string &text) {
2341  intrinsicValue_ = anyParser()->matchString(text);
2342  intrinsicValue_.valueLocation(NOWHERE);
2343  return *this;
2344  }
2345  Switch& intrinsicValue(const ParsedValue &value) { intrinsicValue_ = value; return *this; }
2346  ParsedValue intrinsicValue() const { return intrinsicValue_; }
2371  Switch& explosiveLists(bool b) { explosiveLists_ = b; return *this; }
2372  bool explosiveLists() const { return explosiveLists_; }
2396  Switch& action(const SwitchAction::Ptr &f) { action_ = f; return *this; }
2397  const SwitchAction::Ptr& action() const { return action_; }
2425  Switch& whichValue(WhichValue s) { whichValue_ = s; return *this; }
2426  WhichValue whichValue() const { return whichValue_; }
2437  Switch& valueAugmenter(const ValueAugmenter::Ptr &f) { valueAugmenter_ = f; return *this; }
2438  ValueAugmenter::Ptr valueAugmenter() const { return valueAugmenter_; }
2441 public:
2442  // Used internally
2443  const ParsingProperties& properties() const { return properties_; }
2444 
2445 private:
2446  friend class Parser;
2447  friend class ParserResult;
2448 
2449  void init(const std::string &longName, char shortName);
2450 
2452  std::runtime_error noSeparator(const std::string &switchString, const Cursor&, const ParsingProperties&) const;
2453 
2455  std::runtime_error extraTextAfterSwitch(const std::string &switchString, const Location &endOfSwitch, const Cursor&,
2456  const ParsingProperties&, const ParsedValues&) const;
2457 
2459  std::runtime_error extraTextAfterArgument(const Cursor&, const ParsedValue &va) const;
2460 
2462  std::runtime_error notEnoughArguments(const std::string &switchString, const Cursor&, size_t nargs) const;
2463 
2465  std::runtime_error missingArgument(const std::string &switchString, const Cursor &cursor,
2466  const SwitchArgument &sa, const std::string &reason) const;
2467 
2469  std::runtime_error malformedArgument(const std::string &switchString, const Cursor &cursor,
2470  const SwitchArgument &sa, const std::string &reason) const;
2471 
2478  size_t matchLongName(Cursor&/*in,out*/, const ParsingProperties &props,
2479  const std::string &optionalPart, const std::string &requiredPart) const;
2480 
2487  size_t matchShortName(Cursor&/*in,out*/, const ParsingProperties &props, std::string &name) const;
2488 
2490  bool explode(ParsedValues &pvals /*in,out*/) const;
2491 
2496  void matchLongArguments(const std::string &switchString, Cursor &cursor /*in,out*/, const ParsingProperties &props,
2497  ParsedValues &result /*out*/) const;
2498 
2502  void matchShortArguments(const std::string &switchString, Cursor &cursor /*in,out*/, const ParsingProperties &props,
2503  ParsedValues &result /*out*/, bool mayNestle) const;
2504 
2512  size_t matchArguments(const std::string &switchString, const Location &endOfSwitch, Cursor &cursor /*in,out*/,
2513  const ParsingProperties &props, ParsedValues &result /*out*/, bool isLongSwitch) const;
2514 
2516  std::string synopsisForArgument(const SwitchArgument&) const;
2517 
2518  // If the synopsis is empty, create one from an optional switch group and name space separator
2519  std::string synopsis(const ParsingProperties &swProps, const SwitchGroup *sg, const std::string &nameSpaceSeparator) const;
2520 };
2521 
2523 // Switch groups
2525 
2526 
2554 class SAWYER_EXPORT SwitchGroup {
2555 #include <Sawyer/WarningsOff.h>
2556  std::vector<Switch> switches_;
2557  ParsingProperties properties_;
2558  std::string name_; // name optionally prepended to all switches
2559  std::string title_; // title showing in documentation
2560  std::string docKey_; // for sorting
2561  std::string documentation_;
2562  SortOrder switchOrder_;
2563 #include <Sawyer/WarningsRestore.h>
2564 public:
2567 
2574  explicit SwitchGroup(const std::string &title, const std::string &docKey="")
2575  : title_(title), docKey_(docKey), switchOrder_(DOCKEY_ORDER) {}
2576 
2582  const std::string& title() const { return title_; }
2583  SwitchGroup& title(const std::string &title) { title_ = title; return *this; }
2596  const std::string& name() const { return name_; }
2597  SwitchGroup& name(const std::string &name) { name_ = name; return *this; }
2612  const std::string& docKey() const { return docKey_; }
2613  SwitchGroup& docKey(const std::string &key) { docKey_ = key; return *this; }
2628  SwitchGroup& doc(const std::string &s) { documentation_ = s; return *this; }
2629  const std::string& doc() const { return documentation_; }
2638  ShowGroupName showingGroupNames() const { return properties_.showGroupName; }
2639  void showingGroupNames(ShowGroupName x) { properties_.showGroupName = x; }
2644  SwitchGroup& resetLongPrefixes(const std::string &s1=STR_NONE, const std::string &s2=STR_NONE,
2645  const std::string &s3=STR_NONE, const std::string &s4=STR_NONE);
2646  SwitchGroup& longPrefix(const std::string &s1) { properties_.longPrefixes.push_back(s1); return *this; }
2647  const std::vector<std::string>& longPrefixes() const { return properties_.longPrefixes; }
2652  SwitchGroup& resetShortPrefixes(const std::string &s1=STR_NONE, const std::string &s2=STR_NONE,
2653  const std::string &s3=STR_NONE, const std::string &s4=STR_NONE);
2654  SwitchGroup& shortPrefix(const std::string &s1) { properties_.shortPrefixes.push_back(s1); return *this; }
2655  const std::vector<std::string>& shortPrefixes() const { return properties_.shortPrefixes; }
2660  SwitchGroup& resetValueSeparators(const std::string &s1=STR_NONE, const std::string &s2=STR_NONE,
2661  const std::string &s3=STR_NONE, const std::string &s4=STR_NONE);
2662  SwitchGroup& valueSeparator(const std::string &s1) { properties_.valueSeparators.push_back(s1); return *this; }
2663  const std::vector<std::string>& valueSeparators() const { return properties_.valueSeparators; }
2667  size_t nSwitches() const { return switches_.size(); }
2668 
2671  const std::vector<Switch>& switches() const { return switches_; }
2672 
2674  bool nameExists(const std::string &switchName);
2675 
2678  const Switch& getByName(const std::string &switchName);
2679 
2681  bool keyExists(const std::string &switchKey);
2682 
2684  const Switch& getByKey(const std::string &switchKey);
2685 
2687  SwitchGroup& insert(const Switch&);
2688 
2690  SwitchGroup& insert(const SwitchGroup&);
2691 
2693  SwitchGroup& removeByIndex(size_t n);
2694 
2697  SwitchGroup& removeByName(const std::string &switchName);
2698 
2700  SwitchGroup& removeByKey(const std::string &switchKey);
2701 
2713  const SortOrder& switchOrder() const { return switchOrder_; }
2714  SwitchGroup& switchOrder(SortOrder order) { switchOrder_ = order; return *this; }
2717 public:
2718  // Used internally
2719  const ParsingProperties& properties() const { return properties_; }
2720 
2721 private:
2722  friend class Parser;
2723  bool removeByPointer(const void*);
2724 };
2725 
2728 
2731 
2733 // Parser
2735 
2741 class SAWYER_EXPORT Parser {
2742 #include <Sawyer/WarningsOff.h>
2743  std::vector<SwitchGroup> switchGroups_;
2744  ParsingProperties properties_;
2745  std::string groupNameSeparator_;
2746  std::vector<std::string> terminationSwitches_;
2747  bool shortMayNestle_;
2748  std::vector<std::string> inclusionPrefixes_;
2749  bool skipNonSwitches_;
2750  bool skipUnknownSwitches_;
2751  mutable std::string programName_;
2752  std::string purpose_;
2753  std::string versionString_;
2754  mutable std::string dateString_;
2755  int chapterNumber_;
2756  std::string chapterName_;
2758  StringStringMap sectionDoc_;
2759  StringStringMap sectionOrder_;
2760  Message::SProxy errorStream_;
2761  Optional<std::string> exitMessage_;
2762  SortOrder switchGroupOrder_;
2763  bool reportingAmbiguities_;
2764  std::string environmentVariable_;
2765 #include <Sawyer/WarningsRestore.h>
2766 
2767 public:
2771  : groupNameSeparator_("-"), shortMayNestle_(true), skipNonSwitches_(false), skipUnknownSwitches_(false),
2772  versionString_("alpha"), chapterNumber_(1), chapterName_("User Commands"), switchGroupOrder_(INSERTION_ORDER),
2773  reportingAmbiguities_(true) {
2774  init();
2775  }
2776 
2781  switchGroups_.push_back(sg);
2782  return *this;
2783  }
2784  Parser& with(const SwitchGroup &sg, const std::string &docKey) {
2785  switchGroups_.push_back(sg);
2786  switchGroups_.back().docKey(docKey);
2787  return *this;
2788  }
2789  Parser& with(const std::vector<SwitchGroup> &sgs) {
2790  switchGroups_.insert(switchGroups_.end(), sgs.begin(), sgs.end());
2791  return *this;
2792  }
2793  Parser& with(const Switch &sw) {
2794  switchGroups_.push_back(SwitchGroup().insert(sw));
2795  return *this;
2796  }
2797  Parser& with(Switch sw, const std::string &docKey) {
2798  sw.docKey(docKey);
2799  switchGroups_.push_back(SwitchGroup().insert(sw));
2800  return *this;
2801  }
2807  const std::vector<SwitchGroup>& switchGroups() const {
2808  return switchGroups_;
2809  }
2810  std::vector<SwitchGroup>& switchGroups() {
2811  return switchGroups_;
2812  }
2818  bool switchGroupExists(const std::string &name) const;
2819 
2826  const SwitchGroup& switchGroup(const std::string &name) const;
2827  SwitchGroup& switchGroup(const std::string &name);
2834  bool eraseSwitchGroup(const std::string &name);
2835 
2847  bool reportingAmbiguities() const { return reportingAmbiguities_; }
2848  Parser& reportingAmbiguities(bool b) { reportingAmbiguities_ = b; return *this; }
2858  const std::string& groupNameSeparator() const { return groupNameSeparator_; }
2859  Parser& groupNameSeparator(const std::string &s) { groupNameSeparator_ = s; return *this; }
2871  ShowGroupName showingGroupNames() const { return properties_.showGroupName; }
2872  Parser& showingGroupNames(ShowGroupName x) { properties_.showGroupName = x; return *this; }
2879  Parser& resetLongPrefixes(const std::string &s1=STR_NONE, const std::string &s2=STR_NONE,
2880  const std::string &s3=STR_NONE, const std::string &s4=STR_NONE);
2881  Parser& longPrefix(const std::string &s1) { properties_.longPrefixes.push_back(s1); return *this; }
2882  const std::vector<std::string>& longPrefixes() const { return properties_.longPrefixes; }
2889  Parser& resetShortPrefixes(const std::string &s1=STR_NONE, const std::string &s2=STR_NONE,
2890  const std::string &s3=STR_NONE, const std::string &s4=STR_NONE);
2891  Parser& shortPrefix(const std::string &s1) { properties_.shortPrefixes.push_back(s1); return *this; }
2892  const std::vector<std::string>& shortPrefixes() const { return properties_.shortPrefixes; }
2901  Parser& resetValueSeparators(const std::string &s1=STR_NONE, const std::string &s2=STR_NONE,
2902  const std::string &s3=STR_NONE, const std::string &s4=STR_NONE);
2903  Parser& valueSeparator(const std::string &s1) { properties_.valueSeparators.push_back(s1); return *this; }
2904  const std::vector<std::string>& valueSeparators() const { return properties_.valueSeparators; }
2911  Parser& resetTerminationSwitches(const std::string &s1=STR_NONE, const std::string &s2=STR_NONE,
2912  const std::string &s3=STR_NONE, const std::string &s4=STR_NONE);
2913  Parser& terminationSwitch(const std::string &s1) { terminationSwitches_.push_back(s1); return *this; }
2914  const std::vector<std::string>& terminationSwitches() const { return terminationSwitches_; }
2924  Parser& shortMayNestle(bool b) { shortMayNestle_ = b; return *this; }
2925  bool shortMayNestle() const { return shortMayNestle_; }
2939  Parser& resetInclusionPrefixes(const std::string &s1=STR_NONE, const std::string &s2=STR_NONE,
2940  const std::string &s3=STR_NONE, const std::string &s4=STR_NONE);
2941  Parser& inclusionPrefix(const std::string &s1) { inclusionPrefixes_.push_back(s1); return *this; }
2942  const std::vector<std::string>& inclusionPrefixes() const { return inclusionPrefixes_; }
2952  Parser& skippingNonSwitches(bool b) { skipNonSwitches_ = b; return *this; }
2953  bool skippingNonSwitches() const { return skipNonSwitches_; }
2962  Parser& skippingUnknownSwitches(bool b) { skipUnknownSwitches_ = b; return *this; }
2963  bool skippingUnknownSwitches() const { return skipUnknownSwitches_; }
2983  Parser& errorStream(const Message::SProxy &stream) { errorStream_ = stream; return *this; }
2984  const Message::SProxy& errorStream() const { return errorStream_; }
2993  Parser& exitMessage(const std::string &s) { exitMessage_ = s; return *this; }
2994  std::string exitMessage() const { return exitMessage_ ? *exitMessage_ : std::string(); }
3003  Parser& environmentVariable(const std::string &s) { environmentVariable_ = s; return *this; }
3004  const std::string& environmentVariable() const { return environmentVariable_; }
3010  ParserResult parse(int argc, char *argv[]);
3011 
3013  ParserResult parse(const std::vector<std::string>&);
3014 
3015 #if 0 /* [Robb Matzke 2014-03-04] */
3016 
3018  template<typename Iterator>
3019  ParserResult parse(Iterator begin, Iterator end) {
3020  std::vector<std::string> args(begin, end);
3021  return parse(args);
3022  }
3023 #endif
3024 
3028  static std::vector<std::string> splitLineIntoWords(std::string);
3029 
3035  static std::vector<std::string> readArgsFromFile(const std::string &filename);
3036 
3041  static std::vector<std::string> readArgsFromEnvVar(const std::string &varName);
3042 
3047  std::vector<std::string> expandIncludedFiles(const std::vector<std::string> &args);
3048 
3051  DEFAULT_GROUPING = 0,
3052  PROHIBIT_EMPTY_GROUPS = 0x0001,
3053  SPLIT_SINGLE_GROUP = 0x0002
3054  };
3055 
3063  std::vector<std::vector<std::string> >
3064  regroupArgs(const std::vector<std::string> &args,
3066  unsigned flags = 0 /*GroupingFlags*/);
3067 
3071  Parser& programName(const std::string& programName) { programName_ = programName; return *this; }
3072  const std::string& programName() const;
3079  Parser& purpose(const std::string &purpose) { purpose_ = purpose; return *this; }
3080  const std::string& purpose() const { return purpose_; }
3086  Parser& version(const std::string &versionString, const std::string &dateString="");
3087  Parser& version(const std::pair<std::string, std::string> &p) { return version(p.first, p.second); }
3088  std::pair<std::string, std::string> version() const;
3106  Parser& chapter(int chapterNumber, const std::string &chapterName="");
3107  Parser& chapter(const std::pair<int, std::string> &p) { return chapter(p.first, p.second); }
3108  std::pair<int, std::string> chapter() const;
3149  Parser& doc(const std::string &sectionName, const std::string &docKey, const std::string &text);
3150  Parser& doc(const std::string &sectionName, const std::string &text) { return doc(sectionName, sectionName, text); }
3151  std::vector<std::string> docSections() const;
3152  std::string docForSwitches() const;
3153  std::string docForSection(const std::string &sectionName) const;
3160  std::string documentationMarkup() const;
3161 
3165  std::string podDocumentation() const;
3166 
3168  std::string textDocumentation() const;
3169 
3171  void emitDocumentationToPager() const;
3172 
3173  template<class Grammar>
3174  void emitDocumentationToPager() const {
3175  Grammar grammar;
3176  initDocGrammar(grammar);
3177  grammar.title(programName(), boost::lexical_cast<std::string>(chapter().first), chapter().second);
3178  grammar.version(version().first, version().second);
3179  grammar.emit(documentationMarkup());
3180  }
3181 
3187  SortOrder switchGroupOrder() const { return switchGroupOrder_; }
3188  Parser& switchGroupOrder(SortOrder order) { switchGroupOrder_ = order; return *this; }
3194  void insertLongSwitchStrings(Canonical, NamedSwitches &index /*in,out*/) const;
3195 
3199  void insertShortSwitchStrings(NamedSwitches &index /*in,out*/) const;
3200 
3205  void insertSwitchStrings(Canonical, NamedSwitches &index /*in,out*/) const;
3206 
3210  static void printIndex(std::ostream&, const NamedSwitches&, const std::string &linePrefix = "");
3211 
3215  NamedSwitches findAmbiguities() const;
3216 
3220  NamedSwitches findUnresolvableAmbiguities() const;
3221 
3233  Sawyer::Optional<Switch> removeMatchingSwitch(const std::string &arg);
3234  Sawyer::Optional<Switch> removeMatchingSwitch(const std::vector<std::string> &args);
3237 public:
3238  // Used internally
3239  const ParsingProperties& properties() const { return properties_; }
3240 
3241 private:
3242  void init();
3243 
3244  // Implementation for the public parse methods.
3245  ParserResult parseInternal(std::vector<std::string> programArguments);
3246 
3247  // Parse one switch from the current position in the command line and return the switch descriptor. If the cursor is at
3248  // the end of the command line then return false without updating the cursor or parsed values. If the cursor is at a
3249  // termination switch (e.g., "--") then consume the terminator and return false. If the switch name is valid but the
3250  // arguments cannot be parsed, then throw an error. If the cursor is at what appears to be a switch but no matching switch
3251  // declaration can be found, then throw an error. The cursor will not be modified when an error is thrown.
3252  bool parseOneSwitch(Cursor&, const NamedSwitches &ambiguities, ParserResult&/*out*/);
3253 
3260  const Switch* parseLongSwitch(Cursor&, ParsedValues&, const NamedSwitches &ambiguities, Optional<std::runtime_error>&);
3261 
3270  const Switch* parseShortSwitch(Cursor&, ParsedValues&, const NamedSwitches &ambiguities,
3271  Optional<std::runtime_error>&, bool mayNestle);
3272 
3273  // Returns true if the program argument at the cursor looks like it might be a switch. Apparent switches are any program
3274  // argument that starts with a long or short prefix.
3275  bool apparentSwitch(const Cursor&) const;
3276 
3277  // Returns the best prefix for each switch--the one used for documentation
3278  void preferredSwitchPrefixes(Container::Map<std::string, std::string> &prefixMap /*out*/) const;
3279 
3280  // Construct an error message for an ambiguous switch, switchString, having an optional group name part (including the
3281  // separator), and the required switch name. The switchString must be present in the ambiguities table.
3282  std::string ambiguityErrorMesg(const std::string &longSwitchString, const std::string &optionalPart,
3283  const std::string &longSwitchName, const NamedSwitches &ambiguities);
3284  std::string ambiguityErrorMesg(const std::string &shortSwitchString, const NamedSwitches &ambiguities);
3285 
3286  // Initialize a documentation parser by registering things like @s, @man, etc. The argument is a subclass such as
3287  // Document::PodMarkup.
3288  void initDocGrammar(Document::Markup::Grammar& /*in,out*/) const;
3289 
3290  // FIXME[Robb Matzke 2014-02-21]: Some way to parse command-lines from a config file, or to merge parsed command-lines with
3291  // a yaml config file, etc.
3292 };
3293 
3318 class SAWYER_EXPORT ParserResult {
3319 #include <Sawyer/WarningsOff.h>
3320  Parser parser_;
3321  Cursor cursor_;
3322  ParsedValues values_;
3323 
3324  // Maps a name to indexes into the values_ vector.
3326  NameIndex keyIndex_; // Values per switch key
3327  NameIndex switchIndex_; // Values per switch preferred name
3328 
3329  // List of parsed values organized by their location on the command line. The location is for the switch itself even if
3330  // the values are spread out across subsequent argv members. We do it this way because many of the values are defaults that
3331  // don't actually have an argv location. The integers are indexes into the values_ vector. In other words, this is a
3332  // mapping from switch location to values_ elements for the switch's values.
3334  ArgvIndex argvIndex_;
3335 
3336  // Information about program arguments that the parser skipped over. Indexes into argv_.
3337  typedef std::vector<size_t> SkippedIndex;
3338  SkippedIndex skippedIndex_;
3339 
3340  // Information about terminator switches like "--". Indexes into argv_.
3341  SkippedIndex terminators_;
3342 
3345 #include <Sawyer/WarningsRestore.h>
3346 
3347 private:
3348  friend class Parser;
3349  ParserResult(const Parser &parser, const std::vector<std::string> &argv): parser_(parser), cursor_(argv) {}
3350 
3351 public:
3352  ParserResult() {}
3353 
3356  const ParserResult& apply() const;
3357 
3360  size_t have(const std::string &switchKey) const {
3361  return keyIndex_.getOrDefault(switchKey).size();
3362  }
3363 
3382  const ParsedValue& parsed(const std::string &switchKey, size_t idx) const;
3383  ParsedValues parsed(const std::string &switchKey) const;
3396  std::vector<std::string> skippedArgs() const;
3397 
3404  std::vector<std::string> unreachedArgs() const;
3405 
3420  std::vector<std::string> unparsedArgs(bool includeTerminators=false) const;
3421 
3426  std::vector<std::string> parsedArgs() const;
3427 
3432  const std::vector<std::string>& allArgs() const { return cursor_.strings(); }
3433 
3435  const Parser& parser() const { return parser_; }
3436 
3437 private:
3438  // Insert more parsed values. Values should be inserted one switch's worth at a time (or fewer)
3439  void insertValuesForSwitch(const ParsedValues&, const Parser*, const Switch*);
3440  void insertOneValue(const ParsedValue&, const Switch*, bool save=true);
3441 
3442  // Indicate that we're skipping over a program argument
3443  void skip(const Location&);
3444 
3445  // Add a terminator
3446  void terminator(const Location&);
3447 
3448  Cursor& cursor() { return cursor_; }
3449 };
3450 
3451 } // namespace
3452 } // namespace
3453 
3454 #endif
SharedPointer< RealNumberParser > Ptr
Reference counting pointer for this class.
Switch strings that are not CANONICAL.
Switch & intrinsicValue(const ParsedValue &value)
Property: value for a switch that has no declared arguments.
SharedPointer< ValueParser > Ptr
Reference counting pointer for this class.
SortOrder switchGroupOrder() const
Property: How to order switch groups in documentation.
Container::Map< const SwitchGroup *, std::set< const Switch * > > GroupedSwitches
Subset of switches grouped by their switch groups.
std::vector< ParsedValue > ParsedValues
A vector of parsed values.
Ordered set of values.
Definition: Set.h:52
static Ptr instance(int exitStatus)
Allocating constructor.
Parser & switchGroupOrder(SortOrder order)
Property: How to order switch groups in documentation.
Switch & skipping(SwitchSkipping how)
Property: whether to skip over this switch.
SharedPointer< ShowHelp > Ptr
Reference counting pointer for this class.
Switch & shortName(char c)
Property: switch short name.
ListParser(const ValueParser::Ptr &firstElmtType, const std::string &separatorRe)
Constructor for derived classes.
SwitchGroup & name(const std::string &name)
Property: Group name.
Sum< T >::Ptr sum()
Factory for value agumenter.
const std::vector< std::string > & terminationSwitches() const
Strings that indicate the end of the argument list.
Sum()
Constructor for derived classes.
void cancel()
Cancel the excursion guard.
Sums all previous and current values.
Cursor(const std::string &string)
Constructs a cursor for a single string.
std::ostream & operator<<(std::ostream &, const Location &)
Print a location.
bool isRequired() const
Returns true if this argument is required.
IntegerParser()
Constructor for derived classes.
bool exitOnHelp() const
Property: program exit after help is displayed.
static Ptr instance()
Allocating constructor.
static Ptr instance()
Allocating constructor.
const Message::SProxy & errorStream() const
Specifies a message stream to which errors are sent.
ListParser::Ptr listParser(const ValueParser::Ptr &, const std::string &sepRe="[,;:]\\s*")
Factory for value parsers.
static Ptr instance(const ValueParser::Ptr &firstElmtType, const std::string &separatorRe="[,;:]\\s*")
Allocating constructor.
ShowGroupName
How to show group names in switch synopsis.
Cursor()
Constructs a not-very-useful cursor to nothing.
SharedPointer< EnumParser > Ptr
Reference counting pointer for this class.
const ValueSaver::Ptr valueSaver() const
Property: functor responsible for saving a parsed value in user storage.
bool skippingNonSwitches() const
Whether to skip over non-switch arguments when parsing.
SharedPointer< AnyParser > Ptr
Reference counting pointer for this class.
const ValueSaver::Ptr valueSaver() const
How to save a value at a user-supplied location.
WhichValue
Describes how to handle switches that occur multiple times.
const std::string & arg() const
Return the entire current program argument regardless of where the cursor is in that argument...
static Ptr instance(const ValueSaver::Ptr &valueSaver)
Allocating constructor.
void consumeChars(size_t nchars)
Advance over characters.
SwitchGroup & valueSeparator(const std::string &s1)
Property: strings that separate a long switch from its value.
bool operator<(const Location &other) const
Less than.
Entities appear in the documentation in the same order they are inserted into the container...
static Ptr instance(const std::string &versionString, int exitStatus)
Allocating constructor.
const SwitchArgument & argument(size_t idx) const
Property: switch argument.
void run(const ParserResult &parserResult)
Runs the action.
SharedPointer< Sum > Ptr
Reference counting pointer for this class.
T as() const
Convenient any_cast.
const std::string & docKey() const
Property: Documentation sort key.
bool explosiveLists() const
Property: whether to convert a list value to individual values.
Switch & shortPrefix(const std::string &s1)
Property: prefixes for short names.
Location switchLocation() const
The command-line location of the switch to which this value belongs.
Parser & inclusionPrefix(const std::string &s1)
Strings that indicate that arguments are to be read from a file.
BooleanParser()
Constructor for derived classes.
SwitchGroup(const std::string &title, const std::string &docKey="")
Construct a titled group.
const std::string & doc() const
Property: Detailed description.
bool reportingAmbiguities() const
Property: Whether to report ambiguities.
std::string exitMessage() const
Extra text to print before exit.
static Ptr instance()
Allocating constructor.
RealNumberParser< T >::Ptr realNumberParser(T &storage)
Factory for value parsers.
std::vector< SwitchGroup > & switchGroups()
List of all switch groups.
size_t offset
Character offset within a program argument string.
Parser & terminationSwitch(const std::string &s1)
Strings that indicate the end of the argument list.
The result from parsing a command line.
Describes one command-line switch.
Switch & docKey(const std::string &s)
Property: key to control order of documentation.
const std::string & doc() const
Property: detailed description.
Parser & groupNameSeparator(const std::string &s)
Property: String separating group name from switch name.
Collection of facilities.
Definition: Message.h:1729
Location()
Constructs the location of the first character of the first string.
Parses any one of a set of strings.
StringSetParser::Ptr stringSetParser(std::string &storage)
Factory for value parsers.
const std::vector< std::string > & valueSeparators() const
Strings that separate a long switch from its value.
Parser & with(const Switch &sw)
Add switch declarations.
STL namespace.
Parser & environmentVariable(const std::string &s)
Name of environment variable holding initial arguments.
Holds a value or nothing.
Definition: Optional.h:49
static Ptr instance()
Allocating constructor.
const Parser & parser() const
That parser that created this result.
A collection of related switch declarations.
ShowHelp()
Constructor for derived classes.
bool atEnd() const
Returns true when the cursor is after all arguments.
Ptr with(const std::vector< std::string > sv)
Adds string members.
const std::vector< std::string > & strings() const
All strings for the cursor.
size_t nArguments() const
Total number of arguments.
static Ptr instance(const ValueSaver::Ptr &valueSaver)
Allocating constructor.
Switch & action(const SwitchAction::Ptr &f)
Property: action to occur.
SharedPointer< PositiveIntegerParser > Ptr
Reference counting pointer for this class.
const std::string & defaultValueString() const
The default value string.
Base class for value agumentors.
Parser & valueSeparator(const std::string &s1)
Strings that separate a long switch from its value.
Input stream for command line arguments.
ValueParser(const ValueSaver::Ptr &valueSaver)
Constructor for derived classes.
PositiveIntegerParser(const ValueSaver::Ptr &valueSaver)
Constructor for derived classes.
SwitchGroup()
Construct an unnamed, untitled group.
std::string preferredName() const
Name by which switch prefers to be known.
const std::string & groupNameSeparator() const
Property: String separating group name from switch name.
Parser & with(const std::vector< SwitchGroup > &sgs)
Add switch declarations.
SharedPointer< BooleanParser > Ptr
Reference counting pointer for this class.
bool operator!=(const Location &other) const
Inequality.
Show name as being optional, like "--[group-]switch".
SwitchGroup & longPrefix(const std::string &s1)
Property: prefixes for long names.
Save the first value, or modify previously saved value.
Describes one argument of a command-line switch.
Group inherits value from the parser.
ShowHelp::Ptr showHelp()
Factory for switch action.
A container holding a set of values.
Definition: IntervalSet.h:55
AnyParser< T >::Ptr anyParser(T &storage)
Factory for value parsers.
Parser & version(const std::pair< std::string, std::string > &p)
Program version.
AnyParser(const ValueSaver::Ptr &valueSaver)
Constructor for derived classes.
static Ptr instance(const ValueSaver::Ptr &valueSaver)
Allocating constructor.
Ptr limit(size_t maxLength)
Specify limits for the number of values parsed.
Ptr with(const std::string &name, T value)
Adds enum members.
Functor to print the Unix man page.
const std::vector< std::string > & allArgs() const
The original command line.
Canonical
Format of a switch string.
Location(size_t idx, size_t offset)
Constructs a location that points to a particular character of a particular string.
Switch & doc(const std::string &s)
Property: detailed description.
Name space for the entire library.
size_t switchSequence() const
How this value relates to others created by the same switch.
ShowVersion::Ptr showVersion(const std::string &versionString)
Factory for switch action.
static Ptr instance()
Allocating constructor.
SwitchGroup & docKey(const std::string &key)
Property: Documentation sort key.
Use only the first occurrence and ignore all previous.
IntegerParser(const ValueSaver::Ptr &valueSaver)
Constructor for derived classes.
Parses a positive integer and converts it to numeric type T.
size_t keySequence() const
How this value relates to others with the same key.
Process switch normally, but also add to skipped list.
const std::string & string() const
String representation.
Parser & with(const SwitchGroup &sg)
Add switch declarations.
static Ptr instance(const ValueSaver::Ptr &valueSaver)
Allocating constructor.
EnumParser< T >::Ptr enumParser(T &storage)
Factory for value parsers.
const std::string & shortNames() const
Property: switch short name.
SharedPointer< ValueParser > sharedFromThis()
Create a shared pointer from this.
const ParsedValue & defaultValue() const
The parsed default value.
Ptr nextMember(const ValueParser::Ptr &elmtType, const std::string &separatorRe="[,;:]\\s*")
Specifies element type and separator.
Ptr exactly(size_t length)
Specify limits for the number of values parsed.
Location valueLocation() const
Property: command-line location from whence this value came.
std::string rest() const
Return the part of an argument at and beyond the cursor location.
SharedPointer< StringSetParser > Ptr
Reference counting pointer for this class.
const std::vector< std::string > & valueSeparators() const
Property: strings that separate a long switch from its value.
void consumeArg()
Advance the cursor to the beginning of the next string.
static Ptr instance(const std::string &versionString)
Allocating constructor.
Switch & intrinsicValue(const std::string &text)
Property: value for a switch that has no declared arguments.
const std::vector< Switch > & switches() const
List of all declared switches.
static Ptr instance(const ValueSaver::Ptr &valueSaver)
Allocating constructor.
bool atArgEnd() const
True when the cursor is at the end of an argument.
Parses an enumerated constant.
Switch(const std::string &longName, char shortName='\0')
Constructs a switch declaration.
const std::string & docKey() const
Property: key to control order of documentation.
Functor to print a version string and exit.
Information about a parsed switch value.
Parser & chapter(const std::pair< int, std::string > &p)
Manual chapter.
The parser for a program command line.
SharedPointer< IntegerParser > Ptr
Reference counting pointer for this class.
Parses a non-negative integer and converts it to numeric type T.
bool operator<=(const Location &other) const
Less than or equal.
EnumParser()
Constructor for derived classes.
SharedPointer< NonNegativeIntegerParser > Ptr
Reference counting pointer for this class.
SwitchSkipping skipping() const
Property: whether to skip over this switch.
SharedPointer< ShowHelpAndExit > Ptr
Reference counting pointer for this class.
const std::vector< std::string > & longPrefixes() const
Property: prefixes for long names.
Switch & intrinsicValue(const char *value, std::string &storage)
Property: value for a switch that has no declared arguments.
bool isEmpty() const
True if the value is void.
ParsedValue & switchInfo(const std::string &key, const Location &loc, const std::string &str)
Update switch information.
const std::string & switchString() const
The string for the switch that caused this value to be parsed.
Switch & argument(const SwitchArgument &arg)
Property: switch argument.
const std::string & environmentVariable() const
Name of environment variable holding initial arguments.
Switch & intrinsicValue(const std::string &text, const ValueParser::Ptr &p)
Property: value for a switch that has no declared arguments.
const std::vector< std::string > & longPrefixes() const
Property: prefixes for long names.
Parser & shortMayNestle(bool b)
Indicates whether short switches can nestle together.
ParsedValue & switchKey(const std::string &s)
Property: switch key.
static Ptr instance(Functor &f)
Allocating constructor.
static Ptr instance(const ValueSaver::Ptr &valueSaver)
Allocating constructor.
static Ptr instance(Message::Facilities &facilities)
Allocating constructor.
BooleanParser(const ValueSaver::Ptr &valueSaver)
Constructor for derived classes.
static Ptr instance(const ValueSaver::Ptr &valueSaver)
Allocating constructor.
Parser & longPrefix(const std::string &s1)
Prefixes to use for long command-line switches.
const SortOrder & switchOrder() const
Property: Order of switches in documentation.
Creates SharedPointer from this.
Ptr with(InputIterator begin, InputIterator end)
Adds string members.
EnumParser(const ValueSaver::Ptr &valueSaver)
Constructor for derived classes.
GroupingFlags
Bit flags for argument grouping.
SharedPointer< ConfigureDiagnostics > Ptr
Reference counting pointer for this class.
Functor to print a version string.
Parses any argument as plain text.
const Location & location() const
Property: current position of the cursor.
SharedPointer< class UserAction > Ptr
Reference counting pointer for this class.
const std::vector< SwitchArgument > & arguments() const
Property: switch argument.
Switch & whichValue(WhichValue s)
Property: how to handle multiple occurrences.
Parser & purpose(const std::string &purpose)
Program purpose.
Parser & with(const SwitchGroup &sg, const std::string &docKey)
Add switch declarations.
SwitchArgument(const std::string &name, const ValueParser::Ptr &parser=anyParser())
Construct a new required argument.
Switch & hidden(bool b)
Property: whether this switch appears in documentation.
Switch & explosiveLists(bool b)
Property: whether to convert a list value to individual values.
WhichValue whichValue() const
Property: how to handle multiple occurrences.
bool hidden() const
Property: whether this switch appears in documentation.
static Ptr instance()
Allocating constructor.
const std::string & name() const
Argument name.
StringSetParser(const ValueSaver::Ptr &valueSaver)
Constructor for derived classes.
const std::vector< std::string > & shortPrefixes() const
Prefixes to use for short command-line switches.
ShowVersionAndExit(const std::string &versionString, int exitStatus)
Constructor for derived classes.
void value(const boost::any &v)
Property: the parsed value.
ExcursionGuard(Cursor &cursor)
Construct a guard for a cursor.
SortOrder
The order in which things are sorted in the documentation.
ShowVersionAndExit::Ptr showVersionAndExit(const std::string &versionString, int exitStatus)
Factory for switch action.
SharedPointer< U > dynamicCast() const
Dynamic cast.
SwitchGroup & title(const std::string &title)
Property: Title of the switch group.
virtual ParsedValues operator()(const ParsedValues &savedValues, const ParsedValues &newValues)
Called when a switch's value is about to be stored into the ParserResult.
Parses a boolean value and converts it to numeric type T.
const Value & getOrDefault(const Key &key) const
Lookup and return a value or a default.
Definition: Sawyer/Map.h:577
const std::string & key() const
Property: value storage key.
ParsedValue & valueLocation(const Location &loc)
Property: command-line location from whence this value came.
Switch & intrinsicValue(const T &value, T &storage)
Property: value for a switch that has no declared arguments.
Parser & shortPrefix(const std::string &s1)
Prefixes to use for short command-line switches.
SharedPointer< SwitchAction > Ptr
Reference counting pointer for this class.
const std::string & longName() const
Property: switch long name.
bool isOptional() const
Returns true if this argument is not required.
AnyParser()
Constructor for derived classes.
Parses an integer and converts it to numeric type T.
ShowHelpAndExit::Ptr showHelpAndExit(int exitStatus)
Factory for switch action.
Parser & doc(const std::string &sectionName, const std::string &text)
Documentation for a section of the manual.
const std::vector< std::string > & valueSeparators() const
Property: strings that separate a long switch from its value.
Switch & longPrefix(const std::string &s1)
Property: prefixes for long names.
size_t nSwitches() const
Number of switches declared.
Parser & reportingAmbiguities(bool b)
Property: Whether to report ambiguities.
const std::vector< std::string > & inclusionPrefixes() const
Strings that indicate that arguments are to be read from a file.
bool atEnd(const Location &location) const
Returns true when the cursor is after all arguments.
Parser & skippingNonSwitches(bool b)
Whether to skip over non-switch arguments when parsing.
const Location NOWHERE
Indicates an invalid location.
ShowVersion(const std::string &versionString)
Constructor for derived classes.
SwitchGroup & shortPrefix(const std::string &s1)
Property: prefixes for short names.
const boost::any & value() const
Property: the parsed value.
Wrapper around a user functor.
ShowGroupName showingGroupNames() const
Property: How to show group names in switch documentation.
ShowGroupName showingGroupNames() const
Property: How to show group name in switch synopsis.
Switch & valueSeparator(const std::string &s1)
Property: strings that separate a long switch from its value.
RealNumberParser()
Constructor for derived classes.
Show name as being required, like "--group-switch".
Base class for reference counted objects.
Definition: SharedObject.h:64
size_t idx
Index into some vector of program argument strings.
Skip switch and its argument(s) without saving any value.
const std::vector< std::string > & shortPrefixes() const
Property: prefixes for short names.
void consumeArgs(size_t nargs)
Advance the cursor to the beginning of the next string.
const std::vector< std::string > & longPrefixes() const
Prefixes to use for long command-line switches.
Container::Map< std::string, GroupedSwitches > NamedSwitches
Subset of switches indexed by their command-line representation.
SharedPointer< ConfigureDiagnosticsQuiet > Ptr
Reference counting pointer for this class.
The switch cannot occur more than once.
const std::string & name() const
Property: Group name.
Parser & skippingUnknownSwitches(bool b)
Whether to skip over unrecognized switches.
Map & insert(const Key &key, const Value &value)
Insert or update a key/value pair.
Definition: Sawyer/Map.h:594
const std::string & title() const
Property: Title of the switch group.
size_t have(const std::string &switchKey) const
Returns the number of values for the specified key.
SharedPointer< ShowVersion > Ptr
Reference counting pointer for this class.
SwitchArgument(const std::string &name, const ValueParser::Ptr &parser, const std::string &defaultValueString)
Construct a new switch optional argument.
Entities are sorted according to their documentation keys.
StringSetParser()
Constructor for derived classes.
const Location & startingLocation() const
Starting location.
std::list< ParsedValue > ValueList
Value type for list ParsedValue.
static Ptr instance(const std::string &switchKey, Message::Facilities &facilities, bool exitOnHelp=true)
Allocating constructor.
const std::vector< std::string > & shortPrefixes() const
Property: prefixes for short names.
Use only the last occurrence and ignore all previous.
Save all values as a vector.
Switch & key(const std::string &s)
Property: value storage key.
ParsedValue intrinsicValue() const
Property: value for a switch that has no declared arguments.
Ptr valueSaver(const ValueSaver::Ptr &f)
Property: functor responsible for saving a parsed value in user storage.
Cursor(const std::vector< std::string > &strings)
Construct a cursor from an ordered set of strings.
Position within a command-line.
Ptr with(const std::string &s)
Adds string members.
UserAction< Functor >::Ptr userAction(const Functor &functor)
Factory for switch action.
const std::string & purpose() const
Program purpose.
void exitOnHelp(bool b)
Property: program exit after help is displayed.
static Ptr instance()
Allocating constructor.
Base class parsing a value from input.
Switch strings that are qualified with the switch group name or which belong to a group that has no n...
const std::vector< std::string > & longNames() const
Property: switch long name.
Function to configure diagnostics to quiet mode.
NonNegativeIntegerParser< T >::Ptr nonNegativeIntegerParser(T &storage)
Factory for value parsers.
Parser & with(Switch sw, const std::string &docKey)
Add switch declarations.
IntegerParser< T >::Ptr integerParser(T &storage)
Factory for value parsers.
boost::uint64_t strtoull(const char *, char **, int)
Portable replacement for strtoull.
SharedPointer< ShowVersionAndExit > Ptr
Reference counting pointer for this class.
ConfigureDiagnosticsQuiet::Ptr configureDiagnosticsQuiet(Message::Facilities &)
Factory for switch action.
UserAction(Functor &f)
Constructor for derived classes.
static Ptr instance()
Allocating constructor.
ParsedValue(const boost::any value, const Location &loc, const std::string &str, const ValueSaver::Ptr &saver)
Construct a new value.
ValueParser()
Constructor for derived classes.
Parser & programName(const std::string &programName)
Program name for documentation.
void showingGroupNames(ShowGroupName x)
Property: How to show group name in switch synopsis.
NonNegativeIntegerParser(const ValueSaver::Ptr &valueSaver)
Constructor for derived classes.
bool shortMayNestle() const
Indicates whether short switches can nestle together.
const std::vector< SwitchGroup > & switchGroups() const
List of all switch groups.
boost::int64_t strtoll(const char *, char **, int)
Portable replacement for strtoll.
Parser & errorStream(const Message::SProxy &stream)
Specifies a message stream to which errors are sent.
The union of CANONICAL and NONCANONICAL.
SwitchGroup & switchOrder(SortOrder order)
Property: Order of switches in documentation.
bool atArgBegin() const
True when the cursor is at the beginning of an argument.
bool operator==(const Location &other) const
Equality.
BooleanParser< T >::Ptr booleanParser(T &storage)
Factory for value parsers.
Parses a real number and converts it to numeric type T.
const std::string & switchKey() const
Property: switch key.
ShowHelpAndExit(int exitStatus)
Constructor for derived classes.
ConfigureDiagnostics(const std::string &switchKey, Message::Facilities &facilities, bool exitOnHelp)
Constructor for derived classes.
SwitchSkipping
Whether to skip a switch.
SharedPointer< ListParser > Ptr
Reference counting pointer for this class.
Switch & synopsis(const std::string &s)
Property: abstract summary of the switch syntax.
Parser & showingGroupNames(ShowGroupName x)
Property: How to show group names in switch documentation.
SharedPointer< ValueAugmenter > Ptr
Reference counting pointer for this class.
static Ptr instance()
Allocating constructor.
static Ptr instance(const ValueSaver::Ptr &valueSaver)
Allocating constructor.
Functor to print the Unix man page and exit.
Container associating values with keys.
Definition: Sawyer/Map.h:66
bool initializeLibrary(size_t vmajor=0, size_t vminor=1, size_t vpatch=0, bool withThreads=0)
Explicitly initialize the library.
ValueAugmenter::Ptr valueAugmenter() const
Property: functor to agument values.
NonNegativeIntegerParser()
Constructor for derived classes.
ParsedValue()
Construct a new empty value.
RealNumberParser(const ValueSaver::Ptr &valueSaver)
Constructor for derived classes.
Switch & valueAugmenter(const ValueAugmenter::Ptr &f)
Property: functor to agument values.
const ValueParser::Ptr & parser() const
Returns a pointer to the parser.
ConfigureDiagnostics::Ptr configureDiagnostics(const std::string &, Message::Facilities &, bool exitOnHelp=true)
Factory for switch action.
Stores a vector of enum bit flags.
const SwitchAction::Ptr & action() const
Property: action to occur.
Guards a cursor and restores it when the guard is destroyed.
static Ptr instance()
Allocating constructor.
PositiveIntegerParser< T >::Ptr positiveIntegerParser(T &storage)
Factory for value parsers.
Base class for switch actions.
PositiveIntegerParser()
Constructor for derived classes.
Parser & exitMessage(const std::string &s)
Extra text to print before exit.
SwitchGroup & doc(const std::string &s)
Property: Detailed description.
std::string substr(const Location &limit, const std::string &separator=" ") const
Returns all characters within limits.
bool skippingUnknownSwitches() const
Whether to skip over unrecognized switches.