00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00034 #include "ColumnDataWriter.hpp"
00035 #include "ColumnDataConstants.hpp"
00036 #include "Exception.hpp"
00037
00038 #include <ctype.h>
00039 #include <sstream>
00040 #include <iomanip>
00041 #include <fstream>
00042
00043
00044
00045 ColumnDataWriter::ColumnDataWriter(const std::string& rDirectory,
00046 const std::string& rBaseName,
00047 bool cleanDirectory)
00048 : mOutputFileHandler(rDirectory, cleanDirectory),
00049 mDirectory(rDirectory),
00050 mBaseName(rBaseName),
00051 mIsInDefineMode(true),
00052 mIsFixedDimensionSet(false),
00053 mIsUnlimitedDimensionSet(false),
00054 mUnlimitedDimensionPosition(0),
00055 mFixedDimensionSize(-1),
00056 mpCurrentOutputFile(NULL),
00057 mpCurrentAncillaryFile(NULL),
00058 mpUnlimitedDimensionVariable(NULL),
00059 mpFixedDimensionVariable(NULL),
00060 mHasPutVariable(false),
00061 mNeedAdvanceAlongUnlimitedDimension(false)
00062 {
00063 }
00064
00065 ColumnDataWriter::~ColumnDataWriter()
00066 {
00067
00068 Close();
00069
00070
00071 if (mpUnlimitedDimensionVariable != NULL)
00072 {
00073 delete mpUnlimitedDimensionVariable;
00074 }
00075 if (mpFixedDimensionVariable != NULL)
00076 {
00077 delete mpFixedDimensionVariable;
00078 }
00079 }
00080
00081 std::string ColumnDataWriter::GetOutputDirectory()
00082 {
00083 return mOutputFileHandler.GetOutputDirectoryFullPath();
00084 }
00085
00086 void ColumnDataWriter::Close()
00087 {
00088 if (mpCurrentOutputFile.get() != NULL)
00089 {
00090 mpCurrentOutputFile->close();
00091 mpCurrentOutputFile = out_stream(NULL);
00092 }
00093
00094 if (mpCurrentAncillaryFile.get() != NULL)
00095 {
00096 mpCurrentAncillaryFile->close();
00097 mpCurrentAncillaryFile = out_stream(NULL);
00098 }
00099 }
00100
00101 void ColumnDataWriter::CheckVariableName(const std::string& rName)
00102 {
00103 if (rName.length() == 0)
00104 {
00105 EXCEPTION("Variable name not allowed: may not be blank.");
00106 }
00107 CheckUnitsName(rName);
00108 }
00109
00110 void ColumnDataWriter::CheckUnitsName(const std::string& rName)
00111 {
00112 for (unsigned i=0; i<rName.length(); i++)
00113 {
00114 if (!isalnum(rName[i]) && !(rName[i]=='_'))
00115 {
00116 std::string error = "Variable name/units '" + rName + "' not allowed: may only contain alphanumeric characters or '_'.";
00117 EXCEPTION(error);
00118 }
00119 }
00120 }
00121
00122 int ColumnDataWriter::DefineUnlimitedDimension(const std::string& rDimensionName,
00123 const std::string& rDimensionUnits)
00124 {
00125 if (mIsUnlimitedDimensionSet)
00126 {
00127 EXCEPTION("Unlimited dimension already set. Cannot be defined twice");
00128 }
00129
00130 if (!mIsInDefineMode)
00131 {
00132 EXCEPTION("Cannot define variables when not in Define mode");
00133 }
00134
00135 CheckVariableName(rDimensionName);
00136 CheckUnitsName(rDimensionUnits);
00137
00138 mUnlimitedDimensionName = rDimensionName;
00139 mUnlimitedDimensionUnits = rDimensionUnits;
00140
00141 mpUnlimitedDimensionVariable = new DataWriterVariable;
00142 mpUnlimitedDimensionVariable->mVariableName = rDimensionName;
00143 mpUnlimitedDimensionVariable->mVariableUnits = rDimensionUnits;
00144
00145 mIsUnlimitedDimensionSet = true;
00146
00147 return UNLIMITED_DIMENSION_VAR_ID;
00148 }
00149
00150 int ColumnDataWriter::DefineFixedDimension(const std::string& rDimensionName,
00151 const std::string& rDimensionUnits,
00152 long dimensionSize)
00153 {
00154 if (!mIsInDefineMode)
00155 {
00156 EXCEPTION("Cannot define variables when not in Define mode");
00157 }
00158 if (dimensionSize < 1)
00159 {
00160 EXCEPTION("Fixed dimension must be at least 1 long");
00161 }
00162
00163 CheckVariableName(rDimensionName);
00164 CheckUnitsName(rDimensionUnits);
00165
00166 mFixedDimensionName = rDimensionName;
00167 mFixedDimensionUnits = rDimensionUnits;
00168 mFixedDimensionSize = dimensionSize;
00169
00170 mIsFixedDimensionSet = true;
00171
00172 mpFixedDimensionVariable = new DataWriterVariable;
00173 mpFixedDimensionVariable->mVariableName = rDimensionName;
00174 mpFixedDimensionVariable->mVariableUnits = rDimensionUnits;
00175 return FIXED_DIMENSION_VAR_ID;
00176 }
00177
00178 int ColumnDataWriter::DefineVariable(const std::string& rVariableName,
00179 const std::string& rVariableUnits)
00180 {
00181 if (!mIsInDefineMode)
00182 {
00183 EXCEPTION("Cannot define variables when not in Define mode");
00184 }
00185
00186 CheckVariableName(rVariableName);
00187 CheckUnitsName(rVariableUnits);
00188
00189 int variable_id;
00190
00191 if (rVariableName == mUnlimitedDimensionName)
00192 {
00193 EXCEPTION("Variable name: " + rVariableName + " already in use as unlimited dimension");
00194 }
00195 else if (rVariableName == mFixedDimensionName)
00196 {
00197 EXCEPTION("Variable name: " + rVariableName + " already in use as fixed dimension");
00198 }
00199 else
00200 {
00201
00202 DataWriterVariable new_variable;
00203 new_variable.mVariableName = rVariableName;
00204 new_variable.mVariableUnits = rVariableUnits;
00205 mVariables.push_back(new_variable);
00206
00207
00208
00209 variable_id = mVariables.size()-1;
00210 }
00211
00212 return variable_id;
00213 }
00214
00215 void ColumnDataWriter::EndDefineMode()
00216 {
00217
00218 if (mIsFixedDimensionSet == false && mIsUnlimitedDimensionSet == false)
00219 {
00220 EXCEPTION("Cannot end define mode. No dimensions have been defined.");
00221 }
00222
00223 if (mVariables.size() < 1)
00224 {
00225 EXCEPTION("Cannot end define mode. No variables have been defined.");
00226 }
00227
00228 int unlimited_dimension_variable = (mpUnlimitedDimensionVariable != NULL);
00229 int fixed_dimension_variable = (mpFixedDimensionVariable != NULL);
00230 if (mIsUnlimitedDimensionSet)
00231 {
00232 if (mIsFixedDimensionSet)
00233 {
00234 mRowWidth = (mVariables.size() + fixed_dimension_variable) * (FIELD_WIDTH + SPACING);
00235 mAncillaryRowWidth = FIELD_WIDTH + SPACING;
00236
00237
00238 std::stringstream suffix;
00239 suffix << std::setfill('0') << std::setw(FILE_SUFFIX_WIDTH) << mUnlimitedDimensionPosition;
00240
00241 if (mpUnlimitedDimensionVariable != NULL)
00242 {
00243 std::string ancillary_filename = mBaseName + "_unlimited.dat";
00244 mpCurrentAncillaryFile = mOutputFileHandler.OpenOutputFile(ancillary_filename, std::ios::out);
00245 (*mpCurrentAncillaryFile) << std::setiosflags(std::ios::scientific);
00246 (*mpCurrentAncillaryFile) << std::setprecision(FIELD_WIDTH-6);
00247 if (mpUnlimitedDimensionVariable != NULL)
00248 {
00249 (*mpCurrentAncillaryFile) << mpUnlimitedDimensionVariable->mVariableName
00250 << "(" << mpUnlimitedDimensionVariable->mVariableUnits << ") ";
00251 }
00252 }
00253 mAncillaryRowStartPosition = mpCurrentAncillaryFile->tellp();
00254 std::string filename = mBaseName + "_" + suffix.str() + ".dat";
00255 this->CreateFixedDimensionFile(filename);
00256 }
00257 else
00258 {
00259 mRowWidth = (mVariables.size() + unlimited_dimension_variable) * (FIELD_WIDTH + SPACING);
00260
00261
00262 std::string filename = mBaseName + ".dat";
00263 mpCurrentOutputFile = mOutputFileHandler.OpenOutputFile(filename, std::ios::out);
00264 (*mpCurrentOutputFile) << std::setiosflags(std::ios::scientific);
00265 (*mpCurrentOutputFile) << std::setprecision(FIELD_WIDTH-6);
00266 if (mpUnlimitedDimensionVariable != NULL)
00267 {
00268 (*mpCurrentOutputFile) << mpUnlimitedDimensionVariable->mVariableName
00269 << "(" << mpUnlimitedDimensionVariable->mVariableUnits << ") ";
00270 }
00271
00272
00273
00274 for (unsigned i=0; i<mVariables.size(); i++)
00275 {
00276 (*mpCurrentOutputFile) << mVariables[i].mVariableName << "(" << mVariables[i].mVariableUnits << ")";
00277 if (i < mVariables.size()-1)
00278 {
00279 (*mpCurrentOutputFile) << " ";
00280 }
00281 }
00282 (*mpCurrentOutputFile) << std::endl;
00283 mRowStartPosition = mpCurrentOutputFile->tellp();
00284
00285
00286 std::string blank_line(mRowWidth, ' ');
00287 (*mpCurrentOutputFile) << blank_line;
00288 }
00289 }
00290 else
00291 {
00292
00293 mRowWidth = (mVariables.size() + fixed_dimension_variable) * (FIELD_WIDTH + SPACING);
00294 std::string filename = mBaseName + ".dat";
00295 this->CreateFixedDimensionFile(filename);
00296 }
00297
00298
00299 std::string infoname = mBaseName + ".info";
00300 this->CreateInfoFile(infoname);
00301
00302 mIsInDefineMode = false;
00303 }
00304
00305 void ColumnDataWriter::CreateFixedDimensionFile(const std::string& rFileName)
00306 {
00307
00308 mpCurrentOutputFile = mOutputFileHandler.OpenOutputFile(rFileName, std::ios::out);
00309 (*mpCurrentOutputFile) << std::setiosflags(std::ios::scientific);
00310 (*mpCurrentOutputFile) << std::setprecision(FIELD_WIDTH-6);
00311 if (mpFixedDimensionVariable != NULL)
00312 {
00313 (*mpCurrentOutputFile) << mpFixedDimensionVariable->mVariableName
00314 << "(" << mpFixedDimensionVariable->mVariableUnits << ") ";
00315 }
00316
00317 for (unsigned i = 0; i < mVariables.size(); i++)
00318 {
00319 (*mpCurrentOutputFile) << mVariables[i].mVariableName << "(" << mVariables[i].mVariableUnits << ")";
00320 if (i < mVariables.size()-1)
00321 {
00322 (*mpCurrentOutputFile) << " ";
00323 }
00324 }
00325 (*mpCurrentOutputFile) << std::endl;
00326 mRowStartPosition = mpCurrentOutputFile->tellp();
00327 std::string blank_line(mRowWidth,' ');
00328 for (int i = 0; i < mFixedDimensionSize; i++)
00329 {
00330 (*mpCurrentOutputFile) << blank_line << std::endl;
00331 }
00332 }
00333
00334 void ColumnDataWriter::CreateInfoFile(const std::string& rFileName)
00335 {
00336
00337 out_stream p_info_file = mOutputFileHandler.OpenOutputFile(rFileName, std::ios::out);
00338 (*p_info_file) << "FIXED " << mFixedDimensionSize << std::endl;
00339 (*p_info_file) << "UNLIMITED " << mIsUnlimitedDimensionSet << std::endl;
00340 (*p_info_file) << "VARIABLES " << mVariables.size() << std::endl;
00341 p_info_file->close();
00342 }
00343
00344 void ColumnDataWriter::DoAdvanceAlongUnlimitedDimension()
00345 {
00346 mHasPutVariable = false;
00347 mNeedAdvanceAlongUnlimitedDimension = false;
00348
00349 if (mIsUnlimitedDimensionSet)
00350 {
00351 if (mIsFixedDimensionSet)
00352 {
00353
00354 mpCurrentOutputFile->close();
00355 std::stringstream suffix;
00356 suffix << std::setfill('0') << std::setw(FILE_SUFFIX_WIDTH) << mUnlimitedDimensionPosition + 1;
00357
00358
00359
00360
00361
00362
00363
00364 std::string filename = mBaseName + "_" + suffix.str() + ".dat";
00365 this->CreateFixedDimensionFile(filename);
00366 }
00367 else
00368 {
00369
00370 mpCurrentOutputFile->seekp(mRowStartPosition+mRowWidth);
00371 (*mpCurrentOutputFile) << std::endl;
00372 mRowStartPosition = mpCurrentOutputFile->tellp();
00373 std::string blank_line(mRowWidth,' ');
00374 (*mpCurrentOutputFile) << blank_line;
00375 }
00376 }
00377 else
00378 {
00379 EXCEPTION("Cannot advance along unlimited dimension if it is not defined");
00380 }
00381 mUnlimitedDimensionPosition++;
00382 }
00383
00384 void ColumnDataWriter::AdvanceAlongUnlimitedDimension()
00385 {
00386 if (mHasPutVariable)
00387 {
00388 mNeedAdvanceAlongUnlimitedDimension = true;
00389 }
00390 }
00391
00392 void ColumnDataWriter::PutVariable(int variableID, double variableValue, long dimensionPosition)
00393 {
00394 if (mNeedAdvanceAlongUnlimitedDimension)
00395 {
00396 DoAdvanceAlongUnlimitedDimension();
00397 }
00398
00399
00400 if (mIsInDefineMode)
00401 {
00402 EXCEPTION("Cannot put variables when in Define mode");
00403 }
00404
00405 if (variableID > (int)mVariables.size() ||
00406 (variableID != UNLIMITED_DIMENSION_VAR_ID &&
00407 variableID != FIXED_DIMENSION_VAR_ID &&
00408 variableID < 0))
00409 {
00410 EXCEPTION("variableID unknown");
00411 }
00412
00413 if (mIsFixedDimensionSet)
00414 {
00415 if (dimensionPosition == -1 && variableID != UNLIMITED_DIMENSION_VAR_ID)
00416 {
00417 EXCEPTION("Dimension position not supplied");
00418 }
00419 if (dimensionPosition < -1 || dimensionPosition >= mFixedDimensionSize)
00420 {
00421 EXCEPTION("Dimension position out of range");
00422 }
00423 if (dimensionPosition != -1 && variableID == UNLIMITED_DIMENSION_VAR_ID)
00424 {
00425 EXCEPTION("Dimension position supplied, but not required");
00426 }
00427 }
00428
00429 if (mIsUnlimitedDimensionSet)
00430 {
00431 if (mIsFixedDimensionSet)
00432 {
00433
00434 if (variableID == UNLIMITED_DIMENSION_VAR_ID)
00435 {
00436
00437 if (variableValue >= 0)
00438 {
00439 (*mpCurrentAncillaryFile) << std::endl << " ";
00440 }
00441 else
00442 {
00443 (*mpCurrentAncillaryFile) << std::endl << " ";
00444 }
00445 mpCurrentAncillaryFile->width(FIELD_WIDTH);
00446 (*mpCurrentAncillaryFile) << variableValue;
00447 }
00448 else
00449 {
00450 int position;
00451 if (variableID == FIXED_DIMENSION_VAR_ID)
00452 {
00453 position = mRowStartPosition + (mRowWidth+1) * dimensionPosition + SPACING;
00454 }
00455 else
00456 {
00457
00458 position = mRowStartPosition + (mRowWidth+1) * dimensionPosition +
00459 ((variableID + (mpFixedDimensionVariable != NULL))* (FIELD_WIDTH + SPACING)) + SPACING;
00460 }
00461
00462 if (variableValue >= 0)
00463 {
00464 mpCurrentOutputFile->seekp(position);
00465 mpCurrentOutputFile->width(FIELD_WIDTH);
00466 }
00467 else
00468 {
00469 mpCurrentOutputFile->seekp(position-1);
00470 mpCurrentOutputFile->width(FIELD_WIDTH);
00471 }
00472 (*mpCurrentOutputFile) << variableValue;
00473 }
00474 }
00475 else
00476 {
00477
00478 int position;
00479 if (variableID == UNLIMITED_DIMENSION_VAR_ID)
00480 {
00481 position = mRowStartPosition + SPACING;
00482 }
00483 else
00484 {
00485 position = (variableID + (mpUnlimitedDimensionVariable != NULL)) * (FIELD_WIDTH + SPACING) + mRowStartPosition + SPACING;
00486 }
00487
00488 if (variableValue >= 0)
00489 {
00490 mpCurrentOutputFile->seekp(position);
00491 mpCurrentOutputFile->width(FIELD_WIDTH);
00492 }
00493 else
00494 {
00495 mpCurrentOutputFile->seekp(position-1);
00496 mpCurrentOutputFile->width(FIELD_WIDTH);
00497 }
00498 (*mpCurrentOutputFile) << variableValue;
00499 }
00500 }
00501 else
00502 {
00503
00504 int position;
00505 if (variableID == FIXED_DIMENSION_VAR_ID)
00506 {
00507 position = mRowStartPosition + (mRowWidth+1) * dimensionPosition + SPACING;
00508 }
00509 else
00510 {
00511 position = mRowStartPosition + (mRowWidth+1) * dimensionPosition +
00512 ((variableID + (mpFixedDimensionVariable != NULL))* (FIELD_WIDTH + SPACING)) + SPACING;
00513 }
00514 if (variableValue >= 0)
00515 {
00516 mpCurrentOutputFile->seekp(position);
00517 mpCurrentOutputFile->width(FIELD_WIDTH);
00518 }
00519 else
00520 {
00521 mpCurrentOutputFile->seekp(position-1);
00522 mpCurrentOutputFile->width(FIELD_WIDTH);
00523 }
00524
00525 (*mpCurrentOutputFile) << variableValue;
00526 }
00527
00528 mHasPutVariable = true;
00529 }