00001
00016 #include "OSConfig.h"
00017 #include "OSErrorClass.h"
00018 #include "OSParameters.h"
00019 #include "OSOutput.h"
00020
00021 #include <string>
00022 #include <vector>
00023 #include <iostream>
00024 #include <sstream>
00025
00026 #ifdef HAVE_CSTDIO
00027 # include <cstdio>
00028 #else
00029 # ifdef HAVE_STDIO_H
00030 # include <stdio.h>
00031 # else
00032 # error "don't have header file for stdio"
00033 # endif
00034 #endif
00035
00036
00037
00038
00039 const OSSmartPtr< OSOutput> osoutput = new OSOutput();
00040
00041
00042 OSOutputChannel::OSOutputChannel(std::string name)
00043 {
00044 this->name = name;
00045 for (int i=0; i<ENUM_OUTPUT_AREA_NUMBER_OF_AREAS; i++)
00046 this->printLevel[i] = DEFAULT_OUTPUT_LEVEL;
00047 if (this->name != "stderr" && this->name != "stdout")
00048 {
00049 this->file = fopen (this->name.c_str(), "w+" );
00050 std::string temp = ("Could not open file " + this->name);
00051 if (this->file == NULL) throw ErrorClass(temp);
00052
00053 }
00054 }
00055
00056 OSOutputChannel::~OSOutputChannel()
00057 {
00058 }
00059
00060 std::string OSOutputChannel::Name()
00061 {
00062 return name;
00063 }
00064
00065 bool OSOutputChannel::setPrintLevel(ENUM_OUTPUT_AREA area, ENUM_OUTPUT_LEVEL level)
00066 {
00067 #ifdef NDEBUG
00068 if (level > ENUM_OUTPUT_LEVEL_debug)
00069 throw ErrorClass("Encountered print level not supported in production code.\n Recompile with debug enabled.");
00070 #endif
00071 printLevel[area] = level;
00072 return true;
00073 }
00074
00075 bool OSOutputChannel::setAllPrintLevels(ENUM_OUTPUT_LEVEL level)
00076 {
00077 #ifdef NDEBUG
00078 if (level > ENUM_OUTPUT_LEVEL_debug)
00079 throw ErrorClass("Encountered print level not supported in production code.\n Recompile with debug enabled.");
00080 #endif
00081 for (int i=0; i < ENUM_OUTPUT_AREA_NUMBER_OF_AREAS; i++)
00082 printLevel[i] = level;
00083 return true;
00084
00085 }
00086
00092 bool OSOutputChannel::setAllPrintLevels(ENUM_OUTPUT_LEVEL* level, int dim)
00093 {
00094 if (dim < 0)
00095 throw ErrorClass("Array of output levels must have nonnegative size.");
00096 int n = (dim < ENUM_OUTPUT_AREA_NUMBER_OF_AREAS ? dim : ENUM_OUTPUT_AREA_NUMBER_OF_AREAS);
00097 for (int i=0; i < n; i++)
00098 {
00099 #ifdef NDEBUG
00100 if (level[i] > ENUM_OUTPUT_LEVEL_debug)
00101 throw ErrorClass("Encountered print level not supported in production code.\n Recompile with debug enabled.");
00102 #endif
00103 printLevel[i] = level[i];
00104 }
00105 for (int i=n+1; i < ENUM_OUTPUT_AREA_NUMBER_OF_AREAS; i++)
00106 printLevel[i] = ENUM_OUTPUT_LEVEL_error;
00107 return true;
00108 }
00109
00110 bool OSOutputChannel::isAccepted(ENUM_OUTPUT_AREA area, ENUM_OUTPUT_LEVEL level)
00111 {
00112 return (level <= printLevel[area]);
00113 }
00114
00115 void OSOutputChannel::OSPrintf(ENUM_OUTPUT_AREA area, ENUM_OUTPUT_LEVEL level, std::string str)
00116 {
00117 if (isAccepted(area,level))
00118 {
00119 if (this->name == "stderr")
00120 fprintf(stderr, "%s\n", str.c_str());
00121 else if (this->name == "stdout")
00122 printf("%s\n", str.c_str());
00123 else
00124 if (this->file != NULL)
00125 fprintf(file, "%s\n", str.c_str());
00126 else
00127 throw ErrorClass("File not open for output");
00128 return;
00129 }
00130 }
00131
00132 void OSOutputChannel::flushBuffer()
00133 {
00134 if (file != NULL)
00135 fflush(file);
00136 else
00137 throw ErrorClass("File not open for output");
00138 return;
00139 }
00140
00141 bool OSOutputChannel::Open()
00142 {
00143 if (name == "stdout")
00144 {
00145 file = stdout;
00146 return true;
00147 }
00148 if (name == "stderr")
00149 {
00150 file = stderr;
00151 return true;
00152 }
00153 if (file != NULL)
00154 throw ErrorClass ("File previously opened.");
00155 file = fopen(name.c_str(), "w");
00156 if (file != NULL)
00157 return true;
00158 return false;
00159 }
00160
00161
00162 OSOutput::OSOutput()
00163 {
00164 std::string temp = "stdout";
00165 nOfOutputs = 1;
00166 outputChannel = new OSOutputChannel*[1];
00167 outputChannel[0] = new OSOutputChannel(temp);
00168 }
00169
00170 OSOutput::~OSOutput()
00171 {
00172 for (int i=0; i < nOfOutputs; i++)
00173 delete outputChannel[i];
00174 delete [] outputChannel;
00175 outputChannel = NULL;
00176 nOfOutputs = 0;
00177 }
00178
00179 bool OSOutput::OSPrint(ENUM_OUTPUT_AREA area, ENUM_OUTPUT_LEVEL level, std::string outStr)
00180 {
00181 for (int i=0; i < nOfOutputs; i++)
00182 {
00183 if (outputChannel[i]->isAccepted(area,level))
00184 outputChannel[i]->OSPrintf(area, level, outStr);
00185 }
00186 return true;
00187 }
00188
00189 void OSOutput::FlushAllBuffers()
00190 {
00191 for (int i=0; i < nOfOutputs; i++)
00192 outputChannel[i]->flushBuffer();
00193 }
00194
00195 bool OSOutput::SetPrintLevel(std::string name, ENUM_OUTPUT_LEVEL* level, int dim)
00196 {
00197 int k = FindChannel(name);
00198 if (k < 0)
00199 throw ErrorClass("Device was not defined before");
00200 for (int i=1; i<dim; i++)
00201 {
00202 if (level[i] < 0)
00203 throw ErrorClass("printLevel must be nonnegative");
00204 else if (level[i] >= ENUM_OUTPUT_LEVEL_NUMBER_OF_LEVELS)
00205 throw ErrorClass("illegal printLevel specified");
00206 }
00207 return (outputChannel[k]->setAllPrintLevels(level, dim));
00208 }
00209
00210 bool OSOutput::SetPrintLevel(std::string name, ENUM_OUTPUT_LEVEL level)
00211 {
00212 int aLevel, area;
00213 int k = FindChannel(name);
00214 if (k < 0)
00215 throw ErrorClass("Device was not defined before");
00216 if (level < 0)
00217 throw ErrorClass("printLevel must be nonnegative");
00218 if (level < 100)
00219 if (level >= ENUM_OUTPUT_LEVEL_NUMBER_OF_LEVELS)
00220 throw ErrorClass("illegal printLevel specified");
00221 else
00222 return (outputChannel[k]->setAllPrintLevels((ENUM_OUTPUT_LEVEL)level));
00223 else
00224 {
00225 aLevel = level % 100;
00226 area = (level / 100) - 1;
00227 if (aLevel >= ENUM_OUTPUT_LEVEL_NUMBER_OF_LEVELS || area >= ENUM_OUTPUT_AREA_NUMBER_OF_AREAS)
00228 throw ErrorClass("illegal printLevel specified");
00229 else
00230 return (outputChannel[k]->setPrintLevel((ENUM_OUTPUT_AREA)area,level));
00231 }
00232 }
00233
00234 int OSOutput::AddChannel(std::string name)
00235 {
00236 if (FindChannel(name) >= 0)
00237 {
00238 if (name == "stdout")
00239 return 0;
00240 else
00241 return 1;
00242 }
00243
00244 bool noMem = false;
00245
00246 try
00247 {
00248 int ndev;
00249 int i;
00250
00251 if (this->outputChannel == NULL)
00252 ndev = 0;
00253 else
00254 ndev = this->nOfOutputs;
00255
00256 noMem = true;
00257 OSOutputChannel** temp = new OSOutputChannel*[ndev+1];
00258 noMem = false;
00259 for (i = 0; i < ndev; i++)
00260 temp[i] = this->outputChannel[i];
00261
00262 delete[] this->outputChannel;
00263
00264
00265 noMem = true;
00266 temp[ndev] = new OSOutputChannel(name);
00267 noMem = false;
00268
00269 this->outputChannel = temp;
00270 this->nOfOutputs = ++ndev;
00271 return 0;
00272 }
00273 catch(const ErrorClass& eclass)
00274 {
00275 if (noMem)
00276 return 2;
00277 return 3;
00278 }
00279 }
00280
00281 bool OSOutput::DeleteChannel(std::string name)
00282 {
00283 int k = FindChannel(name);
00284 if (k < 0)
00285 return false;
00286 delete this->outputChannel[k];
00287
00288 int ndev = this->nOfOutputs;
00289 int i;
00290
00291 if (ndev == 1)
00292 {
00293 delete[] this->outputChannel;
00294 this->outputChannel = NULL;
00295 }
00296 else
00297 {
00298 OSOutputChannel** temp = new OSOutputChannel*[ndev-1];
00299 for (i = 0; i < k; i++)
00300 temp[i] = this->outputChannel[i];
00301 for (i = k+1; i < ndev; i++)
00302 temp[i] = this->outputChannel[i+1];
00303
00304 delete[] this->outputChannel;
00305
00306 this->outputChannel = temp;
00307 }
00308
00309 this->nOfOutputs = ++ndev;
00310 return true;
00311 }
00312
00313 int OSOutput::FindChannel(std::string name)
00314 {
00315 for (int i=0; i < nOfOutputs; i++)
00316 if (outputChannel[i]->Name() == name) return i;
00317 return -1;
00318 }
00319