/***************************************************************************
message.h - Print messages
-------------------
begin : Wed Sep 15 2004
copyright : (C) 2004 by Jan Rheinlaender
email : jrheinlaender@users.sourceforge.net
***************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
#ifndef MESSAGE_H
#define MESSAGE_H
#include <iostream>
#include <fstream>
#include <string>
enum message_mode { // *** added in 1.3.1
m_stdc, // Use std::c streams
m_func, // Use a user-defined function
m_ostream // Use a user-defined output stream
};
enum message_type {
t_msg_error, // Stream type for printing error messages
t_msg_warn, // warning messages
t_msg_info, // progress messages
t_msg_null // Rubbish bin
};
typedef void (*msgfuncp)(const std::string&, const std::string&);
#define OUTPUTF *outputfunctionp
#define CONSTRUCTOR \
message::message(msgfuncp f, const message_type t, const int l) { \
mode = m_func; \
type = t; \
level = l; \
strm = new std::ostringstream; \
outputfunctionp = f; \
} \
#define INITDECL static void init(msgfuncp f);
#define INIT \
void msg::init(msgfuncp f) { \
msg_error = message(f, t_msg_error, 1); \
msg_warn = message(f, t_msg_warn, 1); \
msg_info = message(f, t_msg_info, -1); \
devnullstream.open("/dev/null"); \
devnull = message(devnullstream, t_msg_info, 0); \
} \
/// Helper class to initialize class message
class message;
class message_init {
public:
message_init();
private:
/// A boolean used to ensure that init() is only called once in the lifetime of the class
static bool called;
static message_init message_initializer;
};
enum manip_type {
endline, // End of line
endstring // End of string
};
/** *** added in 0.7
Every stream has a priority level, where smaller numbers mean higher priority.
Messages are printed when their priority is smaller or equal to the priority level of the
stream. For example: Stream message::msg_err() has priority 1. This
means that a message with priority 1 will be printed, but a message with priority 2 not.
There are 8 priority levels (0 to 7). Larger priority levels are interpreted in such a way
that, for example, a stream with priority 9 prints messages of level 9 and 1 (9 modulo 1).
@author Jan Rheinlaender
@short Class for printing messages: Errors, warnings and info
**/
class message {
friend class message_init;
public:
/**
* Create a message stream of the given type that will output messages of priority level
* or less. This construction uses the std::cerr etc. output streams
* @param t The type of the messages that will be printed
* @param l The priority level up to which messages will be printed
*/
message(const message_type t, const int l);
/**
* Create a message stream using a user-defined output file stream
* @param t The type of the messages that will be printed
* @param l The priority level up to which messages will be printed
*/
message(std::ostream& of, const message_type t, const int l); // *** added in 1.3.1
/**
* Create a message stream using a user-defined output function
* @param t The type of the messages that will be printed
* @param l The priority level up to which messages will be printed
*/
message(msgfuncp f, const message_type t, const int l); // *** added in 1.3.1
/// Clean up
~message();
/// Set the priority level of the stream
void setlevel(const int l);
/// Return the underlying stream. Use only if absolutely necessary!
//inline std::ostream &stream() { return *strm; } // *** removed in 1.3.1
/**
Return the stream to print messages of priority p. Returns the /dev/null stream
if the priority is not high enough
@param p The priority of the messages
@returns This object
*/
// message& prio(const int p); *** removed in 1.3.1
/**
Check if messages of a certain priority will be printed on this stream. Returns true
if (p % 8) <= the priority level of the stream.
@param p The priority
@returns True or false
*/
inline const bool checkprio(const int p) const { // *** changed in 0.8, inlined in 1.0
if ((level >> 3) > 0) // i.e. level > 7 *** changed in 1.0
return ((p % 8) <= (level % 8));
else
return (p <= level);
}
/// Print a message on the stream
message &operator<<(const char *cp);
/// Print an unsigned int on the stream
message &operator<<(const unsigned int i);
/// Print a long unsigned int on the stream
message &operator<<(const long unsigned int i);
/// Print a signed int on the stream
message &operator<<(const int i);
/// Print a long int on the stream
message &operator<<(const long int i);
/// Print a double on the stream
message &operator<<(const double d);
/// Print a string on the stream
message &operator<<(const std::string &s);
/// manipulators
// TODO: Is there a better way to implement this?
// compare std::ostream & dflt(std::ostream & os); from GiNac
message &operator<<(manip_type m);
/// endline manipulator
message &endl(message &m) { (*strm) << std::endl; return m; } // *** added in 0.9
private:
/// The messaging mode
message_mode mode;
/// The type of the stream
message_type type;
/// The priority level of the stream
int level;
/// The underlying stream for printing the messages
std::ostream *strm;
/// The user-defined output function
msgfuncp outputfunctionp;
// Class methods
private:
/// Initialize
static void init();
};
// Global message printing streams *** removed in 1.3.1
//extern message msg_error;
//extern message msg_warn;
//extern message msg_info;
#endif