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