summaryrefslogtreecommitdiff
path: root/thirdparty/linux/include/coin/coin/CoinMessageHandler.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty/linux/include/coin/coin/CoinMessageHandler.hpp')
-rw-r--r--thirdparty/linux/include/coin/coin/CoinMessageHandler.hpp666
1 files changed, 666 insertions, 0 deletions
diff --git a/thirdparty/linux/include/coin/coin/CoinMessageHandler.hpp b/thirdparty/linux/include/coin/coin/CoinMessageHandler.hpp
new file mode 100644
index 0000000..7922630
--- /dev/null
+++ b/thirdparty/linux/include/coin/coin/CoinMessageHandler.hpp
@@ -0,0 +1,666 @@
+/* $Id: CoinMessageHandler.hpp 1514 2011-12-10 23:35:23Z lou $ */
+// Copyright (C) 2002, International Business Machines
+// Corporation and others. All Rights Reserved.
+// This code is licensed under the terms of the Eclipse Public License (EPL).
+
+#ifndef CoinMessageHandler_H
+#define CoinMessageHandler_H
+
+#include "CoinUtilsConfig.h"
+#include "CoinPragma.hpp"
+
+#include <iostream>
+#include <cstdio>
+#include <string>
+#include <vector>
+
+/** \file CoinMessageHandler.hpp
+ \brief This is a first attempt at a message handler.
+
+ The COIN Project is in favo(u)r of multi-language support. This implementation
+ of a message handler tries to make it as lightweight as possible in the sense
+ that only a subset of messages need to be defined --- the rest default to US
+ English.
+
+ The default handler at present just prints to stdout or to a FILE pointer
+
+ \todo
+ This needs to be worked over for correct operation with ISO character codes.
+*/
+
+/*
+ I (jjf) am strongly in favo(u)r of language support for an open
+ source project, but I have tried to make it as lightweight as
+ possible in the sense that only a subset of messages need to be
+ defined - the rest default to US English. There will be different
+ sets of messages for each component - so at present there is a
+ Clp component and a Coin component.
+
+ Because messages are only used in a controlled environment and have no
+ impact on code and are tested by other tests I have included tests such
+ as language and derivation in other unit tests.
+*/
+/*
+ Where there are derived classes I (jjf) have started message numbers at 1001.
+*/
+
+
+/** \brief Class for one massaged message.
+
+ A message consists of a text string with formatting codes (#message_),
+ an integer identifier (#externalNumber_) which also determines the severity
+ level (#severity_) of the message, and a detail (logging) level (#detail_).
+
+ CoinOneMessage is just a container to hold this information. The
+ interpretation is set by CoinMessageHandler, which see.
+ */
+
+class CoinOneMessage {
+
+public:
+ /**@name Constructors etc */
+ //@{
+ /** Default constructor. */
+ CoinOneMessage();
+ /** Normal constructor */
+ CoinOneMessage(int externalNumber, char detail,
+ const char * message);
+ /** Destructor */
+ ~CoinOneMessage();
+ /** The copy constructor */
+ CoinOneMessage(const CoinOneMessage&);
+ /** assignment operator. */
+ CoinOneMessage& operator=(const CoinOneMessage&);
+ //@}
+
+ /**@name Useful stuff */
+ //@{
+ /// Replace message text (<i>e.g.</i>, text in a different language)
+ void replaceMessage(const char * message);
+ //@}
+
+ /**@name Get and set methods */
+ //@{
+ /** Get message ID number */
+ inline int externalNumber() const
+ {return externalNumber_;}
+ /** \brief Set message ID number
+
+ In the default CoinMessageHandler, this number is printed in the message
+ prefix and is used to determine the message severity level.
+ */
+ inline void setExternalNumber(int number)
+ {externalNumber_=number;}
+ /// Severity
+ inline char severity() const
+ {return severity_;}
+ /// Set detail level
+ inline void setDetail(int level)
+ {detail_=static_cast<char> (level);}
+ /// Get detail level
+ inline int detail() const
+ {return detail_;}
+ /// Return the message text
+ inline char * message() const
+ {return message_;}
+ //@}
+
+ /**@name member data */
+ //@{
+ /// number to print out (also determines severity)
+ int externalNumber_;
+ /// Will only print if detail matches
+ char detail_;
+ /// Severity
+ char severity_;
+ /// Messages (in correct language) (not all 400 may exist)
+ mutable char message_[400];
+ //@}
+};
+
+/** \brief Class to hold and manipulate an array of massaged messages.
+
+ Note that the message index used to reference a message in the array of
+ messages is completely distinct from the external ID number stored with the
+ message.
+*/
+
+class CoinMessages {
+
+public:
+ /** \brief Supported languages
+
+ These are the languages that are supported. At present only
+ us_en is serious and the rest are for testing.
+ */
+ enum Language {
+ us_en = 0,
+ uk_en,
+ it
+ };
+
+ /**@name Constructors etc */
+ //@{
+ /** Constructor with number of messages. */
+ CoinMessages(int numberMessages=0);
+ /** Destructor */
+ ~CoinMessages();
+ /** The copy constructor */
+ CoinMessages(const CoinMessages&);
+ /** assignment operator. */
+ CoinMessages& operator=(const CoinMessages&);
+ //@}
+
+ /**@name Useful stuff */
+ //@{
+ /*! \brief Installs a new message in the specified index position
+
+ Any existing message is replaced, and a copy of the specified message is
+ installed.
+ */
+ void addMessage(int messageNumber, const CoinOneMessage & message);
+ /*! \brief Replaces the text of the specified message
+
+ Any existing text is deleted and the specified text is copied into the
+ specified message.
+ */
+ void replaceMessage(int messageNumber, const char * message);
+ /** Language. Need to think about iso codes */
+ inline Language language() const
+ {return language_;}
+ /** Set language */
+ void setLanguage(Language newlanguage)
+ {language_ = newlanguage;}
+ /// Change detail level for one message
+ void setDetailMessage(int newLevel, int messageNumber);
+ /** \brief Change detail level for several messages
+
+ messageNumbers is expected to contain the indices of the messages to be
+ changed.
+ If numberMessages >= 10000 or messageNumbers is NULL, the detail level
+ is changed on all messages.
+ */
+ void setDetailMessages(int newLevel, int numberMessages,
+ int * messageNumbers);
+ /** Change detail level for all messages with low <= ID number < high */
+ void setDetailMessages(int newLevel, int low, int high);
+
+ /// Returns class
+ inline int getClass() const
+ { return class_;}
+ /// Moves to compact format
+ void toCompact();
+ /// Moves from compact format
+ void fromCompact();
+ //@}
+
+ /**@name member data */
+ //@{
+ /// Number of messages
+ int numberMessages_;
+ /// Language
+ Language language_;
+ /// Source (null-terminated string, maximum 4 characters).
+ char source_[5];
+ /// Class - see later on before CoinMessageHandler
+ int class_;
+ /** Length of fake CoinOneMessage array.
+ First you get numberMessages_ pointers which point to stuff
+ */
+ int lengthMessages_;
+ /// Messages
+ CoinOneMessage ** message_;
+ //@}
+};
+
+// for convenience eol
+enum CoinMessageMarker {
+ CoinMessageEol = 0,
+ CoinMessageNewline = 1
+};
+
+/** Base class for message handling
+
+ The default behavior is described here: messages are printed, and (if the
+ severity is sufficiently high) execution will be aborted. Inherit and
+ redefine the methods #print and #checkSeverity to augment the behaviour.
+
+ Messages can be printed with or without a prefix; the prefix will consist
+ of a source string, the external ID number, and a letter code,
+ <i>e.g.</i>, Clp6024W.
+ A prefix makes the messages look less nimble but is very useful
+ for "grep" <i>etc</i>.
+
+ <h3> Usage </h3>
+
+ The general approach to using the COIN messaging facility is as follows:
+ <ul>
+ <li> Define your messages. For each message, you must supply an external
+ ID number, a log (detail) level, and a format string. Typically, you
+ define a convenience structure for this, something that's easy to
+ use to create an array of initialised message definitions at compile
+ time.
+ <li> Create a CoinMessages object, sized to accommodate the number of
+ messages you've defined. (Incremental growth will happen if
+ necessary as messages are loaded, but it's inefficient.)
+ <li> Load the messages into the CoinMessages object. Typically this
+ entails creating a CoinOneMessage object for each message and
+ passing it as a parameter to CoinMessages::addMessage(). You specify
+ the message's internal ID as the other parameter to addMessage.
+ <li> Create and use a CoinMessageHandler object to print messages.
+ </ul>
+ See, for example, CoinMessage.hpp and CoinMessage.cpp for an example of
+ the first three steps. `Format codes' below has a simple example of
+ printing a message.
+
+ <h3> External ID numbers and severity </h3>
+
+ CoinMessageHandler assumes the following relationship between the
+ external ID number of a message and the severity of the message:
+ \li <3000 are informational ('I')
+ \li <6000 warnings ('W')
+ \li <9000 non-fatal errors ('E')
+ \li >=9000 aborts the program (after printing the message) ('S')
+
+ <h3> Log (detail) levels </h3>
+
+ The default behaviour is that a message will print if its detail level
+ is less than or equal to the handler's log level. If all you want to
+ do is set a single log level for the handler, use #setLogLevel(int).
+
+ If you want to get fancy, here's how it really works: There's an array,
+ #logLevels_, which you can manipulate with #setLogLevel(int,int). Each
+ entry logLevels_[i] specifies the log level for messages of class i (see
+ CoinMessages::class_). If logLevels_[0] is set to the magic number -1000
+ you get the simple behaviour described above, whatever the class of the
+ messages. If logLevels_[0] is set to a valid log level (>= 0), then
+ logLevels_[i] really is the log level for messages of class i.
+
+ <h3> Format codes </h3>
+
+ CoinMessageHandler can print integers (normal, long, and long long),
+ doubles, characters, and strings. See the descriptions of the
+ various << operators.
+
+ When processing a standard message with a format string, the formatting
+ codes specified in the format string will be passed to the sprintf
+ function, along with the argument. When generating a message with no
+ format string, each << operator uses a simple format code appropriate for
+ its argument. Consult the documentation for the standard printf facility
+ for further information on format codes.
+
+ The special format code `%?' provides a hook to enable or disable
+ printing. For each `%?' code, there must be a corresponding call to
+ printing(bool). This provides a way to define optional parts in
+ messages, delineated by the code `%?' in the format string. Printing can
+ be suppressed for these optional parts, but any operands must still be
+ supplied. For example, given the message string
+ \verbatim
+ "A message with%? an optional integer %d and%? a double %g."
+ \endverbatim
+ installed in CoinMessages \c exampleMsgs with index 5, and
+ \c CoinMessageHandler \c hdl, the code
+ \code
+ hdl.message(5,exampleMsgs) ;
+ hdl.printing(true) << 42 ;
+ hdl.printing(true) << 53.5 << CoinMessageEol ;
+ \endcode
+ will print
+ \verbatim
+ A message with an optional integer 42 and a double 53.5.
+ \endverbatim
+ while
+ \code
+ hdl.message(5,exampleMsgs) ;
+ hdl.printing(false) << 42 ;
+ hdl.printing(true) << 53.5 << CoinMessageEol ;
+ \endcode
+ will print
+ \verbatim
+ A message with a double 53.5.
+ \endverbatim
+
+ For additional examples of usage, see CoinMessageHandlerUnitTest in
+ CoinMessageHandlerTest.cpp.
+*/
+
+class CoinMessageHandler {
+
+friend bool CoinMessageHandlerUnitTest () ;
+
+public:
+ /**@name Virtual methods that the derived classes may provide */
+ //@{
+ /** Print message, return 0 normally.
+ */
+ virtual int print() ;
+ /** Check message severity - if too bad then abort
+ */
+ virtual void checkSeverity() ;
+ //@}
+
+ /**@name Constructors etc */
+ //@{
+ /// Constructor
+ CoinMessageHandler();
+ /// Constructor to put to file pointer (won't be closed)
+ CoinMessageHandler(FILE *fp);
+ /** Destructor */
+ virtual ~CoinMessageHandler();
+ /** The copy constructor */
+ CoinMessageHandler(const CoinMessageHandler&);
+ /** Assignment operator. */
+ CoinMessageHandler& operator=(const CoinMessageHandler&);
+ /// Clone
+ virtual CoinMessageHandler * clone() const;
+ //@}
+ /**@name Get and set methods */
+ //@{
+ /// Get detail level of a message.
+ inline int detail(int messageNumber, const CoinMessages &normalMessage) const
+ { return normalMessage.message_[messageNumber]->detail();}
+ /** Get current log (detail) level. */
+ inline int logLevel() const
+ { return logLevel_;}
+ /** \brief Set current log (detail) level.
+
+ If the log level is equal or greater than the detail level of a message,
+ the message will be printed. A rough convention for the amount of output
+ expected is
+ - 0 - none
+ - 1 - minimal
+ - 2 - normal low
+ - 3 - normal high
+ - 4 - verbose
+
+ Please assign log levels to messages accordingly. Log levels of 8 and
+ above (8,16,32, <i>etc</i>.) are intended for selective debugging.
+ The logical AND of the log level specified in the message and the current
+ log level is used to determine if the message is printed. (In other words,
+ you're using individual bits to determine which messages are printed.)
+ */
+ void setLogLevel(int value);
+ /** Get alternative log level. */
+ inline int logLevel(int which) const
+ { return logLevels_[which];}
+ /*! \brief Set alternative log level value.
+
+ Can be used to store alternative log level information within the handler.
+ */
+ void setLogLevel(int which, int value);
+
+ /// Set the number of significant digits for printing floating point numbers
+ void setPrecision(unsigned int new_precision);
+ /// Current number of significant digits for printing floating point numbers
+ inline int precision() { return (g_precision_) ; }
+
+ /// Switch message prefix on or off.
+ void setPrefix(bool yesNo);
+ /// Current setting for printing message prefix.
+ bool prefix() const;
+ /*! \brief Values of double fields already processed.
+
+ As the parameter for a double field is processed, the value is saved
+ and can be retrieved using this function.
+ */
+ inline double doubleValue(int position) const
+ { return doubleValue_[position];}
+ /*! \brief Number of double fields already processed.
+
+ Incremented each time a field of type double is processed.
+ */
+ inline int numberDoubleFields() const
+ {return static_cast<int>(doubleValue_.size());}
+ /*! \brief Values of integer fields already processed.
+
+ As the parameter for a integer field is processed, the value is saved
+ and can be retrieved using this function.
+ */
+ inline int intValue(int position) const
+ { return longValue_[position];}
+ /*! \brief Number of integer fields already processed.
+
+ Incremented each time a field of type integer is processed.
+ */
+ inline int numberIntFields() const
+ {return static_cast<int>(longValue_.size());}
+ /*! \brief Values of char fields already processed.
+
+ As the parameter for a char field is processed, the value is saved
+ and can be retrieved using this function.
+ */
+ inline char charValue(int position) const
+ { return charValue_[position];}
+ /*! \brief Number of char fields already processed.
+
+ Incremented each time a field of type char is processed.
+ */
+ inline int numberCharFields() const
+ {return static_cast<int>(charValue_.size());}
+ /*! \brief Values of string fields already processed.
+
+ As the parameter for a string field is processed, the value is saved
+ and can be retrieved using this function.
+ */
+ inline std::string stringValue(int position) const
+ { return stringValue_[position];}
+ /*! \brief Number of string fields already processed.
+
+ Incremented each time a field of type string is processed.
+ */
+ inline int numberStringFields() const
+ {return static_cast<int>(stringValue_.size());}
+
+ /// Current message
+ inline CoinOneMessage currentMessage() const
+ {return currentMessage_;}
+ /// Source of current message
+ inline std::string currentSource() const
+ {return source_;}
+ /// Output buffer
+ inline const char * messageBuffer() const
+ {return messageBuffer_;}
+ /// Highest message number (indicates any errors)
+ inline int highestNumber() const
+ {return highestNumber_;}
+ /// Get current file pointer
+ inline FILE * filePointer() const
+ { return fp_;}
+ /// Set new file pointer
+ inline void setFilePointer(FILE * fp)
+ { fp_ = fp;}
+ //@}
+
+ /**@name Actions to create a message */
+ //@{
+ /*! \brief Start a message
+
+ Look up the specified message. A prefix will be generated if enabled.
+ The message will be printed if the current log level is equal or greater
+ than the log level of the message.
+ */
+ CoinMessageHandler &message(int messageNumber,
+ const CoinMessages &messages) ;
+
+ /*! \brief Start or continue a message
+
+ With detail = -1 (default), does nothing except return a reference to the
+ handler. (I.e., msghandler.message() << "foo" is precisely equivalent
+ to msghandler << "foo".) If \p msgDetail is >= 0, is will be used
+ as the detail level to determine whether the message should print
+ (assuming class 0).
+
+ This can be used with any of the << operators. One use is to start
+ a message which will be constructed entirely from scratch. Another
+ use is continuation of a message after code that interrupts the usual
+ sequence of << operators.
+ */
+ CoinMessageHandler & message(int detail = -1) ;
+
+ /*! \brief Print a complete message
+
+ Generate a standard prefix and append \c msg `as is'. This is intended as
+ a transition mechanism. The standard prefix is generated (if enabled),
+ and \c msg is appended. The message must be ended with a CoinMessageEol
+ marker. Attempts to add content with << will have no effect.
+
+ The default value of \p detail will not change printing status. If
+ \p detail is >= 0, it will be used as the detail level to determine
+ whether the message should print (assuming class 0).
+
+ */
+ CoinMessageHandler &message(int externalNumber, const char *source,
+ const char *msg,
+ char severity, int detail = -1) ;
+
+ /*! \brief Process an integer parameter value.
+
+ The default format code is `%d'.
+ */
+ CoinMessageHandler & operator<< (int intvalue);
+#if COIN_BIG_INDEX==1
+ /*! \brief Process a long integer parameter value.
+
+ The default format code is `%ld'.
+ */
+ CoinMessageHandler & operator<< (long longvalue);
+#endif
+#if COIN_BIG_INDEX==2
+ /*! \brief Process a long long integer parameter value.
+
+ The default format code is `%ld'.
+ */
+ CoinMessageHandler & operator<< (long long longvalue);
+#endif
+ /*! \brief Process a double parameter value.
+
+ The default format code is `%d'.
+ */
+ CoinMessageHandler & operator<< (double doublevalue);
+ /*! \brief Process a STL string parameter value.
+
+ The default format code is `%g'.
+ */
+ CoinMessageHandler & operator<< (const std::string& stringvalue);
+ /*! \brief Process a char parameter value.
+
+ The default format code is `%s'.
+ */
+ CoinMessageHandler & operator<< (char charvalue);
+ /*! \brief Process a C-style string parameter value.
+
+ The default format code is `%c'.
+ */
+ CoinMessageHandler & operator<< (const char *stringvalue);
+ /*! \brief Process a marker.
+
+ The default format code is `%s'.
+ */
+ CoinMessageHandler & operator<< (CoinMessageMarker);
+ /** Finish (and print) the message.
+
+ Equivalent to using the CoinMessageEol marker.
+ */
+ int finish();
+ /*! \brief Enable or disable printing of an optional portion of a message.
+
+ Optional portions of a message are delimited by `%?' markers, and
+ printing processes one %? marker. If \c onOff is true, the subsequent
+ portion of the message (to the next %? marker or the end of the format
+ string) will be printed. If \c onOff is false, printing is suppressed.
+ Parameters must still be supplied, whether printing is suppressed or not.
+ See the class documentation for an example.
+ */
+ CoinMessageHandler & printing(bool onOff);
+
+ //@}
+
+ /** Log levels will be by type and will then use type
+ given in CoinMessage::class_
+
+ - 0 - Branch and bound code or similar
+ - 1 - Solver
+ - 2 - Stuff in Coin directory
+ - 3 - Cut generators
+ */
+#define COIN_NUM_LOG 4
+/// Maximum length of constructed message (characters)
+#define COIN_MESSAGE_HANDLER_MAX_BUFFER_SIZE 1000
+protected:
+ /**@name Protected member data */
+ //@{
+ /// values in message
+ std::vector<double> doubleValue_;
+ std::vector<int> longValue_;
+ std::vector<char> charValue_;
+ std::vector<std::string> stringValue_;
+ /// Log level
+ int logLevel_;
+ /// Log levels
+ int logLevels_[COIN_NUM_LOG];
+ /// Whether we want prefix (may get more subtle so is int)
+ int prefix_;
+ /// Current message
+ CoinOneMessage currentMessage_;
+ /// Internal number for use with enums
+ int internalNumber_;
+ /// Format string for message (remainder)
+ char * format_;
+ /// Output buffer
+ char messageBuffer_[COIN_MESSAGE_HANDLER_MAX_BUFFER_SIZE];
+ /// Position in output buffer
+ char * messageOut_;
+ /// Current source of message
+ std::string source_;
+ /** 0 - Normal.
+ 1 - Put in values, move along format, but don't print.
+ 2 - A complete message was provided; nothing more to do but print
+ when CoinMessageEol is processed. Any << operators are treated
+ as noops.
+ 3 - do nothing except look for CoinMessageEol (i.e., the message
+ detail level was not sufficient to cause it to print).
+ */
+ int printStatus_;
+ /// Highest message number (indicates any errors)
+ int highestNumber_;
+ /// File pointer
+ FILE * fp_;
+ /// Current format for floating point numbers
+ char g_format_[8];
+ /// Current number of significant digits for floating point numbers
+ int g_precision_ ;
+ //@}
+
+private:
+
+ /** The body of the copy constructor and the assignment operator */
+ void gutsOfCopy(const CoinMessageHandler &rhs) ;
+
+ /*! \brief Internal function to locate next format code.
+
+ Intended for internal use. Side effects modify the format string.
+ */
+ char *nextPerCent(char *start, const bool initial = false) ;
+
+ /*! \brief Internal printing function.
+
+ Makes it easier to split up print into clean, print and check severity
+ */
+ int internalPrint() ;
+
+ /// Decide if this message should print.
+ void calcPrintStatus(int msglvl, int msgclass) ;
+
+
+};
+
+//#############################################################################
+/** A function that tests the methods in the CoinMessageHandler class. The
+ only reason for it not to be a member method is that this way it doesn't
+ have to be compiled into the library. And that's a gain, because the
+ library should be compiled with optimization on, but this method should be
+ compiled with debugging. */
+bool
+CoinMessageHandlerUnitTest();
+
+#endif