ROSE  0.11.145.0
Message.h
1 // See also Rose::Diagnostics in $ROSE/src/Rose/Diagnostics.h
2 // WARNING: Changes to this file must be contributed back to Sawyer or else they will
3 // be clobbered by the next update from Sawyer. The Sawyer repository is at
4 // https://github.com/matzke1/sawyer.
5 
6 
7 
8 
9 #ifndef Sawyer_Message_H
10 #define Sawyer_Message_H
11 
12 #include <Sawyer/Map.h>
13 #include <Sawyer/Optional.h>
14 #include <Sawyer/Sawyer.h>
15 #include <Sawyer/SharedPointer.h>
16 #include <Sawyer/Synchronization.h>
17 
18 #include <boost/config.hpp>
19 #include <boost/logic/tribool.hpp>
20 #include <boost/regex.hpp>
21 #include <cassert>
22 #include <cstring>
23 #include <list>
24 #include <ostream>
25 #include <set>
26 #include <streambuf>
27 #include <string>
28 #include <vector>
29 
30 namespace Sawyer {
31 
276 namespace Message {
277 
285 SAWYER_EXPORT bool initializeLibrary();
286 
287 // Any header that #defines words that are this common is just plain stupid!
288 #if defined(DEBUG) || defined(TRACE) || defined(WHERE) || defined(MARCH) || \
289  defined(INFO) || defined(WARN) || defined(ERROR) || defined(FATAL)
290 # ifdef _MSC_VER
291 # pragma message("Undefining common words from the global namespace: DEBUG, TRACE, WHERE, MARCH, INFO, WARN, ERROR, FATAL")
292 # else
293 # warning "Undefining common words from the global namespace: DEBUG, TRACE, WHERE, MARCH, INFO, WARN, ERROR, FATAL"
294 # endif
295 # undef DEBUG
296 # undef TRACE
297 # undef WHERE
298 # undef MARCH
299 # undef INFO
300 # undef WARN
301 # undef ERROR
302 # undef FATAL
303 #endif
304 
339 };
340 
343 enum AnsiColor { // the values are important: they are the ANSI foreground and background color offsets
345  COLOR_RED = 1,
353 };
354 
355 
356 
358 // Functions
360 
361 SAWYER_EXPORT std::string stringifyImportance(Importance);
362 SAWYER_EXPORT std::string stringifyColor(AnsiColor);
363 SAWYER_EXPORT double now();
364 SAWYER_EXPORT std::string escape(const std::string&);
365 SAWYER_EXPORT bool isTerminal(int fd);
367 // Colors
370 
374 struct SAWYER_EXPORT ColorSpec {
377 #include <Sawyer/WarningsOff.h>
378  boost::tribool bold;
379 #include <Sawyer/WarningsRestore.h>
380 
382  ColorSpec(): foreground(COLOR_DEFAULT), background(COLOR_DEFAULT), bold(false) {}
383 
385  explicit ColorSpec(AnsiColor fg): foreground(fg), background(COLOR_DEFAULT), bold(false) {}
386 
388  ColorSpec(AnsiColor fg, AnsiColor bg, bool bold): foreground(fg), background(bg), bold(bold) {}
389 
391  bool isDefault() const { return COLOR_DEFAULT==foreground && COLOR_DEFAULT==background && !bold ? true : false; }
392 };
393 
397 class SAWYER_EXPORT ColorSet {
398  ColorSpec spec_[N_IMPORTANCE];
399 public:
402  static ColorSet blackAndWhite();
403 
405  static ColorSet fullColor();
406 
409  const ColorSpec& operator[](Importance imp) const { return spec_[imp]; }
410  ColorSpec& operator[](Importance imp) { return spec_[imp]; }
412 };
413 
414 
415 
417 // Message Properties
419 
426 struct SAWYER_EXPORT MesgProps {
427 #include <Sawyer/WarningsOff.h>
430  boost::tribool isBuffered;
435  boost::tribool useColor;
436 #include <Sawyer/WarningsRestore.h>
437 
438  MesgProps(): isBuffered(boost::indeterminate), useColor(boost::indeterminate) {}
439 
443  MesgProps merge(const MesgProps&) const;
444 
446  void print(std::ostream&) const;
447 };
448 
450 SAWYER_EXPORT std::ostream& operator<<(std::ostream &o, const MesgProps &props);
451 
452 
453 
455 // Type defintions
457 
494 typedef std::pair<DestinationPtr, MesgProps> BakedDestination;
495 
497 typedef std::vector<BakedDestination> BakedDestinations;
498 
499 
500 
502 // Messages
504 
513 class SAWYER_EXPORT Mesg {
514  static unsigned nextId_; // class-wide unique ID numbers
515  unsigned id_; // unique message ID
516 #include <Sawyer/WarningsOff.h>
517  std::string text_; // text of the message
518 #include <Sawyer/WarningsRestore.h>
519  bool isComplete_; // true when the message is complete
520  bool isCanceled_; // true when message is being canceled without completing
521  MesgProps props_; // message properties
522 public:
523 
526  : id_(nextId_++), isComplete_(false), isCanceled_(false) {}
527 
529  Mesg(const std::string &facilityName, Importance imp)
530  : id_(nextId_++), isComplete_(false), isCanceled_(false) {
531  props_.facilityName = facilityName;
532  props_.importance = imp;
533  }
534 
536  explicit Mesg(const MesgProps &props)
537  : id_(nextId_++), isComplete_(false), isCanceled_(false), props_(props) {}
538 
540  explicit Mesg(const std::string &mesg)
541  : id_(nextId_++), text_(mesg), isComplete_(true), isCanceled_(false) {}
542 
545  Mesg(const std::string &facilityName, Importance imp, const std::string &mesg)
546  : id_(nextId_++), text_(mesg), isComplete_(true), isCanceled_(false) {
547  props_.facilityName = facilityName;
548  props_.importance = imp;
549  }
550 
552  Mesg(const MesgProps &props, const std::string &mesg)
553  : id_(nextId_++), text_(mesg), isComplete_(true), isCanceled_(false), props_(props) {}
554 
556  unsigned id() const { return id_; }
557 
559  const std::string& text() const { return text_; }
560 
562  bool isComplete() const { return isComplete_; }
563 
566  bool isCanceled() const { return isCanceled_; }
567 
570  bool isEmpty() const { return text_.empty(); }
571 
574  bool hasText() const;
575 
580  const MesgProps& properties() const { return props_; }
581  MesgProps& properties() { return props_; }
585  void complete() { isComplete_ = true; }
586 
589  void cancel() { isCanceled_ = true; }
590 
594  void insert(const std::string&);
595  void insert(char);
599  void post(const BakedDestinations&) const;
600 };
601 
603 // Plumbing lattice nodes
605 
609 class SAWYER_EXPORT Destination: public SharedObject, public SharedFromThis<Destination> {
610 protected:
611  mutable SAWYER_THREAD_TRAITS::RecursiveMutex mutex_;
614 protected:
615  Destination() {}
616 public:
617  virtual ~Destination() {}
618 
627  const MesgProps& defaultPropertiesNS() const { return dflts_; }
628  MesgProps& defaultPropertiesNS() { return dflts_; }
639  const MesgProps& overridePropertiesNS() const { return overrides_; }
640  MesgProps& overridePropertiesNS() { return overrides_; }
650  virtual void bakeDestinations(const MesgProps&, BakedDestinations &baked);
651 
654  virtual void post(const Mesg&, const MesgProps &bakedProperties) = 0;
655 
663  MesgProps mergePropertiesNS(const MesgProps &props);
664 };
665 
669 class SAWYER_EXPORT Multiplexer: public Destination {
670  typedef std::list<DestinationPtr> Destinations;
671 #include <Sawyer/WarningsOff.h>
672  Destinations destinations_;
673 #include <Sawyer/WarningsRestore.h>
674 protected:
677 public:
679  static MultiplexerPtr instance() { return MultiplexerPtr(new Multiplexer); }
680 
681  virtual void bakeDestinations(const MesgProps&, BakedDestinations&) /*override*/;
682  virtual void post(const Mesg&, const MesgProps&) /*override*/;
683 
692  MultiplexerPtr addDestination(const DestinationPtr&);
693 
699  MultiplexerPtr removeDestination(const DestinationPtr&);
700 
708  MultiplexerPtr to(const DestinationPtr&); // more convenient form of addDestination()
709  MultiplexerPtr to(const DestinationPtr&, const DestinationPtr&);
710  MultiplexerPtr to(const DestinationPtr&, const DestinationPtr&, const DestinationPtr&);
711  MultiplexerPtr to(const DestinationPtr&, const DestinationPtr&, const DestinationPtr&, const DestinationPtr&);
713 };
714 
716 // Filters
718 
723 class SAWYER_EXPORT Filter: public Multiplexer {
724 protected:
726  Filter() {}
727 public:
728  virtual void bakeDestinations(const MesgProps&, BakedDestinations&) /*override*/;
729 
738  virtual bool shouldForward(const MesgProps&) = 0; // return true if message should be forwarded to children when baking
739 
743  virtual void forwarded(const MesgProps&) = 0; // message was forwarded to children
744 };
745 
750 class SAWYER_EXPORT SequenceFilter: public Filter {
751  size_t nSkip_; // skip initial messages posted to this sequencer
752  size_t rate_; // emit only 1/Nth of the messages (0 and 1 both mean every message)
753  size_t limit_; // emit at most this many messages (0 means infinite)
754  size_t nPosted_; // number of messages posted (including those suppressed)
755 protected:
757  SequenceFilter(size_t nskip, size_t rate, size_t limit)
758  : nSkip_(nskip), rate_(rate), limit_(limit), nPosted_(0) {}
759 public:
765  static SequenceFilterPtr instance(size_t nskip, size_t rate, size_t limit) {
766  return SequenceFilterPtr(new SequenceFilter(nskip, rate, limit));
767  }
768 
776  size_t nSkip() const;
777  SequenceFilterPtr nSkip(size_t n);
788  size_t rate() const;
789  SequenceFilterPtr rate(size_t n);
800  size_t limit() const;
801  SequenceFilterPtr limit(size_t n);
809  size_t nPosted() const;
810 
811  virtual bool shouldForward(const MesgProps&) /*override*/;
812  virtual void forwarded(const MesgProps&) /*override*/ {}
813 };
814 
819 class SAWYER_EXPORT TimeFilter: public Filter {
820  double initialDelay_; // amount to delay before emitting the first message
821  double minInterval_; // minimum time between messages
822  double prevMessageTime_; // time previous message was emitted
823  double lastBakeTime_; // time cached by shouldForward, used by forwarded
824  size_t nPosted_; // number of messages posted (including those suppressed)
825 protected:
829  explicit TimeFilter(double minInterval)
830  : initialDelay_(0.0), minInterval_(minInterval), prevMessageTime_(0.0), lastBakeTime_(0.0) {}
831 public:
835  static TimeFilterPtr instance(double minInterval) {
836  return TimeFilterPtr(new TimeFilter(minInterval));
837  }
838 
847  double minInterval() const;
848  TimeFilterPtr minInterval(double d);
858  double initialDelay() const;
859  TimeFilterPtr initialDelay(double d);
867  size_t nPosted() const;
868 
869  virtual bool shouldForward(const MesgProps&) /*override*/;
870  virtual void forwarded(const MesgProps&) /*override*/;
871 };
872 
880 class SAWYER_EXPORT ImportanceFilter: public Filter {
881  bool enabled_[N_IMPORTANCE];
882 protected:
886  explicit ImportanceFilter(bool dflt) {
887  memset(enabled_, dflt?0xff:0, sizeof enabled_);
888  }
889 public:
894  static ImportanceFilterPtr instance(bool dflt) {
895  return ImportanceFilterPtr(new ImportanceFilter(dflt));
896  }
897 
905  bool enabled(Importance imp) const;
906  ImportanceFilterPtr enabled(Importance imp, bool b);
912  ImportanceFilterPtr enable(Importance);
913 
917  ImportanceFilterPtr disable(Importance);
918 
919  virtual bool shouldForward(const MesgProps&) /*override*/;
920  virtual void forwarded(const MesgProps&) /*override*/ {}
921 };
922 
924 // Support for final destinations
926 
931 class HighWater {
932  Optional<unsigned> id_;
933  MesgProps props_;
934  size_t ntext_;
935 protected:
936  mutable SAWYER_THREAD_TRAITS::RecursiveMutex mutex_;
937  HighWater(const HighWater&) { abort(); } // not copyable
938  HighWater& operator=(const HighWater&) { abort(); } // not copyable
939 public:
940  HighWater(): ntext_(0) {}
941  explicit HighWater(const Mesg &m, const MesgProps &p) { emitted(m, p); }
942  SAWYER_THREAD_TRAITS::RecursiveMutex& mutex() const { return mutex_; }
943  void emitted(const Mesg&, const MesgProps&);
944  void clear();
945  bool isValid() const;
946  unsigned id() const;
947  MesgProps properties() const;
948  size_t ntext() const;
949 };
950 
959 class Gang: public HighWater, public SharedObject {
960  // Gangs are intentionally leaked. I played with an implementation that removed them from the gangs_ map when they were
961  // destroyed (which also required a GangMap that didn't use shared pointers), but it turned out to not work. The problem
962  // is that some streams are static objects and there's no portable way to control the order that those objects are
963  // destroyed. What was happening was that boost::thread support was destroyed before the static Sawyer::Message::Stream
964  // objects, so when it came time to destroy their Gang objects we could no longer reliably lock classMutex_.
966  static GangMap *gangs_;
967  static const int TTY_GANG = -1;
968  static const int NO_GANG_ID = -2;
969  static SAWYER_THREAD_TRAITS::Mutex classMutex_;
970 protected:
971  Gang() {}
972 public:
973  static GangPtr instance();
974  static GangPtr instanceForId(int id);
975  static GangPtr instanceForTty();
976  static void shutdownNS();
977 private:
978  static GangPtr createNS(int id); // non-synchronized implementation for instance methods
979 };
980 
982 // Messages prefixes
984 
986 class SAWYER_EXPORT Prefix: public SharedObject, public SharedFromThis<Prefix> {
987 #include <Sawyer/WarningsOff.h>
988 public:
990  enum When {
991  NEVER=0,
992  SOMETIMES=1,
993  ALWAYS=2
994  };
995 private:
996  mutable SAWYER_THREAD_TRAITS::RecursiveMutex mutex_;
997  ColorSet colorSet_;
998  Optional<std::string> programName_;
999  bool showProgramName_;
1000  bool showThreadId_;
1001  Optional<double> startTime_;
1002  bool showElapsedTime_;
1003  When showFacilityName_;
1004  bool showImportance_;
1005  void initFromSystem();
1006 #include <Sawyer/WarningsRestore.h>
1007 protected:
1012  : showProgramName_(true), showThreadId_(true), showElapsedTime_(true), showFacilityName_(SOMETIMES),
1013  showImportance_(true) {
1014  initFromSystem();
1015  colorSet_ = ColorSet::fullColor();
1016  }
1017 public:
1018  virtual ~Prefix() {}
1019 
1024  static PrefixPtr instance() { return PrefixPtr(new Prefix); }
1025 
1029  static PrefixPtr silentInstance();
1030 
1038  const ColorSet& colorSet() const { return colorSet_; }
1039  ColorSet& colorSet() { return colorSet_; }
1052  const Optional<std::string>& programName() const { return programName_; }
1053  PrefixPtr programName(const std::string &s) { programName_ = s; return sharedFromThis(); }
1061  void setProgramName();
1062 
1071  bool showProgramName() const { return showProgramName_; }
1072  PrefixPtr showProgramName(bool b) { showProgramName_ = b; return sharedFromThis(); }
1082  bool showThreadId() const { return showThreadId_; }
1083  PrefixPtr showThreadId(bool b) { showThreadId_ = b; return sharedFromThis(); }
1095  const Optional<double> startTime() const;
1096  PrefixPtr startTime(double t);
1107  void setStartTime();
1108 
1117  bool showElapsedTime() const { return showElapsedTime_; }
1118  PrefixPtr showElapsedTime(bool b) { showElapsedTime_ = b; return sharedFromThis(); }
1129  When showFacilityName() const { return showFacilityName_; }
1130  PrefixPtr showFacilityName(When w) { showFacilityName_ = w; return sharedFromThis(); }
1140  bool showImportance() const { return showImportance_; }
1141  PrefixPtr showImportance(bool b) { showImportance_ = b; return sharedFromThis(); }
1149  virtual std::string toString(const Mesg&, const MesgProps&) const;
1150 };
1151 
1153 // Final destinations (sinks)
1155 
1159 class SAWYER_EXPORT UnformattedSink: public Destination {
1160 #include <Sawyer/WarningsOff.h>
1161  GangPtr gang_;
1162  PrefixPtr prefix_;
1163 #include <Sawyer/WarningsRestore.h>
1164 
1165 protected:
1166  bool partialMessagesAllowed_;
1167 
1168 protected:
1170  explicit UnformattedSink(const PrefixPtr &prefix): partialMessagesAllowed_(true) {
1171  gang_ = Gang::instance();
1172  prefix_ = prefix ? prefix : Prefix::instance();
1173  init();
1174  }
1175 public:
1188  GangPtr gang() const;
1189  UnformattedSinkPtr gang(const GangPtr &g);
1218  bool partialMessagesAllowed() const;
1219  UnformattedSinkPtr partialMessagesAllowed(bool);
1230  PrefixPtr prefix() const;
1231  UnformattedSinkPtr prefix(const PrefixPtr &p);
1241  virtual std::string maybeTerminatePrior(const Mesg&, const MesgProps&);
1242 
1250  virtual std::string maybePrefix(const Mesg&, const MesgProps&);
1251 
1260  virtual std::string maybeBody(const Mesg&, const MesgProps&);
1261 
1270  virtual std::string maybeFinal(const Mesg&, const MesgProps&);
1271 
1279  virtual std::string render(const Mesg&, const MesgProps&);
1280 protected:
1284  void gangInternal(const GangPtr &g);
1285 private:
1286  void init();
1287 };
1288 
1290 class SAWYER_EXPORT FdSink: public UnformattedSink {
1291  int fd_; // file descriptor or -1
1292 protected:
1294  FdSink(int fd, const PrefixPtr &prefix): UnformattedSink(prefix), fd_(fd) { init(); }
1295 public:
1297  static FdSinkPtr instance(int fd, const PrefixPtr &prefix=PrefixPtr()) {
1298  return FdSinkPtr(new FdSink(fd, prefix));
1299  }
1300 
1301  virtual void post(const Mesg&, const MesgProps&) /*override*/;
1302 private:
1303  void init();
1304 };
1305 
1307 class SAWYER_EXPORT FileSink: public UnformattedSink {
1308  FILE *file_;
1309 protected:
1311  FileSink(FILE *f, const PrefixPtr &prefix): UnformattedSink(prefix), file_(f) { init(); }
1312 public:
1314  static FileSinkPtr instance(FILE *f, const PrefixPtr &prefix=PrefixPtr()) {
1315  return FileSinkPtr(new FileSink(f, prefix));
1316  }
1317 
1318  virtual void post(const Mesg&, const MesgProps&) /*override*/;
1319 private:
1320  void init();
1321 };
1322 
1324 class SAWYER_EXPORT StreamSink: public UnformattedSink {
1325  std::ostream &stream_;
1326 protected:
1328  StreamSink(std::ostream &stream, const PrefixPtr &prefix): UnformattedSink(prefix), stream_(stream) {}
1329 public:
1331  static StreamSinkPtr instance(std::ostream &stream, const PrefixPtr &prefix=PrefixPtr()) {
1332  return StreamSinkPtr(new StreamSink(stream, prefix));
1333  }
1334 
1335  virtual void post(const Mesg&, const MesgProps&) /*override*/;
1336 };
1337 
1338 #ifndef BOOST_WINDOWS
1339 
1342 class SAWYER_EXPORT SyslogSink: public Destination {
1343 protected:
1345  SyslogSink(const char *ident, int option, int facility);
1346 public:
1350  static SyslogSinkPtr instance(const char *ident, int option, int facility) {
1351  return SyslogSinkPtr(new SyslogSink(ident, option, facility));
1352  }
1353  virtual void post(const Mesg&, const MesgProps&) /*override*/;
1354 private:
1355  void init();
1356 };
1357 #endif
1358 
1360 // Message streams
1362 
1363 class Stream;
1364 class StreamBuf;
1365 
1374 class SAWYER_EXPORT SProxy {
1375  Stream *stream_;
1376 public:
1377  SProxy(): stream_(NULL) {}
1378  SProxy(std::ostream*); /*implicit*/
1379  SProxy(std::ostream&); /*implicit*/
1380  SProxy(const SProxy&);
1381  SProxy& operator=(const SProxy&);
1382  ~SProxy() { reset(); }
1383  Stream& operator*() { return *stream_; }
1384  Stream* operator->() { return stream_; }
1385  Stream* get() const { return stream_; }
1386  operator bool() const;
1387  void reset();
1388 };
1389 
1396 class SAWYER_EXPORT Stream: public std::ostream {
1397  friend class StreamBuf;
1398  mutable SAWYER_THREAD_TRAITS::Mutex mutex_;
1399  size_t nrefs_; // used when we don't have std::move semantics
1400  StreamBuf *streambuf_; // each stream has its own, protected by our mutex
1401 public:
1402 
1404  Stream(const std::string facilityName, Importance imp, const DestinationPtr &destination);
1405 
1407  Stream(const MesgProps &props, const DestinationPtr &destination);
1408 
1414  Stream(const Stream &other);
1415 
1421  Stream& operator=(const Stream &other);
1422 
1433  Stream(const std::ostream &other_);
1434 
1445  Stream& operator=(const std::ostream &other_);
1446 
1447  ~Stream();
1448 
1449  // used internally by SProxy; thread-safe
1450  void incrementRefCount();
1451  size_t decrementRefCount(); // returns new ref count
1452 
1456  SProxy dup() const;
1457 
1458 protected:
1465  void initFromNS(const Stream &other);
1466 
1467 public:
1471  bool enabled() const;
1472 
1473  // We'd like bool context to return a value that can't be used in arithmetic or comparison operators, but unfortunately
1474  // we need to also work with the super class (std::basic_ios) that has an implicit "void*" conversion which conflicts with
1475  // the way Sawyer normally handles this (see SharedPointer for an example). We therefore override the super-class'
1476  // void* conversion and "!" operator instead. We also need to override operator bool if there is one.
1477 
1506  operator void*() const {
1507  return enabled() ? const_cast<Stream*>(this) : NULL;
1508  }
1509 #if __cplusplus >= 201103L
1510  explicit operator bool() const {
1511  return enabled();
1512  }
1513 #else
1514  // Needed on macOS
1515  operator bool() const {
1516  return enabled();
1517  }
1518 #endif
1519 
1522  bool operator!() const { return !enabled(); }
1523 
1524  // See Stream::bool()
1525  #define SAWYER_MESG(message_stream) (message_stream) && (message_stream)
1526  #define SAWYER_MSG(message_stream) (message_stream) && (message_stream)
1527 
1528  #define SAWYER_MESG_FIRST(...) Sawyer::Message::firstEnabled(__VA_ARGS__) && Sawyer::Message::firstEnabled(__VA_ARGS__)
1529  #define SAWYER_MESG_OR(s1, s2) SAWYER_MESG_FIRST(s1, s2)
1530  #define SAWYER_MSG_OR(s1, s2) SAWYER_MESG_FIRST(s1, s2)
1531 
1540  void enable(bool b=true);
1541  void disable() { enable(false); }
1553  void completionString(const std::string &s, bool asDefault=true);
1554  void interruptionString(const std::string &s, bool asDefault=true);
1555  void cancelationString(const std::string &s, bool asDefault=true);
1556  void facilityName(const std::string &s, bool asDefault=true);
1566  DestinationPtr destination() const;
1567  Stream& destination(const DestinationPtr &d);
1576  MesgProps properties() const;
1577 };
1578 
1579 SAWYER_EXPORT Stream& firstEnabled(Stream &s1);
1580 SAWYER_EXPORT Stream& firstEnabled(Stream &s1, Stream &s2);
1581 SAWYER_EXPORT Stream& firstEnabled(Stream &s1, Stream &s2, Stream &s3);
1582 SAWYER_EXPORT Stream& firstEnabled(Stream &s1, Stream &s2, Stream &s3, Stream &s4);
1583 SAWYER_EXPORT Stream& firstEnabled(Stream &s1, Stream &s2, Stream &s3, Stream &s4, Stream &s5);
1584 
1606 class SAWYER_EXPORT Facility {
1607  static const unsigned CONSTRUCTED_MAGIC = 0x73617779;
1608  unsigned constructed_;
1609  mutable SAWYER_THREAD_TRAITS::Mutex mutex_;
1610 #include <Sawyer/WarningsOff.h>
1611  std::string name_, comment_;
1612  std::vector<SProxy> streams_;
1613 #include <Sawyer/WarningsRestore.h>
1614 
1615 public:
1621  Facility(): constructed_(CONSTRUCTED_MAGIC) {}
1622 
1626  Facility(const Facility &other);
1627 
1631  Facility& operator=(const Facility &src);
1632 
1633  Facility(const std::string &name, const DestinationPtr &destination): constructed_(CONSTRUCTED_MAGIC), name_(name) {
1634  initStreams(destination);
1635  }
1636 
1637  ~Facility() {
1638  constructed_ = 0;
1639  }
1640 
1644  Facility& initialize(const std::string &name);
1645 
1647  Facility& initialize(const std::string &name, const DestinationPtr &destination);
1648 
1656  bool isConstructed() const { return constructed_ == CONSTRUCTED_MAGIC; }
1657 
1672  Stream& get(Importance imp);
1674  return get(imp);
1675  }
1681  static bool isValidName(const std::string&);
1682 
1688  std::string name() const;
1689 
1698  std::string comment() const;
1699  Facility& comment(const std::string&);
1708  Facility& renameStreams(const std::string &name = "");
1709 
1716  Facility& initStreams(const DestinationPtr&);
1717 
1718 protected:
1719  // Parse a name into a vector of components. Returns an empty vector if the name is not valid.
1720  static std::vector<std::string> parseName(const std::string&);
1721 
1722 };
1723 
1736 class SAWYER_EXPORT Facilities {
1737 public:
1738  typedef std::set<Importance> ImportanceSet;
1739 private:
1741  mutable SAWYER_THREAD_TRAITS::Mutex mutex_;
1742 #include <Sawyer/WarningsOff.h>
1743  FacilityMap facilities_;
1744  ImportanceSet impset_;
1745  bool impsetInitialized_;
1746 #include <Sawyer/WarningsRestore.h>
1747 public:
1748 
1751  //initializeLibrary(); -- delay until later for sake of static initialization of Message::mfacilities
1752  // Initialize impset_ for the sake of insertAndAdjust(), but do not consider it to be truly initialized until after
1753  // a MessageFacility is inserted.
1754  impset_.insert(WARN);
1755  impset_.insert(ERROR);
1756  impset_.insert(FATAL);
1757  impsetInitialized_ = false;
1758  }
1759 
1761  Facilities(const Facilities&);
1762 
1764  Facilities& operator=(const Facilities&);
1765 
1771  ImportanceSet impset() const;
1772 
1782  Facilities& impset(Importance, bool enabled);
1783 
1802  Facilities& insert(Facility &facility, const std::string &name="");
1803  Facilities& insertAndAdjust(Facility &facility, std::string name="");
1809  Facilities& erase(const std::string &name);
1810 
1814  Facilities& erase(Facility &facility);
1815 
1824  Facility& facility(const std::string &name) const;
1825 
1829  std::vector<std::string> facilityNames() const;
1830 
1868  std::string control(const std::string &s);
1869 
1873  std::string configuration() const;
1874 
1886  Facilities& reenable();
1887  Facilities& reenableFrom(const Facilities &other);
1899  Facilities& enable(Importance, bool b=true);
1900  Facilities& disable(Importance imp) { return enable(imp, false); }
1911  Facilities& disable(const std::string &switch_name) { return enable(switch_name, false); }
1912  Facilities& enable(const std::string &switch_name, bool b=true);
1923  Facilities& enable(bool b=true);
1924  Facilities& disable() { return enable(false); }
1931  void shutdown();
1932 
1938  void print(std::ostream&) const;
1939 
1940 private:
1942  struct ControlTerm {
1943  ControlTerm(const boost::regex &facilityNamePattern, bool enable)
1944  : facilityNamePattern(facilityNamePattern), lo(DEBUG), hi(DEBUG), enable(enable) {}
1945  std::string toString() const;
1946  boost::regex facilityNamePattern;
1947  Importance lo, hi;
1948  bool enable;
1949  };
1950 
1951  Facilities& insertNS(Facility&, std::string); // non-synchronized version
1952  Facilities& enableNS(Importance, bool); // non-synchronized version
1953 
1954  // Error information thrown internally.
1955  struct ControlError {
1956  ControlError(const std::string &mesg, const char *position): mesg(mesg), inputPosition(position) {}
1957  std::string mesg;
1958  const char *inputPosition;
1959  };
1960 
1961  // Functions used by the control() method
1962  static boost::regex parseFacilityNamePattern(const char* &input);
1963  static std::string parseEnablement(const char* &input);
1964  static std::string parseRelation(const char* &input);
1965  static std::string parseImportanceName(const char* &input);
1966  static Importance importanceFromString(const std::string&);
1967  static std::list<ControlTerm> parseImportanceList(const boost::regex &facilityNamePattern, const char* &input, bool isGlobal);
1968 
1969  // Remove Facility objects that have apparently been destroyed
1970  void eraseDestroyedNS();
1971 
1972  // Return the list of facilities whose name matches the pattern.
1973  std::vector<Facility*> matchingFacilitiesNS(const boost::regex &namePattern) const;
1974 };
1975 
1976 
1978 
1981 SAWYER_EXPORT extern DestinationPtr merr;
1982 
1984 SAWYER_EXPORT extern Facility mlog;
1985 
1989 SAWYER_EXPORT extern Facilities mfacilities;
1990 
1999 SAWYER_EXPORT extern SProxy assertionStream;
2000 
2007 SAWYER_EXPORT void shutdown();
2008 
2009 
2011 // Facilities guard
2013 
2018 class SAWYER_EXPORT FacilitiesGuard {
2019  Facilities &facilities_;
2021  State state_;
2022 public:
2027  : facilities_(mfacilities) {
2028  save();
2029  }
2030 
2032  explicit FacilitiesGuard(Facilities &facilities)
2033  : facilities_(facilities) {
2034  save();
2035  }
2036 
2039  restore();
2040  }
2041 
2042 private:
2043  void save();
2044  void restore();
2045 };
2046 
2048 // The most commonly used stuff
2050 
2063 namespace Common {
2064 
2065 using Message::DEBUG;
2066 using Message::TRACE;
2067 using Message::WHERE;
2068 using Message::MARCH;
2069 using Message::INFO;
2070 using Message::WARN;
2071 using Message::ERROR;
2072 using Message::FATAL;
2073 
2074 using Message::Stream;
2075 using Message::Facility;
2076 using Message::Facilities;
2077 
2078 } // namespace
2079 
2080 
2081 } // namespace
2082 } // namespace
2083 
2084 #endif
PrefixPtr showImportance(bool b)
Property: whether to show the importance property.
Definition: Message.h:1141
static TimeFilterPtr instance(double minInterval)
Allocating constructor.
Definition: Message.h:835
Facilities()
Constructs an empty container of Facility objects.
Definition: Message.h:1750
std::string stringifyColor(AnsiColor)
Convert an AnsiColor enum to a string.
size_t ntext() const
Zero if !isValid().
static GangPtr instanceForId(int id)
The gang for the specified ID, creating a new one if necessary.
Messages intended to be useful primarily to the author of the code.
Definition: Message.h:314
ANSI "red" color.
Definition: Message.h:345
ImportanceFilter(bool dflt)
Constructor for derived classes.
Definition: Message.h:886
static MultiplexerPtr instance()
Allocating constructor.
Definition: Message.h:679
ANSI Color specification for text written to a terminal.
Definition: Message.h:374
ANSI "magenta" color.
Definition: Message.h:349
ColorSpec(AnsiColor fg)
Constructs an object that specifies only a foreground color.
Definition: Message.h:385
void emitted(const Mesg &, const MesgProps &)
Make specified message the high water mark.
static StreamSinkPtr instance(std::ostream &stream, const PrefixPtr &prefix=PrefixPtr())
Allocating constructor.
Definition: Message.h:1331
FacilitiesGuard(Facilities &facilities)
Saves and restores specified message facilities.
Definition: Message.h:2032
ANSI "cyan" color.
Definition: Message.h:350
MesgProps & properties()
Returns a reference to message properties.
Definition: Message.h:581
boost::tribool bold
Use ANSI "bold" attribute?
Definition: Message.h:378
FdSink(int fd, const PrefixPtr &prefix)
Constructor for derived classes.
Definition: Message.h:1294
bool showImportance() const
Property: whether to show the importance property.
Definition: Message.h:1140
Send free-format messages to a Unix file descriptor.
Definition: Message.h:1290
const MesgProps & defaultPropertiesNS() const
Default values for message properties.
Definition: Message.h:627
bool isCanceled() const
Returns true if the message has entered the canceled state.
Definition: Message.h:566
boost::tribool isBuffered
Whether the output buffered and emitted on a per-message basis.
Definition: Message.h:430
Optional< Importance > importance
The message importance level.
Definition: Message.h:429
Collection of streams.
Definition: Message.h:1606
~FacilitiesGuard()
Restores previously saved facility settings.
Definition: Message.h:2038
Facility()
Construct an empty facility.
Definition: Message.h:1621
bool isDefault() const
Returns true if this object is in its default-constructed state.
Definition: Message.h:391
std::vector< BakedDestination > BakedDestinations
Baked properties for multiple destinations.
Definition: Message.h:497
Mesg(const MesgProps &props)
Creates a new, partial message that is empty.
Definition: Message.h:536
Optional< std::string > interruptionStr
String to append when a partial message is interrupted.
Definition: Message.h:432
MesgProps overrides_
Override properties applied to incoming message.
Definition: Message.h:613
bool isValid() const
Returns true if high water is defined.
Collection of facilities.
Definition: Message.h:1736
SharedPointer< class Filter > FilterPtr
Smart pointer.
Definition: Message.h:477
Mesg(const std::string &mesg)
Creates a new, completed message with the specified text.
Definition: Message.h:540
bool isTerminal(int fd)
True if fd is a tty.
Error messages that indicate an abnormal situation from which the program was able to at least partia...
Definition: Message.h:330
SharedPointer< class FileSink > FileSinkPtr
Smart pointer.
Definition: Message.h:485
PrefixPtr showThreadId(bool b)
Property: whether to show the thread ID in the message prefix area.
Definition: Message.h:1083
Mesg(const std::string &facilityName, Importance imp)
Creates a new, partial message that is empty.
Definition: Message.h:529
std::set< Importance > ImportanceSet
A set of importance levels.
Definition: Message.h:1738
FacilitiesGuard()
Saves and restores the global message facilities.
Definition: Message.h:2026
std::pair< DestinationPtr, MesgProps > BakedDestination
Baked properties for a destination.
Definition: Message.h:494
bool isComplete() const
Returns true if the message has entered the completed state.
Definition: Message.h:562
void clear()
Reset to initial state.
Base class for internal nodes that filter messages.
Definition: Message.h:723
Facility mlog
Facility used by Sawyer components.
Information printed at the beginning of each free-format message.
Definition: Message.h:986
TimeFilter(double minInterval)
Constructor for derived classes.
Definition: Message.h:829
unsigned id() const
Exception unless isValid().
const ColorSpec & operator[](Importance imp) const
Colors for a message.
Definition: Message.h:409
ColorSet & colorSet()
Property: colors to use for the prefix if coloring is enabled.
Definition: Message.h:1039
ColorSpec & operator[](Importance imp)
Colors for a message.
Definition: Message.h:410
Messages that indicate an abnormal situation from which the program was unable to recover...
Definition: Message.h:332
ColorSpec()
Constructs an object with default foreground and background colors.
Definition: Message.h:382
ANSI "black" color.
Definition: Message.h:344
bool isEmpty() const
Returns true if the message has no text.
Definition: Message.h:570
Filters messages based on importance level.
Definition: Message.h:880
ANSI default color.
Definition: Message.h:352
const std::string & text() const
Return the message text.
Definition: Message.h:559
Mesg()
Creates a new, partial message that is empty.
Definition: Message.h:525
Stream & operator[](Importance imp)
Returns a stream for the specified importance level.
Definition: Message.h:1673
SharedPointer< class ImportanceFilter > ImportanceFilterPtr
Smart pointer.
Definition: Message.h:480
Reference-counting intrusive smart pointer.
Definition: SharedPointer.h:68
When showFacilityName() const
Property: whether to show the facilityName property.
Definition: Message.h:1129
Name space for the entire library.
Definition: FeasiblePath.h:767
boost::tribool useColor
Whether to use ANSI escape sequences to colorize output.
Definition: Message.h:435
SharedPointer< class Prefix > PrefixPtr
Smart pointer.
Definition: Message.h:482
static ImportanceFilterPtr instance(bool dflt)
Allocating constructor.
Definition: Message.h:894
Filter()
Constructor for derived classes.
Definition: Message.h:726
ANSI "white" color.
Definition: Message.h:351
SharedPointer< class SyslogSink > SyslogSinkPtr
Smart pointer.
Definition: Message.h:487
static ColorSet fullColor()
Returns a color set that uses various foreground colors for the different message importance levels...
Saves and restores facilities.
Definition: Message.h:2018
AnsiColor
Colors used by sinks that write to terminals.
Definition: Message.h:343
Sawyer::SynchronizationTraits< Sawyer::SingleThreadedTag >::RecursiveMutex mutex_
Mutex protecting data members here and in subclasses.
Definition: Message.h:611
PrefixPtr programName(const std::string &s)
Property: program name.
Definition: Message.h:1053
When
When to show something.
Definition: Message.h:990
SharedPointer< class Destination > DestinationPtr
Smart pointer.
Definition: Message.h:475
virtual void forwarded(const MesgProps &)
Called once by bakeDestinations if shouldForward() returned true.
Definition: Message.h:812
static SyslogSinkPtr instance(const char *ident, int option, int facility)
Allocating constructor.
Definition: Message.h:1350
bool isConstructed() const
Returns true if called on an object that has been constructed.
Definition: Message.h:1656
Progress reports and other similar rapidly updating partial messages.
Definition: Message.h:325
Sends messages to the syslog daemon.
Definition: Message.h:1342
unsigned id() const
Return unique message ID.
Definition: Message.h:556
PrefixPtr showElapsedTime(bool b)
Property: whether to show time deltas.
Definition: Message.h:1118
Sends incoming messages to multiple destinations.
Definition: Message.h:669
Optional< std::string > lineTermination
Line termination for completion, interruption, and cancelation.
Definition: Message.h:434
Facilities mfacilities
Library-provided facility group.
Properties for messages.
Definition: Message.h:426
Multiplexer()
Constructor for derived classes.
Definition: Message.h:676
void cancel()
Cause the message to enter the canceled state.
Definition: Message.h:589
SharedPointer< class SequenceFilter > SequenceFilterPtr
Smart pointer.
Definition: Message.h:478
MesgProps & defaultPropertiesNS()
Default values for message properties.
Definition: Message.h:628
Colors to use for each message importance.
Definition: Message.h:397
bool showElapsedTime() const
Property: whether to show time deltas.
Definition: Message.h:1117
Creates SharedPointer from this.
static void shutdownNS()
Reset to initial state to free memory.
Mesg(const std::string &facilityName, Importance imp, const std::string &mesg)
Creates a new, completed message with the specified text.
Definition: Message.h:545
const Optional< std::string > & programName() const
Property: program name.
Definition: Message.h:1052
Send free-format messages to a C FILE pointer.
Definition: Message.h:1307
void disable()
Enable or disable a stream.
Definition: Message.h:1541
ANSI "blue" color.
Definition: Message.h:348
SharedPointer< class Gang > GangPtr
Smart pointer.
Definition: Message.h:481
const ColorSet & colorSet() const
Property: colors to use for the prefix if coloring is enabled.
Definition: Message.h:1038
SharedPointer< class TimeFilter > TimeFilterPtr
Smart pointer.
Definition: Message.h:479
Facilities & disable(const std::string &switch_name)
Enable/disable a facility by name.
Definition: Message.h:1911
bool showProgramName() const
Property: whether to show the program name in the message prefix area.
Definition: Message.h:1071
static FileSinkPtr instance(FILE *f, const PrefixPtr &prefix=PrefixPtr())
Allocating constructor.
Definition: Message.h:1314
A single message.
Definition: Message.h:513
static SequenceFilterPtr instance(size_t nskip, size_t rate, size_t limit)
Construct an instance.
Definition: Message.h:765
Facilities & disable(Importance imp)
Enable/disable specific importance level across all facilities.
Definition: Message.h:1900
Importance
Level of importance for a message.
Definition: Message.h:313
void shutdown()
Reset global variables to initial states.
Filters messages based on time.
Definition: Message.h:819
SharedPointer< class FdSink > FdSinkPtr
Smart pointer.
Definition: Message.h:484
std::string stringifyImportance(Importance)
Convert an Importance enum to a string.
MesgProps dflts_
Default properties merged into each incoming message.
Definition: Message.h:612
const MesgProps & overridePropertiesNS() const
Overrides message properties.
Definition: Message.h:639
SProxy assertionStream
The stream to be used for assertions.
FileSink(FILE *f, const PrefixPtr &prefix)
Constructor for derived classes.
Definition: Message.h:1311
Base class for all types of message destinations.
Definition: Message.h:609
Base class for reference counted objects.
Definition: SharedObject.h:64
DestinationPtr merr
Library-provided message destination.
void complete()
Cause the message to enter the completed state.
Definition: Message.h:585
Number of distinct importance levels.
Definition: Message.h:338
static FdSinkPtr instance(int fd, const PrefixPtr &prefix=PrefixPtr())
Allocating constructor.
Definition: Message.h:1297
SharedPointer< class StreamSink > StreamSinkPtr
Smart pointer.
Definition: Message.h:486
UnformattedSink(const PrefixPtr &prefix)
Constructor for derived classes.
Definition: Message.h:1170
Send free-format messages to a C++ I/O stream.
Definition: Message.h:1324
PrefixPtr showFacilityName(When w)
Property: whether to show the facilityName property.
Definition: Message.h:1130
virtual void forwarded(const MesgProps &)
Called once by bakeDestinations if shouldForward() returned true.
Definition: Message.h:920
std::string escape(const std::string &)
Convert a string to its C representation.
Warning messages that indicate an unusual situation from which the program was able to fully recover...
Definition: Message.h:328
MesgProps & overridePropertiesNS()
Overrides message properties.
Definition: Message.h:640
static PrefixPtr instance()
Allocating constructor.
Definition: Message.h:1024
Detailed tracing information useful to end-users that are trying to understand program internals...
Definition: Message.h:317
Prefix()
Constructor for derived classes.
Definition: Message.h:1011
ANSI "yellow" color.
Definition: Message.h:347
StreamSink(std::ostream &stream, const PrefixPtr &prefix)
Constructor for derived classes.
Definition: Message.h:1328
static GangPtr instanceForTty()
Returns the gang for streams that are emitting to a tty.
std::ostream & operator<<(std::ostream &o, const MesgProps &props)
Print the values for all message properties.
const MesgProps & properties() const
Returns a reference to message properties.
Definition: Message.h:580
Optional< std::string > completionStr
String to append to the end of each complete message.
Definition: Message.h:431
double now()
Current system time in seconds.
Optional< std::string > cancelationStr
String to append to a partial message when it is destroyed.
Definition: Message.h:433
static GangPtr instance()
New non-shared gang with NO_GANG_ID.
Mesg(const MesgProps &props, const std::string &mesg)
Creates a new, completed message with the specified text.
Definition: Message.h:552
Converts text to messages.
Definition: Message.h:1396
SequenceFilter(size_t nskip, size_t rate, size_t limit)
Constructor for derived classes.
Definition: Message.h:757
ColorSpec(AnsiColor fg, AnsiColor bg, bool bold)
Constructs an object with fully-specified colors.
Definition: Message.h:388
SharedPointer< class UnformattedSink > UnformattedSinkPtr
Smart pointer.
Definition: Message.h:483
Optional< std::string > facilityName
The name of the logging facility that produced this message.
Definition: Message.h:428
Base class for final destinations that are free-format.
Definition: Message.h:1159
AnsiColor background
Background color, or COLOR_DEFAULT.
Definition: Message.h:376
PrefixPtr showProgramName(bool b)
Property: whether to show the program name in the message prefix area.
Definition: Message.h:1072
bool showThreadId() const
Property: whether to show the thread ID in the message prefix area.
Definition: Message.h:1082
ANSI "green" color.
Definition: Message.h:346
bool initializeLibrary()
Explicitly initialize the library.
Facilities & disable()
Enable/disable all facilities.
Definition: Message.h:1924
Container associating values with keys.
Definition: Sawyer/Map.h:66
Informative messages.
Definition: Message.h:326
SharedPointer< class Multiplexer > MultiplexerPtr
Smart pointer.
Definition: Message.h:476
bool operator!() const
Returns false if this stream is enabled.
Definition: Message.h:1522
AnsiColor foreground
Foreground color, or COLOR_DEFAULT.
Definition: Message.h:375
Granular tracing information useful to end-users that are trying to understand program internals...
Definition: Message.h:322
Filters messages based on how many messages have been seen.
Definition: Message.h:750