00001 /* 00002 * Copyright (c) 1999-2003 Bert Kampes 00003 * Copyright (c) 1999-2003 Delft University of Technology, The Netherlands 00004 * 00005 * This file is part of Doris, the Delft o-o radar interferometric software. 00006 * 00007 * Doris program is free software; you can redistribute it and/or modify 00008 * it under the terms of the GNU General Public License as published by 00009 * the Free Software Foundation; either version 2 of the License, or 00010 * (at your option) any later version. 00011 * 00012 * Doris is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU General Public License 00018 * along with this program; if not, write to the Free Software 00019 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00020 * 00021 * Publications that contain results produced by the Doris software should 00022 * contain an acknowledgment. (For example: The interferometric processing 00023 * was performed using the freely available Doris software package developed 00024 * by the Delft Institute for Earth-Oriented Space Research (DEOS), Delft 00025 * University of Technology, or include a reference to: Bert Kampes and 00026 * Stefania Usai. \"Doris: The Delft Object-oriented Radar Interferometric 00027 * software.\" In: proceedings 2nd ITC ORS symposium, August 1999. (cdrom)). 00028 * 00029 */ 00030 /**************************************************************** 00031 * $Source: /users/kampes/DEVELOP/DORIS/doris/src/RCS/bk_messages.hh,v $ * 00032 * $Revision: 3.9 $ * 00033 * $Date: 2005/04/06 15:29:03 $ * 00034 * $Author: kampes $ * 00035 * 00036 * definition of bk_message class * 00037 #%// BK 10-Apr-2003 00038 ****************************************************************/ 00039 00040 #ifndef BK_MESSAGES_H 00041 #define BK_MESSAGES_H 00042 using namespace std; 00043 00044 #include <iostream> // cout 00045 #include <iomanip> // setw() 00046 #include <strstream> // mem.buf 00047 #include <cstring> // strcpy() 00048 #include <cstdlib> // exit() 00049 00050 // #if majorversion>3 and g++ 00051 //#include <stringstream> // new mem.buf 00052 //#include <string> 00053 00054 00055 00056 // ---------------------------------------------------------------- 00057 // --- Choice was either to make something like: 00058 // --- message ERROR; 00059 // --- message DEBUG; 00060 // --- message INFO; 00061 // --- with functions like: ERROR.doprint(1); ERROR.setidentifyer("ERROR"); 00062 // --- ERROR << "dsaada" << 4.5 << setw(4) << nw; 00063 // --- ERROR.print(); 00064 // --- with separate bufs, or to combine them in a single object 00065 // --- like: 00066 // --- messages logging; 00067 // --- logging.setlevel("INFO"); 00068 // --- logging << "dsaada" << 4.5 << setw(4) << nw; 00069 // --- logging.info(); 00070 // --- The first is nice, different separated bufs, and easy to change 00071 // --- existing code. However, 00072 // --- The latter is better with Doris, since it allows things like 00073 // --- if (good) then logging.info() else logging.warning(); 00074 // --- But by using construction like 00075 // --- WARNING.print(INFO.get_str()); this is solved 00076 // --- #%// BK 10-Apr-2003 00077 // 00078 // most important member functions: 00079 // get_str(): leave buffer unaffected, pointer to a copy 00080 // print("sss"): leave buffer unaffected, print a copy 00081 // print(): leave buffer unaffected, terminate buffer, rewind buffer; 00082 // this means that you have to rrewind the buffer yourself if you misuse it 00083 // as storage, like TRACE.rewind(); 00084 // INFO.precision(10); /* permanent */ INFO << setp(13)<<q;// once 00085 // INFO.width(11); 00086 // INFO.reset(); 00087 // ---------------------------------------------------------------- 00088 // EXAMPLE USEAGE: 00089 // ---------------------------------------------------------------- 00090 // in code simply change with a define calls to ERROR to give a WARNING summary, etc. 00091 // #define printERROR cout<<"this is defined...\n"; warning.summary(); error<<" ("<<__FILE__<<": "<<__LINE__<<")"; error.print(); 00092 // 00093 // ---------------------------------------------------------------- 00094 // in globals, put them as extern to access them everywhere 00095 // #include "globals.h" 00096 // --- declaration of global info message object --- 00097 // bk_messages error; 00098 //bk_messages INFO; 00099 //bk_messages DEBUG; 00100 //int main( int argc, char* argv[]) 00101 // { 00102 // DEBUG.setidentifyer("DEBUG"); 00103 // INFO.setidentifyer("INFO"); 00104 // INFO.doprint(1); 00105 // INFO.dostderr(0); 00106 // INFO.bellrings(2); 00107 // DEBUG << 421; 00108 // DEBUG << " dsadsaa: " << 433 ; 00109 // DEBUG << 421.1; 00110 // DEBUG << setw(20) << double(421.1) << ";;;"; 00111 // DEBUG.print(); 00112 // INFO << "this is a info message"; 00113 // INFO.print(); 00114 // INFO.print("this is a another info message"); 00115 // INFO.summary(); 00116 // return 0; 00117 // } 00118 00119 00120 00121 // ---------------------------------------------------------------- 00122 // ---------------------------------------------------------------- 00123 // ---------------------------------------------------------------- 00124 class bk_messages 00125 { 00126 // ______ Private data of bk_message class ______ 00127 private: 00128 bool print_cout;// switch to print or not to cout 00129 bool print_cerr;// switch to print or not to cerr 00130 bool do_exit_;// switch to exit after print or not 00131 int ringbell_;// number of times to ring bell. 00132 int strwidth;// original str.width(); 00133 int strprecision;// original str.precision(); 00134 char name_[10];// identifyer, <9 chars (PROGRESS) 00135 ostrstream buf;// message buffer stream 00136 int nummessages;// counter 00137 char first_messages[6][256];// summary first 6 at end or at exit; 00138 00139 // ______ Public function of bk_message class ______ 00140 public: 00141 // ___Constructor/Destructor___ 00142 bk_messages() 00143 { 00144 //cerr << "YOU ARE IN THE CONSTRUCTOR\n"; 00145 print_cout = true;// default do print; 00146 print_cerr = false;// default no print to cerr; 00147 do_exit_ = false;// default no exit after print 00148 ringbell_ = 0;// default no bell; 00149 strwidth = buf.width(); 00150 strprecision= buf.precision(); 00151 strcpy(name_,"???????");// default identifyer 00152 nummessages = 0; 00153 // --- allocate enough space, then freeze it?, and keep this 00154 // --- stream as is --- 00155 // --- this is required, at g++, and can't really hurt --- 00156 buf.seekp(0); 00157 buf << ends 00158 << "This is the constructor...This is the constructor..." 00159 << "This is the constructor...This is the constructor..." 00160 << "This is the constructor...This is the constructor..." 00161 << "This is the constructor...This is the constructor..." 00162 << "This is the constructor...This is the constructor..." 00163 << ends; 00164 buf.seekp(0);// reset pointer 00165 // //buf.rdbuf()->freeze(0); // Unfreeze 00166 // //buf.rdbuf()->freeze(); // freeze string, keep allocated mem 00167 // buf.freeze();// freeze string, keep allocated memory ??? 00168 } 00169 00170 // ___Constructor/Destructor___ 00171 ~bk_messages() //{;}// nothing to destruct 00172 { 00173 delete []buf.str(); 00174 }// dealloc 00175 00176 // ___Helper functions___ 00177 void terminate() {buf<<ends;} 00178 void rewind() {buf.seekp(0);} 00179 char* get_id() {return name_;} 00180 void dostderr(bool s) {print_cerr = s;} 00181 void doprint(bool s) {print_cout = s;} 00182 void doexit(bool s) {do_exit_ = s;} 00183 void bellrings(int s) {ringbell_ = s;} 00184 int width() const {return int(buf.width());} 00185 void width(int s) {buf.width(s);} 00186 int precision() const {return int(buf.precision());} 00187 void precision(int s) {buf.precision(s);} 00188 //void setiosflags(long s) {buf.setiosflags(s);} 00189 //void resetiosflags(long s) {buf.resetiosflags(s);} 00190 //void unsetf(long s) {buf.unsetf(s);} // is this standard? 00191 void reset() {// what does resetiosflags do? 00192 // add all flags? 00193 buf << resetiosflags( 00194 ios::fixed | 00195 ios::showpoint | 00196 ios::skipws | 00197 ios::showpos | 00198 ios::scientific | 00199 ios::left | 00200 ios::right | 00201 ios::floatfield | 00202 ios::adjustfield); 00203 width(strwidth); 00204 precision(strprecision); 00205 terminate(); 00206 rewind(); 00207 } 00208 00209 // ___Set a name to prepend to message string___ 00210 void setidentifyer(const char *id) 00211 { 00212 // ___ only use first 9 of ID string ___ 00213 if (strlen(id)>=10) 00214 { 00215 strncpy(name_,id, 9); 00216 strcat(name_,'\0');// terminate id 00217 } 00218 else 00219 { 00220 strcpy(name_,id);// identifyer 00221 } 00222 // ___ default message behavior for some identifyers ___ 00223 if (!strcmp(id,"ERROR")) 00224 { 00225 do_exit_ = true;// default message behavior 00226 print_cerr = true; 00227 ringbell_ = 3; 00228 } 00229 else if (!strcmp(id,"WARNING")) 00230 { 00231 ringbell_ = 2; 00232 print_cerr = true; 00233 } 00234 else if (!strcmp(id,"PROGRESS")) 00235 { 00236 ringbell_ = 1; 00237 print_cerr = true; 00238 } 00239 } 00240 00241 // ___ problem that buf.str() empties string buffer, thus do cp ___ 00242 // ___ append a null, since common use will be to get a copy after written fully ___ 00243 // ___ this returns a pointer to buf, thus, that may be changed afterwards ___ 00244 // ___ use immediately? ___ 00245 //char* get_str() {return buf.str();} 00246 char* get_str() 00247 { 00248 char *s = buf.str(); 00249 buf.freeze(0);// unfreeze, since str() freezes it (does not seem to work?) 00250 return s; 00251 } 00252 00253 // ___What it is all about, print the message___ 00254 // ___the buffer pointer is set to (0), but the message is not deleted___ 00255 // ___so people can access the buffer multiple times___ 00256 // ___but you cannot add to it later...____ 00257 void print() 00258 { 00259 // --- Allways rewind string to prevent unlimited growth --- 00260 // --- Only terminate it when new info is there ------------ 00261 //cerr << "pcount: " << buf.pcount() << endl; 00262 if (buf.pcount()>0) {terminate(); rewind();} 00263 print(buf.str()); 00264 buf.freeze(); 00265 } 00266 00267 // ___What it is all about, print the message___ 00268 // ___the buffer pointer is set to (0), but the message is not deleted___ 00269 // ___so people can access the buffer multiple times___ 00270 // ___but you cannot add to it later...____ 00271 void print(const char *s) 00272 { 00273 if (nummessages<6) strcpy(first_messages[nummessages],s); 00274 nummessages++; 00275 // --- only print if level has been set ---------------------- 00276 if(print_cout==true) 00277 { 00278 if (do_exit_==true) 00279 cout << endl << "!!! ABNORMAL TERMINATION !!!" << endl; 00280 cout << setw(8) << setiosflags(ios::left) << name_ << ": " << s << endl; 00281 if (print_cerr==true) 00282 cerr << setw(8) << setiosflags(ios::left) << name_ << ": " << s << endl; 00283 // --- Ring bell ----------------------------------------- 00284 for (int i=0;i<ringbell_;++i) cerr << "\a"; 00285 // --- Exit ---------------------------------------------- 00286 if (do_exit_==true) 00287 { 00288 /* with a define you can print other stuff at exit... 00289 * #define printERROR cout<<"this is defined...\n"; \ 00290 * warning.summary(); error<<" ("<<__FILE__<<": " 00291 * <<__LINE__<<")"; error.print(); 00292 */ 00293 cerr << endl << "!!! ABNORMAL TERMINATION !!!" << endl; 00294 exit(9999); 00295 // Bert Kampes, 31-Mar-2005: throw relevant exception 00296 //cerr << "throwing string exception" << endl; 00297 //throw("!!! ABNORMAL TERMINATION !!!");// handle exception as string 00298 } 00299 } 00300 } 00301 00302 00303 // --- SUMMARY OF FIRST 6 MESSAGES ---------------------------- 00304 // --- on stderr and stdout ----------------------------------- 00305 void summary() 00306 { 00307 for (int i=0;i<ringbell_;++i) cerr << "\a"; 00308 cout << endl << " --- " << setiosflags(ios::left) << name_ << " SUMMARY ---" << endl; 00309 //if (print_cerr==true) 00310 cerr << endl << " --- " << setiosflags(ios::left) << name_ << " SUMMARY ---" << endl; 00311 switch (nummessages) 00312 { 00313 case 0: 00314 cout << "There were no messages." << endl; 00315 cerr << "There were no messages." << endl; 00316 break; 00317 case 1: 00318 cout << "There was 1 message:" << endl 00319 << " 1: " << first_messages[0] << endl; 00320 cerr << "There was 1 message:" << endl 00321 << " 1: " << first_messages[0] << endl; 00322 break; 00323 default: 00324 cout << "There were " << nummessages << " messages:" << endl; 00325 cerr << "There were " << nummessages << " messages:" << endl; 00326 for (int i=0; i<nummessages; ++i) 00327 { 00328 if (i==6) 00329 { 00330 cout << " " << i+1 << ": [...]" << endl; 00331 cerr << " " << i+1 << ": [...]" << endl; 00332 break; // only first six 00333 } 00334 cout << " " << i+1 << ": " << first_messages[i] << endl; 00335 cerr << " " << i+1 << ": " << first_messages[i] << endl; 00336 } 00337 }// switch nummessages 00338 } 00339 00340 // ___Operator to build string from different types___ 00341 // ostream& operator << (const int X) {return buf << X;} 00342 template <class Type> 00343 ostream& operator << (const Type X) {return buf << X;} 00344 00345 // ___ e.g., cout << info; ___ 00346 // ___ e.g., ofile << info; ___ 00347 // friend ostream& operator << (ostream& s) 00348 // ostream& operator << (ostream& s, const bk_message &X) 00349 // { 00350 // if(print_cout==true) 00351 // { 00352 // X.terminate(); 00353 // s << X.getid() << ": " << X.getstr() << endl; 00354 // X.rewind(); 00355 // buf << ends; 00356 // s << name_ << ": " << buf.str() << endl; 00357 // buf.seekp(0); 00358 // } 00359 // return s; 00360 // } 00361 00362 };// eof class 00363 00364 00365 #endif // BK_MESSAGES_H 00366