| 1 | /* $Id: CoinMessageHandler.hpp 1448 2011-06-19 15:34:41Z stefan $ */ |
| 2 | // Copyright (C) 2002, International Business Machines |
| 3 | // Corporation and others. All Rights Reserved. |
| 4 | // This code is licensed under the terms of the Eclipse Public License (EPL). |
| 5 | |
| 6 | #ifndef CoinMessageHandler_H |
| 7 | #define CoinMessageHandler_H |
| 8 | |
| 9 | #include "CoinUtilsConfig.h" |
| 10 | #include "CoinPragma.hpp" |
| 11 | |
| 12 | #include <iostream> |
| 13 | #include <cstdio> |
| 14 | #include <string> |
| 15 | #include <vector> |
| 16 | |
| 17 | /** \file CoinMessageHandler.hpp |
| 18 | \brief This is a first attempt at a message handler. |
| 19 | |
| 20 | The COIN Project is in favo(u)r of multi-language support. This implementation |
| 21 | of a message handler tries to make it as lightweight as possible in the sense |
| 22 | that only a subset of messages need to be defined --- the rest default to US |
| 23 | English. |
| 24 | |
| 25 | The default handler at present just prints to stdout or to a FILE pointer |
| 26 | |
| 27 | \todo |
| 28 | This needs to be worked over for correct operation with ISO character codes. |
| 29 | */ |
| 30 | |
| 31 | /* |
| 32 | I (jjf) am strongly in favo(u)r of language support for an open |
| 33 | source project, but I have tried to make it as lightweight as |
| 34 | possible in the sense that only a subset of messages need to be |
| 35 | defined - the rest default to US English. There will be different |
| 36 | sets of messages for each component - so at present there is a |
| 37 | Clp component and a Coin component. |
| 38 | |
| 39 | Because messages are only used in a controlled environment and have no |
| 40 | impact on code and are tested by other tests I have include tests such |
| 41 | as language and derivation in other unit tests. |
| 42 | */ |
| 43 | |
| 44 | /** \brief Class for one massaged message. |
| 45 | |
| 46 | A message consists of a text string with formatting codes (#message_), |
| 47 | an integer identifier (#externalNumber_) which also determines the severity |
| 48 | level (#severity_) of the message, and a detail (logging) level (#detail_). |
| 49 | |
| 50 | CoinOneMessage is just a container to hold this information. The |
| 51 | interpretation is set by CoinMessageHandler, which see. |
| 52 | */ |
| 53 | |
| 54 | class CoinOneMessage { |
| 55 | |
| 56 | public: |
| 57 | /**@name Constructors etc */ |
| 58 | //@{ |
| 59 | /** Default constructor. */ |
| 60 | CoinOneMessage(); |
| 61 | /** Normal constructor */ |
| 62 | CoinOneMessage(int externalNumber, char detail, |
| 63 | const char * message); |
| 64 | /** Destructor */ |
| 65 | ~CoinOneMessage(); |
| 66 | /** The copy constructor */ |
| 67 | CoinOneMessage(const CoinOneMessage&); |
| 68 | /** assignment operator. */ |
| 69 | CoinOneMessage& operator=(const CoinOneMessage&); |
| 70 | //@} |
| 71 | |
| 72 | /**@name Useful stuff */ |
| 73 | //@{ |
| 74 | /// Replace message text (<i>e.g.</i>, text in a different language) |
| 75 | void replaceMessage(const char * message); |
| 76 | //@} |
| 77 | |
| 78 | /**@name Get and set methods */ |
| 79 | //@{ |
| 80 | /** Get message ID number */ |
| 81 | inline int externalNumber() const |
| 82 | {return externalNumber_;} |
| 83 | /** \brief Set message ID number |
| 84 | |
| 85 | In the default CoinMessageHandler, this number is printed in the message |
| 86 | prefix and is used to determine the message severity level. |
| 87 | */ |
| 88 | inline void setExternalNumber(int number) |
| 89 | {externalNumber_=number;} |
| 90 | /// Severity |
| 91 | inline char severity() const |
| 92 | {return severity_;} |
| 93 | /// Set detail level |
| 94 | inline void setDetail(int level) |
| 95 | {detail_=static_cast<char> (level);} |
| 96 | /// Get detail level |
| 97 | inline int detail() const |
| 98 | {return detail_;} |
| 99 | /// Return the message text |
| 100 | inline char * message() const |
| 101 | {return message_;} |
| 102 | //@} |
| 103 | |
| 104 | /**@name member data */ |
| 105 | //@{ |
| 106 | /// number to print out (also determines severity) |
| 107 | int externalNumber_; |
| 108 | /// Will only print if detail matches |
| 109 | char detail_; |
| 110 | /// Severity |
| 111 | char severity_; |
| 112 | /// Messages (in correct language) (not all 400 may exist) |
| 113 | mutable char message_[400]; |
| 114 | //@} |
| 115 | }; |
| 116 | |
| 117 | /** \brief Class to hold and manipulate an array of massaged messages. |
| 118 | |
| 119 | Note that the message index used to reference a message in the array of |
| 120 | messages is completely distinct from the external ID number stored with the |
| 121 | message. |
| 122 | */ |
| 123 | |
| 124 | class CoinMessages { |
| 125 | |
| 126 | public: |
| 127 | /** \brief Supported languages |
| 128 | |
| 129 | These are the languages that are supported. At present only |
| 130 | us_en is serious and the rest are for testing. |
| 131 | */ |
| 132 | enum Language { |
| 133 | us_en = 0, |
| 134 | uk_en, |
| 135 | it |
| 136 | }; |
| 137 | |
| 138 | /**@name Constructors etc */ |
| 139 | //@{ |
| 140 | /** Constructor with number of messages. */ |
| 141 | CoinMessages(int numberMessages=0); |
| 142 | /** Destructor */ |
| 143 | ~CoinMessages(); |
| 144 | /** The copy constructor */ |
| 145 | CoinMessages(const CoinMessages&); |
| 146 | /** assignment operator. */ |
| 147 | CoinMessages& operator=(const CoinMessages&); |
| 148 | //@} |
| 149 | |
| 150 | /**@name Useful stuff */ |
| 151 | //@{ |
| 152 | /*! \brief Installs a new message in the specified index position |
| 153 | |
| 154 | Any existing message is replaced, and a copy of the specified message is |
| 155 | installed. |
| 156 | */ |
| 157 | void addMessage(int messageNumber, const CoinOneMessage & message); |
| 158 | /*! \brief Replaces the text of the specified message |
| 159 | |
| 160 | Any existing text is deleted and the specified text is copied into the |
| 161 | specified message. |
| 162 | */ |
| 163 | void replaceMessage(int messageNumber, const char * message); |
| 164 | /** Language. Need to think about iso codes */ |
| 165 | inline Language language() const |
| 166 | {return language_;} |
| 167 | /** Set language */ |
| 168 | void setLanguage(Language newlanguage) |
| 169 | {language_ = newlanguage;} |
| 170 | /// Change detail level for one message |
| 171 | void setDetailMessage(int newLevel, int messageNumber); |
| 172 | /** \brief Change detail level for several messages |
| 173 | |
| 174 | messageNumbers is expected to contain the indices of the messages to be |
| 175 | changed. |
| 176 | If numberMessages >= 10000 or messageNumbers is NULL, the detail level |
| 177 | is changed on all messages. |
| 178 | */ |
| 179 | void setDetailMessages(int newLevel, int numberMessages, |
| 180 | int * messageNumbers); |
| 181 | /** Change detail level for all messages with low <= ID number < high */ |
| 182 | void setDetailMessages(int newLevel, int low, int high); |
| 183 | |
| 184 | /// Returns class |
| 185 | inline int getClass() const |
| 186 | { return class_;} |
| 187 | /// Moves to compact format |
| 188 | void toCompact(); |
| 189 | /// Moves from compact format |
| 190 | void fromCompact(); |
| 191 | //@} |
| 192 | |
| 193 | /**@name member data */ |
| 194 | //@{ |
| 195 | /// Number of messages |
| 196 | int numberMessages_; |
| 197 | /// Language |
| 198 | Language language_; |
| 199 | /// Source (null-terminated string, maximum 4 characters). |
| 200 | char source_[5]; |
| 201 | /// Class - see later on before CoinMessageHandler |
| 202 | int class_; |
| 203 | /** Length of fake CoinOneMessage array. |
| 204 | First you get numberMessages_ pointers which point to stuff |
| 205 | */ |
| 206 | int lengthMessages_; |
| 207 | /// Messages |
| 208 | CoinOneMessage ** message_; |
| 209 | //@} |
| 210 | }; |
| 211 | |
| 212 | // for convenience eol |
| 213 | enum CoinMessageMarker { |
| 214 | CoinMessageEol = 0, |
| 215 | CoinMessageNewline = 1 |
| 216 | }; |
| 217 | |
| 218 | /** Base class for message handling |
| 219 | |
| 220 | The default behavior is described here: messages are printed, and (if the |
| 221 | severity is sufficiently high) execution will be aborted. Inherit and |
| 222 | redefine the methods #print and #checkSeverity to augment the behaviour. |
| 223 | |
| 224 | Messages can be printed with or without a prefix; the prefix will consist |
| 225 | of a source string, the external ID number, and a letter code, |
| 226 | <i>e.g.</i>, Clp6024W. |
| 227 | A prefix makes the messages look less nimble but is very useful |
| 228 | for "grep" <i>etc</i>. |
| 229 | |
| 230 | <h3> Usage </h3> |
| 231 | |
| 232 | The general approach to using the COIN messaging facility is as follows: |
| 233 | <ul> |
| 234 | <li> Define your messages. For each message, you must supply an external |
| 235 | ID number, a log (detail) level, and a format string. Typically, you |
| 236 | define a convenience structure for this, something that's easy to |
| 237 | use to create an array of initialised message definitions at compile |
| 238 | time. |
| 239 | <li> Create a CoinMessages object, sized to accommodate the number of |
| 240 | messages you've defined. (Incremental growth will happen if |
| 241 | necessary as messages are loaded, but it's inefficient.) |
| 242 | <li> Load the messages into the CoinMessages object. Typically this |
| 243 | entails creating a CoinOneMessage object for each message and |
| 244 | passing it as a parameter to CoinMessages::addMessage(). You specify |
| 245 | the message's internal ID as the other parameter to addMessage. |
| 246 | <li> Create and use a CoinMessageHandler object to print messages. |
| 247 | </ul> |
| 248 | See, for example, CoinMessage.hpp and CoinMessage.cpp for an example of |
| 249 | the first three steps. `Format codes' below has a simple example of |
| 250 | printing a message. |
| 251 | |
| 252 | <h3> External ID numbers and severity </h3> |
| 253 | |
| 254 | CoinMessageHandler assumes the following relationship between the |
| 255 | external ID number of a message and the severity of the message: |
| 256 | \li <3000 are informational ('I') |
| 257 | \li <6000 warnings ('W') |
| 258 | \li <9000 non-fatal errors ('E') |
| 259 | \li >=9000 aborts the program (after printing the message) ('S') |
| 260 | |
| 261 | <h3> Format codes </h3> |
| 262 | |
| 263 | CoinMessageHandler can print integers (normal, long, and long long), |
| 264 | doubles, characters, and strings. See the descriptions of the |
| 265 | various << operators. |
| 266 | |
| 267 | When processing a standard message with a format string, the formatting |
| 268 | codes specified in the format string will be passed to the sprintf |
| 269 | function, along with the argument. When generating a message with no |
| 270 | format string, each << operator uses a simple format code appropriate for |
| 271 | its argument. Consult the documentation for the standard printf facility |
| 272 | for further information on format codes. |
| 273 | |
| 274 | The special format code `%?' provides a hook to enable or disable |
| 275 | printing. For each `%?' code, there must be a corresponding call to |
| 276 | printing(bool). This provides a way to define optional parts in |
| 277 | messages, delineated by the code `%?' in the format string. Printing can |
| 278 | be suppressed for these optional parts, but any operands must still be |
| 279 | supplied. For example, given the message string |
| 280 | \verbatim |
| 281 | "A message with%? an optional integer %d and%? a double %g." |
| 282 | \endverbatim |
| 283 | installed in CoinMessages \c exampleMsgs with index 5, and |
| 284 | \c CoinMessageHandler \c hdl, the code |
| 285 | \code |
| 286 | hdl.message(5,exampleMsgs) ; |
| 287 | hdl.printing(true) << 42 ; |
| 288 | hdl.printing(true) << 53.5 << CoinMessageEol ; |
| 289 | \endcode |
| 290 | will print |
| 291 | \verbatim |
| 292 | A message with an optional integer 42 and a double 53.5. |
| 293 | \endverbatim |
| 294 | while |
| 295 | \code |
| 296 | hdl.message(5,exampleMsgs) ; |
| 297 | hdl.printing(false) << 42 ; |
| 298 | hdl.printing(true) << 53.5 << CoinMessageEol ; |
| 299 | \endcode |
| 300 | will print |
| 301 | \verbatim |
| 302 | A message with a double 53.5. |
| 303 | \endverbatim |
| 304 | |
| 305 | For additional examples of usage, see CoinMessageHandlerUnitTest in |
| 306 | CoinMessageHandlerTest.cpp. |
| 307 | */ |
| 308 | |
| 309 | /* |
| 310 | Where there are derived classes I (jjf) have started message numbers at 1001. |
| 311 | */ |
| 312 | |
| 313 | class CoinMessageHandler { |
| 314 | |
| 315 | friend bool CoinMessageHandlerUnitTest () ; |
| 316 | |
| 317 | private: |
| 318 | /** The body of the copy constructor and the assignment operator */ |
| 319 | void gutsOfCopy(const CoinMessageHandler& rhs); |
| 320 | |
| 321 | public: |
| 322 | /**@name Virtual methods that the derived classes may provide */ |
| 323 | //@{ |
| 324 | /** Print message, return 0 normally. |
| 325 | */ |
| 326 | virtual int print() ; |
| 327 | /** Check message severity - if too bad then abort |
| 328 | */ |
| 329 | virtual void checkSeverity() ; |
| 330 | //@} |
| 331 | |
| 332 | /**@name Constructors etc */ |
| 333 | //@{ |
| 334 | /// Constructor |
| 335 | CoinMessageHandler(); |
| 336 | /// Constructor to put to file pointer (won't be closed) |
| 337 | CoinMessageHandler(FILE *fp); |
| 338 | /** Destructor */ |
| 339 | virtual ~CoinMessageHandler(); |
| 340 | /** The copy constructor */ |
| 341 | CoinMessageHandler(const CoinMessageHandler&); |
| 342 | /** Assignment operator. */ |
| 343 | CoinMessageHandler& operator=(const CoinMessageHandler&); |
| 344 | /// Clone |
| 345 | virtual CoinMessageHandler * clone() const; |
| 346 | //@} |
| 347 | /**@name Get and set methods */ |
| 348 | //@{ |
| 349 | /// Get detail level of a message. |
| 350 | inline int detail(int messageNumber, const CoinMessages &normalMessage) const |
| 351 | { return normalMessage.message_[messageNumber]->detail();} |
| 352 | /** Get current log (detail) level. */ |
| 353 | inline int logLevel() const |
| 354 | { return logLevel_;} |
| 355 | /** \brief Set current log (detail) level. |
| 356 | |
| 357 | If the log level is equal or greater than the detail level of a message, |
| 358 | the message will be printed. A rough convention for the amount of output |
| 359 | expected is |
| 360 | - 0 - none |
| 361 | - 1 - minimal |
| 362 | - 2 - normal low |
| 363 | - 3 - normal high |
| 364 | - 4 - verbose |
| 365 | |
| 366 | Please assign log levels to messages accordingly. Log levels of 8 and |
| 367 | above (8,16,32, <i>etc</i>.) are intended for selective debugging. |
| 368 | The logical AND of the log level specified in the message and the current |
| 369 | log level is used to determine if the message is printed. (In other words, |
| 370 | you're using individual bits to determine which messages are printed.) |
| 371 | */ |
| 372 | void setLogLevel(int value); |
| 373 | /** Get alternative log level. */ |
| 374 | inline int logLevel(int which) const |
| 375 | { return logLevels_[which];} |
| 376 | /*! \brief Set alternative log level value. |
| 377 | |
| 378 | Can be used to store alternative log level information within the handler. |
| 379 | */ |
| 380 | void setLogLevel(int which, int value); |
| 381 | |
| 382 | /// Set the number of significant digits for printing floating point numbers |
| 383 | void setPrecision(unsigned int new_precision); |
| 384 | /// Current number of significant digits for printing floating point numbers |
| 385 | inline int precision() { return (g_precision_) ; } |
| 386 | |
| 387 | /// Switch message prefix on or off. |
| 388 | void setPrefix(bool yesNo); |
| 389 | /// Current setting for printing message prefix. |
| 390 | bool prefix() const; |
| 391 | /*! \brief Values of double fields already processed. |
| 392 | |
| 393 | As the parameter for a double field is processed, the value is saved |
| 394 | and can be retrieved using this function. |
| 395 | */ |
| 396 | inline double doubleValue(int position) const |
| 397 | { return doubleValue_[position];} |
| 398 | /*! \brief Number of double fields already processed. |
| 399 | |
| 400 | Incremented each time a field of type double is processed. |
| 401 | */ |
| 402 | inline int numberDoubleFields() const |
| 403 | {return static_cast<int>(doubleValue_.size());} |
| 404 | /*! \brief Values of integer fields already processed. |
| 405 | |
| 406 | As the parameter for a integer field is processed, the value is saved |
| 407 | and can be retrieved using this function. |
| 408 | */ |
| 409 | inline int intValue(int position) const |
| 410 | { return longValue_[position];} |
| 411 | /*! \brief Number of integer fields already processed. |
| 412 | |
| 413 | Incremented each time a field of type integer is processed. |
| 414 | */ |
| 415 | inline int numberIntFields() const |
| 416 | {return static_cast<int>(longValue_.size());} |
| 417 | /*! \brief Values of char fields already processed. |
| 418 | |
| 419 | As the parameter for a char field is processed, the value is saved |
| 420 | and can be retrieved using this function. |
| 421 | */ |
| 422 | inline char charValue(int position) const |
| 423 | { return charValue_[position];} |
| 424 | /*! \brief Number of char fields already processed. |
| 425 | |
| 426 | Incremented each time a field of type char is processed. |
| 427 | */ |
| 428 | inline int numberCharFields() const |
| 429 | {return static_cast<int>(charValue_.size());} |
| 430 | /*! \brief Values of string fields already processed. |
| 431 | |
| 432 | As the parameter for a string field is processed, the value is saved |
| 433 | and can be retrieved using this function. |
| 434 | */ |
| 435 | inline std::string stringValue(int position) const |
| 436 | { return stringValue_[position];} |
| 437 | /*! \brief Number of string fields already processed. |
| 438 | |
| 439 | Incremented each time a field of type string is processed. |
| 440 | */ |
| 441 | inline int numberStringFields() const |
| 442 | {return static_cast<int>(stringValue_.size());} |
| 443 | |
| 444 | /// Current message |
| 445 | inline CoinOneMessage currentMessage() const |
| 446 | {return currentMessage_;} |
| 447 | /// Source of current message |
| 448 | inline std::string currentSource() const |
| 449 | {return source_;} |
| 450 | /// Output buffer |
| 451 | inline const char * messageBuffer() const |
| 452 | {return messageBuffer_;} |
| 453 | /// Highest message number (indicates any errors) |
| 454 | inline int highestNumber() const |
| 455 | {return highestNumber_;} |
| 456 | /// Get current file pointer |
| 457 | inline FILE * filePointer() const |
| 458 | { return fp_;} |
| 459 | /// Set new file pointer |
| 460 | inline void setFilePointer(FILE * fp) |
| 461 | { fp_ = fp;} |
| 462 | //@} |
| 463 | |
| 464 | /**@name Actions to create a message */ |
| 465 | //@{ |
| 466 | /*! \brief Start a message |
| 467 | |
| 468 | Look up the specified message. A prefix will be generated if enabled. |
| 469 | The message will be printed if the current log level is equal or greater |
| 470 | than the log level of the message. |
| 471 | */ |
| 472 | CoinMessageHandler & message(int messageNumber, |
| 473 | const CoinMessages & messages); |
| 474 | /*! \brief Start or continue a message |
| 475 | |
| 476 | Does nothing except return a reference to the handler. This can be used |
| 477 | with any of the << operators. One use is to start a message which will be |
| 478 | constructed entirely from scratch. Another use is continuation of a |
| 479 | message after code that interrupts the usual sequence of << operators. |
| 480 | */ |
| 481 | CoinMessageHandler & message(); |
| 482 | /*! \brief Generate a standard prefix and append \c msg `as is'. |
| 483 | |
| 484 | Intended as a transition mechanism. The standard prefix is generated (if |
| 485 | enabled), and \c msg is appended. Only the operator<<(CoinMessageMarker) |
| 486 | operator can be used with a message started with this call. |
| 487 | */ |
| 488 | CoinMessageHandler & message(int externalNumber,const char * , |
| 489 | const char * msg,char severity); |
| 490 | /*! \brief Process an integer parameter value. |
| 491 | |
| 492 | The default format code is `%d'. |
| 493 | */ |
| 494 | CoinMessageHandler & operator<< (int intvalue); |
| 495 | #if COIN_BIG_INDEX==1 |
| 496 | /*! \brief Process a long integer parameter value. |
| 497 | |
| 498 | The default format code is `%ld'. |
| 499 | */ |
| 500 | CoinMessageHandler & operator<< (long longvalue); |
| 501 | #endif |
| 502 | #if COIN_BIG_INDEX==2 |
| 503 | /*! \brief Process a long long integer parameter value. |
| 504 | |
| 505 | The default format code is `%ld'. |
| 506 | */ |
| 507 | CoinMessageHandler & operator<< (long long longvalue); |
| 508 | #endif |
| 509 | /*! \brief Process a double parameter value. |
| 510 | |
| 511 | The default format code is `%d'. |
| 512 | */ |
| 513 | CoinMessageHandler & operator<< (double doublevalue); |
| 514 | /*! \brief Process a STL string parameter value. |
| 515 | |
| 516 | The default format code is `%g'. |
| 517 | */ |
| 518 | CoinMessageHandler & operator<< (const std::string& stringvalue); |
| 519 | /*! \brief Process a char parameter value. |
| 520 | |
| 521 | The default format code is `%s'. |
| 522 | */ |
| 523 | CoinMessageHandler & operator<< (char charvalue); |
| 524 | /*! \brief Process a C-style string parameter value. |
| 525 | |
| 526 | The default format code is `%c'. |
| 527 | */ |
| 528 | CoinMessageHandler & operator<< (const char *stringvalue); |
| 529 | /*! \brief Process a marker. |
| 530 | |
| 531 | The default format code is `%s'. |
| 532 | */ |
| 533 | CoinMessageHandler & operator<< (CoinMessageMarker); |
| 534 | /** Finish (and print) the message. |
| 535 | |
| 536 | Equivalent to using the CoinMessageEol marker. |
| 537 | */ |
| 538 | int finish(); |
| 539 | /*! \brief Enable or disable printing of an optional portion of a message. |
| 540 | |
| 541 | Optional portions of a message are delimited by `%?' markers, and |
| 542 | printing processes one %? marker. If \c onOff is true, the subsequent |
| 543 | portion of the message (to the next %? marker or the end of the format |
| 544 | string) will be printed. If \c onOff is false, printing is suppressed. |
| 545 | Parameters must still be supplied, whether printing is suppressed or not. |
| 546 | See the class documentation for an example. |
| 547 | */ |
| 548 | CoinMessageHandler & printing(bool onOff); |
| 549 | |
| 550 | /*! \brief Internal function to locate next format code. |
| 551 | |
| 552 | Intended for internal use. Side effects modify the format string. |
| 553 | */ |
| 554 | char * nextPerCent(char * start , const bool initial=false); |
| 555 | /*! \brief Internal printing function. |
| 556 | |
| 557 | Makes it easier to split up print into clean, print and check severity |
| 558 | */ |
| 559 | int internalPrint(); |
| 560 | //@} |
| 561 | |
| 562 | /** Log levels will be by type and will then use type |
| 563 | given in CoinMessage::class_ |
| 564 | |
| 565 | - 0 - Branch and bound code or similar |
| 566 | - 1 - Solver |
| 567 | - 2 - Stuff in Coin directory |
| 568 | - 3 - Cut generators |
| 569 | */ |
| 570 | #define COIN_NUM_LOG 4 |
| 571 | /// Maximum length of constructed message (characters) |
| 572 | #define COIN_MESSAGE_HANDLER_MAX_BUFFER_SIZE 1000 |
| 573 | protected: |
| 574 | /**@name Protected member data */ |
| 575 | //@{ |
| 576 | /// values in message |
| 577 | std::vector<double> doubleValue_; |
| 578 | std::vector<int> longValue_; |
| 579 | std::vector<char> charValue_; |
| 580 | std::vector<std::string> stringValue_; |
| 581 | /// Log level |
| 582 | int logLevel_; |
| 583 | /// Log levels |
| 584 | int logLevels_[COIN_NUM_LOG]; |
| 585 | /// Whether we want prefix (may get more subtle so is int) |
| 586 | int prefix_; |
| 587 | /// Current message |
| 588 | CoinOneMessage currentMessage_; |
| 589 | /// Internal number for use with enums |
| 590 | int internalNumber_; |
| 591 | /// Format string for message (remainder) |
| 592 | char * format_; |
| 593 | /// Output buffer |
| 594 | char messageBuffer_[COIN_MESSAGE_HANDLER_MAX_BUFFER_SIZE]; |
| 595 | /// Position in output buffer |
| 596 | char * messageOut_; |
| 597 | /// Current source of message |
| 598 | std::string source_; |
| 599 | /** 0 - normal, |
| 600 | 1 - put in values, move along format, no print |
| 601 | 2 - put in values, no print |
| 602 | 3 - skip message |
| 603 | */ |
| 604 | int printStatus_; |
| 605 | /// Highest message number (indicates any errors) |
| 606 | int highestNumber_; |
| 607 | /// File pointer |
| 608 | FILE * fp_; |
| 609 | /// Current format for floating point numbers |
| 610 | char g_format_[8]; |
| 611 | /// Current number of significant digits for floating point numbers |
| 612 | int g_precision_ ; |
| 613 | //@} |
| 614 | |
| 615 | }; |
| 616 | |
| 617 | //############################################################################# |
| 618 | /** A function that tests the methods in the CoinMessageHandler class. The |
| 619 | only reason for it not to be a member method is that this way it doesn't |
| 620 | have to be compiled into the library. And that's a gain, because the |
| 621 | library should be compiled with optimization on, but this method should be |
| 622 | compiled with debugging. */ |
| 623 | bool |
| 624 | CoinMessageHandlerUnitTest(); |
| 625 | |
| 626 | #endif |
| 627 | |