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
00033 #include "ColumnDataWriter.hpp"
00034
00035
00036 using std::string;
00042 ColumnDataWriter::ColumnDataWriter(string directory, string baseName, bool cleanDirectory) :
00043 mOutputFileHandler(directory, cleanDirectory),
00044 mDirectory(directory),
00045 mBaseName(baseName),
00046 mIsInDefineMode(true),
00047 mIsFixedDimensionSet(false),
00048 mIsUnlimitedDimensionSet(false),
00049 mUnlimitedDimensionPosition(0),
00050 mFixedDimensionSize(-1),
00051 mpCurrentOutputFile(NULL),
00052 mpCurrentAncillaryFile(NULL),
00053 mpUnlimitedDimensionVariable(NULL),
00054 mpFixedDimensionVariable(NULL),
00055 mHasPutVariable(false),
00056 mNeedAdvanceAlongUnlimitedDimension(false)
00057 {}
00062 ColumnDataWriter::~ColumnDataWriter()
00063 {
00064
00065 Close();
00066
00067
00068 if (mpUnlimitedDimensionVariable != NULL)
00069 {
00070 delete mpUnlimitedDimensionVariable;
00071 }
00072 if (mpFixedDimensionVariable != NULL)
00073 {
00074 delete mpFixedDimensionVariable;
00075 }
00076 }
00077
00081 std::string ColumnDataWriter::GetOutputDirectory(void)
00082 {
00083 return mOutputFileHandler.GetOutputDirectoryFullPath();
00084 }
00085
00089 void ColumnDataWriter::Close()
00090 {
00091 if (mpCurrentOutputFile.get() != NULL)
00092 {
00093 mpCurrentOutputFile->close();
00094 mpCurrentOutputFile = out_stream(NULL);
00095 }
00096
00097 if (mpCurrentAncillaryFile.get() != NULL)
00098 {
00099 mpCurrentAncillaryFile->close();
00100 mpCurrentAncillaryFile = out_stream(NULL);
00101 }
00102 }
00103
00104
00105 void ColumnDataWriter::CheckVariableName(std::string name)
00106 {
00107 if (name.length() == 0)
00108 {
00109 EXCEPTION("Variable name not allowed: may not be blank.");
00110 }
00111 CheckUnitsName(name);
00112 }
00113
00114 void ColumnDataWriter::CheckUnitsName(std::string name)
00115 {
00116 for (unsigned i=0; i<name.length(); i++)
00117 {
00118 if (!isalnum(name[i]) && !(name[i]=='_'))
00119 {
00120 std::string error = "Variable name/units '" + name + "' not allowed: may only contain alphanumeric characters or '_'.";
00121 EXCEPTION(error);
00122 }
00123 }
00124 }
00125
00134 int ColumnDataWriter::DefineUnlimitedDimension(string dimensionName, string dimensionUnits)
00135 {
00136 if (mIsUnlimitedDimensionSet)
00137 {
00138 EXCEPTION("Unlimited dimension already set. Cannot be defined twice");
00139 }
00140
00141 if (!mIsInDefineMode)
00142 {
00143 EXCEPTION("Cannot define variables when not in Define mode");
00144 }
00145
00146 CheckVariableName(dimensionName);
00147 CheckUnitsName(dimensionUnits);
00148
00149 mUnlimitedDimensionName = dimensionName;
00150 mUnlimitedDimensionUnits = dimensionUnits;
00151
00152 mpUnlimitedDimensionVariable = new DataWriterVariable;
00153 mpUnlimitedDimensionVariable->mVariableName = dimensionName;
00154 mpUnlimitedDimensionVariable->mVariableUnits = dimensionUnits;
00155
00156 mIsUnlimitedDimensionSet = true;
00157
00158 return UNLIMITED_DIMENSION_VAR_ID;
00159 }
00160
00170 int ColumnDataWriter::DefineFixedDimension(string dimensionName, string dimensionUnits, long dimensionSize)
00171 {
00172 if (!mIsInDefineMode)
00173 {
00174 EXCEPTION("Cannot define variables when not in Define mode");
00175 }
00176 if (dimensionSize < 1)
00177 {
00178 EXCEPTION("Fixed dimension must be at least 1 long");
00179 }
00180
00181 CheckVariableName(dimensionName);
00182 CheckUnitsName(dimensionUnits);
00183
00184 mFixedDimensionName = dimensionName;
00185 mFixedDimensionUnits = dimensionUnits;
00186 mFixedDimensionSize = dimensionSize;
00187
00188 mIsFixedDimensionSet = true;
00189
00190 mpFixedDimensionVariable = new DataWriterVariable;
00191 mpFixedDimensionVariable->mVariableName = dimensionName;
00192 mpFixedDimensionVariable->mVariableUnits = dimensionUnits;
00193 return FIXED_DIMENSION_VAR_ID;
00194 }
00195
00206 int ColumnDataWriter::DefineVariable(string variableName, string variableUnits)
00207 {
00208 if (!mIsInDefineMode)
00209 {
00210 EXCEPTION("Cannot define variables when not in Define mode");
00211 }
00212
00213 CheckVariableName(variableName);
00214 CheckUnitsName(variableUnits);
00215
00216 DataWriterVariable new_variable;
00217 new_variable.mVariableName = variableName;
00218 new_variable.mVariableUnits = variableUnits;
00219 int variable_id;
00220
00221 if (variableName == mUnlimitedDimensionName)
00222 {
00223 EXCEPTION("Variable name: " + variableName + " already in use as unlimited dimension");
00224 }
00225 else if (variableName == mFixedDimensionName)
00226 {
00227 EXCEPTION("Variable name: " + variableName + " already in use as fixed dimension");
00228 }
00229 else
00230 {
00231
00232 mVariables.push_back(new_variable);
00233
00234
00235 variable_id = mVariables.size()-1;
00236 }
00237
00238 return variable_id;
00239 }
00240
00241
00246 void ColumnDataWriter::EndDefineMode()
00247 {
00248
00249 if (mIsFixedDimensionSet == false && mIsUnlimitedDimensionSet == false)
00250 {
00251 EXCEPTION("Cannot end define mode. No dimensions have been defined.");
00252 }
00253
00254 if (mVariables.size() < 1)
00255 {
00256 EXCEPTION("Cannot end define mode. No variables have been defined.");
00257 }
00258
00259 int unlimited_dimension_variable = (mpUnlimitedDimensionVariable != NULL);
00260 int fixed_dimension_variable = (mpFixedDimensionVariable != NULL);
00261 if (mIsUnlimitedDimensionSet)
00262 {
00263 if (mIsFixedDimensionSet)
00264 {
00265 mRowWidth = (mVariables.size() + fixed_dimension_variable) * (FIELD_WIDTH + SPACING);
00266 mAncillaryRowWidth = FIELD_WIDTH + SPACING;
00267
00268 std::stringstream suffix;
00269 suffix << std::setfill('0') << std::setw(FILE_SUFFIX_WIDTH) << mUnlimitedDimensionPosition;
00270
00271 if (mpUnlimitedDimensionVariable != NULL)
00272 {
00273 std::string ancillary_filename = mBaseName + "_unlimited.dat";
00274 mpCurrentAncillaryFile = mOutputFileHandler.OpenOutputFile(
00275 ancillary_filename, std::ios::out);
00276 (*mpCurrentAncillaryFile) << std::setiosflags(std::ios::scientific);
00277 (*mpCurrentAncillaryFile) << std::setprecision(FIELD_WIDTH-6);
00278 if (mpUnlimitedDimensionVariable != NULL)
00279 {
00280 (*mpCurrentAncillaryFile) << mpUnlimitedDimensionVariable->mVariableName
00281 << "(" << mpUnlimitedDimensionVariable->mVariableUnits << ") ";
00282 }
00283 }
00284 mAncillaryRowStartPosition = mpCurrentAncillaryFile->tellp();
00285 std::string filename = mBaseName + "_" + suffix.str() + ".dat";
00286 this->CreateFixedDimensionFile(filename);
00287 }
00288 else
00289 {
00290 mRowWidth = (mVariables.size() + unlimited_dimension_variable) * (FIELD_WIDTH + SPACING);
00291
00292 std::string filename = mBaseName + ".dat";
00293 mpCurrentOutputFile = mOutputFileHandler.OpenOutputFile(filename, std::ios::out);
00294 (*mpCurrentOutputFile) << std::setiosflags(std::ios::scientific);
00295 (*mpCurrentOutputFile) << std::setprecision(FIELD_WIDTH-6);
00296 if (mpUnlimitedDimensionVariable != NULL)
00297 {
00298 (*mpCurrentOutputFile) << mpUnlimitedDimensionVariable->mVariableName
00299 << "(" << mpUnlimitedDimensionVariable->mVariableUnits << ") ";
00300 }
00301
00302
00303
00304 for (unsigned i = 0; i < mVariables.size(); i++)
00305 {
00306 (*mpCurrentOutputFile) << mVariables[i].mVariableName << "(" << mVariables[i].mVariableUnits << ")";
00307 if (i < mVariables.size()-1)
00308 {
00309 (*mpCurrentOutputFile) << " ";
00310 }
00311 }
00312 (*mpCurrentOutputFile) << std::endl;
00313 mRowStartPosition = mpCurrentOutputFile->tellp();
00314
00315 std::string blank_line(mRowWidth,' ');
00316 (*mpCurrentOutputFile) << blank_line;
00317 }
00318 }
00319 else
00320 {
00321
00322 mRowWidth = (mVariables.size() + fixed_dimension_variable) * (FIELD_WIDTH + SPACING);
00323 std::string filename = mBaseName + ".dat";
00324 this->CreateFixedDimensionFile(filename);
00325 }
00326
00327
00328 std::string infoname = mBaseName + ".info";
00329 this->CreateInfoFile(infoname);
00330
00331 mIsInDefineMode = false;
00332 }
00333
00338 void ColumnDataWriter::CreateFixedDimensionFile(std::string filename)
00339 {
00340
00341 mpCurrentOutputFile = mOutputFileHandler.OpenOutputFile(filename, std::ios::out);
00342 (*mpCurrentOutputFile) << std::setiosflags(std::ios::scientific);
00343 (*mpCurrentOutputFile) << std::setprecision(FIELD_WIDTH-6);
00344 if (mpFixedDimensionVariable != NULL)
00345 {
00346 (*mpCurrentOutputFile) << mpFixedDimensionVariable->mVariableName
00347 << "(" << mpFixedDimensionVariable->mVariableUnits << ") ";
00348 }
00349
00350 for (unsigned i = 0; i < mVariables.size(); i++)
00351 {
00352 (*mpCurrentOutputFile) << mVariables[i].mVariableName << "(" << mVariables[i].mVariableUnits << ")";
00353 if (i < mVariables.size()-1)
00354 {
00355 (*mpCurrentOutputFile) << " ";
00356 }
00357 }
00358 (*mpCurrentOutputFile) << std::endl;
00359 mRowStartPosition = mpCurrentOutputFile->tellp();
00360 std::string blank_line(mRowWidth,' ');
00361 for (int i = 0; i < mFixedDimensionSize; i++)
00362 {
00363 (*mpCurrentOutputFile) << blank_line << std::endl;
00364 }
00365
00366 }
00367
00368
00369
00373 void ColumnDataWriter::CreateInfoFile(std::string filename)
00374 {
00375
00376 out_stream p_info_file = mOutputFileHandler.OpenOutputFile(filename, std::ios::out);
00377 (*p_info_file) << "FIXED " << mFixedDimensionSize << std::endl;
00378 (*p_info_file) << "UNLIMITED " << mIsUnlimitedDimensionSet << std::endl;
00379 (*p_info_file) << "VARIABLES " << mVariables.size() << std::endl;
00380 p_info_file->close();
00381 }
00382
00383
00389 void ColumnDataWriter::DoAdvanceAlongUnlimitedDimension()
00390 {
00391 mHasPutVariable = false;
00392 mNeedAdvanceAlongUnlimitedDimension = false;
00393
00394 if (mIsUnlimitedDimensionSet)
00395 {
00396 if (mIsFixedDimensionSet)
00397 {
00398
00399 mpCurrentOutputFile->close();
00400 std::stringstream suffix;
00401 suffix << std::setfill('0') << std::setw(FILE_SUFFIX_WIDTH) << mUnlimitedDimensionPosition + 1;
00402
00403
00404
00405
00406
00407
00408
00409
00410 std::string filename = mBaseName + "_" + suffix.str() + ".dat";
00411 this->CreateFixedDimensionFile(filename);
00412 }
00413 else
00414 {
00415
00416 mpCurrentOutputFile->seekp(mRowStartPosition+mRowWidth);
00417 (*mpCurrentOutputFile) << std::endl;
00418 mRowStartPosition = mpCurrentOutputFile->tellp();
00419 std::string blank_line(mRowWidth,' ');
00420 (*mpCurrentOutputFile) << blank_line;
00421 }
00422 }
00423 else
00424 {
00425 EXCEPTION("Cannot advance along unlimited dimension if it is not defined");
00426 }
00427 mUnlimitedDimensionPosition++;
00428 }
00429
00430
00435 void ColumnDataWriter::AdvanceAlongUnlimitedDimension()
00436 {
00437 if (mHasPutVariable)
00438 mNeedAdvanceAlongUnlimitedDimension = true;
00439 }
00440
00441
00442
00447 void ColumnDataWriter::PutVariable(int variableID, double variableValue, long dimensionPosition)
00448 {
00449 if (mNeedAdvanceAlongUnlimitedDimension)
00450 DoAdvanceAlongUnlimitedDimension();
00451
00452
00453 if (mIsInDefineMode)
00454 {
00455 EXCEPTION("Cannot put variables when in Define mode");
00456 }
00457
00458 if (variableID > (int)mVariables.size() ||
00459 (variableID != UNLIMITED_DIMENSION_VAR_ID &&
00460 variableID != FIXED_DIMENSION_VAR_ID &&
00461 variableID < 0))
00462 {
00463 EXCEPTION("variableID unknown");
00464 }
00465
00466 if (mIsFixedDimensionSet)
00467 {
00468 if (dimensionPosition == -1 && variableID != UNLIMITED_DIMENSION_VAR_ID)
00469 {
00470 EXCEPTION("Dimension position not supplied");
00471 }
00472 if (dimensionPosition < -1 || dimensionPosition >= mFixedDimensionSize)
00473 {
00474 EXCEPTION("Dimension position out of range");
00475 }
00476 if (dimensionPosition != -1 && variableID == UNLIMITED_DIMENSION_VAR_ID)
00477 {
00478 EXCEPTION("Dimension position supplied, but not required");
00479 }
00480 }
00481
00482 if (mIsUnlimitedDimensionSet)
00483 {
00484 if (mIsFixedDimensionSet)
00485 {
00486
00487 if (variableID == UNLIMITED_DIMENSION_VAR_ID)
00488 {
00489
00490 if (variableValue >= 0)
00491 {
00492 (*mpCurrentAncillaryFile) << std::endl << " ";
00493 }
00494 else
00495 {
00496 (*mpCurrentAncillaryFile) << std::endl << " ";
00497 }
00498 mpCurrentAncillaryFile->width(FIELD_WIDTH);
00499 (*mpCurrentAncillaryFile) << variableValue;
00500 }
00501 else
00502 {
00503 int position;
00504 if (variableID == FIXED_DIMENSION_VAR_ID)
00505 {
00506 position = mRowStartPosition + (mRowWidth+1) * dimensionPosition + SPACING;
00507 }
00508 else
00509 {
00510
00511 position = mRowStartPosition + (mRowWidth+1) * dimensionPosition +
00512 ((variableID + (mpFixedDimensionVariable != NULL))* (FIELD_WIDTH + SPACING)) + SPACING;
00513 }
00514
00515 if (variableValue >= 0)
00516 {
00517 mpCurrentOutputFile->seekp(position);
00518 mpCurrentOutputFile->width(FIELD_WIDTH);
00519 }
00520 else
00521 {
00522 mpCurrentOutputFile->seekp(position-1);
00523 mpCurrentOutputFile->width(FIELD_WIDTH);
00524 }
00525 (*mpCurrentOutputFile) << variableValue;
00526 }
00527 }
00528 else
00529 {
00530
00531 int position;
00532 if (variableID == UNLIMITED_DIMENSION_VAR_ID)
00533 {
00534 position = mRowStartPosition + SPACING;
00535 }
00536 else
00537 {
00538 position = (variableID + (mpUnlimitedDimensionVariable != NULL)) * (FIELD_WIDTH + SPACING) + mRowStartPosition + SPACING;
00539 }
00540
00541 if (variableValue >= 0)
00542 {
00543 mpCurrentOutputFile->seekp(position);
00544 mpCurrentOutputFile->width(FIELD_WIDTH);
00545 }
00546 else
00547 {
00548 mpCurrentOutputFile->seekp(position-1);
00549 mpCurrentOutputFile->width(FIELD_WIDTH);
00550 }
00551 (*mpCurrentOutputFile) << variableValue;
00552 }
00553 }
00554 else
00555 {
00556
00557 int position;
00558 if (variableID == FIXED_DIMENSION_VAR_ID)
00559 {
00560 position = mRowStartPosition + (mRowWidth+1) * dimensionPosition + SPACING;
00561 }
00562 else
00563 {
00564 position = mRowStartPosition + (mRowWidth+1) * dimensionPosition +
00565 ((variableID + (mpFixedDimensionVariable != NULL))* (FIELD_WIDTH + SPACING)) + SPACING;
00566 }
00567 if (variableValue >= 0)
00568 {
00569 mpCurrentOutputFile->seekp(position);
00570 mpCurrentOutputFile->width(FIELD_WIDTH);
00571 }
00572 else
00573 {
00574 mpCurrentOutputFile->seekp(position-1);
00575 mpCurrentOutputFile->width(FIELD_WIDTH);
00576 }
00577
00578 (*mpCurrentOutputFile) << variableValue;
00579
00580 }
00581
00582 mHasPutVariable = true;
00583 }