00001
00002
00003
00004 #include "CoinFinite.hpp"
00005
00006 #include "CoinMessageHandler.hpp"
00007 #include <cassert>
00008 #include <map>
00009
00010
00011 CoinOneMessage::CoinOneMessage()
00012 {
00013 externalNumber_=-1;
00014 message_=NULL;
00015 severity_='I';
00016 detail_=0;
00017 }
00018
00019 CoinOneMessage::~CoinOneMessage()
00020 {
00021 free(message_);
00022 }
00023
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
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
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
00067 void
00068 CoinOneMessage::replaceMessage( const char * message)
00069 {
00070 free(message_);
00071 message_=strdup(message);
00072 }
00073
00074
00075
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
00091 CoinMessages::~CoinMessages()
00092 {
00093 int i;
00094 for (i=0;i<numberMessages_;i++)
00095 delete message_[i];
00096 delete [] message_;
00097 }
00098
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
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
00143 void
00144 CoinMessages::addMessage(int messageNumber, const CoinOneMessage & message)
00145 {
00146 if (messageNumber>=numberMessages_) {
00147
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
00161 void
00162 CoinMessages::replaceMessage(int messageNumber,
00163 const char * message)
00164 {
00165 assert(messageNumber<numberMessages_);
00166 message_[messageNumber]->replaceMessage(message);
00167 }
00168
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
00181 void
00182 CoinMessages::setDetailMessages(int newLevel, int numberMessages,
00183 int * messageNumbers)
00184 {
00185 int i;
00186 if (numberMessages<3) {
00187
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
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
00214 int
00215 CoinMessageHandler::print()
00216 {
00217 if (messageOut_>messageBuffer_) {
00218 *messageOut_=0;
00219
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
00233 abort();
00234 }
00235 }
00236 return 0;
00237 }
00238
00239
00240
00241
00242
00243
00244
00245
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
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
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
00305 CoinMessageHandler::~CoinMessageHandler()
00306 {
00307 }
00308
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
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
00373 CoinMessageHandler *
00374 CoinMessageHandler::clone() const
00375 {
00376 return new CoinMessageHandler(*this);
00377 }
00378
00379 CoinMessageHandler &
00380 CoinMessageHandler::message(int messageNumber,
00381 const CoinMessages &normalMessage)
00382 {
00383 if (messageOut_!=messageBuffer_) {
00384
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
00399 int detail = currentMessage_.detail_;
00400 printStatus_=0;
00401 if (detail>=8) {
00402
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
00420
00421
00422 CoinMessageHandler &
00423 CoinMessageHandler::message(int externalNumber,const char * source,
00424 const char * msg, char severity)
00425 {
00426 if (messageOut_!=messageBuffer_) {
00427
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
00439 printStatus_=2;
00440 highestNumber_ = max(highestNumber_,externalNumber);
00441
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
00452
00453 CoinMessageHandler &
00454 CoinMessageHandler::printing(bool onOff)
00455 {
00456
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
00468
00469 int
00470 CoinMessageHandler::finish()
00471 {
00472 if (messageOut_!=messageBuffer_) {
00473
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
00488
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
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';
00509 } else {
00510 start+=2;
00511 if (initial) {
00512 *messageOut_='%';
00513 messageOut_++;
00514 }
00515 }
00516 } else {
00517 foundNext=true;
00518
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
00535 CoinMessageHandler &
00536 CoinMessageHandler::operator<< (int intvalue)
00537 {
00538 if (printStatus_==3)
00539 return *this;
00540 longValue_[numberIntFields_++] = intvalue;
00541 if (printStatus_<2) {
00542 if (format_) {
00543
00544 *format_='%';
00545 char * next = nextPerCent(format_+1);
00546
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;
00564 doubleValue_[numberDoubleFields_++] = doublevalue;
00565 if (printStatus_<2) {
00566 if (format_) {
00567
00568 *format_='%';
00569 char * next = nextPerCent(format_+1);
00570
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;
00588 longValue_[numberIntFields_++] = longvalue;
00589 if (printStatus_<2) {
00590 if (format_) {
00591
00592 *format_='%';
00593 char * next = nextPerCent(format_+1);
00594
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;
00612 stringValue_[numberStringFields_++] = stringvalue;
00613 if (printStatus_<2) {
00614 if (format_) {
00615
00616 *format_='%';
00617 char * next = nextPerCent(format_+1);
00618
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;
00636 longValue_[numberCharFields_++] = charvalue;
00637 if (printStatus_<2) {
00638 if (format_) {
00639
00640 *format_='%';
00641 char * next = nextPerCent(format_+1);
00642
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;
00660 stringValue_[numberStringFields_++] = stringvalue;
00661 if (printStatus_<2) {
00662 if (format_) {
00663
00664 *format_='%';
00665 char * next = nextPerCent(format_+1);
00666
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
00694 format_ = NULL;
00695 }
00696 return *this;
00697 }
00698
00699
00700 CoinMessageHandler &
00701 CoinMessageHandler::message()
00702 {
00703 return * this;
00704 }