MOAB: Mesh Oriented datABase
(version 5.2.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 { MB_SET_ERR( MB_UNSUPPORTED_OPERATION, "Attempt to launch NC writer in parallel without pnetcdf support" ); } 00214 #endif 00215 00216 const int rank = myPcomm->proc_config().proc_rank(); 00217 dbgOut.set_rank( rank ); 00218 #endif 00219 00220 return MB_SUCCESS; 00221 } 00222 00223 // This is the inverse process to create conventional tags 00224 // Will look at <pargal_source>/src/core/fileinfo.cpp, init dim, vars, atts 00225 ErrorCode WriteNC::process_conventional_tags( EntityHandle fileSet ) 00226 { 00227 ErrorCode rval; 00228 00229 // Start copy 00230 Tag dimNamesTag = 0; 00231 std::string tag_name = "__DIM_NAMES"; 00232 const void* data = NULL; 00233 int dimNamesSz = 0; 00234 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 ); 00235 rval = mbImpl->tag_get_by_ptr( dimNamesTag, &fileSet, 1, &data, &dimNamesSz );MB_CHK_SET_ERR( rval, "Trouble getting data of conventional tag " << tag_name ); 00236 const char* p = static_cast< const char* >( data ); 00237 dbgOut.tprintf( 1, "__DIM_NAMES tag has string length %d\n", dimNamesSz ); 00238 00239 std::size_t start = 0; 00240 00241 Tag dimLensTag = 0; 00242 tag_name = "__DIM_LENS"; 00243 data = NULL; 00244 int dimLensSz = 0; 00245 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 ); 00246 rval = mbImpl->tag_get_by_ptr( dimLensTag, &fileSet, 1, &data, &dimLensSz );MB_CHK_SET_ERR( rval, "Trouble getting data of conventional tag " << tag_name ); 00247 const int* int_p = static_cast< const int* >( data ); 00248 dbgOut.tprintf( 1, "__DIM_LENS tag has %d values\n", dimLensSz ); 00249 00250 int idxDim = 0; 00251 // Dim names are separated by '\0' in the string of __DIM_NAMES tag 00252 for( std::size_t i = 0; i != static_cast< std::size_t >( dimNamesSz ); i++ ) 00253 { 00254 if( p[i] == '\0' ) 00255 { 00256 std::string dim_name( &p[start], i - start ); 00257 int len = int_p[idxDim]; 00258 dimNames.push_back( dim_name ); 00259 dimLens.push_back( len ); 00260 dbgOut.tprintf( 2, "Dimension %s has length %d\n", dim_name.c_str(), len ); 00261 // FIXME: Need info from moab to set unlimited dimension 00262 // Currently assume each file has the same number of time dimensions 00263 /*if ((dim_name == "time") || (dim_name == "Time")) 00264 insert(dim_name, *(new pcdim(dim_name, len * m_file_names.size(), true))); 00265 else 00266 insert(dim_name, *(new pcdim(dim_name, len)));*/ 00267 start = i + 1; 00268 idxDim++; 00269 } 00270 } 00271 00272 Tag meshTypeTag = 0; 00273 tag_name = "__MESH_TYPE"; 00274 data = NULL; 00275 int meshTypeSz = 0; 00276 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 ); 00277 rval = mbImpl->tag_get_by_ptr( meshTypeTag, &fileSet, 1, &data, &meshTypeSz );MB_CHK_SET_ERR( rval, "Trouble getting data of conventional tag " << tag_name ); 00278 p = static_cast< const char* >( data ); 00279 grid_type = std::string( &p[0], meshTypeSz ); 00280 dbgOut.tprintf( 2, "Mesh type: %s\n", grid_type.c_str() ); 00281 00282 // Read <__VAR_NAMES_LOCATIONS> tag 00283 Tag varNamesLocsTag = 0; 00284 tag_name = "__VAR_NAMES_LOCATIONS"; 00285 data = NULL; 00286 int varNamesLocsSz = 0; 00287 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 ); 00288 rval = mbImpl->tag_get_by_ptr( varNamesLocsTag, &fileSet, 1, &data, &varNamesLocsSz );MB_CHK_SET_ERR( rval, "Trouble getting data of conventional tag " << tag_name ); 00289 int_p = static_cast< const int* >( data ); 00290 std::vector< int > varNamesLocs( varNamesLocsSz ); 00291 std::copy( int_p, int_p + varNamesLocsSz, varNamesLocs.begin() ); 00292 00293 Tag varNamesTag = 0; 00294 tag_name = "__VAR_NAMES"; 00295 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 ); 00296 data = NULL; 00297 int varNamesSz = 0; 00298 rval = mbImpl->tag_get_by_ptr( varNamesTag, &fileSet, 1, &data, &varNamesSz );MB_CHK_SET_ERR( rval, "Trouble getting data of conventional tag " << tag_name ); 00299 dbgOut.tprintf( 2, "__VAR_NAMES tag has string length %d\n", varNamesSz ); 00300 p = static_cast< const char* >( data ); 00301 00302 start = 0; 00303 int idxVar = 0; 00304 int sz; 00305 // Var names are separated by '\0' in the string of __VAR_NAMES tag 00306 for( std::size_t i = 0; i != static_cast< std::size_t >( varNamesSz ); i++ ) 00307 { 00308 if( p[i] == '\0' ) 00309 { 00310 std::string var_name( &p[start], i - start ); 00311 00312 dbgOut.tprintf( 2, "var name: %s index %d \n", var_name.c_str(), idxVar ); 00313 // Process var name: 00314 // This will create/initiate map; we will populate variableDataStruct with info about 00315 // dims, tags, etc reference & is important; otherwise variableDataStruct will go out of 00316 // scope, and deleted :( 00317 VarData& variableDataStruct = varInfo[var_name]; 00318 variableDataStruct.varName = var_name; 00319 variableDataStruct.entLoc = varNamesLocs[idxVar]; 00320 00321 dbgOut.tprintf( 2, "at var name %s varInfo size %d \n", var_name.c_str(), (int)varInfo.size() ); 00322 00323 sz = 0; 00324 Tag dims_tag = 0; 00325 std::string dim_names = "__" + var_name + "_DIMS"; 00326 rval = mbImpl->tag_get_handle( dim_names.c_str(), 0, MB_TYPE_OPAQUE, dims_tag, MB_TAG_ANY ); 00327 if( MB_SUCCESS != rval ) 00328 { 00329 if( MB_TAG_NOT_FOUND == rval ) 00330 { 00331 dbgOut.tprintf( 2, "tag : %s not found, continue \n", dim_names.c_str() ); 00332 start = i + 1; 00333 idxVar++; 00334 continue; 00335 } 00336 MB_SET_ERR( rval, "Trouble getting conventional tag " << dim_names ); 00337 } 00338 rval = mbImpl->tag_get_length( dims_tag, sz );MB_CHK_SET_ERR( rval, "Trouble getting size of dimensions for variable " << var_name ); 00339 sz /= sizeof( Tag ); // The type is MB_TYPE_OPAQUE, but it is a list of tags, so we 00340 // need to divide by the size of Tag 00341 // sz is used for number of dimension tags in this list 00342 dbgOut.tprintf( 2, "var name: %s has %d dimensions \n", var_name.c_str(), sz ); 00343 00344 variableDataStruct.varDims.resize( sz ); 00345 const void* ptr = NULL; 00346 rval = mbImpl->tag_get_by_ptr( dims_tag, &fileSet, 1, &ptr ); 00347 00348 const Tag* ptags = static_cast< const moab::Tag* >( ptr ); 00349 for( std::size_t j = 0; j != static_cast< std::size_t >( sz ); j++ ) 00350 { 00351 std::string dim_name; 00352 rval = mbImpl->tag_get_name( ptags[j], dim_name );MB_CHK_SET_ERR( rval, "Trouble getting dimension of variable " << var_name ); 00353 dbgOut.tprintf( 2, "var name: %s has %s as dimension \n", var_name.c_str(), dim_name.c_str() ); 00354 std::vector< std::string >::iterator vit = std::find( dimNames.begin(), dimNames.end(), dim_name ); 00355 if( vit == dimNames.end() ) 00356 MB_SET_ERR( MB_FAILURE, "Dimension " << dim_name << " not found for variable " << var_name ); 00357 variableDataStruct.varDims[j] = (int)( vit - dimNames.begin() ); // Will be used for writing 00358 // This will have to change to actual file dimension, for writing 00359 } 00360 00361 // Attributes for this variable 00362 std::stringstream ssTagName; 00363 ssTagName << "__" << var_name << "_ATTRIBS"; 00364 tag_name = ssTagName.str(); 00365 Tag varAttTag = 0; 00366 rval = 00367 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 ); 00368 const void* varAttPtr = NULL; 00369 int varAttSz = 0; 00370 rval = mbImpl->tag_get_by_ptr( varAttTag, &fileSet, 1, &varAttPtr, &varAttSz );MB_CHK_SET_ERR( rval, "Trouble getting data of conventional tag " << tag_name ); 00371 if( MB_SUCCESS == rval ) dbgOut.tprintf( 2, "Tag retrieved for variable %s\n", tag_name.c_str() ); 00372 00373 std::string attribString( (char*)varAttPtr, (char*)varAttPtr + varAttSz ); 00374 if( attribString == "NO_ATTRIBS" ) 00375 { 00376 // This variable has no attributes 00377 variableDataStruct.numAtts = 0; 00378 } 00379 else if( attribString == "DUMMY_VAR" ) 00380 { 00381 // This variable is a dummy coordinate variable 00382 variableDataStruct.numAtts = 0; 00383 dummyVarNames.insert( variableDataStruct.varName ); 00384 } 00385 else 00386 { 00387 ssTagName << "_LEN"; 00388 tag_name = ssTagName.str(); 00389 Tag varAttLenTag = 0; 00390 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 ); 00391 int varAttLenSz = 0; 00392 rval = mbImpl->tag_get_length( varAttLenTag, varAttLenSz );MB_CHK_SET_ERR( rval, "Trouble getting length of conventional tag " << tag_name ); 00393 std::vector< int > varAttLen( varAttLenSz ); 00394 rval = mbImpl->tag_get_data( varAttLenTag, &fileSet, 1, &varAttLen[0] );MB_CHK_SET_ERR( rval, "Trouble getting data of conventional tag " << tag_name ); 00395 00396 rval = process_concatenated_attribute( varAttPtr, varAttSz, varAttLen, variableDataStruct.varAtts );MB_CHK_SET_ERR( rval, "Trouble processing attributes of variable " << var_name ); 00397 00398 if( MB_SUCCESS == rval ) dbgOut.tprintf( 2, "Tag metadata for variable %s\n", tag_name.c_str() ); 00399 } 00400 // End attribute 00401 00402 start = i + 1; 00403 idxVar++; 00404 } // if (p[i] == '\0') 00405 } 00406 00407 // Global attributes 00408 tag_name = "__GLOBAL_ATTRIBS"; 00409 Tag globalAttTag = 0; 00410 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 ); 00411 std::vector< int > gattLen; 00412 00413 const void* gattptr = NULL; 00414 int globalAttSz = 0; 00415 rval = mbImpl->tag_get_by_ptr( globalAttTag, &fileSet, 1, &gattptr, &globalAttSz );MB_CHK_SET_ERR( rval, "Trouble getting data of conventional tag " << tag_name ); 00416 00417 if( MB_SUCCESS == rval ) dbgOut.tprintf( 2, "Tag value retrieved for %s size %d\n", tag_name.c_str(), globalAttSz ); 00418 00419 // <__GLOBAL_ATTRIBS_LEN> 00420 tag_name = "__GLOBAL_ATTRIBS_LEN"; 00421 Tag globalAttLenTag = 0; 00422 00423 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 ); 00424 int sizeGAtt = 0; 00425 rval = mbImpl->tag_get_length( globalAttLenTag, sizeGAtt );MB_CHK_SET_ERR( rval, "Trouble getting length of conventional tag " << tag_name ); 00426 gattLen.resize( sizeGAtt ); 00427 rval = mbImpl->tag_get_data( globalAttLenTag, &fileSet, 1, &gattLen[0] );MB_CHK_SET_ERR( rval, "Trouble getting data of conventional tag " << tag_name ); 00428 if( MB_SUCCESS == rval ) dbgOut.tprintf( 2, "Tag retrieved for variable %s\n", tag_name.c_str() ); 00429 00430 rval = process_concatenated_attribute( gattptr, globalAttSz, gattLen, globalAtts );MB_CHK_SET_ERR( rval, "Trouble processing global attributes" ); 00431 00432 return MB_SUCCESS; 00433 } 00434 00435 // Reverse process from create_attrib_string 00436 ErrorCode WriteNC::process_concatenated_attribute( const void* attPtr, int attSz, std::vector< int >& attLen, 00437 std::map< std::string, AttData >& attributes ) 00438 { 00439 std::size_t start = 0; 00440 std::size_t att_counter = 0; 00441 std::string concatString( (char*)attPtr, (char*)attPtr + attSz ); 00442 00443 for( std::size_t i = 0; i != (size_t)attSz; i++ ) 00444 { 00445 if( concatString[i] == '\0' ) 00446 { 00447 std::string att_name( &concatString[start], i - start ); 00448 start = i + 1; 00449 while( concatString[i] != ';' ) 00450 ++i; 00451 std::string data_type( &concatString[start], i - start ); 00452 ++i; 00453 start = i; 00454 i = attLen[att_counter]; 00455 if( concatString[i] != ';' ) MB_SET_ERR( MB_FAILURE, "Error parsing attributes" ); 00456 00457 std::string data_val( &concatString[start], i - start ); 00458 start = i + 1; 00459 00460 AttData& attrib = attributes[att_name]; 00461 attrib.attValue = data_val; 00462 attrib.attLen = data_val.size(); 00463 00464 if( data_type == "char" ) 00465 attrib.attDataType = NC_CHAR; 00466 else if( data_type == "double" ) 00467 attrib.attDataType = NC_DOUBLE; 00468 else if( data_type == "float" ) 00469 attrib.attDataType = NC_FLOAT; 00470 else if( data_type == "int" ) 00471 attrib.attDataType = NC_INT; 00472 else if( data_type == "short" ) 00473 attrib.attDataType = NC_SHORT; 00474 00475 ++att_counter; 00476 dbgOut.tprintf( 2, " Process attribute %s with value %s \n", att_name.c_str(), data_val.c_str() ); 00477 } 00478 } 00479 00480 return MB_SUCCESS; 00481 } 00482 00483 } // namespace moab