Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members  

wvlog.cc

Go to the documentation of this file.
00001 /*
00002  * Worldvisions Weaver Software:
00003  *   Copyright (C) 1997-2002 Net Integration Technologies, Inc.
00004  * 
00005  * Functions needed to implement general WvLog class.
00006  * 
00007  * See wvlog.h for more information.
00008  */
00009 #include "wvlogrcv.h"
00010 #include <ctype.h>
00011 
00012 WvLogRcvBaseList WvLog::receivers;
00013 int WvLog::num_receivers = 0, WvLog::num_logs = 0;
00014 WvLogRcvBase *WvLog::default_receiver = NULL;
00015 
00016 char *WvLogRcv::loglevels[WvLog::NUM_LOGLEVELS] = {
00017     "Crit",
00018     "Err",
00019     "Warn",
00020     "Notice",
00021     "Info",
00022     "*1",
00023     "*2",
00024     "*3",
00025     "*4",
00026     "*5",
00027 };
00028 
00029 
00030 
00032 
00033 
00034 
00035 WvLog::WvLog(const WvString &_app, LogLevel _loglevel, const WvLog *par)
00036         : app(_app)
00037 {
00038     app.unique();
00039     parent = par;
00040     loglevel = _loglevel;
00041     num_logs++;
00042 }
00043 
00044 
00045 WvLog::WvLog(const WvLog &l)
00046 {
00047     parent = l.parent ? l.parent : &l;
00048     app = parent->app;
00049     loglevel = parent->loglevel;
00050     num_logs++;
00051 }
00052 
00053 
00054 WvLog::~WvLog()
00055 {
00056     num_logs--;
00057     if (!num_logs && default_receiver)
00058     {
00059         num_receivers++; // deleting default does not really reduce
00060         delete default_receiver;
00061         default_receiver = NULL;
00062     }
00063 }
00064 
00065 
00066 bool WvLog::isok() const
00067 {
00068     return true;
00069 }
00070 
00071 
00072 size_t WvLog::uwrite(const void *_buf, size_t len)
00073 {
00074     if (!num_receivers)
00075     {
00076         if (!default_receiver)
00077         {
00078             // nobody's listening -- create a receiver on the console
00079             default_receiver = new WvLogConsole(dup(2));
00080             num_receivers--; // default does not qualify!
00081         }
00082         default_receiver->log(parent ? parent : this, loglevel,
00083                               (const char *)_buf, len);
00084         return len;
00085     }
00086     else if (default_receiver)
00087     {
00088         // no longer empty list -- delete our default to stderr
00089         num_receivers++; // deleting default does not really reduce
00090         delete default_receiver;
00091         default_receiver = NULL;
00092     }
00093     
00094     WvLogRcvBaseList::Iter i(receivers);
00095     for (i.rewind(); i.next(); )
00096     {
00097         WvLogRcvBase &rc = i;
00098         rc.log(parent ? parent : this, loglevel, (const char *)_buf, len);
00099     }
00100     
00101     return len;
00102 }
00103 
00104 
00105 
00107 
00108 
00109 
00110 WvLogRcvBase::WvLogRcvBase()
00111 {
00112     WvLog::receivers.append(this, false);
00113     WvLog::num_receivers++;
00114 }
00115 
00116 
00117 WvLogRcvBase::~WvLogRcvBase()
00118 {
00119     WvLog::receivers.unlink(this);
00120     WvLog::num_receivers--;
00121 }
00122 
00123 
00124 const char *WvLogRcvBase::appname(const WvLog *log) const
00125 {
00126     return log->app;
00127 }
00128 
00129 
00130 
00132 
00133 
00134 
00135 WvLogRcv::WvLogRcv(WvLog::LogLevel _max_level)
00136 {
00137     last_source = NULL;
00138     last_level = WvLog::NUM_LOGLEVELS;
00139     max_level = _max_level;
00140     at_newline = true;
00141 }
00142 
00143 
00144 WvLogRcv::~WvLogRcv()
00145 {
00146 }
00147 
00148 
00149 void WvLogRcv::_make_prefix()
00150 {
00151     prefix = WvString("%s<%s>: ",
00152                       appname(last_source), loglevels[last_level]);
00153     prelen = strlen(prefix);
00154 }
00155 
00156 
00157 void WvLogRcv::_begin_line()
00158 {
00159     mid_line(prefix, prelen);
00160 }
00161 
00162 
00163 void WvLogRcv::_end_line()
00164 {
00165     // do nothing
00166 }
00167 
00168 
00169 void WvLogRcv::log(const WvLog *source, int _loglevel,
00170                         const char *_buf, size_t len)
00171 {
00172     WvLog::LogLevel loglevel = (WvLog::LogLevel)_loglevel;
00173     char hex[5];
00174     
00175     if (loglevel > max_level)
00176         return;
00177 
00178     // only need to start a new line with new headers if they headers have
00179     // changed.  if the source and level are the same as before, just continue
00180     // the previous log entry.
00181     if (source != last_source || loglevel != last_level)
00182     {
00183         end_line();
00184         last_source = source;
00185         last_level = loglevel;
00186         _make_prefix();
00187     }
00188     
00189     char *buf = (char *)_buf, *bufend = buf + len, *cptr;
00190 
00191     // loop through the buffer, printing each character or its [hex] equivalent
00192     // if it is unprintable.  Also eat newlines unless they are appropriate.
00193     while (buf < bufend)
00194     {
00195         if (buf[0] == '\n' || buf[0] == '\r')
00196         {
00197             end_line();
00198             buf++;
00199             continue;
00200         }
00201 
00202         begin_line();
00203 
00204         if (buf[0] == '\t')
00205         {
00206             mid_line(" ", 1);
00207             buf++;
00208             continue;
00209         }
00210         else if (!isascii(buf[0]) || !isprint(buf[0]))
00211         {
00212             snprintf(hex, 5, "[%02x]", *(unsigned char *)buf);
00213             mid_line(hex, 4);
00214             buf++;
00215             continue;
00216         }
00217 
00218         // like strchr, but size-limited instead of null-terminated
00219         for (cptr = buf; cptr < bufend; cptr++)
00220             if (*cptr == '\n' || !isascii(*cptr) || !isprint(*cptr)) break;
00221         
00222         if (*cptr == '\n') // end of line
00223         {
00224             mid_line(buf, cptr - buf);
00225             buf = cptr;
00226         }
00227         else if (!isascii(*cptr) || !isprint(*cptr))
00228         {
00229             mid_line(buf, cptr - buf);
00230             buf = cptr;
00231         }
00232         else // end of buffer
00233         {
00234             mid_line(buf, bufend - buf);
00235             buf = bufend;
00236         }
00237     }
00238 }
00239 
00240 
00241 
00243 
00244 
00245 
00246 WvLogConsole::WvLogConsole(int _fd, WvLog::LogLevel _max_level)
00247         : WvStream(_fd), WvLogRcv(_max_level)
00248 {
00249 }
00250 
00251 
00252 WvLogConsole::~WvLogConsole()
00253 {
00254     end_line();
00255 }
00256 
00257 
00258 void WvLogConsole::_mid_line(const char *str, size_t len)
00259 {
00260     uwrite(str, len);
00261 }

Generated on Fri Apr 5 15:16:52 2002 for WvStreams by doxygen1.2.15