MOAB: Mesh Oriented datABase
(version 5.3.1)
|
00001 #include "WriteNC.hpp" 00002 #include "moab/CN.hpp" 00003 #include "MBTagConventions.hpp" 00004 #include "MBParallelConventions.h" 00005 #include "moab/Interface.hpp" 00006 #include "moab/Range.hpp" 00007 #include "moab/WriteUtilIface.hpp" 00008 #include "moab/FileOptions.hpp" 00009 #include "NCWriteHelper.hpp" 00010 00011 #include <fstream> 00012 #include <map> 00013 #include <set> 00014 00015 #include <iostream> 00016 #include <sstream> 00017 00018 #ifdef WIN32 00019 #ifdef size_t 00020 #undef size_t 00021 #endif 00022 #endif 00023 00024 namespace moab 00025 { 00026 00027 WriterIface* WriteNC::factory( Interface* iface ) 00028 { 00029 return new WriteNC( iface ); 00030 } 00031 00032 WriteNC::WriteNC( Interface* impl ) 00033 : mbImpl( impl ), dbgOut( stderr ), 00034 #ifdef MOAB_HAVE_MPI 00035 myPcomm( NULL ), 00036 #endif 00037 noMesh( false ), noVars( false ), append( false ), mGlobalIdTag( 0 ), isParallel( false ), myHelper( NULL ) 00038 { 00039 assert( impl != NULL ); 00040 impl->query_interface( mWriteIface ); 00041 } 00042 00043 WriteNC::~WriteNC() 00044 { 00045 mbImpl->release_interface( mWriteIface ); 00046 if( myHelper != NULL ) delete myHelper; 00047 } 00048 00049 //! Writes out a file 00050 ErrorCode WriteNC::write_file( const char* file_name, const bool overwrite, const FileOptions& options, 00051 const EntityHandle* file_set, const int num_set, const std::vector< std::string >&, 00052 const Tag*, int, int ) 00053 { 00054 ErrorCode rval; 00055 // See if opts has variable(s) specified 00056 std::vector< std::string > var_names; 00057 std::vector< std::string > desired_names; 00058 std::vector< int > tstep_nums; 00059 std::vector< double > tstep_vals; 00060 00061 // Get and cache predefined tag handles 00062 mGlobalIdTag = mbImpl->globalId_tag(); 00063 00064 // num set has to be 1, we will write only one set, the original file set used to load 00065 if( num_set != 1 ) MB_SET_ERR( MB_FAILURE, "We should write only one set (the file set used to read data into)" ); 00066 00067 rval = parse_options( options, var_names, desired_names, tstep_nums, tstep_vals );MB_CHK_SET_ERR( rval, "Trouble parsing option string" ); 00068 00069 // Important to create some data that will be used to write the file; dimensions, variables, etc 00070 // new variables still need to have some way of defining their dimensions 00071 // maybe it will be passed as write options 00072 rval = process_conventional_tags( *file_set );MB_CHK_SET_ERR( rval, "Trouble processing conventional tags" ); 00073 00074 // Create or append the file 00075 if( append ) 00076 dbgOut.tprintf( 1, "opening file %s for appending \n", file_name ); 00077 else 00078 dbgOut.tprintf( 1, "creating file %s\n", file_name ); 00079 fileName = file_name; 00080 int success; 00081 00082 if( append ) 00083 { 00084 int omode = NC_WRITE; 00085 #ifdef MOAB_HAVE_PNETCDF 00086 if( isParallel ) 00087 success = NCFUNC( open )( myPcomm->proc_config().proc_comm(), file_name, omode, MPI_INFO_NULL, &fileId ); 00088 else 00089 success = NCFUNC( open )( MPI_COMM_SELF, file_name, omode, MPI_INFO_NULL, &fileId ); 00090 #else 00091 // This is a regular netcdf file, open in write mode 00092 success = NCFUNC( open )( file_name, omode, &fileId ); 00093 #endif 00094 if( success ) MB_SET_ERR( MB_FAILURE, "Trouble opening file " << file_name << " for appending" ); 00095 } 00096 else 00097 { // Case when the file is new, will be overwritten, most likely 00098 int cmode = overwrite ? NC_CLOBBER : NC_NOCLOBBER; 00099 #ifdef MOAB_HAVE_PNETCDF 00100 if( isParallel ) 00101 success = NCFUNC( create )( myPcomm->proc_config().proc_comm(), file_name, cmode, MPI_INFO_NULL, &fileId ); 00102 else 00103 success = NCFUNC( create )( MPI_COMM_SELF, file_name, cmode, MPI_INFO_NULL, &fileId ); 00104 #else 00105 // This is a regular netcdf file 00106 success = NCFUNC( create )( file_name, cmode, &fileId ); 00107 #endif 00108 if( success ) MB_SET_ERR( MB_FAILURE, "Trouble creating file " << file_name << " for writing" ); 00109 } 00110 00111 if( NULL != myHelper ) delete myHelper; 00112 00113 // Get appropriate helper instance for WriteNC class based on some info in the file set 00114 myHelper = NCWriteHelper::get_nc_helper( this, fileId, options, *file_set ); 00115 if( NULL == myHelper ) { MB_SET_ERR( MB_FAILURE, "Failed to get NCWriteHelper class instance" ); } 00116 00117 rval = myHelper->collect_mesh_info();MB_CHK_SET_ERR( rval, "Trouble collecting mesh information" ); 00118 00119 rval = myHelper->collect_variable_data( var_names, tstep_nums );MB_CHK_SET_ERR( rval, "Trouble collecting variable data" ); 00120 00121 rval = myHelper->init_file( var_names, desired_names, append );MB_CHK_SET_ERR( rval, "Trouble initializing file" ); 00122 00123 rval = myHelper->write_values( var_names, tstep_nums );MB_CHK_SET_ERR( rval, "Trouble writing values to file" ); 00124 00125 success = NCFUNC( close )( fileId ); 00126 if( success ) MB_SET_ERR( MB_FAILURE, "Trouble closing file" ); 00127 00128 return MB_SUCCESS; 00129 } 00130 00131 ErrorCode WriteNC::parse_options( const FileOptions& opts, std::vector< std::string >& var_names, 00132 std::vector< std::string >& desired_names, std::vector< int >& tstep_nums, 00133 std::vector< double >& tstep_vals ) 00134 { 00135 int tmpval; 00136 if( MB_SUCCESS == opts.get_int_option( "DEBUG_IO", 1, tmpval ) ) 00137 { 00138 dbgOut.set_verbosity( tmpval ); 00139 dbgOut.set_prefix( "NCWrite" ); 00140 } 00141 00142 ErrorCode rval = opts.get_strs_option( "VARIABLE", var_names ); 00143 if( MB_TYPE_OUT_OF_RANGE == rval ) 00144 noVars = true; 00145 else 00146 noVars = false; 00147 00148 rval = opts.get_strs_option( "RENAME", desired_names ); 00149 if( MB_ENTITY_NOT_FOUND == rval ) 00150 { 00151 if( !noVars ) 00152 { 00153 desired_names.resize( var_names.size() ); 00154 std::copy( var_names.begin(), var_names.end(), desired_names.begin() ); 00155 } 00156 } 00157 // Either way 00158 assert( desired_names.size() == var_names.size() ); 00159 00160 opts.get_ints_option( "TIMESTEP", tstep_nums ); 00161 opts.get_reals_option( "TIMEVAL", tstep_vals ); 00162 rval = opts.get_null_option( "NOMESH" ); 00163 if( MB_SUCCESS == rval ) noMesh = true; 00164 00165 rval = opts.get_null_option( "APPEND" ); 00166 if( MB_SUCCESS == rval ) append = true; 00167 00168 if( 2 <= dbgOut.get_verbosity() ) 00169 { 00170 if( !var_names.empty() ) 00171 { 00172 std::cerr << "Variables requested: "; 00173 for( unsigned int i = 0; i < var_names.size(); i++ ) 00174 std::cerr << var_names[i]; 00175 std::cerr << std::endl; 00176 } 00177 if( !tstep_nums.empty() ) 00178 { 00179 std::cerr << "Timesteps requested: "; 00180 for( unsigned int i = 0; i < tstep_nums.size(); i++ ) 00181 std::cerr << tstep_nums[i]; 00182 std::cerr << std::endl; 00183 } 00184 if( !tstep_vals.empty() ) 00185 { 00186 std::cerr << "Time vals requested: "; 00187 for( unsigned int i = 0; i < tstep_vals.size(); i++ ) 00188 std::cerr << tstep_vals[i]; 00189 std::cerr << std::endl; 00190 } 00191 } 00192 00193 // FIXME: copied from ReadNC, may need revise 00194 #ifdef MOAB_HAVE_MPI 00195 isParallel = ( opts.match_option( "PARALLEL", "WRITE_PART" ) != MB_ENTITY_NOT_FOUND ); 00196 00197 if( !isParallel ) 00198 // Return success here, since rval still has _NOT_FOUND from not finding option 00199 // in this case, myPcomm will be NULL, so it can never be used; always check for isParallel 00200 // before any use for myPcomm 00201 return MB_SUCCESS; 00202 00203 int pcomm_no = 0; 00204 rval = opts.get_int_option( "PARALLEL_COMM", pcomm_no ); 00205 if( MB_TYPE_OUT_OF_RANGE == rval ) { MB_SET_ERR( rval, "Invalid value for PARALLEL_COMM option" ); } 00206 00207 myPcomm = ParallelComm::get_pcomm( mbImpl, pcomm_no ); 00208 if( 0 == myPcomm ) { myPcomm = new ParallelComm( mbImpl, MPI_COMM_WORLD ); } 00209 00210 #ifndef MOAB_HAVE_PNETCDF 00211 const int procs = myPcomm->proc_config().proc_size(); 00212 if( procs > 1 ) 00213 { 00214 MB_SET_ERR( MB_UNSUPPORTED_OPERATION, "Attempt to launch NC writer in parallel without pnetcdf support" ); 00215 } 00216 #endif 00217 00218 const int rank = myPcomm->proc_config().proc_rank(); 00219 dbgOut.set_rank( rank ); 00220 #endif 00221 00222 return MB_SUCCESS; 00223 } 00224 00225 // This is the inverse process to create conventional tags 00226 // Will look at <pargal_source>/src/core/fileinfo.cpp, init dim, vars, atts 00227 ErrorCode WriteNC::process_conventional_tags( EntityHandle fileSet ) 00228 { 00229 ErrorCode rval; 00230 00231 // Start copy 00232 Tag dimNamesTag = 0; 00233 std::string tag_name = "__DIM_NAMES"; 00234 const void* data = NULL; 00235 int dimNamesSz = 0; 00236 rval = mbImpl->tag_get_handle( tag_name.c_str(), 0, MB_TYPE_OPAQUE, dimNamesTag, MB_TAG_ANY );MB_CHK_SET_ERR( rval, "Trouble getting conventional tag " << tag_name ); 00237 rval = mbImpl->tag_get_by_ptr( dimNamesTag, &fileSet, 1, &data, &dimNamesSz );MB_CHK_SET_ERR( rval, "Trouble getting data of conventional tag " << tag_name ); 00238 const char* p = static_cast< const char* >( data ); 00239 dbgOut.tprintf( 1, "__DIM_NAMES tag has string length %d\n", dimNamesSz ); 00240 00241 std::size_t start = 0; 00242 00243 Tag dimLensTag = 0; 00244 tag_name = "__DIM_LENS"; 00245 data = NULL; 00246 int dimLensSz = 0; 00247 rval = mbImpl->tag_get_handle( tag_name.c_str(), 0, MB_TYPE_INTEGER, dimLensTag, MB_TAG_ANY );MB_CHK_SET_ERR( rval, "Trouble getting conventional tag " << tag_name ); 00248 rval = mbImpl->tag_get_by_ptr( dimLensTag, &fileSet, 1, &data, &dimLensSz );MB_CHK_SET_ERR( rval, "Trouble getting data of conventional tag " << tag_name ); 00249 const int* int_p = static_cast< const int* >( data ); 00250 dbgOut.tprintf( 1, "__DIM_LENS tag has %d values\n", dimLensSz ); 00251 00252 int idxDim = 0; 00253 // Dim names are separated by '\0' in the string of __DIM_NAMES tag 00254 for( std::size_t i = 0; i != static_cast< std::size_t >( dimNamesSz ); i++ ) 00255 { 00256 if( p[i] == '\0' ) 00257 { 00258 std::string dim_name( &p[start], i - start ); 00259 int len = int_p[idxDim]; 00260 dimNames.push_back( dim_name ); 00261 dimLens.push_back( len ); 00262 dbgOut.tprintf( 2, "Dimension %s has length %d\n", dim_name.c_str(), len ); 00263 // FIXME: Need info from moab to set unlimited dimension 00264 // Currently assume each file has the same number of time dimensions 00265 /*if ((dim_name == "time") || (dim_name == "Time")) 00266 insert(dim_name, *(new pcdim(dim_name, len * m_file_names.size(), true))); 00267 else 00268 insert(dim_name, *(new pcdim(dim_name, len)));*/ 00269 start = i + 1; 00270 idxDim++; 00271 } 00272 } 00273 00274 Tag meshTypeTag = 0; 00275 tag_name = "__MESH_TYPE"; 00276 data = NULL; 00277 int meshTypeSz = 0; 00278 rval = mbImpl->tag_get_handle( tag_name.c_str(), 0, MB_TYPE_OPAQUE, meshTypeTag, MB_TAG_ANY );MB_CHK_SET_ERR( rval, "Trouble getting conventional tag " << tag_name ); 00279 rval = mbImpl->tag_get_by_ptr( meshTypeTag, &fileSet, 1, &data, &meshTypeSz );MB_CHK_SET_ERR( rval, "Trouble getting data of conventional tag " << tag_name ); 00280 p = static_cast< const char* >( data ); 00281 grid_type = std::string( &p[0], meshTypeSz ); 00282 dbgOut.tprintf( 2, "Mesh type: %s\n", grid_type.c_str() ); 00283 00284 // Read <__VAR_NAMES_LOCATIONS> tag 00285 Tag varNamesLocsTag = 0; 00286 tag_name = "__VAR_NAMES_LOCATIONS"; 00287 data = NULL; 00288 int varNamesLocsSz = 0; 00289 rval = mbImpl->tag_get_handle( tag_name.c_str(), 0, MB_TYPE_INTEGER, varNamesLocsTag, MB_TAG_ANY );MB_CHK_SET_ERR( rval, "Trouble getting conventional tag " << tag_name ); 00290 rval = mbImpl->tag_get_by_ptr( varNamesLocsTag, &fileSet, 1, &data, &varNamesLocsSz );MB_CHK_SET_ERR( rval, "Trouble getting data of conventional tag " << tag_name ); 00291 int_p = static_cast< const int* >( data ); 00292 std::vector< int > varNamesLocs( varNamesLocsSz ); 00293 std::copy( int_p, int_p + varNamesLocsSz, varNamesLocs.begin() ); 00294 00295 Tag varNamesTag = 0; 00296 tag_name = "__VAR_NAMES"; 00297 rval = mbImpl->tag_get_handle( tag_name.c_str(), 0, MB_TYPE_OPAQUE, varNamesTag, MB_TAG_ANY );MB_CHK_SET_ERR( rval, "Trouble getting conventional tag " << tag_name ); 00298 data = NULL; 00299 int varNamesSz = 0; 00300 rval = mbImpl->tag_get_by_ptr( varNamesTag, &fileSet, 1, &data, &varNamesSz );MB_CHK_SET_ERR( rval, "Trouble getting data of conventional tag " << tag_name ); 00301 dbgOut.tprintf( 2, "__VAR_NAMES tag has string length %d\n", varNamesSz ); 00302 p = static_cast< const char* >( data ); 00303 00304 start = 0; 00305 int idxVar = 0; 00306 int sz; 00307 // Var names are separated by '\0' in the string of __VAR_NAMES tag 00308 for( std::size_t i = 0; i != static_cast< std::size_t >( varNamesSz ); i++ ) 00309 { 00310 if( p[i] == '\0' ) 00311 { 00312 std::string var_name( &p[start], i - start ); 00313 00314 dbgOut.tprintf( 2, "var name: %s index %d \n", var_name.c_str(), idxVar ); 00315 // Process var name: 00316 // This will create/initiate map; we will populate variableDataStruct with info about 00317 // dims, tags, etc reference & is important; otherwise variableDataStruct will go out of 00318 // scope, and deleted :( 00319 VarData& variableDataStruct = varInfo[var_name]; 00320 variableDataStruct.varName = var_name; 00321 variableDataStruct.entLoc = varNamesLocs[idxVar]; 00322 00323 dbgOut.tprintf( 2, "at var name %s varInfo size %d \n", var_name.c_str(), (int)varInfo.size() ); 00324 00325 sz = 0; 00326 Tag dims_tag = 0; 00327 std::string dim_names = "__" + var_name + "_DIMS"; 00328 rval = mbImpl->tag_get_handle( dim_names.c_str(), 0, MB_TYPE_OPAQUE, dims_tag, MB_TAG_ANY ); 00329 if( MB_SUCCESS != rval ) 00330 { 00331 if( MB_TAG_NOT_FOUND == rval ) 00332 { 00333 dbgOut.tprintf( 2, "tag : %s not found, continue \n", dim_names.c_str() ); 00334 start = i + 1; 00335 idxVar++; 00336 continue; 00337 } 00338 MB_SET_ERR( rval, "Trouble getting conventional tag " << dim_names ); 00339 } 00340 rval = mbImpl->tag_get_length( dims_tag, sz );MB_CHK_SET_ERR( rval, "Trouble getting size of dimensions for variable " << var_name ); 00341 sz /= sizeof( Tag ); // The type is MB_TYPE_OPAQUE, but it is a list of tags, so we 00342 // need to divide by the size of Tag 00343 // sz is used for number of dimension tags in this list 00344 dbgOut.tprintf( 2, "var name: %s has %d dimensions \n", var_name.c_str(), sz ); 00345 00346 variableDataStruct.varDims.resize( sz ); 00347 const void* ptr = NULL; 00348 rval = mbImpl->tag_get_by_ptr( dims_tag, &fileSet, 1, &ptr ); 00349 00350 const Tag* ptags = static_cast< const moab::Tag* >( ptr ); 00351 for( std::size_t j = 0; j != static_cast< std::size_t >( sz ); j++ ) 00352 { 00353 std::string dim_name; 00354 rval = mbImpl->tag_get_name( ptags[j], dim_name );MB_CHK_SET_ERR( rval, "Trouble getting dimension of variable " << var_name ); 00355 dbgOut.tprintf( 2, "var name: %s has %s as dimension \n", var_name.c_str(), dim_name.c_str() ); 00356 std::vector< std::string >::iterator vit = std::find( dimNames.begin(), dimNames.end(), dim_name ); 00357 if( vit == dimNames.end() ) 00358 MB_SET_ERR( MB_FAILURE, "Dimension " << dim_name << " not found for variable " << var_name ); 00359 variableDataStruct.varDims[j] = (int)( vit - dimNames.begin() ); // Will be used for writing 00360 // This will have to change to actual file dimension, for writing 00361 } 00362 00363 // Attributes for this variable 00364 std::stringstream ssTagName; 00365 ssTagName << "__" << var_name << "_ATTRIBS"; 00366 tag_name = ssTagName.str(); 00367 Tag varAttTag = 0; 00368 rval = 00369 mbImpl->tag_get_handle( tag_name.c_str(), 0, MB_TYPE_OPAQUE, varAttTag, MB_TAG_SPARSE | MB_TAG_VARLEN );MB_CHK_SET_ERR( rval, "Trouble getting conventional tag " << tag_name ); 00370 const void* varAttPtr = NULL; 00371 int varAttSz = 0; 00372 rval = mbImpl->tag_get_by_ptr( varAttTag, &fileSet, 1, &varAttPtr, &varAttSz );MB_CHK_SET_ERR( rval, "Trouble getting data of conventional tag " << tag_name ); 00373 if( MB_SUCCESS == rval ) dbgOut.tprintf( 2, "Tag retrieved for variable %s\n", tag_name.c_str() ); 00374 00375 std::string attribString( (char*)varAttPtr, (char*)varAttPtr + varAttSz ); 00376 if( attribString == "NO_ATTRIBS" ) 00377 { 00378 // This variable has no attributes 00379 variableDataStruct.numAtts = 0; 00380 } 00381 else if( attribString == "DUMMY_VAR" ) 00382 { 00383 // This variable is a dummy coordinate variable 00384 variableDataStruct.numAtts = 0; 00385 dummyVarNames.insert( variableDataStruct.varName ); 00386 } 00387 else 00388 { 00389 ssTagName << "_LEN"; 00390 tag_name = ssTagName.str(); 00391 Tag varAttLenTag = 0; 00392 rval = mbImpl->tag_get_handle( tag_name.c_str(), 0, MB_TYPE_INTEGER, varAttLenTag, MB_TAG_ANY );MB_CHK_SET_ERR( rval, "Trouble getting conventional tag " << tag_name ); 00393 int varAttLenSz = 0; 00394 rval = mbImpl->tag_get_length( varAttLenTag, varAttLenSz );MB_CHK_SET_ERR( rval, "Trouble getting length of conventional tag " << tag_name ); 00395 std::vector< int > varAttLen( varAttLenSz ); 00396 rval = mbImpl->tag_get_data( varAttLenTag, &fileSet, 1, &varAttLen[0] );MB_CHK_SET_ERR( rval, "Trouble getting data of conventional tag " << tag_name ); 00397 00398 rval = process_concatenated_attribute( varAttPtr, varAttSz, varAttLen, variableDataStruct.varAtts );MB_CHK_SET_ERR( rval, "Trouble processing attributes of variable " << var_name ); 00399 00400 if( MB_SUCCESS == rval ) dbgOut.tprintf( 2, "Tag metadata for variable %s\n", tag_name.c_str() ); 00401 } 00402 // End attribute 00403 00404 start = i + 1; 00405 idxVar++; 00406 } // if (p[i] == '\0') 00407 } 00408 00409 // Global attributes 00410 tag_name = "__GLOBAL_ATTRIBS"; 00411 Tag globalAttTag = 0; 00412 rval = mbImpl->tag_get_handle( tag_name.c_str(), 0, MB_TYPE_OPAQUE, globalAttTag, MB_TAG_SPARSE | MB_TAG_VARLEN );MB_CHK_SET_ERR( rval, "Trouble getting conventional tag " << tag_name ); 00413 std::vector< int > gattLen; 00414 00415 const void* gattptr = NULL; 00416 int globalAttSz = 0; 00417 rval = mbImpl->tag_get_by_ptr( globalAttTag, &fileSet, 1, &gattptr, &globalAttSz );MB_CHK_SET_ERR( rval, "Trouble getting data of conventional tag " << tag_name ); 00418 00419 if( MB_SUCCESS == rval ) dbgOut.tprintf( 2, "Tag value retrieved for %s size %d\n", tag_name.c_str(), globalAttSz ); 00420 00421 // <__GLOBAL_ATTRIBS_LEN> 00422 tag_name = "__GLOBAL_ATTRIBS_LEN"; 00423 Tag globalAttLenTag = 0; 00424 00425 rval = mbImpl->tag_get_handle( tag_name.c_str(), 0, MB_TYPE_INTEGER, globalAttLenTag, MB_TAG_ANY );MB_CHK_SET_ERR( rval, "Trouble getting conventional tag " << tag_name ); 00426 int sizeGAtt = 0; 00427 rval = mbImpl->tag_get_length( globalAttLenTag, sizeGAtt );MB_CHK_SET_ERR( rval, "Trouble getting length of conventional tag " << tag_name ); 00428 gattLen.resize( sizeGAtt ); 00429 rval = mbImpl->tag_get_data( globalAttLenTag, &fileSet, 1, &gattLen[0] );MB_CHK_SET_ERR( rval, "Trouble getting data of conventional tag " << tag_name ); 00430 if( MB_SUCCESS == rval ) dbgOut.tprintf( 2, "Tag retrieved for variable %s\n", tag_name.c_str() ); 00431 00432 rval = process_concatenated_attribute( gattptr, globalAttSz, gattLen, globalAtts );MB_CHK_SET_ERR( rval, "Trouble processing global attributes" ); 00433 00434 return MB_SUCCESS; 00435 } 00436 00437 // Reverse process from create_attrib_string 00438 ErrorCode WriteNC::process_concatenated_attribute( const void* attPtr, int attSz, std::vector< int >& attLen, 00439 std::map< std::string, AttData >& attributes ) 00440 { 00441 std::size_t start = 0; 00442 std::size_t att_counter = 0; 00443 std::string concatString( (char*)attPtr, (char*)attPtr + attSz ); 00444 00445 for( std::size_t i = 0; i != (size_t)attSz; i++ ) 00446 { 00447 if( concatString[i] == '\0' ) 00448 { 00449 std::string att_name( &concatString[start], i - start ); 00450 start = i + 1; 00451 while( concatString[i] != ';' ) 00452 ++i; 00453 std::string data_type( &concatString[start], i - start ); 00454 ++i; 00455 start = i; 00456 i = attLen[att_counter]; 00457 if( concatString[i] != ';' ) MB_SET_ERR( MB_FAILURE, "Error parsing attributes" ); 00458 00459 std::string data_val( &concatString[start], i - start ); 00460 start = i + 1; 00461 00462 AttData& attrib = attributes[att_name]; 00463 attrib.attValue = data_val; 00464 attrib.attLen = data_val.size(); 00465 00466 if( data_type == "char" ) 00467 attrib.attDataType = NC_CHAR; 00468 else if( data_type == "double" ) 00469 attrib.attDataType = NC_DOUBLE; 00470 else if( data_type == "float" ) 00471 attrib.attDataType = NC_FLOAT; 00472 else if( data_type == "int" ) 00473 attrib.attDataType = NC_INT; 00474 else if( data_type == "short" ) 00475 attrib.attDataType = NC_SHORT; 00476 00477 ++att_counter; 00478 dbgOut.tprintf( 2, " Process attribute %s with value %s \n", att_name.c_str(), data_val.c_str() ); 00479 } 00480 } 00481 00482 return MB_SUCCESS; 00483 } 00484 00485 } // namespace moab