1/* $Id: CoinMessageHandler.cpp 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#include "CoinMessageHandler.hpp"
7#include "CoinHelperFunctions.hpp"
8#include <cassert>
9#include <cstdlib>
10#include <cstddef>
11#include <map>
12
13/* Default constructor. */
14CoinOneMessage::CoinOneMessage()
15{
16 externalNumber_=-1;
17 message_[0]='\0';
18 severity_='I';
19 detail_=0;
20}
21/* Destructor */
22CoinOneMessage::~CoinOneMessage()
23{
24}
25/* The copy constructor */
26CoinOneMessage::CoinOneMessage(const CoinOneMessage & rhs)
27{
28 externalNumber_=rhs.externalNumber_;
29 strcpy(message_,rhs.message_);
30 severity_=rhs.severity_;
31 detail_=rhs.detail_;
32}
33/* assignment operator. */
34CoinOneMessage&
35CoinOneMessage::operator=(const CoinOneMessage & rhs)
36{
37 if (this != &rhs) {
38 externalNumber_=rhs.externalNumber_;
39 strcpy(message_,rhs.message_);
40 severity_=rhs.severity_;
41 detail_=rhs.detail_;
42 }
43 return *this;
44}
45/* Normal constructor */
46CoinOneMessage::CoinOneMessage(int externalNumber, char detail,
47 const char * message)
48{
49 externalNumber_=externalNumber;
50 strcpy(message_,message);
51 if (externalNumber<3000)
52 severity_='I';
53 else if (externalNumber<6000)
54 severity_='W';
55 else if (externalNumber<9000)
56 severity_='E';
57 else
58 severity_='S';
59 detail_=detail;
60}
61// Replaces messages (i.e. a different language)
62void
63CoinOneMessage::replaceMessage( const char * message)
64{
65 strcpy(message_,message);
66}
67
68
69/* Constructor with number of messages. */
70CoinMessages::CoinMessages(int numberMessages)
71{
72 numberMessages_=numberMessages;
73 language_=us_en;
74 strcpy(source_,"Unk");
75 class_=1;
76 lengthMessages_=-1;
77 if (numberMessages_) {
78 message_ = new CoinOneMessage * [numberMessages_];
79 int i;
80 for (i=0;i<numberMessages_;i++)
81 message_[i]=NULL;
82 } else {
83 message_=NULL;
84 }
85}
86/* Destructor */
87CoinMessages::~CoinMessages()
88{
89 int i;
90 if (lengthMessages_<0) {
91 for (i=0;i<numberMessages_;i++)
92 delete message_[i];
93 }
94 delete [] message_;
95}
96/* The copy constructor */
97CoinMessages::CoinMessages(const CoinMessages & rhs)
98{
99 numberMessages_=rhs.numberMessages_;
100 language_=rhs.language_;
101 strcpy(source_,rhs.source_);
102 class_=rhs.class_;
103 lengthMessages_=rhs.lengthMessages_;
104 if (lengthMessages_<0) {
105 if (numberMessages_) {
106 message_ = new CoinOneMessage * [numberMessages_];
107 int i;
108 for (i=0;i<numberMessages_;i++)
109 if (rhs.message_[i])
110 message_[i]=new CoinOneMessage(*(rhs.message_[i]));
111 else
112 message_[i] = NULL;
113 } else {
114 message_=NULL;
115 }
116 } else {
117 char * temp = CoinCopyOfArray(reinterpret_cast<char *> (rhs.message_),lengthMessages_);
118 message_ = reinterpret_cast<CoinOneMessage **> (temp);
119 std::ptrdiff_t offset = temp - reinterpret_cast<char *> (rhs.message_);
120 int i;
121 //printf("new address %x(%x), rhs %x - length %d\n",message_,temp,rhs.message_,lengthMessages_);
122 for (i=0;i<numberMessages_;i++) {
123 if (message_[i]) {
124 char * newAddress = (reinterpret_cast<char *> (message_[i])) + offset;
125 assert (newAddress-temp<lengthMessages_);
126 message_[i] = reinterpret_cast<CoinOneMessage *> (newAddress);
127 //printf("message %d at %x is %s\n",i,message_[i],message_[i]->message());
128 //printf("message %d at %x wass %s\n",i,rhs.message_[i],rhs.message_[i]->message());
129 }
130 }
131 }
132}
133/* assignment operator. */
134CoinMessages&
135CoinMessages::operator=(const CoinMessages & rhs)
136{
137 if (this != &rhs) {
138 language_=rhs.language_;
139 strcpy(source_,rhs.source_);
140 class_=rhs.class_;
141 if (lengthMessages_<0) {
142 int i;
143 for (i=0;i<numberMessages_;i++)
144 delete message_[i];
145 }
146 delete [] message_;
147 numberMessages_=rhs.numberMessages_;
148 lengthMessages_=rhs.lengthMessages_;
149 if (lengthMessages_<0) {
150 if (numberMessages_) {
151 message_ = new CoinOneMessage * [numberMessages_];
152 int i;
153 for (i=0;i<numberMessages_;i++)
154 if (rhs.message_[i])
155 message_[i]=new CoinOneMessage(*(rhs.message_[i]));
156 else
157 message_[i] = NULL;
158 } else {
159 message_=NULL;
160 }
161 } else {
162 char * temp = CoinCopyOfArray(reinterpret_cast<char *> (rhs.message_),lengthMessages_);
163 message_ = reinterpret_cast<CoinOneMessage **> (temp);
164 std::ptrdiff_t offset = temp - reinterpret_cast<char *> (rhs.message_);
165 int i;
166 //printf("new address %x(%x), rhs %x - length %d\n",message_,temp,rhs.message_,lengthMessages_);
167 for (i=0;i<numberMessages_;i++) {
168 if (message_[i]) {
169 char * newAddress = (reinterpret_cast<char *> (message_[i])) + offset;
170 assert (newAddress-temp<lengthMessages_);
171 message_[i] = reinterpret_cast<CoinOneMessage *> (newAddress);
172 //printf("message %d at %x is %s\n",i,message_[i],message_[i]->message());
173 //printf("message %d at %x wass %s\n",i,rhs.message_[i],rhs.message_[i]->message());
174 }
175 }
176 }
177 }
178 return *this;
179}
180// Puts message in correct place
181void
182CoinMessages::addMessage(int messageNumber, const CoinOneMessage & message)
183{
184 if (messageNumber>=numberMessages_) {
185 // should not happen but allow for it
186 CoinOneMessage ** temp = new CoinOneMessage * [messageNumber+1];
187 int i;
188 for (i=0;i<numberMessages_;i++)
189 temp[i] = message_[i];
190 for (;i<=messageNumber;i++)
191 temp[i] = NULL;
192 delete [] message_;
193 message_ = temp;
194 }
195 if (lengthMessages_>=0)
196 fromCompact();
197 delete message_[messageNumber];
198 message_[messageNumber]=new CoinOneMessage(message);
199}
200// Replaces messages (i.e. a different language)
201void
202CoinMessages::replaceMessage(int messageNumber,
203 const char * message)
204{
205 if (lengthMessages_>=0)
206 fromCompact();
207 assert(messageNumber<numberMessages_);
208 message_[messageNumber]->replaceMessage(message);
209}
210// Changes detail level for one message
211void
212CoinMessages::setDetailMessage(int newLevel, int messageNumber)
213{
214 int i;
215 // Last message is null (corresponds to DUMMY)
216 for (i=0;i<numberMessages_-1;i++) {
217 if (message_[i]->externalNumber()==messageNumber) {
218 message_[i]->setDetail(newLevel);
219 break;
220 }
221 }
222}
223// Changes detail level for several messages
224void
225CoinMessages::setDetailMessages(int newLevel, int numberMessages,
226 int * messageNumbers)
227{
228 int i;
229 if (numberMessages<3&&messageNumbers) {
230 // do one by one
231 int j;
232 for (j=0;j<numberMessages;j++) {
233 int messageNumber = messageNumbers[j];
234 for (i=0;i<numberMessages_;i++) {
235 if (message_[i]->externalNumber()==messageNumber) {
236 message_[i]->setDetail(newLevel);
237 break;
238 }
239 }
240 }
241 } else if (numberMessages<10000&&messageNumbers) {
242 // do backward mapping
243 int backward[10000];
244 for (i=0;i<10000;i++)
245 backward[i]=-1;
246 for (i=0;i<numberMessages_;i++)
247 backward[message_[i]->externalNumber()]=i;
248 for (i=0;i<numberMessages;i++) {
249 int iback = backward[messageNumbers[i]];
250 if (iback>=0)
251 message_[iback]->setDetail(newLevel);
252 }
253 } else {
254 // do all (except for dummy end)
255 for (i=0;i<numberMessages_-1;i++) {
256 message_[i]->setDetail(newLevel);
257 }
258 }
259}
260
261// Changes detail level for all messages >= low and < high
262void
263CoinMessages::setDetailMessages(int newLevel, int low, int high)
264{
265 // do all (except for dummy end) if in range
266 for (int i=0;i<numberMessages_-1;i++) {
267 int iNumber = message_[i]->externalNumber();
268 if (iNumber>=low&&iNumber<high)
269 message_[i]->setDetail(newLevel);
270 }
271}
272/*
273 Moves to compact format
274
275 Compact format is an initial array of CoinOneMessage pointers, followed by a
276 bulk store that holds compressed CoinOneMessage objects, where the
277 message_ array is truncated to be just as large as necessary.
278*/
279void
280CoinMessages::toCompact()
281{
282 if (numberMessages_&&lengthMessages_<0) {
283 lengthMessages_=numberMessages_*CoinSizeofAsInt(CoinOneMessage *);
284 int i;
285 for (i=0;i<numberMessages_;i++) {
286 if (message_[i]) {
287 int length = static_cast<int>(strlen(message_[i]->message()));
288 length = static_cast<int>((message_[i]->message()+length+1)-
289 reinterpret_cast<char *> (message_[i]));
290 assert (length<COIN_MESSAGE_HANDLER_MAX_BUFFER_SIZE);
291 int leftOver = length %8;
292 if (leftOver)
293 length += 8-leftOver;
294 lengthMessages_+=length;
295 }
296 }
297 // space
298 char * temp = new char [lengthMessages_];
299 CoinOneMessage ** newMessage = reinterpret_cast<CoinOneMessage **> (temp);
300 temp += numberMessages_*CoinSizeofAsInt(CoinOneMessage *);
301 CoinOneMessage message;
302 //printf("new address %x(%x) - length %d\n",newMessage,temp,lengthMessages_);
303 lengthMessages_=numberMessages_*CoinSizeofAsInt(CoinOneMessage *);
304 for (i=0;i<numberMessages_;i++) {
305 if (message_[i]) {
306 message = *message_[i];
307 int length = static_cast<int>(strlen(message.message()));
308 length = static_cast<int>((message.message()+length+1)-
309 reinterpret_cast<char *> (&message));
310 assert (length<COIN_MESSAGE_HANDLER_MAX_BUFFER_SIZE);
311 int leftOver = length %8;
312 memcpy(temp,&message,length);
313 newMessage[i]=reinterpret_cast<CoinOneMessage *> (temp);
314 //printf("message %d at %x is %s\n",i,newMessage[i],newMessage[i]->message());
315 if (leftOver)
316 length += 8-leftOver;
317 temp += length;
318 lengthMessages_+=length;
319 } else {
320 // null message
321 newMessage[i]=NULL;
322 }
323 }
324 for (i=0;i<numberMessages_;i++)
325 delete message_[i];
326 delete [] message_;
327 message_ = newMessage;
328 }
329}
330// Moves from compact format
331void
332CoinMessages::fromCompact()
333{
334 if (numberMessages_&&lengthMessages_>=0) {
335 CoinOneMessage ** temp = new CoinOneMessage * [numberMessages_];
336 int i;
337 for (i=0;i<numberMessages_;i++) {
338 if (message_[i])
339 temp[i]=new CoinOneMessage(*(message_[i]));
340 else
341 temp[i]=NULL;
342 }
343 delete [] message_;
344 message_ = temp;
345 }
346 lengthMessages_=-1;
347}
348
349// Clean, print message and check severity, return 0 normally
350int
351CoinMessageHandler::internalPrint()
352{
353 int returnCode=0;
354 if (messageOut_>messageBuffer_) {
355 *messageOut_=0;
356 //take off trailing spaces and commas
357 messageOut_--;
358 while (messageOut_>=messageBuffer_) {
359 if (*messageOut_==' '||*messageOut_==',') {
360 *messageOut_=0;
361 messageOut_--;
362 } else {
363 break;
364 }
365 }
366 // Now do print which can be overridden
367 returnCode=print();
368 // See what to do on error
369 checkSeverity();
370 }
371 return returnCode;
372}
373// Print message, return 0 normally
374int
375CoinMessageHandler::print()
376{
377#ifndef NDEBUG
378 fprintf(fp_,"%s\n",messageBuffer_);
379#endif
380 return 0;
381}
382// Check severity
383void
384CoinMessageHandler::checkSeverity()
385{
386 if (currentMessage_.severity_=='S') {
387 fprintf(fp_,"Stopping due to previous errors.\n");
388 //Should do walkback
389 abort();
390 }
391}
392/* Amount of print out:
393 0 - none
394 1 - minimal
395 2 - normal low
396 3 - normal high
397 4 - verbose
398 above that 8,16,32 etc just for selective debug and are for
399 printf messages in code
400*/
401void
402CoinMessageHandler::setLogLevel(int value)
403{
404 if (value>=-1)
405 logLevel_=value;
406}
407void
408CoinMessageHandler::setLogLevel(int which,int value)
409{
410 if (which>=0&&which<COIN_NUM_LOG) {
411 if (value>=-1)
412 logLevels_[which]=value;
413 }
414}
415void
416CoinMessageHandler::setPrecision(unsigned int new_precision) {
417
418 char new_string[8] = {'%','.','8','f','\0','\0','\0','\0'};
419
420 //we assume that the precision is smaller than one thousand
421 new_precision = std::min<unsigned int>(999,new_precision);
422 if (new_precision == 0)
423 new_precision = 1;
424 g_precision_ = new_precision ;
425 int idx = 2;
426 int base = 100;
427 bool print = false;
428 while (base > 0) {
429
430 char c = static_cast<char>(new_precision / base);
431 new_precision = new_precision % base;
432 if (c != 0)
433 print = true;
434 if (print) {
435 new_string[idx] = static_cast<char>(c + '0');
436 idx++;
437 }
438 base /= 10;
439 }
440 new_string[idx] = 'g';
441 strcpy(g_format_,new_string);
442}
443void
444CoinMessageHandler::setPrefix(bool value)
445{
446 if (value)
447 prefix_ = 255;
448 else
449 prefix_ =0;
450}
451bool
452CoinMessageHandler::prefix() const
453{
454 return (prefix_!=0);
455}
456// Constructor
457CoinMessageHandler::CoinMessageHandler() :
458 logLevel_(1),
459 prefix_(255),
460 currentMessage_(),
461 internalNumber_(0),
462 format_(NULL),
463 printStatus_(0),
464 highestNumber_(-1),
465 fp_(stdout)
466{
467 const char* g_default = "%.8g";
468
469 strcpy(g_format_,g_default);
470 g_precision_ = 8 ;
471
472 for (int i=0;i<COIN_NUM_LOG;i++)
473 logLevels_[i]=-1000;
474 messageBuffer_[0]='\0';
475 messageOut_ = messageBuffer_;
476 source_="Unk";
477}
478// Constructor
479CoinMessageHandler::CoinMessageHandler(FILE * fp) :
480 logLevel_(1),
481 prefix_(255),
482 currentMessage_(),
483 internalNumber_(0),
484 format_(NULL),
485 printStatus_(0),
486 highestNumber_(-1),
487 fp_(fp)
488{
489 const char* g_default = "%.8g";
490
491 strcpy(g_format_,g_default);
492 g_precision_ = 8 ;
493
494 for (int i=0;i<COIN_NUM_LOG;i++)
495 logLevels_[i]=-1000;
496 messageBuffer_[0]='\0';
497 messageOut_ = messageBuffer_;
498 source_="Unk";
499}
500/* Destructor */
501CoinMessageHandler::~CoinMessageHandler()
502{
503}
504
505void
506CoinMessageHandler::gutsOfCopy(const CoinMessageHandler& rhs)
507{
508 logLevel_=rhs.logLevel_;
509 prefix_ = rhs.prefix_;
510 if (rhs.format_ && *rhs.format_ == '\0')
511 { *rhs.format_ = '%' ;
512 currentMessage_=rhs.currentMessage_;
513 *rhs.format_ = '\0' ; }
514 else
515 { currentMessage_=rhs.currentMessage_; }
516 internalNumber_=rhs.internalNumber_;
517 int i;
518 for ( i=0;i<COIN_NUM_LOG;i++)
519 logLevels_[i]=rhs.logLevels_[i];
520 doubleValue_=rhs.doubleValue_;
521 longValue_=rhs.longValue_;
522 charValue_=rhs.charValue_;
523 stringValue_=rhs.stringValue_;
524 std::ptrdiff_t offset ;
525 if (rhs.format_)
526 { offset = rhs.format_ - rhs.currentMessage_.message();
527 format_ = currentMessage_.message()+offset; }
528 else
529 { format_ = NULL ; }
530 std::memcpy(messageBuffer_,rhs.messageBuffer_,
531 COIN_MESSAGE_HANDLER_MAX_BUFFER_SIZE);
532 offset = rhs.messageOut_-rhs.messageBuffer_;
533 messageOut_= messageBuffer_+offset;
534 printStatus_= rhs.printStatus_;
535 highestNumber_= rhs.highestNumber_;
536 fp_ = rhs.fp_;
537 source_ = rhs.source_;
538 strcpy(g_format_,rhs.g_format_);
539 g_precision_ = rhs.g_precision_ ;
540}
541/* The copy constructor */
542CoinMessageHandler::CoinMessageHandler(const CoinMessageHandler& rhs)
543{
544 gutsOfCopy(rhs);
545}
546/* assignment operator. */
547CoinMessageHandler &
548CoinMessageHandler::operator=(const CoinMessageHandler& rhs)
549{
550 if (this != &rhs) {
551 gutsOfCopy(rhs);
552 }
553 return *this;
554}
555// Clone
556CoinMessageHandler *
557CoinMessageHandler::clone() const
558{
559 return new CoinMessageHandler(*this);
560}
561// Start a message
562CoinMessageHandler &
563CoinMessageHandler::message(int messageNumber,
564 const CoinMessages &normalMessage)
565{
566 if (messageOut_!=messageBuffer_) {
567 // put out last message
568 internalPrint();
569 }
570 internalNumber_=messageNumber;
571 currentMessage_= *(normalMessage.message_[messageNumber]);
572 source_ = normalMessage.source_;
573 format_ = currentMessage_.message_;
574 messageBuffer_[0]='\0';
575 messageOut_=messageBuffer_;
576 highestNumber_ = CoinMax(highestNumber_,currentMessage_.externalNumber_);
577 // do we print
578 int detail = currentMessage_.detail_;
579 printStatus_=0;
580 if (logLevels_[0]==-1000) {
581 if (detail>=8&&logLevel_>=0) {
582 // bit setting - debug
583 if ((detail&logLevel_)==0)
584 printStatus_ = 3;
585 } else if (logLevel_<detail) {
586 printStatus_ = 3;
587 }
588 } else if (logLevels_[normalMessage.class_]<detail) {
589 printStatus_ = 3;
590 }
591 if (!printStatus_) {
592 if (prefix_) {
593 sprintf(messageOut_,"%s%4.4d%c ",source_.c_str(),
594 currentMessage_.externalNumber_,
595 currentMessage_.severity_);
596 messageOut_ += strlen(messageOut_);
597 }
598 format_ = nextPerCent(format_,true);
599 }
600 return *this;
601}
602/* The following is to help existing codes interface
603 Starts message giving number and complete text
604*/
605CoinMessageHandler &
606CoinMessageHandler::message(int externalNumber,const char * source,
607 const char * msg, char severity)
608{
609 if (messageOut_!=messageBuffer_) {
610 // put out last message
611 internalPrint();
612 }
613 internalNumber_=externalNumber;
614 currentMessage_= CoinOneMessage();
615 currentMessage_.setExternalNumber(externalNumber);
616 source_ = source;
617 // mark so will not update buffer
618 printStatus_=2;
619 highestNumber_ = CoinMax(highestNumber_,externalNumber);
620 // If we get here we always print
621 if (prefix_) {
622 sprintf(messageOut_,"%s%4.4d%c ",source_.c_str(),
623 externalNumber,
624 severity);
625 }
626 strcat(messageBuffer_,msg);
627 messageOut_=messageBuffer_+strlen(messageBuffer_);
628 return *this;
629}
630 /* Allows for skipping printing of part of message,
631 but putting in data */
632 CoinMessageHandler &
633CoinMessageHandler::printing(bool onOff)
634{
635 // has no effect if skipping or whole message in
636 if (printStatus_<2) {
637 assert(format_[1]=='?');
638 *format_ = '%' ;
639 if (onOff)
640 printStatus_=0;
641 else
642 printStatus_=1;
643 format_ = nextPerCent(format_+2,true);
644 }
645 return *this;
646}
647/* Stop (and print)
648*/
649int
650CoinMessageHandler::finish()
651{
652 if (messageOut_!=messageBuffer_) {
653 // put out last message
654 internalPrint();
655 }
656 internalNumber_=-1;
657 format_ = NULL;
658 messageBuffer_[0]='\0';
659 messageOut_=messageBuffer_;
660 printStatus_=0;
661 doubleValue_.clear();
662 longValue_.clear();
663 charValue_.clear();
664 stringValue_.clear();
665 return 0;
666}
667/* Gets position of next field in format
668 If we're scanning the initial portion of the string (prior to the first
669 `%' code) the prefix will be copied to the output buffer. Normally, the
670 text from the current position up to and including a % code is is processed
671 by the relevant operator<< method.
672*/
673char *
674CoinMessageHandler::nextPerCent(char * start , const bool initial)
675{
676 if (start) {
677 bool foundNext=false;
678 while (!foundNext) {
679 char * nextPerCent = strchr(start,'%');
680 if (nextPerCent) {
681 if (initial&&!printStatus_) {
682 int numberToCopy=static_cast<int>(nextPerCent-start);
683 strncpy(messageOut_,start,numberToCopy);
684 messageOut_+=numberToCopy;
685 }
686 // %? is skipped over as it is just a separator
687 if (nextPerCent[1]!='?') {
688 start=nextPerCent;
689 if (start[1]!='%') {
690 foundNext=true;
691 if (!initial)
692 *start='\0'; //zap
693 } else {
694 start+=2;
695 if (initial) {
696 *messageOut_='%';
697 messageOut_++;
698 }
699 }
700 } else {
701 foundNext=true;
702 // skip to % and zap
703 start=nextPerCent;
704 *start='\0';
705 }
706 } else {
707 if (initial&&!printStatus_) {
708 strcpy(messageOut_,start);
709 messageOut_+=strlen(messageOut_);
710 }
711 start=0;
712 foundNext=true;
713 }
714 }
715 }
716 return start;
717}
718// Adds into message
719CoinMessageHandler &
720CoinMessageHandler::operator<< (int intvalue)
721{
722 if (printStatus_==3)
723 return *this; // not doing this message
724 longValue_.push_back(intvalue);
725 if (printStatus_<2) {
726 if (format_) {
727 //format is at % (but may be changed to null)
728 *format_='%';
729 char * next = nextPerCent(format_+1);
730 // could check
731 if (!printStatus_) {
732 sprintf(messageOut_,format_,intvalue);
733 messageOut_+=strlen(messageOut_);
734 }
735 format_=next;
736 } else {
737 sprintf(messageOut_," %d",intvalue);
738 messageOut_+=strlen(messageOut_);
739 }
740 }
741 return *this;
742}
743CoinMessageHandler &
744CoinMessageHandler::operator<< (double doublevalue)
745{
746 if (printStatus_==3)
747 return *this; // not doing this message
748 doubleValue_.push_back(doublevalue);
749
750 if (printStatus_<2) {
751 if (format_) {
752 //format is at \0 (but changed to %)
753 *format_='%';
754 char * next = nextPerCent(format_+1);
755 // could check
756 if (!printStatus_) {
757 if (format_[1] == '.' && format_[2] >= '0' && format_[2] <= '9') {
758 // an explicitly specified precision currently overrides the
759 // precision of the message handler
760 sprintf(messageOut_,format_,doublevalue);
761 }
762 else {
763 sprintf(messageOut_,g_format_,doublevalue);
764 if (next != format_+2) {
765 messageOut_+=strlen(messageOut_);
766 sprintf(messageOut_,format_+2);
767 }
768 }
769 messageOut_+=strlen(messageOut_);
770 }
771 format_=next;
772 } else {
773 sprintf(messageOut_," ");
774 messageOut_ += 1;
775 sprintf(messageOut_,g_format_,doublevalue);
776 messageOut_+=strlen(messageOut_);
777 }
778 }
779 return *this;
780}
781#if COIN_BIG_INDEX==1
782CoinMessageHandler &
783CoinMessageHandler::operator<< (long longvalue)
784{
785 if (printStatus_==3)
786 return *this; // not doing this message
787 longValue_.push_back(longvalue);
788 if (printStatus_<2) {
789 if (format_) {
790 //format is at % (but may be changed to null)
791 *format_='%';
792 char * next = nextPerCent(format_+1);
793 // could check
794 if (!printStatus_) {
795 sprintf(messageOut_,format_,longvalue);
796 messageOut_+=strlen(messageOut_);
797 }
798 format_=next;
799 } else {
800 sprintf(messageOut_," %ld",longvalue);
801 messageOut_+=strlen(messageOut_);
802 }
803 }
804 return *this;
805}
806#endif
807#if COIN_BIG_INDEX==2
808CoinMessageHandler &
809CoinMessageHandler::operator<< (long long longvalue)
810{
811 if (printStatus_==3)
812 return *this; // not doing this message
813 longValue_.push_back(longvalue);
814 if (printStatus_<2) {
815 if (format_) {
816 //format is at % (but may be changed to null)
817 *format_='%';
818 char * next = nextPerCent(format_+1);
819 // could check
820 if (!printStatus_) {
821 sprintf(messageOut_,format_,longvalue);
822 messageOut_+=strlen(messageOut_);
823 }
824 format_=next;
825 } else {
826 sprintf(messageOut_," %ld",longvalue);
827 messageOut_+=strlen(messageOut_);
828 }
829 }
830 return *this;
831}
832#endif
833CoinMessageHandler &
834CoinMessageHandler::operator<< (const std::string& stringvalue)
835{
836 if (printStatus_==3)
837 return *this; // not doing this message
838 stringValue_.push_back(stringvalue);
839 if (printStatus_<2) {
840 if (format_) {
841 //format is at % (but changed to 0)
842 *format_='%';
843 char * next = nextPerCent(format_+1);
844 // could check
845 if (!printStatus_) {
846 sprintf(messageOut_,format_,stringvalue.c_str());
847 messageOut_+=strlen(messageOut_);
848 }
849 format_=next;
850 } else {
851 sprintf(messageOut_," %s",stringvalue.c_str());
852 messageOut_+=strlen(messageOut_);
853 }
854 }
855 return *this;
856}
857CoinMessageHandler &
858CoinMessageHandler::operator<< (char charvalue)
859{
860 if (printStatus_==3)
861 return *this; // not doing this message
862 charValue_.push_back(charvalue);
863 if (printStatus_<2) {
864 if (format_) {
865 //format is at % (but changed to 0)
866 *format_='%';
867 char * next = nextPerCent(format_+1);
868 // could check
869 if (!printStatus_) {
870 sprintf(messageOut_,format_,charvalue);
871 messageOut_+=strlen(messageOut_);
872 }
873 format_=next;
874 } else {
875 sprintf(messageOut_," %c",charvalue);
876 messageOut_+=strlen(messageOut_);
877 }
878 }
879 return *this;
880}
881CoinMessageHandler &
882CoinMessageHandler::operator<< (const char *stringvalue)
883{
884 if (printStatus_==3)
885 return *this; // not doing this message
886 stringValue_.push_back(stringvalue);
887 if (printStatus_<2) {
888 if (format_) {
889 //format is at % (but changed to 0)
890 *format_='%';
891 char * next = nextPerCent(format_+1);
892 // could check
893 if (!printStatus_) {
894 sprintf(messageOut_,format_,stringvalue);
895 messageOut_+=strlen(messageOut_);
896 }
897 format_=next;
898 } else {
899 sprintf(messageOut_," %s",stringvalue);
900 messageOut_+=strlen(messageOut_);
901 }
902 }
903 return *this;
904}
905CoinMessageHandler &
906CoinMessageHandler::operator<< (CoinMessageMarker marker)
907{
908 if (printStatus_!=3) {
909 switch (marker) {
910 case CoinMessageEol:
911 finish();
912 break;
913 case CoinMessageNewline:
914 strcat(messageOut_,"\n");
915 messageOut_++;
916 break;
917 }
918 } else {
919 // skipping - tidy up
920 format_ = NULL;
921 }
922 return *this;
923}
924
925// returns current
926CoinMessageHandler &
927CoinMessageHandler::message()
928{
929 return * this;
930}
931