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