Source: include/status.H


Annotated List
Files
Globals
Hierarchy
Index
/* -------------------------------------------------------------------------
   status.H - Status Messages for Handling Both Errors and Logs
   -------------------------------------------------------------------------
   Copyright (C) 2000-2001 Eric R. Schendel
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.
 
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
 
   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.               
   ------------------------------------------------------------------------- */

#ifndef LOGS_H
#define LOGS_H

#include <iostream>
#include <string>

/**
 * Namespace for status messages such as for logging and errors. This
 * namespace also keeps all the default definitions and helper functions
 * dealing with the status message classes.
 *
 * @short Namespace for Status Messages such as Logs and Errors
 * @see StatusMsgs#StatusMsg StatusMsgs#Log StatusMsgs#Error
 */
namespace StatusMsgs {

/**
 * Enumeration for keeping track of a log's priority level.
 * This enum has two functions:
 *
 * The first is selecting what types of logs are displayed. This is set by
 * a @ref Log::Log constructor or the @ref Log::setLogLevel method.
 *
 * <pre>
 * NONE: Will not display log messages.
 * LOW : Will display all log messages expect NONE (LOW, MED, & HIGH).
 * MED : Will display log messages with more detail (MED & HIGH).
 * HIGH: Will display only the essential log messages (HIGH).
 * </pre>
 *
 * The second is to assign a priority level to a log message. This is set by
 * the @ref Log::operator() method.
 *
 * <pre>
 * NONE: Log message will not be displayed (making it useless).
 * LOW : Log message is of little value.  It is more for tracing through
 *       the program internally (useful mostly for developers).
 * MED : Log message represents more detail compared to HIGH level log
 *       messages such as pointing out some potential problems.
 * HIGH: Log message is of great importance by pointing out major operations.
 * </pre>
 *
 * @see StatusMsgs#Log
 */
enum LogLevel {NONE = 0, LOW = 1, MED = 2, HIGH = 3};

/**
 * Enumeration for keeping track of an error's severity level.
 *
 * <pre>
 * SUCCESS : No errors were recorded which is the default state.
 * MINOR   : Error is of something that can possible happen but is not desired.
 *           No error message is displayed and program execution continues on.
 * MAJOR   : Error is of something that is not suppose to happen but should not
 *           cripple the program. So the error message is displayed and program
 *           execution continues on.
 * CRITICAL: Error is of something that should not happen at all and program
 *           execution will terminate immediately.
 * </pre>
 *
 * @see StatusMsgs#Error
 */
enum ErrLevel {SUCCESS = 0, MINOR = 1, MAJOR = 2, CRITICAL = 3};

/**
 * Default header size: [5]
 */
const short SM_HDRSZ = 5;

/**
 * Default message body size: [38]
 */
const short SM_BODYSZ = 38;

/**
 * Default divider between message body and header: ["  "]
 */
const char SM_DIVIDER[] = "  ";

/**
 * Default message header border: ["|"]
 */
const char SM_BORDER[] = "|";

/**
 * Default message header boarder for errors: ["="]
 */
const char SM_ERR_BORDER[] = "=";

/**
 * Default message body: ["<Default Message>"]
 */
const char SM_DBODY[] = "<Default Message>";

/**
 * Default header for status messages: ["MSG"]
 */
const char SM_MESSAGE[] = "MSG";

/**
 * Default header for log messages: ["LOG"]
 */
const char SM_LOG[] = "LOG";

/**
 * Default header for error messages: ["ERROR"]
 */
const char SM_ERROR[] = "ERROR";

/**
 * Default left bracket used for message arguments: ["["]
 */
const char SM_LBRACK[] = "[";

/**
 * Default right bracket used for message arguments: ["]"]
 */
const char SM_RBRACK[] = "]";

/**
 * String to represent a NULL string: [""]
 */
const char SM_NULL[] = "";


/**
 * This base class is responsible for storing, handling, and printing
 * status messages which consists of a header and message body. This
 * primarily helps in simplifying the task of displaying system messages to
 * the user and/or developer.
 *
 * To make the output formating of all status messages work together, global
 * variables were created to handle the message header and body sizes.
 * Therefore when one of these change, it effects all status messages which use
 * the StatusMsg base class.
 *
 * @short Base Class For Handling System Status Messages
 * @see StatusMsgs#Log StatusMsgs#Error
 */
class StatusMsg {

   public:

      /**
       * Sets default message of @ref SM_DBODY[]
       */
      StatusMsg();

      /**
       * Copy constructor
       */
      StatusMsg(const StatusMsg& msg);

      /**
       * Sets default message of @ref SM_DBODY[] along with specified string
       * header and with border style, header size, and body size if needed.
       *
       * @param header Header of status message
       * @param border Default header border: @ref SM_BORDER[]
       * @param hsize  Default header size for all objects: @ref SM_HDRSZ
       * @param bsize  Default body size for all objects: @ref SM_BODYSZ
       */
      StatusMsg(const string& header, const string border = SM_BORDER,
                const short hsize = head_size, const short bsize = body_size);

      /**
       * Set header of message along with boarder style if needed
       *
       * @param hd  Header
       * @param bdr Header border
       */
      void setHeader(const string hd,
                     const string bdr = SM_BORDER) { hdr = hd; div = bdr; }

      /**
       * Set boarder style
       *
       * @param bdr Header border
       */
      void setBoader(const string bdr) { div = bdr; }

      /**
       * Set body of message along with one string argument if needed
       *
       * @param bdy Status message
       * @param ag  Argument associated with message. Only able to handle
       *            one but might handle more in the future if needed. By
       *            default the argument is none.
       */
      void setBody(const string bdy,
                   const string ag = SM_NULL) { body = bdy; arg = ag; }

      /**
       * Same as above but handles an unsigned character for the argument
       */
      void setBody(const string bdy, const unsigned char& ag);

      /**
       * Same as above but handles an unsigned integer for the argument
       */
      void setBody(const string bdy, const unsigned long ag);

      /**
       * Set header size for all StatusMsg objects. This method can be called
       * either by an object or directly within the class by
       * "StatusMsg::setHeaderSize(size)". If the actual string size of the
       * header is less then this size, then spaces are appended to the
       * header when displayed. And if the string size is greater than this
       * size then the header is truncated when displayed.
       *
       * @param hsz Header Size. If 0, then a header is not displayed.
       */
      static void setHeaderSize(const short hsz);

      /**
       * Set message body size for all StatusMsg object. This method can be
       * called either by an object or directly within the class by
       * "StatusMsg::setBodySize(size)". If the actual string size is less than
       * this size and an arguement exists, then spaces are added in between
       * when displayed. And if the string size is greater than this size
       * then the message is truncated when displayed.
       *
       * @param msg Message Body Size
       */
      static void setBodySize(const short msz) { body_size = msz; }

      /**
       * @return body of message
       */
      string getBody() const { return body; }

      /**
       * @return argument of message
       */
      string getArgument() const { return arg; }

      /**
       * Display status message with the appropriate formatting of the
       * header and message body along with its argument if it exists. A
       * default message would look something like:
       *
       * <pre>
       * |header|  Default Message               [Argument]
       * </pre>
       *
       * @param out ostream to output onto (default: cout)
       */
      void printMsg(ostream& out = cout) const;

   private:
      static short head_size;
      static short body_size;

      string hdr;
      string body;
      string arg;
      string div;

};


/**
 * This class is a superset of @ref StatusMsg responsible for handling log
 * messages. This class is very helpful in that it allows easy tracking of
 * program execution where log messages can be assigned different levels of
 * importance.
 *
 * see @ref LogLevel
 *
 * @short Class For Handling Log Messages
 */
class Log: public StatusMsg {

   public:

      /**
       * Set log to default message and to display all log priority levels.
       *
       * @see StatusMsgs StatusMsgs#StatusMsg::StatusMsg
       */
      Log(): StatusMsg() { out = &clog; setHeader(SM_LOG); lvl = LOW; }

      /**
       * Set log to default header mainly telling function or location of
       * logging within the program.
       *
       * @param hdr    Header
       * @param level  Default log level display setting: All except NONE
       * @param ostr   Default ostream to output onto: clog
       *
       * @see StatusMsgs StatusMsgs#StatusMsg::StatusMsg StatusMsgs#LogLevel
       */
      Log(const string hdr, const LogLevel level = LOW, ostream& ostr = clog);

      /**
       * Parameter passing operator to return the log level for assignments
       * requiring an enum LogLevel value. This is helpful in passing a
       * LogLevel parameter as the object name, such as Log instead of
       * Log.getLogLevel().
       *
       * see @ref LogLevel
       *
       * @return Current log level
       */
      operator LogLevel() const { return getLogLevel(); }

      /**
       * This method allows for "log(LogLevel,message)" operations which
       * first performs a check to make sure that the log's message priority
       * level is acceptable related to the level specified by a @ref Log
       * constructor. If it is, then the body message is set and printed.
       *
       * @param level Priority level of log message
       * @param msg   Main message of log
       * @param arg   Message argument of log (default: no argument)
       * @param ostr  ostream to output onto. If none specified, then the
       *              ostream set by the @ref Log constructor or @ref setOutput
       *              method is used. Note that clog ostream will not work as
       *              an option to this method.
       */
      void operator()(const LogLevel& level, const string msg,
                      const string arg = SM_NULL, ostream& ostr = clog);

      /**
       * Same as above but handles an unsigned character for the argument
       */
      void operator()(const LogLevel& level, const string msg,
                      const unsigned char& arg, ostream& ostr = clog);

      /**
       * Same as above but handles a character for the argument
       */
      void operator()(const LogLevel& level, const string msg,
                      const char& arg, ostream& ostr = clog);

      /**
       * Same as above but handles an unsigned integer for the argument
       */
      void operator()(const LogLevel& level, const string msg,
                      const unsigned int arg, ostream& ostr = clog);

      /**
       * Same as above but handles an integer for the argument
       */
      void operator()(const LogLevel& level, const string msg,
                      const int arg, ostream& ostr = clog);

      /**
       * Same as above but handles an unsigned long for the argument
       */
      void operator()(const LogLevel& level, const string msg,
                      const unsigned long arg, ostream& ostr = clog);

      /**
       * Same as above but handles a long for the argument
       */
      void operator()(const LogLevel& level, const string msg,
                      const long arg, ostream& ostr = clog);

      /**
       * This overload operator is basically the same as the one above except
       * this one is geared more towards lazy people who do not need to specify
       * priority levels of log messages. The default LogLevel is HIGH, so when
       * used in conjunction with the Log constructor with zero arguments, this
       * method will print all logs.
       *
       * @param msg   Main message of log
       * @param arg   Message argument of log (default: no argument)
       * @param ostr  ostream to output onto. If none specified, then the
       *              ostream set by the @ref Log constructor or @ref setOutput
       *              method is used. Note that clog ostream will not work as
       *              an option to this method.
       */
      void operator()(const string msg, const long arg,
                      ostream& ostr = clog) { (*this)(HIGH, msg, arg, ostr); }

      /**
       * Same as above but handles an unsigned long for the argument
       */
      void operator()(const string msg, const unsigned long arg,
                      ostream& ostr = clog) { (*this)(HIGH, msg, arg, ostr); }

      /**
       * Same as above but handles an integer for the argument
       */
      void operator()(const string msg, const int arg,
                      ostream& ostr = clog) { (*this)(HIGH, msg, arg, ostr); }

      /**
       * Same as above but handles an unsigned integer for the argument
       */
      void operator()(const string msg, const unsigned int arg,
                      ostream& ostr = clog) { (*this)(HIGH, msg, arg, ostr); }

      /**
       * Same as above but handles a character for the argument
       */
      void operator()(const string msg, const char& arg,
                      ostream& ostr = clog) { (*this)(HIGH, msg, arg, ostr); }

      /**
       * Same as above but handles an unsigned character for the argument
       */
      void operator()(const string msg, const unsigned char& arg,
                      ostream& ostr = clog) { (*this)(HIGH, msg, arg, ostr); }

      /**
       * Same as above but handles a character string for the argument
       */
      void operator()(const string msg, const string arg = SM_NULL,
                      ostream& ostr = clog) { (*this)(HIGH, msg, arg, ostr); }

      /**
       * This method changes the default log level display setting which is
       * originally set by a @ref Log constructor.
       *
       * see @ref LogLevel
       *
       * @param level Log level display setting
       */
      void setLogLevel(const LogLevel level) { lvl = level; }

      /**
       * This method changes the current output ostream.
       *
       * @param newout New ostream for log's default output
       */
      void setOutput(ostream& newout) { out = &newout; }

      /**
       * This method returns the log level display setting which is set by
       * either the @ref Log constructor or @ref setLogLevel method.
       *
       * see @ref LogLevel
       *
       * @return Current log level
       */
      LogLevel getLogLevel() const { return lvl; }

   private:
      ostream* out;
      LogLevel lvl;

};


/**
 * The Error class is a superset of @ref StatusMsg responsible for handling
 * error messages which can have different levels of severity. This class gives
 * an easy object oriented way of handling errors within a program and is found
 * to be much easier to deal with compared to exceptions.
 *
 * Chances are all error messages within a program will want to be directed to
 * one particular output and have the same header, therefore the Error ostream
 * and error message header has been defined as global. This allows for the
 * ability to easily redefine the location of error outputs for all Error
 * objects with just one method call to @ref setOutput .
 *
 * see @ref StatusMsgs::ErrLevel
 *
 * @short Class For Handling Error Messages
 */
class Error: public StatusMsg {

   public:

      /**
       * Set Error to default header. The header size is automatically assigned
       * with the length of the hdr string, and by default creation this object
       * is assigned the ErrLevel of SUCCESS which has an error number of 0.
       *
       * @param hdr    Default header
       * @param border Default header border
       *
       * @see StatusMsgs StatusMsgs#StatusMsg::StatusMsg
       */
      Error(const string hdr = eheader, const string border = eboarder);

      /** Copy constructor */
      Error(const Error& err);

      /**
       * Copy assignment which has the special purpose of making sure that if
       * an error exists in the original or new object, then the error with
       * the greatest severity is maintained.
       */
      Error& operator=(const Error& err);

      /**
       * Conversion operator to return error status for assignments requiring
       * a boolean value. A way to understand this operator is for example
       * "if(!err)" is "if no error then" and "if(err)" is "if error then".
       *
       * @return true if error and false otherwise
       */
      operator bool() const { return (lvl != SUCCESS); }

      /**
       * Conversion operator to return the error number for assignments
       * requiring an integer value. This is very useful in returning the error
       * status of a program at termination.
       *
       * @return Error status number (Success = 0 or Error > 0)
       */
      operator int() const { return num; }

      /**
       * Conversion operator to return the error level for assignments
       * requiring an enum ErrLevel value. This is neccessary for doing compare
       * expression with ErrLevel values, such as "if(err == MINOR) {...}".
       *
       * see @ref ErrLevel
       *
       * @return Error level
       */
      operator ErrLevel() const { return lvl; }

      /**
       * This method allows for "err(ErrLevel,message)" operations to specify
       * the error message along with an error level, or if a message 
       * argument is not available, it instead only updates the current error
       * level along with actions. This method takes different actions
       * depending on the ErrLevel passed to it:
       *
       * <pre>
       * SUCCESS : Sets object to original successful state.
       * MINOR   : If msg argument exists, it sets the status message body.
       *           Then it sets or updates the error number to MINOR.
       * MAJOR   : If msg argument exists, it sets the status message body.
       *           Then it sets or updates the error number to MAJOR. Also
       *           it ends up printing the message body.
       * CRITICAL: If msg argument exists, it sets the status message body.
       *           Then it prints the status message body along with the
       *           system error message as the argument. It then causes
       *           the program to exit immediately with the system error
       *           number.
       * </pre>
       *
       * @param level Set or update priority level of error message
       * @param msg   Main message of error (default: previous message)
       * @param arg   Message argument of error (default: no argument)
       * @param out   ostream to output onto (default: global variable eout)
       */
      void operator()(const ErrLevel& level, string msg = SM_DBODY,
                      string arg = SM_NULL, ostream& out = *eout);

      /**
       * Same as above but handles an unsigned character for the argument
       */
      void operator()(const ErrLevel& level, const string msg,
                      const unsigned char& arg, ostream& out = *eout);

      /**
       * Same as above but handles a character for the argument
       */
      void operator()(const ErrLevel& level, const string msg,
                      const char& arg, ostream& out = *eout);

      /**
       * Same as above but handles an unsigned integer for the argument
       */
      void operator()(const ErrLevel& level, const string msg,
                      const unsigned int arg, ostream& out = *eout);

      /**
       * Same as above but handles an integer for the argument
       */
      void operator()(const ErrLevel& level, const string msg,
                      const int arg, ostream& out = *eout);

      /**
       * Same as above but handles an unsigned long for the argument
       */
      void operator()(const ErrLevel& level, const string msg,
                      const unsigned long arg, ostream& out = *eout);

      /**
       * Same as above but handles a long for the argument
       */
      void operator()(const ErrLevel& level, const string msg,
                      const long arg, ostream& out = *eout);

      /**
       * This overload operator is basically the same as the one above, except
       * this one is geared more towards lazy people who do not need to specify
       * priority levels of error messages. The error level will default to
       * MAJOR which is usually the most used error type.
       *
       * @param msg   Main message of error
       * @param arg   Message argument of error (default: no argument)
       * @param out   ostream to output onto (default: global variable eout)
       */
      void operator()(const string msg, const long arg,
                      ostream& out = *eout) { (*this)(MAJOR, msg, arg, out); }

      /**
       * Same as above but handles an unsigned long for the argument
       */
      void operator()(const string msg, const unsigned long arg,
                      ostream& out = *eout) { (*this)(MAJOR, msg, arg, out); }

      /**
       * Same as above but handles an integer for the argument
       */
      void operator()(const string msg, const int arg,
                      ostream& out = *eout) { (*this)(MAJOR, msg, arg, out); }

      /**
       * Same as above but handles an unsigned integer for the argument
       */
      void operator()(const string msg, const unsigned int arg,
                      ostream& out = *eout) { (*this)(MAJOR, msg, arg, out); }

      /**
       * Same as above but handles a character for the argument
       */
      void operator()(const string msg, const char& arg,
                      ostream& out = *eout) { (*this)(MAJOR, msg, arg, out); }

      /**
       * Same as above but handles an unsigned character for the argument
       */
      void operator()(const string msg, const unsigned char& arg,
                      ostream& out = *eout) { (*this)(MAJOR, msg, arg, out); }

      /**
       * Same as above but handles character string for the argument.
       */
      void operator()(const string msg, const string arg = SM_NULL,
                      ostream& out = *eout) { (*this)(MAJOR, msg, arg, out); }

      /**
       * This method can be called either by an object or directly within the
       * class by "Error::setOuput(ostream)". This powerful method changes the
       * output ostream for all Error objects.
       *
       * @param newout New ostream for all error message outputs
       */
      static void setOutput(ostream& newout) { eout = &newout; }

      /**
       * This method can be called either by an object or directly within the
       * class by "Error::setHeader(header)". This powerful method changes the
       * header and/or boarder for all Error objects.
       *
       * @param newheader  New header
       * @param newboarder New header boarder
       */
      static void setHeader(const string newheader,
                            const string newboarder = eboarder);

   private:
      static ostream* eout;
      static string eheader;
      static string eboarder;

      ErrLevel lvl;
      int num;

};

/**
 * Helper function to allow compares between error levels.
 *
 * see @ref ErrLevel
 */
bool operator==(ErrLevel, ErrLevel);

} // namespace StatusMsgs //

#endif

Generated on Fri Mar 9 02:04:42 2001, using kdoc 2.0a43.