Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | Related Pages

CoinMessageHandler.cpp

00001 // Copyright (C) 2002, International Business Machines
00002 // Corporation and others.  All Rights Reserved.
00003 
00004 #include "CoinFinite.hpp"
00005 
00006 #include "CoinMessageHandler.hpp"
00007 #include <cassert>
00008 #include <map>
00009 
00010 /* Default constructor. */
00011 CoinOneMessage::CoinOneMessage()
00012 {
00013   externalNumber_=-1;
00014   message_=NULL;
00015   severity_='I';
00016   detail_=0;
00017 }
00018 /* Destructor */
00019 CoinOneMessage::~CoinOneMessage()
00020 {
00021   free(message_);
00022 }
00023 /* The copy constructor */
00024 CoinOneMessage::CoinOneMessage(const CoinOneMessage & rhs)
00025 {
00026   externalNumber_=rhs.externalNumber_;
00027   if (rhs.message_)
00028     message_=strdup(rhs.message_);
00029   else
00030     message_=NULL;
00031   severity_=rhs.severity_;
00032   detail_=rhs.detail_;
00033 }
00034 /* assignment operator. */
00035 CoinOneMessage& 
00036 CoinOneMessage::operator=(const CoinOneMessage & rhs)
00037 {
00038   if (this != &rhs) {
00039     externalNumber_=rhs.externalNumber_;
00040     free(message_);
00041     if (rhs.message_)
00042       message_=strdup(rhs.message_);
00043     else
00044       message_=NULL;
00045     severity_=rhs.severity_;
00046     detail_=rhs.detail_;
00047   }
00048   return *this;
00049 }
00050 /* Normal constructor */
00051 CoinOneMessage::CoinOneMessage(int externalNumber, char detail,
00052                 const char * message)
00053 {
00054   externalNumber_=externalNumber;
00055   message_=strdup(message);
00056   if (externalNumber<3000)
00057     severity_='I';
00058   else if (externalNumber<6000)
00059     severity_='W';
00060   else if (externalNumber<9000)
00061     severity_='E';
00062   else
00063     severity_='S';
00064   detail_=detail;
00065 }
00066 // Replaces messages (i.e. a different language)
00067 void 
00068 CoinOneMessage::replaceMessage( const char * message)
00069 {
00070   free(message_);
00071   message_=strdup(message);
00072 }
00073 
00074 
00075 /* Constructor with number of messages. */
00076 CoinMessages::CoinMessages(int numberMessages)
00077 {
00078   numberMessages_=numberMessages;
00079   language_=us_en;
00080   strcpy(source_,"Unk");
00081   if (numberMessages_) {
00082     message_ = new CoinOneMessage * [numberMessages_];
00083     int i;
00084     for (i=0;i<numberMessages_;i++) 
00085       message_[i]=NULL;
00086   } else {
00087     message_=NULL;
00088   }
00089 }
00090 /* Destructor */
00091 CoinMessages::~CoinMessages()
00092 {
00093   int i;
00094   for (i=0;i<numberMessages_;i++) 
00095     delete message_[i];
00096   delete [] message_;
00097 }
00098 /* The copy constructor */
00099 CoinMessages::CoinMessages(const CoinMessages & rhs)
00100 {
00101   numberMessages_=rhs.numberMessages_;
00102   language_=rhs.language_;
00103   strcpy(source_,rhs.source_);
00104   if (numberMessages_) {
00105     message_ = new CoinOneMessage * [numberMessages_];
00106     int i;
00107     for (i=0;i<numberMessages_;i++) 
00108       if (rhs.message_[i])
00109         message_[i]=new CoinOneMessage(*(rhs.message_[i]));
00110       else
00111         message_[i] = NULL;
00112   } else {
00113     message_=NULL;
00114   }
00115 }
00116 /* assignment operator. */
00117 CoinMessages& 
00118 CoinMessages::operator=(const CoinMessages & rhs)
00119 {
00120   if (this != &rhs) {
00121     language_=rhs.language_;
00122     strcpy(source_,rhs.source_);
00123     int i;
00124     for (i=0;i<numberMessages_;i++)
00125         delete message_[i];
00126     delete [] message_;
00127     numberMessages_=rhs.numberMessages_;
00128     if (numberMessages_) {
00129       message_ = new CoinOneMessage * [numberMessages_];
00130       int i;
00131       for (i=0;i<numberMessages_;i++) 
00132         if (rhs.message_[i])
00133           message_[i]=new CoinOneMessage(*(rhs.message_[i]));
00134         else
00135           message_[i] = NULL;
00136     } else {
00137       message_=NULL;
00138     }
00139   }
00140   return *this;
00141 }
00142 // Puts message in correct place
00143 void 
00144 CoinMessages::addMessage(int messageNumber, const CoinOneMessage & message)
00145 {
00146   if (messageNumber>=numberMessages_) {
00147     // should not happen but allow for it
00148     CoinOneMessage ** temp = new CoinOneMessage * [messageNumber+1];
00149     int i;
00150     for (i=0;i<numberMessages_;i++) 
00151       temp[i] = message_[i];
00152     for (;i<=messageNumber;i++) 
00153       temp[i] = NULL;
00154     delete [] message_;
00155     message_ = temp;
00156   }
00157   delete message_[messageNumber];
00158   message_[messageNumber]=new CoinOneMessage(message);
00159 }
00160 // Replaces messages (i.e. a different language)
00161 void 
00162 CoinMessages::replaceMessage(int messageNumber, 
00163                              const char * message)
00164 {
00165   assert(messageNumber<numberMessages_);
00166   message_[messageNumber]->replaceMessage(message);
00167 }
00168 // Changes detail level for one message
00169 void 
00170 CoinMessages::setDetailMessage(int newLevel, int messageNumber)
00171 {
00172   int i;
00173   for (i=0;i<numberMessages_;i++) {
00174     if (message_[i]->externalNumber()==messageNumber) {
00175       message_[i]->setDetail(newLevel);
00176       break;
00177     }
00178   }
00179 }
00180 // Changes detail level for several messages
00181 void 
00182 CoinMessages::setDetailMessages(int newLevel, int numberMessages,
00183                                int * messageNumbers)
00184 {
00185   int i;
00186   if (numberMessages<3) {
00187     // do one by one
00188     int j;
00189     for (j=0;j<numberMessages;j++) {
00190       int messageNumber = messageNumbers[j];
00191       for (i=0;i<numberMessages_;i++) {
00192         if (message_[i]->externalNumber()==messageNumber) {
00193           message_[i]->setDetail(newLevel);
00194           break;
00195         }
00196       }
00197     }
00198   } else {
00199     // do backward mapping
00200     int backward[10000];
00201     for (i=0;i<10000;i++) 
00202       backward[i]=-1;
00203     for (i=0;i<numberMessages_;i++) 
00204       backward[message_[i]->externalNumber()]=i;
00205     for (i=0;i<numberMessages;i++) {
00206       int iback = backward[messageNumbers[i]];
00207       if (iback>=0)
00208         message_[iback]->setDetail(newLevel);
00209     }
00210   }
00211 }
00212 
00213 // Print message, return 0 normally
00214 int 
00215 CoinMessageHandler::print() 
00216 {
00217   if (messageOut_>messageBuffer_) {
00218     *messageOut_=0;
00219     //take off trailing spaces and commas
00220     messageOut_--;
00221     while (messageOut_>=messageBuffer_) {
00222       if (*messageOut_==' '||*messageOut_==',') {
00223         *messageOut_=0;
00224         messageOut_--;
00225       } else {
00226         break;
00227       } 
00228     } 
00229     fprintf(fp_,"%s\n",messageBuffer_);
00230     if (currentMessage_.severity_=='S') {
00231       fprintf(fp_,"Stopping due to previous errors.\n");
00232       //Should do walkback
00233       abort();
00234     } 
00235   }
00236   return 0;
00237 }
00238 /* Amount of print out:
00239    0 - none
00240    1 - minimal
00241    2 - normal low
00242    3 - normal high
00243    4 - verbose
00244    above that 8,16,32 etc just for selective debug and are for
00245    printf messages in code
00246 */
00247 void 
00248 CoinMessageHandler::setLogLevel(int value)
00249 {
00250   if (value>=0)
00251     logLevel_=value;
00252 }
00253 void 
00254 CoinMessageHandler::setPrefix(bool value)
00255 {
00256   if (value)
00257     prefix_ = 255;
00258   else
00259     prefix_ =0;
00260 }
00261 bool  
00262 CoinMessageHandler::prefix() const
00263 {
00264   return (prefix_!=0);
00265 }
00266 // Constructor
00267 CoinMessageHandler::CoinMessageHandler() :
00268   logLevel_(1),
00269   prefix_(255),
00270   currentMessage_(),
00271   internalNumber_(0),
00272   format_(NULL),
00273   numberDoubleFields_(0),
00274   numberIntFields_(0),
00275   numberCharFields_(0),
00276   numberStringFields_(0),
00277   printStatus_(0),
00278   highestNumber_(-1),
00279   fp_(stdout)
00280 {
00281   messageBuffer_[0]='\0';
00282   messageOut_ = messageBuffer_;
00283   source_="Unk";
00284 }
00285 // Constructor
00286 CoinMessageHandler::CoinMessageHandler(FILE * fp) :
00287   logLevel_(1),
00288   prefix_(255),
00289   currentMessage_(),
00290   internalNumber_(0),
00291   format_(NULL),
00292   numberDoubleFields_(0),
00293   numberIntFields_(0),
00294   numberCharFields_(0),
00295   numberStringFields_(0),
00296   printStatus_(0),
00297   highestNumber_(-1),
00298   fp_(fp)
00299 {
00300   messageBuffer_[0]='\0';
00301   messageOut_ = messageBuffer_;
00302   source_="Unk";
00303 }
00304 /* Destructor */
00305 CoinMessageHandler::~CoinMessageHandler()
00306 {
00307 }
00308 /* The copy constructor */
00309 CoinMessageHandler::CoinMessageHandler(const CoinMessageHandler& rhs)
00310 {
00311   logLevel_=rhs.logLevel_;
00312   prefix_ = rhs.prefix_;
00313   currentMessage_=rhs.currentMessage_;
00314   internalNumber_=rhs.internalNumber_;
00315   int i;
00316   numberDoubleFields_ = rhs.numberDoubleFields_;
00317   for (i=0;i<numberDoubleFields_;i++) 
00318     doubleValue_[i]=rhs.doubleValue_[i];
00319   numberIntFields_ = rhs.numberIntFields_;
00320   for (i=0;i<numberIntFields_;i++) 
00321     longValue_[i]=rhs.longValue_[i];
00322   numberCharFields_ = rhs.numberCharFields_;
00323   for (i=0;i<numberCharFields_;i++) 
00324     charValue_[i]=rhs.charValue_[i];
00325   numberStringFields_ = rhs.numberStringFields_;
00326   for (i=0;i<numberStringFields_;i++) 
00327     stringValue_[i]=rhs.stringValue_[i];
00328   int offset = rhs.format_ - rhs.currentMessage_.message();
00329   format_ = currentMessage_.message()+offset;
00330   strcpy(messageBuffer_,rhs.messageBuffer_);
00331   offset = rhs.messageOut_-rhs.messageBuffer_;
00332   messageOut_= messageBuffer_+offset;
00333   printStatus_= rhs.printStatus_;
00334   highestNumber_= rhs.highestNumber_;
00335   fp_ = rhs.fp_;
00336   source_ = rhs.source_;
00337 }
00338 /* assignment operator. */
00339 CoinMessageHandler & 
00340 CoinMessageHandler::operator=(const CoinMessageHandler& rhs)
00341 {
00342   if (this != &rhs) {
00343     logLevel_=rhs.logLevel_;
00344     prefix_ = rhs.prefix_;
00345     currentMessage_=rhs.currentMessage_;
00346     internalNumber_=rhs.internalNumber_;
00347     int i;
00348     numberDoubleFields_ = rhs.numberDoubleFields_;
00349     for (i=0;i<numberDoubleFields_;i++) 
00350       doubleValue_[i]=rhs.doubleValue_[i];
00351     numberIntFields_ = rhs.numberIntFields_;
00352     for (i=0;i<numberIntFields_;i++) 
00353       longValue_[i]=rhs.longValue_[i];
00354     numberCharFields_ = rhs.numberCharFields_;
00355     for (i=0;i<numberCharFields_;i++) 
00356       charValue_[i]=rhs.charValue_[i];
00357     numberStringFields_ = rhs.numberStringFields_;
00358     for (i=0;i<numberStringFields_;i++) 
00359       stringValue_[i]=rhs.stringValue_[i];
00360     int offset = rhs.format_ - rhs.currentMessage_.message();
00361     format_ = currentMessage_.message()+offset;
00362     strcpy(messageBuffer_,rhs.messageBuffer_);
00363     offset = rhs.messageOut_-rhs.messageBuffer_;
00364     messageOut_= messageBuffer_+offset;
00365     printStatus_= rhs.printStatus_;
00366     highestNumber_= rhs.highestNumber_;
00367     fp_ = rhs.fp_;
00368     source_ = rhs.source_;
00369   }
00370   return *this;
00371 }
00372 // Clone
00373 CoinMessageHandler * 
00374 CoinMessageHandler::clone() const
00375 {
00376   return new CoinMessageHandler(*this);
00377 }
00378 // Start a message
00379 CoinMessageHandler & 
00380 CoinMessageHandler::message(int messageNumber,
00381                            const CoinMessages &normalMessage)
00382 {
00383   if (messageOut_!=messageBuffer_) {
00384     // put out last message
00385     print();
00386   }
00387   numberDoubleFields_=0;
00388   numberIntFields_=0;
00389   numberCharFields_=0;
00390   numberStringFields_=0;
00391   internalNumber_=messageNumber;
00392   currentMessage_= *(normalMessage.message_[messageNumber]);
00393   source_ = normalMessage.source_;
00394   format_ = currentMessage_.message_;
00395   messageBuffer_[0]='\0';
00396   messageOut_=messageBuffer_;
00397   highestNumber_ = max(highestNumber_,currentMessage_.externalNumber_);
00398   // do we print
00399   int detail = currentMessage_.detail_;
00400   printStatus_=0;
00401   if (detail>=8) {
00402     // bit setting - debug
00403     if ((detail&logLevel_)==0)
00404       printStatus_ = 3;
00405   } else if (logLevel_<detail) {
00406     printStatus_ = 3;
00407   }
00408   if (!printStatus_) {
00409     if (prefix_) {
00410       sprintf(messageOut_,"%s%4.4d%c ",source_.c_str(),
00411               currentMessage_.externalNumber_,
00412               currentMessage_.severity_);
00413       messageOut_ += strlen(messageOut_);
00414     }
00415     format_ = nextPerCent(format_,true);
00416   }
00417   return *this;
00418 }
00419 /* The following is to help existing codes interface
00420    Starts message giving number and complete text
00421 */
00422 CoinMessageHandler & 
00423 CoinMessageHandler::message(int externalNumber,const char * source,
00424                            const char * msg, char severity)
00425 {
00426   if (messageOut_!=messageBuffer_) {
00427     // put out last message
00428     print();
00429   }
00430   numberDoubleFields_=0;
00431   numberIntFields_=0;
00432   numberCharFields_=0;
00433   numberStringFields_=0;
00434   internalNumber_=externalNumber;
00435   currentMessage_= CoinOneMessage();
00436   currentMessage_.setExternalNumber(externalNumber);
00437   source_ = source;
00438   // mark so will not update buffer
00439   printStatus_=2;
00440   highestNumber_ = max(highestNumber_,externalNumber);
00441   // If we get here we always print
00442   if (prefix_) {
00443     sprintf(messageOut_,"%s%4.4d%c ",source_.c_str(),
00444             externalNumber,
00445             severity);
00446   }
00447   strcat(messageBuffer_,msg);
00448   messageOut_=messageBuffer_+strlen(messageBuffer_);
00449   return *this;
00450 }
00451   /* Allows for skipping printing of part of message,
00452       but putting in data */
00453   CoinMessageHandler & 
00454 CoinMessageHandler::printing(bool onOff)
00455 {
00456   // has no effect if skipping or whole message in
00457   if (printStatus_<2) {
00458     assert(format_[1]=='?');
00459     if (onOff)
00460       printStatus_=0;
00461     else
00462       printStatus_=1;
00463     format_ = nextPerCent(format_+2,true);
00464   }
00465   return *this;
00466 }
00467 /* Stop (and print) 
00468 */
00469 int 
00470 CoinMessageHandler::finish()
00471 {
00472   if (messageOut_!=messageBuffer_) {
00473     // put out last message
00474     print();
00475   }
00476   numberDoubleFields_=0;
00477   numberIntFields_=0;
00478   numberCharFields_=0;
00479   numberStringFields_=0;
00480   internalNumber_=-1;
00481   format_ = NULL;
00482   messageBuffer_[0]='\0';
00483   messageOut_=messageBuffer_;
00484   printStatus_=true;
00485   return 0;
00486 }
00487 /* Gets position of next field in format
00488    if initial then copies until first % */
00489 char * 
00490 CoinMessageHandler::nextPerCent(char * start , const bool initial)
00491 {
00492   if (start) {
00493     bool foundNext=false;
00494     while (!foundNext) {
00495       char * nextPerCent = strchr(start,'%');
00496       if (nextPerCent) {
00497         // %? is skipped over as it is just a separator
00498         if (nextPerCent[1]!='?') {
00499           if (initial&&!printStatus_) {
00500             int numberToCopy=nextPerCent-start;
00501             strncpy(messageOut_,start,numberToCopy);
00502             messageOut_+=numberToCopy;
00503           } 
00504           start=nextPerCent;
00505           if (start[1]!='%') {
00506             foundNext=true;
00507             if (!initial) 
00508               *start='\0'; //zap
00509           } else {
00510             start+=2;
00511             if (initial) {
00512               *messageOut_='%';
00513               messageOut_++;
00514             } 
00515           }
00516         } else {
00517           foundNext=true;
00518           // skip to % and zap
00519           start=nextPerCent;
00520           *start='\0'; 
00521         }
00522       } else {
00523         if (initial&&!printStatus_) {
00524           strcpy(messageOut_,start);
00525           messageOut_+=strlen(messageOut_);
00526         } 
00527         start=0;
00528         foundNext=true;
00529       } 
00530     } 
00531   } 
00532   return start;
00533 }
00534 // Adds into message
00535 CoinMessageHandler & 
00536 CoinMessageHandler::operator<< (int intvalue)
00537 {
00538   if (printStatus_==3)
00539     return *this; // not doing this message
00540   longValue_[numberIntFields_++] = intvalue;
00541   if (printStatus_<2) {
00542     if (format_) {
00543       //format is at % (but may be changed to null)
00544       *format_='%';
00545       char * next = nextPerCent(format_+1);
00546       // could check
00547       if (!printStatus_) {
00548         sprintf(messageOut_,format_,intvalue);
00549         messageOut_+=strlen(messageOut_);
00550       }
00551       format_=next;
00552     } else {
00553       sprintf(messageOut_," %d",intvalue);
00554       messageOut_+=strlen(messageOut_);
00555     } 
00556   }
00557   return *this;
00558 }
00559 CoinMessageHandler & 
00560 CoinMessageHandler::operator<< (double doublevalue)
00561 {
00562   if (printStatus_==3)
00563     return *this; // not doing this message
00564   doubleValue_[numberDoubleFields_++] = doublevalue;
00565   if (printStatus_<2) {
00566     if (format_) {
00567       //format is at % (but changed to 0)
00568       *format_='%';
00569       char * next = nextPerCent(format_+1);
00570       // could check
00571       if (!printStatus_) {
00572         sprintf(messageOut_,format_,doublevalue);
00573         messageOut_+=strlen(messageOut_);
00574       }
00575       format_=next;
00576     } else {
00577       sprintf(messageOut_," %g",doublevalue);
00578       messageOut_+=strlen(messageOut_);
00579     } 
00580   }
00581   return *this;
00582 }
00583 CoinMessageHandler & 
00584 CoinMessageHandler::operator<< (long longvalue)
00585 {
00586   if (printStatus_==3)
00587     return *this; // not doing this message
00588   longValue_[numberIntFields_++] = longvalue;
00589   if (printStatus_<2) {
00590     if (format_) {
00591       //format is at % (but may be changed to null)
00592       *format_='%';
00593       char * next = nextPerCent(format_+1);
00594       // could check
00595       if (!printStatus_) {
00596         sprintf(messageOut_,format_,longvalue);
00597         messageOut_+=strlen(messageOut_);
00598       }
00599       format_=next;
00600     } else {
00601       sprintf(messageOut_," %ld",longvalue);
00602       messageOut_+=strlen(messageOut_);
00603     } 
00604   }
00605   return *this;
00606 }
00607 CoinMessageHandler & 
00608 CoinMessageHandler::operator<< (std::string stringvalue)
00609 {
00610   if (printStatus_==3)
00611     return *this; // not doing this message
00612   stringValue_[numberStringFields_++] = stringvalue;
00613   if (printStatus_<2) {
00614     if (format_) {
00615       //format is at % (but changed to 0)
00616       *format_='%';
00617       char * next = nextPerCent(format_+1);
00618       // could check
00619       if (!printStatus_) {
00620         sprintf(messageOut_,format_,stringvalue.c_str());
00621         messageOut_+=strlen(messageOut_);
00622       }
00623       format_=next;
00624     } else {
00625       sprintf(messageOut_," %s",stringvalue.c_str());
00626       messageOut_+=strlen(messageOut_);
00627     } 
00628   }
00629   return *this;
00630 }
00631 CoinMessageHandler & 
00632 CoinMessageHandler::operator<< (char charvalue)
00633 {
00634   if (printStatus_==3)
00635     return *this; // not doing this message
00636   longValue_[numberCharFields_++] = charvalue;
00637   if (printStatus_<2) {
00638     if (format_) {
00639       //format is at % (but changed to 0)
00640       *format_='%';
00641       char * next = nextPerCent(format_+1);
00642       // could check
00643       if (!printStatus_) {
00644         sprintf(messageOut_,format_,charvalue);
00645         messageOut_+=strlen(messageOut_);
00646       }
00647       format_=next;
00648     } else {
00649       sprintf(messageOut_," %c",charvalue);
00650       messageOut_+=strlen(messageOut_);
00651     } 
00652   }
00653   return *this;
00654 }
00655 CoinMessageHandler & 
00656 CoinMessageHandler::operator<< (const char *stringvalue)
00657 {
00658   if (printStatus_==3)
00659     return *this; // not doing this message
00660   stringValue_[numberStringFields_++] = stringvalue;
00661   if (printStatus_<2) {
00662     if (format_) {
00663       //format is at % (but changed to 0)
00664       *format_='%';
00665       char * next = nextPerCent(format_+1);
00666       // could check
00667       if (!printStatus_) {
00668         sprintf(messageOut_,format_,stringvalue);
00669         messageOut_+=strlen(messageOut_);
00670       }
00671       format_=next;
00672     } else {
00673       sprintf(messageOut_," %s",stringvalue);
00674       messageOut_+=strlen(messageOut_);
00675     } 
00676   }
00677   return *this;
00678 }
00679 CoinMessageHandler & 
00680 CoinMessageHandler::operator<< (CoinMessageMarker marker)
00681 {
00682   if (printStatus_!=3) {
00683     switch (marker) {
00684     case CoinMessageEol:
00685       finish();
00686       break;
00687     case CoinMessageNewline:
00688       strcat(messageOut_,"\n");
00689       messageOut_++;
00690       break;
00691     }
00692   } else {
00693     // skipping - tidy up
00694     format_ = NULL;
00695   }
00696   return *this;
00697 }
00698 
00699 // returns current 
00700 CoinMessageHandler & 
00701 CoinMessageHandler::message()
00702 {
00703   return * this;
00704 }

Generated on Wed Dec 3 14:34:19 2003 for Coin by doxygen 1.3.5