Line data Source code
1 : // -*- C++ -*-
2 : /***************************************************************************
3 : *
4 : * The IPPL Framework
5 : *
6 : * This program was prepared by PSI.
7 : * All rights in the program are reserved by PSI.
8 : * Neither PSI nor the author(s)
9 : * makes any warranty, express or implied, or assumes any liability or
10 : * responsibility for the use of this software
11 : *
12 : * Visit www.amas.web.psi for more details
13 : *
14 : ***************************************************************************/
15 :
16 : // -*- C++ -*-
17 : /***************************************************************************
18 : *
19 : * The IPPL Framework
20 : *
21 : *
22 : * Visit http://people.web.psi.ch/adelmann/ for more details
23 : *
24 : ***************************************************************************/
25 :
26 : // include files
27 : #include "Ippl.h"
28 :
29 : #include "Utility/Inform.h"
30 :
31 : #include <cstring>
32 : #include <fstream>
33 :
34 : // range of Inform message levels
35 : constexpr int MIN_INFORM_LEVEL = 1;
36 : constexpr int MAX_INFORM_LEVEL = 5;
37 :
38 : /////////////////////////////////////////////////////////////////////
39 : // manipulator functions
40 :
41 : // signal we wish to send the message
42 0 : Inform& endl(Inform& inf) {
43 0 : inf << '\n';
44 0 : return inf.outputMessage();
45 : }
46 :
47 : // set the current msg level
48 0 : Inform& level1(Inform& inf) {
49 0 : return inf.setMessageLevel(1);
50 : }
51 0 : Inform& level2(Inform& inf) {
52 0 : return inf.setMessageLevel(2);
53 : }
54 0 : Inform& level3(Inform& inf) {
55 0 : return inf.setMessageLevel(3);
56 : }
57 0 : Inform& level4(Inform& inf) {
58 0 : return inf.setMessageLevel(4);
59 : }
60 0 : Inform& level5(Inform& inf) {
61 0 : return inf.setMessageLevel(5);
62 : }
63 :
64 : /////////////////////////////////////////////////////////////////////
65 : // perform initialization for this object; called by the constructors.
66 : // arguments = prefix string, print node
67 2376 : void Inform::setup(const char* myname, int pnode) {
68 2376 : On = true;
69 :
70 2376 : if (ippl::Info != NULL) {
71 1590 : OutputLevel = ippl::Info->getOutputLevel();
72 : } else {
73 786 : OutputLevel = MIN_INFORM_LEVEL;
74 : }
75 2376 : MsgLevel = MIN_INFORM_LEVEL;
76 2376 : PrintNode = pnode;
77 :
78 2376 : if (myname != 0) {
79 2376 : Name = strcpy(new char[strlen(myname) + 1], myname);
80 : } else {
81 0 : Name = 0;
82 : }
83 2376 : }
84 :
85 : /////////////////////////////////////////////////////////////////////
86 : // class constructor
87 804 : Inform::Inform(const char* myname, int pnode)
88 804 : : FormatBuf(std::ios::out)
89 804 : , OpenedSuccessfully(true) {
90 : // in this case, the default destination stream is cout
91 804 : NeedClose = false;
92 804 : MsgDest = &std::cout;
93 :
94 : // perform all other needed initialization
95 804 : setup(myname, pnode);
96 804 : }
97 :
98 : /////////////////////////////////////////////////////////////////////
99 : // class constructor specifying a file to open
100 0 : Inform::Inform(const char* myname, const char* fname, const WriteMode opnmode, int pnode)
101 0 : : FormatBuf(std::ios::out)
102 0 : , OpenedSuccessfully(true) {
103 : // only open a file if we're on the proper node
104 0 : MsgDest = 0;
105 0 : if (pnode >= 0 && pnode == ippl::Comm->rank()) {
106 0 : if (opnmode == OVERWRITE)
107 0 : MsgDest = new std::ofstream(fname, std::ios::out);
108 : else
109 0 : MsgDest = new std::ofstream(fname, std::ios::app);
110 : }
111 :
112 : // make sure it was opened properly
113 0 : if (MsgDest == 0 || !(*MsgDest)) {
114 0 : if (pnode >= 0 && pnode == ippl::Comm->rank()) {
115 0 : std::cerr << "Inform: Cannot open file '" << fname << "'." << std::endl;
116 : }
117 0 : NeedClose = false;
118 0 : MsgDest = &std::cout;
119 0 : OpenedSuccessfully = false;
120 : } else {
121 0 : NeedClose = true;
122 : }
123 :
124 : // perform all other needed initialization
125 0 : setup(myname, pnode);
126 0 : }
127 :
128 : /////////////////////////////////////////////////////////////////////
129 : // class constructor specifying an output stream to use
130 1572 : Inform::Inform(const char* myname, std::ostream& os, int pnode)
131 1572 : : FormatBuf(std::ios::out)
132 1572 : , OpenedSuccessfully(true) {
133 : // just store a ref to the provided stream
134 1572 : NeedClose = false;
135 1572 : MsgDest = &os;
136 :
137 : // perform all other needed initialization
138 1572 : setup(myname, pnode);
139 1572 : }
140 :
141 : /////////////////////////////////////////////////////////////////////
142 : // class constructor specifying an other Inform instance
143 0 : Inform::Inform(const char* myname, const Inform& os, int pnode)
144 0 : : FormatBuf(std::ios::out)
145 0 : , MsgDest(os.MsgDest)
146 0 : , OpenedSuccessfully(true) {
147 : // just store a ref to the provided stream
148 0 : NeedClose = false;
149 :
150 : // perform all other needed initialization
151 0 : setup(myname, pnode);
152 0 : }
153 :
154 : /////////////////////////////////////////////////////////////////////
155 : // class destructor ... frees up space
156 2376 : Inform::~Inform(void) {
157 2376 : delete[] Name;
158 2376 : if (NeedClose)
159 0 : delete MsgDest;
160 2376 : }
161 :
162 : // print out just a single line, from the given buffer
163 0 : void Inform::display_single_line(char* buf) {
164 : // output the prefix name if necessary ... if no name was given, do
165 : // not print any prefix at all
166 0 : if (Name != 0) {
167 0 : *MsgDest << Name;
168 :
169 : // output the node number if necessary
170 0 : if (ippl::Comm->size() > 1)
171 0 : *MsgDest << "{" << ippl::Comm->rank() << "}";
172 :
173 : // output the message level number if necessary
174 0 : if (MsgLevel > 1)
175 0 : *MsgDest << "[" << MsgLevel << "]";
176 :
177 : // output the end of the prefix string if necessary
178 0 : if (Name != 0)
179 0 : *MsgDest << "> ";
180 : }
181 :
182 : // finally, print out the message itself
183 0 : *MsgDest << buf << std::endl;
184 0 : }
185 :
186 : /////////////////////////////////////////////////////////////////////
187 : // Print out the message in the given buffer.
188 0 : void Inform::display_message(char* buf) {
189 : // check if we should even print out the message
190 0 : if (On && MsgLevel <= OutputLevel && buf != 0) {
191 : // get location of final string term char
192 0 : char* stend = buf + strlen(buf);
193 :
194 : // print blank lines for leading endlines
195 0 : while (*buf == '\n') {
196 0 : *buf = '\0';
197 0 : display_single_line(buf++);
198 : }
199 :
200 : // print out all lines in the string now
201 0 : while ((buf = strtok(buf, "\n")) != 0) {
202 0 : display_single_line(buf);
203 0 : buf += strlen(buf);
204 0 : if (buf < stend)
205 0 : buf++;
206 :
207 : // print out contiguous blank lines, if any
208 0 : while (*buf == '\n') {
209 0 : *buf = '\0';
210 0 : display_single_line(buf++);
211 : }
212 : }
213 : }
214 0 : MsgLevel = MIN_INFORM_LEVEL;
215 0 : }
216 :
217 0 : void Inform::setDestination(std::ostream& dest) {
218 0 : if (NeedClose)
219 0 : delete MsgDest;
220 :
221 0 : MsgDest = &dest;
222 :
223 0 : NeedClose = false;
224 0 : }
225 :
226 : /////////////////////////////////////////////////////////////////////
227 : // Set the current output level for this Inform object.
228 2358 : Inform& Inform::setOutputLevel(const int ol) {
229 2358 : if (ol >= (MIN_INFORM_LEVEL - 1) && ol <= MAX_INFORM_LEVEL)
230 2358 : OutputLevel = ol;
231 2358 : return *this;
232 : }
233 :
234 : /////////////////////////////////////////////////////////////////////
235 : // Set the current message level for the current message in this Inform object.
236 0 : Inform& Inform::setMessageLevel(const int ol) {
237 0 : if (ol >= MIN_INFORM_LEVEL && ol <= MAX_INFORM_LEVEL)
238 0 : MsgLevel = ol;
239 0 : return *this;
240 : }
241 :
242 : /////////////////////////////////////////////////////////////////////
243 : // the signal has been given ... process the message. Return ref to object.
244 0 : Inform& Inform::outputMessage(void) {
245 : // print out the message (only if this is the master node)
246 0 : if (PrintNode < 0 || PrintNode == ippl::Comm->rank()) {
247 0 : FormatBuf << std::ends;
248 : // extract C string and display
249 0 : MsgBuf = FormatBuf.str();
250 0 : char* cstring = const_cast<char*>(MsgBuf.c_str());
251 0 : display_message(cstring);
252 : // clear buffer contents
253 : // MsgBuf = string("");
254 : // FormatBuf.str(MsgBuf);
255 : }
256 :
257 : // reset this ostrstream to the start
258 0 : FormatBuf.seekp(0, std::ios::beg);
259 0 : return *this;
260 : }
261 :
262 : /////////////////////////////////////////////////////////////////////
263 : // test program
264 :
265 : #ifdef DEBUG_INFORM_CLASS
266 :
267 : int main(int argc, char* argv[]) {
268 : int i;
269 :
270 : // create an Inform instance
271 : Inform inf("Inform Test");
272 :
273 : // copy in the argv's ... then print them out
274 : for (i = 0; i < argc; i++)
275 : inf << "Argument " << i << " = " << argv[i] << "\n";
276 : inf << endl << endl;
277 :
278 : // do another one to make sure
279 : inf.setOutputLevel(3);
280 : inf << level2 << "This is the second test." << endl;
281 :
282 : return 0;
283 : }
284 :
285 : #endif
286 :
287 : /***************************************************************************
288 : * $RCSfile: Inform.cpp,v $ $Author: adelmann $
289 : * $Revision: 1.1.1.1 $ $Date: 2003/01/23 07:40:33 $
290 : * IPPL_VERSION_ID: $Id: Inform.cpp,v 1.1.1.1 2003/01/23 07:40:33 adelmann Exp $
291 : ***************************************************************************/
|