OSOutput.cpp
Go to the documentation of this file.
1 /* $Id: OSOutput.cpp 3172 2012-11-12 04:59:24Z Gassmann $ */
16 #include "OSConfig.h"
17 #include "OSErrorClass.h"
18 #include "OSParameters.h"
19 #include "OSOutput.h"
20 
21 #include <string>
22 #include <vector>
23 #include <iostream>
24 #include <sstream>
25 
26 #ifdef HAVE_CSTDIO
27 # include <cstdio>
28 #else
29 # ifdef HAVE_STDIO_H
30 # include <stdio.h>
31 # else
32 # error "don't have header file for stdio"
33 # endif
34 #endif
35 
36 
37 // define the osoutput instance that takes care of all output (see ticket 14)
38 // It is declared here as a global variable so as to minimize the changes to the API
39 const OSSmartPtr</*const*/ OSOutput> osoutput = new OSOutput();
40 
41 
43 {
44  this->name = name;
45  for (int i=0; i<ENUM_OUTPUT_AREA_NUMBER_OF_AREAS; i++)
46  this->printLevel[i] = DEFAULT_OUTPUT_LEVEL;
47  if (this->name != "stderr" && this->name != "stdout")
48  {
49  this->file = fopen (this->name.c_str(), "w+" );
50  std::string temp = ("Could not open file " + this->name);
51  if (this->file == NULL) throw ErrorClass(temp);
52  }
53 }
54 
56 {
57 }
58 
59 std::string OSOutputChannel::Name()
60 {
61  return name;
62 }
63 
65 {
66 #ifdef NDEBUG
67  if (level > ENUM_OUTPUT_LEVEL_debug)
68  throw ErrorClass("Encountered print level not supported in production code.\n Recompile with debug enabled.");
69 #endif
70  printLevel[area] = level;
71  return true;
72 }
73 
75 {
76 #ifdef NDEBUG
77  if (level > ENUM_OUTPUT_LEVEL_debug)
78  throw ErrorClass("Encountered print level not supported in production code.\n Recompile with debug enabled.");
79 #endif
80  for (int i=0; i < ENUM_OUTPUT_AREA_NUMBER_OF_AREAS; i++)
81  printLevel[i] = level;
82  return true;
83 
84 }
85 
92 {
93  if (dim < 0)
94  throw ErrorClass("Array of output levels must have nonnegative size.");
96  for (int i=0; i < n; i++)
97  {
98 #ifdef NDEBUG
99  if (level[i] > ENUM_OUTPUT_LEVEL_debug)
100  throw ErrorClass("Encountered print level not supported in production code.\n Recompile with debug enabled.");
101 #endif
102  printLevel[i] = level[i];
103  }
104  for (int i=n+1; i < ENUM_OUTPUT_AREA_NUMBER_OF_AREAS; i++)
106  return true;
107  }
108 
110 {
111  return (level <= printLevel[area]);
112 }
113 
115 {
116  if (isAccepted(area,level))
117  {
118  if (this->name == "stderr")
119  fprintf(stderr, "%s\n", str.c_str());
120  else if (this->name == "stdout")
121  printf("%s\n", str.c_str());
122  else
123  if (this->file != NULL)
124  fprintf(file, "%s\n", str.c_str());
125  else
126  throw ErrorClass("File not open for output");
127  return;
128  }
129 }
130 
132 {
133  if (file != NULL)
134  fflush(file);
135  else
136  throw ErrorClass("File not open for output");
137  return;
138 }
139 
141 {
142  if (name == "stdout")
143  {
144  file = stdout;
145  return true;
146  }
147  if (name == "stderr")
148  {
149  file = stderr;
150  return true;
151  }
152  if (file != NULL)
153  throw ErrorClass ("File previously opened.");
154  file = fopen(name.c_str(), "w");
155  if (file != NULL)
156  return true;
157  return false;
158 }
159 
160 
162 {
163  std::string temp = "stdout";
164  nOfOutputs = 1;
165  outputChannel = new OSOutputChannel*[1];
166  outputChannel[0] = new OSOutputChannel(temp);
167 }
168 
170 {
171  for (int i=0; i < nOfOutputs; i++)
172  delete outputChannel[i];
173  delete [] outputChannel;
174  outputChannel = NULL;
175  nOfOutputs = 0;
176 }
177 
178 bool OSOutput::OSPrint(ENUM_OUTPUT_AREA area, ENUM_OUTPUT_LEVEL level, std::string outStr)
179 {
180  for (int i=0; i < nOfOutputs; i++)
181  {
182  if (outputChannel[i]->isAccepted(area,level))
183  outputChannel[i]->OSPrintf(area, level, outStr);
184  }
185  return true;
186 }
187 
189 {
190  for (int i=0; i < nOfOutputs; i++)
191  outputChannel[i]->flushBuffer();
192 }
193 
194 bool OSOutput::SetPrintLevel(std::string name, ENUM_OUTPUT_LEVEL* level, int dim)
195 {
196  int k = FindChannel(name);
197  if (k < 0)
198  throw ErrorClass("Device was not defined before");
199  for (int i=1; i<dim; i++)
200  {
201  if (level[i] < 0)
202  throw ErrorClass("printLevel must be nonnegative");
203  else if (level[i] >= ENUM_OUTPUT_LEVEL_NUMBER_OF_LEVELS)
204  throw ErrorClass("illegal printLevel specified");
205  }
206  return (outputChannel[k]->setAllPrintLevels(level, dim));
207 }
208 
209 bool OSOutput::SetPrintLevel(std::string name, ENUM_OUTPUT_LEVEL level)
210 {
211  int aLevel, area;
212  int k = FindChannel(name);
213  if (k < 0)
214  throw ErrorClass("Device was not defined before");
215  if (level < 0)
216  throw ErrorClass("printLevel must be nonnegative");
217  if (level < 100)
219  throw ErrorClass("illegal printLevel specified");
220  else
221  return (outputChannel[k]->setAllPrintLevels((ENUM_OUTPUT_LEVEL)level));
222  else
223  {
224  aLevel = level % 100;
225  area = level / 100;
227  throw ErrorClass("illegal printLevel specified");
228  else
229  return (outputChannel[k]->setPrintLevel((ENUM_OUTPUT_AREA)area, (ENUM_OUTPUT_LEVEL)aLevel));
230  }
231 }
232 
233 int OSOutput::AddChannel(std::string name)
234 {
235  if (FindChannel(name) >= 0)
236  {
237  if (name == "stdout")
238  return 0;
239  else
240  return 1;
241  }
242 
243  bool noMem = false;
244 
245  try
246  {
247  int ndev;
248  int i;
249 
250  if (this->outputChannel == NULL)
251  ndev = 0;
252  else
253  ndev = this->nOfOutputs;
254 
255  noMem = true;
256  OSOutputChannel** temp = new OSOutputChannel*[ndev+1]; //Allocate the new pointers
257  noMem = false;
258  for (i = 0; i < ndev; i++)
259  temp[i] = this->outputChannel[i]; //copy the pointers
260 
261  delete[] this->outputChannel; //delete old pointers
262 
263 // add in the new element
264  noMem = true;
265  temp[ndev] = new OSOutputChannel(name);
266  noMem = false;
267 
268  this->outputChannel = temp; //hook the new pointers into the data structure
269  this->nOfOutputs = ++ndev;
270  return 0;
271  }
272  catch(const ErrorClass& eclass)
273  {
274  if (noMem)
275  return 2;
276  return 3;
277  }
278 }// AddChannel
279 
280 bool OSOutput::DeleteChannel(std::string name)
281 {
282  int k = FindChannel(name);
283  if (k < 0)
284  return false;
285  delete this->outputChannel[k];
286 
287  int ndev = this->nOfOutputs;
288  int i;
289 
290  if (ndev == 1)
291  {
292  delete[] this->outputChannel;
293  this->outputChannel = NULL;
294  }
295  else
296  {
297  OSOutputChannel** temp = new OSOutputChannel*[ndev-1]; //Allocate the new pointers
298  for (i = 0; i < k; i++)
299  temp[i] = this->outputChannel[i]; //copy the pointers
300  for (i = k+1; i < ndev; i++)
301  temp[i] = this->outputChannel[i+1]; //skip the deleted channel
302 
303  delete[] this->outputChannel; //delete old pointers
304 
305  this->outputChannel = temp; //hook the new pointers into the data structure
306  }
307 
308  this->nOfOutputs = ++ndev;
309  return true;
310 }// DeleteChannel
311 
312 int OSOutput::FindChannel(std::string name)
313 {
314  for (int i=0; i < nOfOutputs; i++)
315  if (outputChannel[i]->Name() == name) return i;
316  return -1;
317 }
318 
#define DEFAULT_OUTPUT_LEVEL
Definition: OSParameters.h:121
OSOutputChannel(std::string name)
Constructor.
Definition: OSOutput.cpp:42
const OSSmartPtr< OSOutput > osoutput
Definition: OSOutput.cpp:39
bool setAllPrintLevels(ENUM_OUTPUT_LEVEL level)
Set the print level for all areas.
Definition: OSOutput.cpp:74
int AddChannel(std::string name)
Add a channel to the array outputChannel.
Definition: OSOutput.cpp:233
bool OSPrint(ENUM_OUTPUT_AREA area, ENUM_OUTPUT_LEVEL level, std::string outStr)
This is the main method to output a string All output generated by the program should ultimately use ...
Definition: OSOutput.cpp:178
int printLevel[ENUM_OUTPUT_AREA_NUMBER_OF_AREAS]
vector of integers indicating the level for each area
Definition: OSOutput.h:57
OSOutput()
Constructor.
Definition: OSOutput.cpp:161
void flushBuffer()
Flush output buffer.
Definition: OSOutput.cpp:131
Template class for Smart Pointers.
Definition: OSSmartPtr.hpp:156
This class handles all the output from OSSolverService, OSAmplClient and other executables derived fr...
Definition: OSOutput.h:146
a class that holds information about one output channel (file, device, stream, peripheral, etc.)
Definition: OSOutput.h:41
void OSPrintf(ENUM_OUTPUT_AREA area, ENUM_OUTPUT_LEVEL level, std::string str)
Send one string to the output device provided that the output device &quot;accepts&quot; the output (i...
Definition: OSOutput.cpp:114
~OSOutputChannel()
Destructor.
Definition: OSOutput.cpp:55
ENUM_OUTPUT_LEVEL
Enumeration for the different verbosity levels that can be used in producing output.
Definition: OSParameters.h:107
void fint fint * k
bool DeleteChannel(std::string name)
Delete a channel from the array outputChannel.
Definition: OSOutput.cpp:280
FILE * file
holds a pointer to the file or device
Definition: OSOutput.h:52
OSOutputChannel ** outputChannel
The array of output channels currently in use.
Definition: OSOutput.h:228
void FlushAllBuffers()
Flush all buffers.
Definition: OSOutput.cpp:188
ENUM_OUTPUT_AREA
Enumeration for the different areas that can produce output.
Definition: OSParameters.h:128
bool isAccepted(ENUM_OUTPUT_AREA area, ENUM_OUTPUT_LEVEL level)
Test if the device accepts a particular combination of print level and area (i.e., if the output should be printed)
Definition: OSOutput.cpp:109
std::string Name()
Get the name of the output channel.
Definition: OSOutput.cpp:59
int FindChannel(std::string name)
Find the position of a channel within the array *outputChannel.
Definition: OSOutput.cpp:312
~OSOutput()
Destructor.
Definition: OSOutput.cpp:169
bool setPrintLevel(ENUM_OUTPUT_AREA area, ENUM_OUTPUT_LEVEL level)
Set the print level for a particular area.
Definition: OSOutput.cpp:64
used for throwing exceptions.
Definition: OSErrorClass.h:31
void fint * n
bool SetPrintLevel(std::string name, ENUM_OUTPUT_LEVEL *level, int dim)
Modify all print levels associated with a channel.
Definition: OSOutput.cpp:194
int nOfOutputs
The number of output channels that have been defined.
Definition: OSOutput.h:223
std::string name
used to give a name to the file or device
Definition: OSOutput.h:47