Implemented J2K desc to/from MD
[asdcplib.git] / src / KM_log.h
index 0042119a2aa67b01a450c38279bb01b853bad2c8..9279f300a41c6d0e9736a53be8f969adf7e22184 100755 (executable)
@@ -1,5 +1,5 @@
 /*
-Copyright (c) 2004-2007, John Hurst
+Copyright (c) 2004-2009, John Hurst
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
@@ -38,6 +38,8 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <KM_util.h>
 #include <stdarg.h>
 #include <errno.h>
+#include <iosfwd>
+#include <set>
 
 #define LOG_MSG_IMPL(t) \
   va_list args; \
@@ -86,26 +88,28 @@ namespace Kumu
     LOG_NOTICE,   // application user info
     LOG_ALERT,    // application non-fatal or near-miss error
     LOG_CRIT,     // application fatal error
+    LOG_MAX
   };
 
 
   // OR these values together to come up with sink filter flags.
-  // The default mask is 0x0000ffff (no time stamp, no pid, all messages).
-  const i32_t LOG_ALLOW_TIMESTAMP = 0x01000000;
-  const i32_t LOG_ALLOW_PID       = 0x02000000;
-
-  const i32_t LOG_ALLOW_DEBUG     = 0x00000001;
-  const i32_t LOG_ALLOW_INFO      = 0x00000002;
-  const i32_t LOG_ALLOW_WARN      = 0x00000004;
-  const i32_t LOG_ALLOW_ERROR     = 0x00000008;
-  const i32_t LOG_ALLOW_NOTICE    = 0x00000010;
-  const i32_t LOG_ALLOW_ALERT     = 0x00000020;
-  const i32_t LOG_ALLOW_CRIT      = 0x00000040;
-
-  const i32_t LOG_ALLOW_DEFAULT   = 0x00008000; // show messages having an unknown type
-  const i32_t LOG_ALLOW_NONE      = 0x00000000;
-  const i32_t LOG_ALLOW_MESSAGES  = 0x0000ffff;
-  const i32_t LOG_ALLOW_ANY       = 0xffffffff;
+  // The default mask is LOG_ALLOW_ALL (all messages).
+  const i32_t LOG_ALLOW_DEBUG      = 0x00000001;
+  const i32_t LOG_ALLOW_INFO       = 0x00000002;
+  const i32_t LOG_ALLOW_WARN       = 0x00000004;
+  const i32_t LOG_ALLOW_ERROR      = 0x00000008;
+  const i32_t LOG_ALLOW_NOTICE     = 0x00000010;
+  const i32_t LOG_ALLOW_ALERT      = 0x00000020;
+  const i32_t LOG_ALLOW_CRIT       = 0x00000040;
+  const i32_t LOG_ALLOW_NONE       = 0x00000000;
+  const i32_t LOG_ALLOW_ALL        = 0x000fffff;
+
+  // options are used to control display format default is 0.
+  const i32_t LOG_OPTION_TYPE      = 0x01000000;
+  const i32_t LOG_OPTION_TIMESTAMP = 0x02000000;
+  const i32_t LOG_OPTION_PID       = 0x04000000;
+  const i32_t LOG_OPTION_NONE      = 0x00000000;
+  const i32_t LOG_OPTION_ALL       = 0xfff00000;
 
   // A log message with environmental metadata
  class LogEntry : public IArchive
@@ -120,7 +124,12 @@ namespace Kumu
     LogEntry(ui32_t pid, LogType_t t, const char* m) : PID(pid), Type(t), Msg(m) { assert(m); }
     virtual ~LogEntry() {}
 
-    bool   CreateStringWithFilter(i32_t, std::string&) const;
+    // returns true if the message Type is present in the mask
+    bool   TestFilter(i32_t mask_value) const;
+
+    // renders the message into outstr using the given dispaly options
+    // returns outstr&
+    std::string& CreateStringWithOptions(std::string& outstr, i32_t mask_value) const;
 
     // IArchive
     bool   HasValue() const { return ! Msg.empty(); }
@@ -129,23 +138,56 @@ namespace Kumu
     bool   Unarchive(MemIOReader* Reader);
   };
 
+  //
+  std::basic_ostream<char, std::char_traits<char> >&
+    operator<<(std::basic_ostream<char, std::char_traits<char> >& strm, LogEntry const& Entry);
+
 
-  typedef ArchivableList<LogEntry> LogEntryList_t;
+  typedef ArchivableList<LogEntry> LogEntryList;
   
   //
   class ILogSink
     {
     protected:
       i32_t m_filter;
+      i32_t m_options;
+      Mutex m_lock;
+      std::set<ILogSink*> m_listeners;
+
+      // you must obtain m_lock BEFORE calling this from your own WriteEntry
+      void WriteEntryToListeners(const LogEntry& entry)
+      {
+       std::set<ILogSink*>::iterator i;
+       for ( i = m_listeners.begin(); i != m_listeners.end(); ++i )
+         (*i)->WriteEntry(entry);
+      }
+
+      KM_NO_COPY_CONSTRUCT(ILogSink);
 
     public:
+    ILogSink() : m_filter(LOG_ALLOW_ALL), m_options(LOG_OPTION_NONE) {}
       virtual ~ILogSink() {}
 
-      void  SetFilterFlags(i32_t f) { m_filter = f; }
-      i32_t GetFilterFlags() const  { return m_filter; }
       void  SetFilterFlag(i32_t f) { m_filter |= f; }
       void  UnsetFilterFlag(i32_t f) { m_filter &= ~f; }
-      bool  TestFilterFlag(i32_t f) const  { return ((m_filter & f) != 0); }
+      bool  TestFilterFlag(i32_t f) const  { return ((m_filter & f) == f); }
+
+      void  SetOptionFlag(i32_t o) { m_options |= o; }
+      void  UnsetOptionFlag(i32_t o) { m_options &= ~o; }
+      bool  TestOptionFlag(i32_t o) const  { return ((m_options & o) == o); }
+
+      void AddListener(ILogSink& s) {
+       if ( &s != this )
+         {
+           AutoMutex l(m_lock);
+           m_listeners.insert(&s);
+         }
+      }
+
+      void DelListener(ILogSink& s) {
+       AutoMutex l(m_lock);
+       m_listeners.erase(&s);
+      }
 
       // library messages
       void Error(const char* fmt, ...)    { LOG_MSG_IMPL(LOG_ERROR); }
@@ -175,75 +217,56 @@ namespace Kumu
   ILogSink& DefaultLogSink();
 
 
-  // Sets a log sink as the default until the object is destroyed.
-  // The original default sink is saved and then restored on delete.
-  class LogSinkContext
-  {
-    KM_NO_COPY_CONSTRUCT(LogSinkContext);
-    LogSinkContext();
-    ILogSink* m_orig;
+  // attach a log sink as a listener until deleted
+  class LogSinkListenContext
+    {
+      ILogSink* m_log_source;
+      ILogSink* m_sink;
+      KM_NO_COPY_CONSTRUCT(LogSinkListenContext);
+      LogSinkListenContext();
+
+    public:
+      LogSinkListenContext(ILogSink& source, ILogSink& sink)
+       {
+         m_log_source = &source;
+         m_sink = &sink;
+         m_log_source->AddListener(*m_sink);
+       }
+
+      ~LogSinkListenContext()
+       {
+         m_log_source->DelListener(*m_sink);
+       }
+    };
 
-  public:
-    LogSinkContext(ILogSink& sink) {
-      m_orig = &DefaultLogSink();
-      SetDefaultLogSink(&sink);
-    }
-
-    ~LogSinkContext() {
-      SetDefaultLogSink(m_orig);
-    }
-  };
 
   //------------------------------------------------------------------------------------------
   //
 
-  // write messages to two subordinate log sinks 
-  class TeeLogSink : public ILogSink
-  {
-    KM_NO_COPY_CONSTRUCT(TeeLogSink);
-    TeeLogSink();
-
-    ILogSink& m_a;
-    ILogSink& m_b;
-
-  public:
-    TeeLogSink(ILogSink& a, ILogSink& b) : m_a(a), m_b(b) {}
-    virtual ~TeeLogSink() {}
-
-    void WriteEntry(const LogEntry& Entry) {
-      m_a.WriteEntry(Entry);
-      m_a.WriteEntry(Entry);
-    }
-  };
-
-  // collect log messages into the given list
+  // collect log messages into the given list, does not test filter
   class EntryListLogSink : public ILogSink
   {
+    LogEntryList& m_Target;
     KM_NO_COPY_CONSTRUCT(EntryListLogSink);
     EntryListLogSink();
 
-    LogEntryList_t& m_Target;
-
   public:
-    EntryListLogSink(LogEntryList_t& target) : m_Target(target) {}
+    EntryListLogSink(LogEntryList& target) : m_Target(target) {}
     virtual ~EntryListLogSink() {}
 
-    void WriteEntry(const LogEntry& Entry) {
-      m_Target.push_back(Entry);
-    }
+    void WriteEntry(const LogEntry& Entry);
   };
 
 
   // write messages to a POSIX stdio stream
   class StdioLogSink : public ILogSink
     {
-      Mutex m_Lock;
       FILE* m_stream;
       KM_NO_COPY_CONSTRUCT(StdioLogSink);
 
     public:
-      StdioLogSink() : m_stream(stderr) {};
-      StdioLogSink(FILE* stream) : m_stream(stream) {}
+    StdioLogSink() : m_stream(stderr) {}
+    StdioLogSink(FILE* stream) : m_stream(stream) {}
       virtual ~StdioLogSink() {}
 
     void WriteEntry(const LogEntry&);
@@ -253,7 +276,6 @@ namespace Kumu
   // write messages to the Win32 debug stream
   class WinDbgLogSink : public ILogSink
     {
-      Mutex m_Lock;
       KM_NO_COPY_CONSTRUCT(WinDbgLogSink);
 
     public:
@@ -268,7 +290,6 @@ namespace Kumu
   // write messages to a POSIX file descriptor
   class StreamLogSink : public ILogSink
     {
-      Mutex m_Lock;
       int   m_fd;
       KM_NO_COPY_CONSTRUCT(StreamLogSink);
       StreamLogSink();
@@ -279,6 +300,22 @@ namespace Kumu
 
       void WriteEntry(const LogEntry&);
     };
+
+  // write messages to the syslog facility
+  class SyslogLogSink : public ILogSink
+    {
+      KM_NO_COPY_CONSTRUCT(SyslogLogSink);
+      SyslogLogSink();
+  
+    public:
+      SyslogLogSink(const std::string& source_name, int facility);
+      virtual ~SyslogLogSink();
+      void WriteEntry(const LogEntry&);
+    };
+
+  // convert a string into the appropriate syslog facility id
+  int SyslogNameToFacility(const std::string& facility_name);
+
 #endif