/*************************************************************************** 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 #include #include 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