MOAB: Mesh Oriented datABase  (version 5.4.1)
WriteNC.cpp
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines