LogIO.h

Go to the documentation of this file.
00001 //# LogIO.h: ostream-like interface to creating log messages.
00002 //# Copyright (C) 1997,1999,2000,2001,2003
00003 //# Associated Universities, Inc. Washington DC, USA.
00004 //#
00005 //# This library is free software; you can redistribute it and/or modify it
00006 //# under the terms of the GNU Library General Public License as published by
00007 //# the Free Software Foundation; either version 2 of the License, or (at your
00008 //# option) any later version.
00009 //#
00010 //# This library is distributed in the hope that it will be useful, but WITHOUT
00011 //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00012 //# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
00013 //# License for more details.
00014 //#
00015 //# You should have received a copy of the GNU Library General Public License
00016 //# along with this library; if not, write to the Free Software Foundation,
00017 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
00018 //#
00019 //# Correspondence concerning AIPS++ should be addressed as follows:
00020 //#        Internet email: aips2-request@nrao.edu.
00021 //#        Postal address: AIPS++ Project Office
00022 //#                        National Radio Astronomy Observatory
00023 //#                        520 Edgemont Road
00024 //#                        Charlottesville, VA 22903-2475 USA
00025 //#
00026 //#
00027 //# $Id$
00028 
00029 #ifndef CASA_LOGIO_H
00030 #define CASA_LOGIO_H
00031 
00032 //# Includes
00033 #include <casacore/casa/aips.h>
00034 #include <casacore/casa/Logging/LogMessage.h>
00035 #include <casacore/casa/Logging/LogSink.h>
00036 #include <casacore/casa/BasicSL/Complex.h>
00037 #include <casacore/casa/iosstrfwd.h>
00038 
00039 namespace casacore { //# NAMESPACE CASACORE - BEGIN
00040 
00041 //# Forward Declarations
00042 class LogSink;
00043 class LogOrigin;
00044 
00045 // <summary>
00046 // ostream-like interface to creating log messages.
00047 // </summary>
00048 
00049 // <use visibility=export>
00050 
00051 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="tLogIO.cc" demos="dLogging.cc">
00052 // </reviewed>
00053 
00054 // <prerequisite>
00055 //   <li> <linkto class=LogSink>LogSink</linkto> class
00056 //   <li> <linkto class=LogMessage>LogMessage</linkto> class
00057 //   <li> <linkto class=LogMessage>LogOrigin</linkto> class
00058 // </prerequisite>
00059 //
00060 // <etymology>
00061 // <src>Log</src> message, <src>I</src>nput/<src>O</src>utput.
00062 // </etymology>
00063 //
00064 // <synopsis>
00065 // LogIO is intended to be used in a way similar to the ostream class.
00066 // However, rather than sending it's output to a file or stdout, it bundles
00067 // its output up into <linkto class=LogMessage>LogMessage</linkto> objects 
00068 // and posts them to a <linkto class=LogSink>LogSink</linkto>.
00069 //
00070 // When you use the "<<" operator on a LogIO, you are building up a log message
00071 // inside the LogIO object. The message is posted when:
00072 // <ol>
00073 //    <li> <src>LogIO::POST()</src> is called
00074 //    <li> You send the <src>LogIO::POST</src> or <src>LogIO::EXCEPTION</src>
00075 //         commands to the LogIO with the shift (<src> << </src>) command.
00076 //    <li> The LogIO object is destructed.
00077 // </ol>
00078 // Note that log messages may span multiple lines, so sending the LogIO a
00079 // newline (via "\n" or endl) does not force the message to be emitted.
00080 // </synopsis>
00081 //
00082 // <example>
00083 // A LogIO may be created in the following ways:
00084 // <srcblock>
00085 //    LogIO   os;
00086 // </srcblock>
00087 // Here, <src>os</src> is attached to the global log sink, and no origin
00088 // information is set.
00089 //
00090 // <srcblock>
00091 //    TableLogSink tab(...);
00092 //    LogIO   os(tab);
00093 // </srcblock>
00094 // Here, <src>os</src> is attached to <src>tab</src> (and also to the global
00095 // log sink since every sink's <src>post</src> also calls the global sink's
00096 // <src>post</src>).
00097 //
00098 // 
00099 // <srcblock>
00100 //    LogIO   os(LogOrigin("class", "func(args)", WHERE));
00101 // </srcblock>
00102 // Here, <src>os</src> is attached to the global sink and the origin
00103 // information is set to <src>class::func(args)</src> and the line number and
00104 // source file information is set (with <src>WHERE</src>).
00105 //
00106 // <srcblock>
00107 //    TableLogSink tab(...);
00108 //    LogIO   os(LogOrigin("class", "func(args)", WHERE), tab);
00109 // </srcblock>
00110 // Here all the above information is set.
00111 //
00112 // Once you have a <src>LogIO</src>, using it is pretty simple:
00113 // <srcblock>
00114 //   os << "Every good boy deserves" << 5 << " pieces of fudge!";
00115 // </srcblock>
00116 //
00117 // This accumulates the message but does not send it. If you want to force it
00118 // to be sent you can do so with either of the following methods:
00119 // <srcblock>
00120 //    os << LogIO::POST;     // From the Commands enum
00121 //    os.post();             // Member function
00122 // </srcblock>
00123 // Note that after a post the priority is reset to NORMAL.
00124 //
00125 // If you want to change the level of the message you can also do so with the
00126 // shift operator:
00127 // <srcblock>
00128 //   os << LogIO::DEBUGGING << "Boring message" << 
00129 //         LogIO::SEVERE << "Error!" << LogIO::POST;
00130 // </srcblock>
00131 // Note that changing the priority changes the priority of the entire
00132 // message. The message does not get posted until the POST is done.
00133 // So in the above example the DEBUGGING priority does not do anything
00134 // because the priority is overwritten by the SEVERE one.
00135 //
00136 // You can also change the origin information with the << operator:
00137 // <srcblock>
00138 //    os << LogOrigin("class", "func(args)");
00139 //    os << WHERE;
00140 // </srcblock>
00141 //
00142 // A class which has an operator<< to std::ostream but not LogIO can be handled
00143 // as follows:
00144 // <srcblock>
00145 //   os << LogIO::SEVERE << " at ";
00146 //   os.output() << MEpoch::Convert(time_p, MEpoch::Ref(MEpoch::UTC))();
00147 //   os << LogIO::POST;
00148 // </srcblock>
00149 // </example>
00150 //
00151 // <motivation>
00152 // The earlier method of creating log messages solely through LogSink and
00153 // LogMessage required the programmer to type in more lines of code than
00154 // this solution. Also, this interface makes it easy to drop log messages
00155 // into existing code that uses ostreams.
00156 // </motivation>
00157 //
00158 // <todo asof="1997/01/29">
00159 //   <li> Add << operators for all classes that have ostream<< defined.
00160 //        (We could probably do it with a template, but might result
00161 //        in ambiguity).
00162 //   <li> Have a function for changing the LogSink only? (You can get
00163 //        much the same effect with operator=).
00164 //        them?
00165 // </todo>
00166 
00167 class LogIO
00168 {
00169 public:
00170     // Special commands to the LogIO object
00171     enum Command {
00172         // Post the accumulated message. Equivalent to calling LogIO::post().
00173         POST, 
00174         // Post the accumulated message then throw an exception.
00175         // Always posts the message at SEVERE priority. Equivalent to calling 
00176         // LogIO::postThenThrow().
00177         EXCEPTION, 
00178         // Change the message priority to SEVERE.
00179         SEVERE, 
00180         // Change the message priority to WARN.
00181         WARN, 
00182         // Change the message priority to NORMAL.
00183         NORMAL, 
00184         NORMAL1, 
00185         NORMAL2, 
00186         NORMAL3, 
00187         NORMAL4, 
00188         NORMAL5, 
00189         // Change the message priority to DEBUGGING.
00190         DEBUG1,
00191         DEBUG2,
00192         DEBUGGING};
00193 
00194     // Attach this LogIO object to the global sink with no origin information.
00195     LogIO();
00196     // Attach this LogIO object to the supplied sink. A referencing copy of
00197     // the sink is made inside the LogIO object, so you do not need to worry
00198     // about memory management.
00199     LogIO(LogSink &sink);
00200     // Attach this LogIO object to the supplied origin and global sink.
00201     LogIO(const LogOrigin &OR);
00202     // Attach this LogIO object to the supplied origin and sink.
00203     LogIO(const LogOrigin &OR, LogSink &sink);
00204     
00205     // Copying uses reference semantics, i.e. the same sink will be shared
00206     // by both copies.
00207     // <group>
00208     LogIO(const LogIO &other);
00209     LogIO &operator=(const LogIO &other);
00210     // </group>
00211 
00212     // The destructor will post any accumulated message that has not already
00213     // been posted.
00214     ~LogIO();
00215     
00216     // Post the accumulated message.  If you wish, you can post the messages
00217     // only locally to the sink.
00218     // After the post the priority is reset to NORMAL.
00219     void post();
00220     void post(LogMessage &amess);
00221 
00222     // Post the accumulated message locally.
00223     // After the post the priority is reset to NORMAL.
00224     void postLocally();
00225 
00226     // Post the accumulated message at SEVERE priority and then throw an
00227     // exception.
00228     // After the post the priority is reset to NORMAL.
00229     template<typename EXC> void postThenThrow (const EXC& exc)
00230       { preparePostThenThrow(exc); sink_p.postThenThrow (msg_p, exc); }
00231 
00232     // Change the priority of the message. It does NOT post the accumulated
00233     // message at the old priority first.
00234     void priority(LogMessage::Priority which);
00235     LogMessage::Priority priority();
00236     // Change the location in the origin. Almost always this is called with the
00237     // macro WHERE as its argument.
00238     void sourceLocation(const SourceLocation *where);
00239     // Change the origin of the accumulated message.
00240     void origin(const LogOrigin &origin);
00241 
00242     // Acumulate output in this ostream.
00243     ostream& output();
00244 
00245     // Occasionally it is useful to interrogate the local log sink.
00246     LogSinkInterface &localSink();
00247     const LogSinkInterface &localSink() const;
00248 
00249 private:
00250     // Prepare message stream for postThenThrow function.
00251     void preparePostThenThrow (const AipsError& x);
00252 
00253     LogSink sink_p;
00254     LogMessage msg_p;
00255     ostringstream *text_p;
00256 
00257 };
00258 
00259 // <summary>
00260 // Functions to send commands to a LogIO object.
00261 // </summary>
00262 // The following commands don't change the accumulated message, rather they
00263 // send commands to the LogIO object, either to:
00264 // <ol>
00265 //   <li>post the current message: <src>os << "message" << LogIO::POST;</src>
00266 //   <li>post the current message and then throw an exception: 
00267 //       <src>os << "error" << LogIO::EXCEPTION;</src>
00268 //   <li> Change the priority of the current message:
00269 //        <src>os << LogIO::DEBUGGING;</src>
00270 //   <li> Change the origin of the message:
00271 //        <srcblock>
00272 //          os << LogOrigin(...);
00273 //          os << WHERE;             // Changes only source file/line number
00274 //        </srcblock>
00275 // </ol>
00276 // <group name=command>
00277 LogIO &operator<<(LogIO &os, LogIO::Command item);
00278 LogIO &operator<<(LogIO &os, const SourceLocation *item);
00279 LogIO &operator<<(LogIO &os, const LogOrigin &OR);
00280 // </group>
00281 
00282 // <summary>
00283 // Functions to accumulate text in the output message.
00284 // </summary>
00285 // Accumulate text in the output message. The last entry is for things like 
00286 // <src>endl</src>.
00287 // <group name=output>
00288 LogIO &operator<<(LogIO &os, const String &item);
00289 LogIO &operator<<(LogIO &os, const char *item);
00290 LogIO &operator<<(LogIO &os, Double item);
00291 LogIO &operator<<(LogIO &os, Complex item);
00292 LogIO &operator<<(LogIO &os, DComplex item);
00293 LogIO &operator<<(LogIO &os, Int item);
00294 LogIO &operator<<(LogIO &os, uInt item);
00295 LogIO &operator<<(LogIO &os, Int64 item);
00296 LogIO &operator<<(LogIO &os, uInt64 item);
00297 LogIO &operator<<(LogIO &os, uLong item);
00298 LogIO &operator<<(LogIO &os, Long item);
00299 LogIO &operator<<(LogIO &os, Bool item);
00300 LogIO &operator<<(LogIO &os, ostream &(*item)(ostream &));
00301 // </group>
00302 
00303 inline LogSinkInterface &LogIO::localSink()
00304 {
00305     return sink_p.localSink();
00306 }
00307 
00308 inline const LogSinkInterface &LogIO::localSink() const
00309 {
00310     return sink_p.localSink();
00311 }
00312 
00313 
00314 } //# NAMESPACE CASACORE - END
00315 
00316 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on 31 Aug 2016 for casa by  doxygen 1.6.1