ncdf4a13/cxx/netcdf.cpp

Go to the documentation of this file.
00001 /*********************************************************************
00002  *   Copyright 1992, University Corporation for Atmospheric Research
00003  *   See netcdf/README file for copying and redistribution conditions.
00004  *
00005  *   Purpose:   Implements class interface for netCDF over C interface
00006  *
00007  *   $Header: /upc/share/CVS/netcdf-3/cxx/netcdf.cpp,v 1.11 2005/11/05 01:39:52 ed Exp $
00008  *********************************************************************/
00009 
00010 #include <config.h>
00011 #include <string.h>
00012 #include <stdlib.h>
00013 #include "netcdfcpp.h"
00014 
00015 #ifndef TRUE
00016 #define TRUE 1
00017 #define FALSE 0
00018 #endif
00019 
00020 static const int ncGlobal = NC_GLOBAL; // psuedo-variable for global attributes
00021 
00022 static const int ncBad = -1;    // failure return for netCDF C interface 
00023 
00024 NcFile::~NcFile( void )
00025 {
00026     (void) close();
00027 }
00028 
00029 NcBool NcFile::is_valid( void ) const
00030 {
00031     return the_id != ncBad;
00032 }
00033 
00034 int NcFile::num_dims( void ) const
00035 {
00036     int num = 0;
00037     if (is_valid())
00038       ncinquire(the_id, &num, 0, 0, 0);
00039     return num;
00040 }
00041 
00042 int NcFile::num_vars( void ) const
00043 {
00044     int num = 0;
00045     if (is_valid())
00046       ncinquire(the_id, 0, &num, 0, 0);
00047     return num;
00048 }
00049 
00050 int NcFile::num_atts( void ) const
00051 {
00052     int num = 0;
00053     if (is_valid())
00054       ncinquire(the_id, 0, 0, &num, 0);
00055     return num;
00056 }
00057 
00058 NcDim* NcFile::get_dim( NcToken name ) const
00059 {
00060     int dimid = ncdimid(the_id, name);
00061     return get_dim(dimid);
00062 }
00063 
00064 NcVar* NcFile::get_var( NcToken name ) const
00065 {
00066     int varid = ncvarid(the_id, name);
00067     return get_var(varid);
00068 }
00069 
00070 NcAtt* NcFile::get_att( NcToken aname ) const
00071 {
00072     return is_valid() ? globalv->get_att(aname) : 0;
00073 }
00074 
00075 NcDim* NcFile::get_dim( int i ) const
00076 {
00077     if (! is_valid() || i < 0 || i >= num_dims())
00078       return 0;
00079     return dimensions[i];
00080 }
00081 
00082 NcVar* NcFile::get_var( int i ) const
00083 {
00084     if (! is_valid() || i < 0 || i >= num_vars())
00085       return 0;
00086     return variables[i];
00087 }
00088 
00089 NcAtt* NcFile::get_att( int n ) const
00090 {
00091     return is_valid() ? globalv->get_att(n) : 0;
00092 }
00093 
00094 NcDim* NcFile::rec_dim( ) const
00095 {
00096     if (! is_valid())
00097       return 0;
00098     int recdim;
00099     ncinquire(the_id, 0, 0, 0, &recdim);
00100     if (recdim == -1)
00101       return 0;
00102     return get_dim(recdim);
00103 }
00104 
00105 NcDim* NcFile::add_dim(NcToken name, long size)
00106 {
00107     if (!is_valid() || !define_mode())
00108       return 0;
00109     int n = num_dims();
00110     NcDim* dimp = new NcDim(this, name, size);
00111     dimensions[n] = dimp;       // for garbage collection on close()
00112     return dimp;
00113 }
00114 
00115 NcDim* NcFile::add_dim(NcToken name)
00116 {
00117     return add_dim(name, NC_UNLIMITED);
00118 }
00119 
00120 // To create scalar, 1-dimensional, ..., 5-dimensional variables, just supply
00121 // as many dimension arguments as necessary
00122 
00123 NcVar* NcFile::add_var(NcToken name, NcType type, // scalar to 5D var
00124                             const NcDim* dim0,
00125                             const NcDim* dim1,
00126                             const NcDim* dim2,
00127                             const NcDim* dim3,
00128                             const NcDim* dim4)
00129 {
00130     if (!is_valid() || !define_mode())
00131       return 0;
00132     int dims[5];
00133     int ndims = 0;
00134     if (dim0) {
00135         ndims++;
00136         dims[0] = dim0->id();
00137         if (dim1) {
00138             ndims++;
00139             dims[1] = dim1->id();
00140             if (dim2) {
00141                 ndims++;
00142                 dims[2] = dim2->id();
00143                 if (dim3) {
00144                     ndims++;
00145                     dims[3] = dim3->id();
00146                     if (dim4) {
00147                         ndims++;
00148                         dims[4] = dim4->id();
00149                     }
00150                 }
00151             }
00152         }
00153     }
00154     int n = num_vars();
00155     NcVar* varp =
00156       new NcVar(this, ncvardef(the_id, name, (nc_type) type, ndims, dims));
00157     variables[n] = varp;
00158     return varp;
00159 }
00160 
00161 // For variables with more than 5 dimensions, use n-dimensional interface
00162 // with vector of dimensions.
00163 
00164 NcVar* NcFile::add_var(NcToken name, NcType type, int ndims, const NcDim** dims)
00165 {
00166     if (!is_valid() || !define_mode())
00167       return 0;
00168     int* dimids = new int[ndims];
00169     for (int i=0; i < ndims; i++)
00170       dimids[i] = dims[i]->id();
00171     int n = num_vars();
00172     NcVar* varp =
00173       new NcVar(this, ncvardef(the_id, name, (nc_type) type, ndims, dimids));
00174     variables[n] = varp;
00175     delete [] dimids;
00176     return varp;
00177 }
00178 
00179 #define NcFile_add_scalar_att(TYPE)                                           \
00180 NcBool NcFile::add_att(NcToken aname, TYPE val)                               \
00181 {                                                                             \
00182     return globalv->add_att(aname, val);                                      \
00183 }
00184 
00185 NcFile_add_scalar_att(char)
00186 NcFile_add_scalar_att(ncbyte)
00187 NcFile_add_scalar_att(short)
00188 NcFile_add_scalar_att(int)
00189 NcFile_add_scalar_att(long)
00190 NcFile_add_scalar_att(float)
00191 NcFile_add_scalar_att(double)
00192 NcFile_add_scalar_att(const char*)
00193 
00194 #define NcFile_add_vector_att(TYPE)                                           \
00195 NcBool NcFile::add_att(NcToken aname, int n, const TYPE* val)                 \
00196 {                                                                             \
00197     return globalv->add_att(aname, n, val);                                   \
00198 }
00199 
00200 NcFile_add_vector_att(char)
00201 NcFile_add_vector_att(ncbyte)
00202 NcFile_add_vector_att(short)
00203 NcFile_add_vector_att(int)
00204 NcFile_add_vector_att(long)
00205 NcFile_add_vector_att(float)
00206 NcFile_add_vector_att(double)
00207 
00208 NcBool NcFile::set_fill( FillMode a_mode )
00209 {
00210   if (ncsetfill(the_id, a_mode) != ncBad) {
00211     the_fill_mode = a_mode;
00212     return TRUE;
00213   }
00214   return FALSE;
00215 }
00216 
00217 NcFile::FillMode NcFile::get_fill( void ) const
00218 {
00219     return the_fill_mode;
00220 }
00221 
00222 NcFile::FileFormat NcFile::get_format( void ) const
00223 {
00224     int the_format;
00225     nc_inq_format(the_id, &the_format);
00226     switch (the_format) {
00227     case NC_FORMAT_CLASSIC:
00228         return Classic;
00229     case NC_FORMAT_64BIT:
00230         return Offset64Bits;
00231     case NC_FORMAT_NETCDF4:
00232         return Netcdf4;
00233     case NC_FORMAT_NETCDF4_CLASSIC:
00234         return Netcdf4Classic;
00235     default:
00236         return BadFormat;
00237     }
00238 }
00239 
00240 NcBool NcFile::sync( void )
00241 {
00242     if (!data_mode())
00243       return 0;
00244     if (ncsync(the_id) == ncBad)
00245       return 0;
00246     int i;
00247     for (i = 0; i < num_dims(); i++) {
00248         if (dimensions[i]->is_valid()) {
00249             dimensions[i]->sync();
00250         } else {                // someone else added a new dimension
00251             dimensions[i] = new NcDim(this,i);
00252         }
00253     }
00254     for (i = 0; i < num_vars(); i++) {
00255         if (variables[i]->is_valid()) {
00256             variables[i]->sync();
00257         } else {                // someone else added a new variable
00258             variables[i] = new NcVar(this,i);
00259         }
00260     }
00261     return 1;
00262 }
00263 
00264 NcBool NcFile::close( void )
00265 {
00266     int i;
00267     
00268     if (the_id == ncBad)
00269       return 0;
00270     for (i = 0; i < num_dims(); i++)
00271       delete dimensions[i];
00272     for (i = 0; i < num_vars(); i++)
00273       delete variables[i];
00274     delete [] dimensions;
00275     delete [] variables;
00276     delete globalv;
00277     int old_id = the_id;
00278     the_id = ncBad;
00279     return ncclose(old_id) != ncBad;
00280 }
00281 
00282 NcBool NcFile::abort( void )
00283 {
00284     return ncabort(the_id) != ncBad;
00285 }
00286 
00287 NcBool NcFile::define_mode( void )
00288 {
00289     if (! is_valid())
00290       return FALSE;
00291     if (in_define_mode)
00292       return TRUE;
00293     if (ncredef(the_id) == ncBad)
00294       return FALSE;
00295     in_define_mode = 1;
00296     return TRUE;
00297 }
00298 
00299 NcBool NcFile::data_mode( void )
00300 {
00301     if (! is_valid())
00302       return FALSE;
00303     if (! in_define_mode)
00304       return TRUE;
00305     if (ncendef(the_id) == ncBad)
00306       return FALSE;
00307     in_define_mode = 0;
00308     return TRUE;
00309 }
00310 
00311 int NcFile::id( void ) const
00312 {
00313     return the_id;
00314 }
00315 
00316 NcFile::NcFile( const char* path, FileMode fmode, 
00317                 size_t* chunksizeptr, size_t initialsize, FileFormat fformat  )
00318 {
00319     NcError err(NcError::silent_nonfatal); // constructor must not fail
00320 
00321     int mode = NC_NOWRITE;
00322     the_fill_mode = Fill;
00323     int status;
00324     
00325     // If the user wants a 64-bit offset format, set that flag.
00326     if (fformat == Offset64Bits)
00327        mode |= NC_64BIT_OFFSET;
00328 #ifdef USE_NETCDF4
00329     else if (fformat == Netcdf4)
00330        mode |= NC_NETCDF4;
00331     else if (fformat == Netcdf4Classic)
00332        mode |= NC_NETCDF4|NC_CLASSIC_MODEL;
00333 #endif
00334 
00335     switch (fmode) {
00336     case Write:
00337         mode = NC_WRITE;
00338         /*FALLTHRU*/
00339     case ReadOnly:
00340         // use netcdf-3 interface to permit specifying tuning parameter
00341         status = nc__open(path, mode, chunksizeptr, &the_id);
00342         if(status != NC_NOERR)
00343         {
00344                 nc_advise("ncopen", status, "filename \"%s\"", path);
00345                 the_id =  -1;
00346         }
00347         in_define_mode = 0;
00348         break;
00349     case New:
00350         mode = NC_NOCLOBBER;
00351         /*FALLTHRU*/
00352     case Replace:
00353         // use netcdf-3 interface to permit specifying tuning parameters
00354         status = nc__create(path, mode, initialsize,
00355                                       chunksizeptr, &the_id);
00356         if(status != NC_NOERR)
00357         {
00358                 nc_advise("nccreate", status, "filename \"%s\"", path);
00359                 the_id =  -1;
00360         }
00361         in_define_mode = 1;
00362         break;
00363     default:
00364         the_id = ncBad;
00365         in_define_mode = 0;
00366         break;
00367     }
00368     if (is_valid()) {
00369         dimensions = new NcDim*[MAX_NC_DIMS];
00370         variables = new NcVar*[MAX_NC_VARS];
00371         int i;
00372         for (i = 0; i < num_dims(); i++)
00373             dimensions[i] = new NcDim(this, i);
00374         for (i = 0; i < num_vars(); i++)
00375             variables[i] = new NcVar(this, i);
00376         globalv = new NcVar(this, ncGlobal);
00377     } else {
00378         dimensions = 0;
00379         variables = 0;
00380         globalv = 0;
00381     }
00382 }
00383 
00384 NcToken NcDim::name( void ) const
00385 {
00386     return the_name;
00387 }
00388 
00389 long NcDim::size( void ) const
00390 {
00391     long sz = 0;
00392     if (the_file)
00393       ncdiminq(the_file->id(), the_id, (char*)0, &sz);
00394     return sz;
00395 }
00396 
00397 NcBool NcDim::is_valid( void ) const
00398 {
00399     return the_file->is_valid() && the_id != ncBad;
00400 }
00401 
00402 NcBool NcDim::is_unlimited( void ) const
00403 {
00404     if (!the_file)
00405       return FALSE;
00406     int recdim;
00407     ncinquire(the_file->id(), 0, 0, 0, &recdim);
00408     return the_id == recdim;
00409 }
00410 
00411 NcBool NcDim::rename(NcToken newname)
00412 {
00413     if (strlen(newname) > strlen(the_name)) {
00414         if (! the_file->define_mode())
00415             return FALSE;
00416     }
00417     NcBool ret = ncdimrename(the_file->id(), the_id, newname) != ncBad;
00418     if (ret) {
00419         delete [] the_name;
00420         the_name = new char[1 + strlen(newname)];
00421         strcpy(the_name, newname);
00422     }
00423     return ret;
00424 }
00425 
00426 int NcDim::id( void ) const
00427 {
00428     return the_id;
00429 }
00430 
00431 NcBool NcDim::sync(void) 
00432 {    
00433     char nam[MAX_NC_NAME];
00434     if (the_name) {
00435         delete [] the_name;
00436     }
00437     if (the_file && ncdiminq(the_file->id(), the_id, nam, 0) != ncBad) {
00438         the_name = new char[strlen(nam) + 1]; 
00439         strcpy(the_name, nam);
00440         return TRUE;
00441     }
00442     the_name = 0;
00443     return FALSE;
00444 }
00445 
00446 NcDim::NcDim(NcFile* nc, int id)
00447         : the_file(nc), the_id(id)
00448 {
00449     char nam[MAX_NC_NAME];
00450     if (the_file && ncdiminq(the_file->id(), the_id, nam, 0) != ncBad) {
00451         the_name = new char[strlen(nam) + 1]; 
00452         strcpy(the_name, nam);
00453     } else {
00454         the_name = 0;
00455     }
00456 }
00457 
00458 NcDim::NcDim(NcFile* nc, NcToken name, long sz)
00459         : the_file(nc)
00460 {
00461     the_id = ncdimdef(the_file->id(), name, sz);
00462     if (the_id != ncBad) {
00463         the_name = new char[strlen(name) + 1];
00464         strcpy(the_name, name);
00465     } else {
00466         the_name = 0;
00467     }
00468 }
00469 
00470 NcDim::~NcDim( void )
00471 {
00472     delete [] the_name;
00473 }
00474 
00475 #define Nc_as(TYPE) name2(as_,TYPE)
00476 #define NcTypedComponent_as(TYPE)                                         \
00477 TYPE NcTypedComponent::Nc_as(TYPE)( long n ) const                        \
00478 {                                                                         \
00479   NcValues* tmp = values();                                               \
00480   TYPE rval = tmp->Nc_as(TYPE)(n);                                        \
00481   delete tmp;                                                             \
00482   return rval;                                                            \
00483 }
00484 NcTypedComponent_as(ncbyte)
00485 NcTypedComponent_as(char)
00486 NcTypedComponent_as(short)
00487 NcTypedComponent_as(int)
00488 NcTypedComponent_as(nclong)
00489 NcTypedComponent_as(long)
00490 NcTypedComponent_as(float)
00491 NcTypedComponent_as(double)
00492 
00493 char* NcTypedComponent::as_string( long n ) const
00494 {
00495     NcValues* tmp = values();
00496     char* rval = tmp->as_string(n);
00497     delete tmp;
00498     return rval;
00499 }
00500 
00501 NcTypedComponent::NcTypedComponent ( NcFile* nc )
00502         : the_file(nc)
00503 {}
00504 
00505 NcValues* NcTypedComponent::get_space( long numVals ) const
00506 {
00507     NcValues* valp;
00508     if (numVals < 1)
00509         numVals = num_vals();
00510     switch (type()) {
00511       case ncFloat:
00512         valp = new NcValues_float(numVals);
00513         break;
00514       case ncDouble:
00515         valp = new NcValues_double(numVals);
00516         break;
00517       case ncInt:
00518         valp = new NcValues_int(numVals);
00519         break;
00520       case ncShort:
00521         valp = new NcValues_short(numVals);
00522         break;
00523       case ncByte:
00524       case ncChar:
00525         valp = new NcValues_char(numVals);
00526         break;
00527       case ncNoType:
00528       default:
00529         valp = 0;
00530     }
00531     return valp;
00532 }
00533 
00534 NcVar::~NcVar( void )
00535 {
00536     delete[] the_cur;
00537     delete[] cur_rec;
00538     delete[] the_name;
00539 }
00540 
00541 NcToken NcVar::name( void ) const
00542 {
00543     return the_name;
00544 }
00545 
00546 NcType NcVar::type( void ) const
00547 {
00548     nc_type typ;
00549     ncvarinq(the_file->id(), the_id, 0, &typ, 0, 0, 0);
00550     return (NcType) typ;
00551 }
00552 
00553 NcBool NcVar::is_valid( void ) const
00554 {
00555     return the_file->is_valid() && the_id != ncBad;
00556 }
00557 
00558 int NcVar::num_dims( void ) const
00559 {
00560     int ndim;
00561     ncvarinq(the_file->id(), the_id, 0, 0, &ndim, 0, 0);
00562     return ndim;
00563 }
00564 
00565 // The i-th dimension for this variable
00566 NcDim* NcVar::get_dim( int i ) const
00567 {
00568     int ndim;
00569     int dims[MAX_NC_DIMS];
00570     if(ncvarinq(the_file->id(), the_id, 0, 0, &ndim, dims, 0) == ncBad ||
00571        i < 0 || i >= ndim)
00572       return 0;
00573     return the_file->get_dim(dims[i]);
00574 }
00575 
00576 long* NcVar::edges( void ) const        // edge lengths (dimension sizes)
00577 {
00578     long* evec = new long[num_dims()];
00579     for(int i=0; i < num_dims(); i++)
00580       evec[i] = get_dim(i)->size();
00581     return evec;
00582 }
00583 
00584 int NcVar::num_atts( void ) const // handles variable and global atts
00585 {
00586     int natt = 0;
00587     if (the_file->is_valid())
00588       if (the_id == ncGlobal)
00589         natt = the_file->num_atts();
00590       else
00591         ncvarinq(the_file->id(), the_id, 0, 0, 0, 0, &natt);
00592     return natt;
00593 }
00594 
00595 NcAtt* NcVar::get_att( NcToken aname ) const
00596 {
00597     NcAtt* att = new NcAtt(the_file, this, aname);
00598     if (! att->is_valid()) {
00599         delete att;
00600         return 0;
00601     }
00602     return att;
00603 }
00604 
00605 NcAtt* NcVar::get_att( int n ) const
00606 {
00607     if (n < 0 || n >= num_atts())
00608       return 0;
00609     NcToken aname = attname(n);
00610     NcAtt* ap = get_att(aname);
00611     delete [] (char*)aname;
00612     return ap;
00613 }
00614 
00615 long NcVar::num_vals( void ) const
00616 {
00617     long prod = 1;
00618     for (int d = 0; d < num_dims(); d++)
00619         prod *= get_dim(d)->size();
00620     return  prod;
00621 }
00622 
00623 NcValues* NcVar::values( void ) const
00624 {
00625     int ndims = num_dims();
00626     long crnr[MAX_NC_DIMS];
00627     long edgs[MAX_NC_DIMS];
00628     for (int i = 0; i < ndims; i++) {
00629         crnr[i] = 0;
00630         edgs[i] = get_dim(i)->size();
00631     }
00632     NcValues* valp = get_space();
00633     if (ncvarget(the_file->id(), the_id, crnr, edgs, valp->base()) == ncBad)
00634         return 0;
00635     return valp;
00636 }
00637 
00638 int NcVar::dim_to_index(NcDim *rdim)
00639 {
00640   for (int i=0; i < num_dims() ; i++) {
00641     if (strcmp(get_dim(i)->name(),rdim->name()) == 0) {
00642       return i;
00643     }
00644   }
00645   // we should fail and gripe about it here....
00646   return -1;
00647 }
00648 
00649 void NcVar::set_rec(NcDim *rdim, long slice)
00650 {
00651   int i = dim_to_index(rdim);
00652   // we should fail and gripe about it here....
00653   if (slice >= get_dim(i)->size() && ! get_dim(i)->is_unlimited())
00654           return;  
00655   cur_rec[i] = slice;
00656   return;
00657 } 
00658 
00659 void NcVar::set_rec(long rec)
00660 {
00661   // Since we can't ask for the record dimension here
00662   // just assume [0] is it.....
00663   set_rec(get_dim(0),rec);
00664   return;
00665 } 
00666 
00667 NcValues* NcVar::get_rec(void)
00668 {
00669     return get_rec(get_dim(0), cur_rec[0]);
00670 }
00671 
00672 NcValues* NcVar::get_rec(long rec)
00673 {
00674     return get_rec(get_dim(0), rec);
00675 }
00676 
00677 NcValues* NcVar::get_rec(NcDim* rdim, long slice)
00678 {
00679     int idx = dim_to_index(rdim);
00680     long size = num_dims();
00681     long* start = new long[size];
00682     for (int i=1; i < size ; i++) start[i] = 0;
00683     start[idx] = slice;
00684     NcBool result = set_cur(start);
00685     if (! result ) {
00686         delete [] start;
00687         return 0;
00688     }
00689 
00690     long* edge = edges();
00691     edge[idx] = 1;
00692     NcValues* valp = get_space(rec_size(rdim));
00693     if (ncvarget(the_file->id(), the_id, start, edge, valp->base()) == ncBad) {
00694         delete [] start;
00695         delete [] edge;
00696         delete valp;
00697         return 0;
00698     }
00699     delete [] start;
00700     delete [] edge;
00701     return valp;
00702 } 
00703 
00704 
00705 #define NcVar_put_rec(TYPE)                                                   \
00706 NcBool NcVar::put_rec( const TYPE* vals)                                      \
00707 {                                                                             \
00708     return put_rec(get_dim(0), vals, cur_rec[0]);                             \
00709 }                                                                             \
00710                                                                               \
00711 NcBool NcVar::put_rec( NcDim *rdim, const TYPE* vals)                         \
00712 {                                                                             \
00713     int idx = dim_to_index(rdim);                                             \
00714     return put_rec(rdim, vals, cur_rec[idx]);                                 \
00715 }                                                                             \
00716                                                                               \
00717 NcBool NcVar::put_rec( const TYPE* vals,                                      \
00718                      long rec)                                                \
00719 {                                                                             \
00720    return put_rec(get_dim(0), vals, rec);                                     \
00721 }                                                                             \
00722                                                                               \
00723 NcBool NcVar::put_rec( NcDim* rdim, const TYPE* vals,                         \
00724                      long slice)                                              \
00725 {                                                                             \
00726     int idx = dim_to_index(rdim);                                             \
00727     long size = num_dims();                                                   \
00728     long* start = new long[size];                                             \
00729     for (int i=1; i < size ; i++) start[i] = 0;                               \
00730     start[idx] = slice;                                                       \
00731     NcBool result = set_cur(start);                                           \
00732     delete [] start;                                                          \
00733     if (! result )                                                            \
00734       return FALSE;                                                           \
00735                                                                               \
00736     long* edge = edges();                                                     \
00737     edge[idx] = 1;                                                            \
00738     result = put(vals, edge);                                                 \
00739     delete [] edge;                                                           \
00740     return result;                                                            \
00741 }
00742 
00743 NcVar_put_rec(ncbyte)
00744 NcVar_put_rec(char)
00745 NcVar_put_rec(short)
00746 NcVar_put_rec(int)
00747 NcVar_put_rec(long)
00748 NcVar_put_rec(float)
00749 NcVar_put_rec(double)
00750 
00751 long NcVar::rec_size(void) {
00752     return rec_size(get_dim(0));
00753 }
00754 
00755 long NcVar::rec_size(NcDim *rdim) {
00756     int idx = dim_to_index(rdim); 
00757     long size = 1;
00758     long* edge = edges();
00759     for( int i = 0 ; i<num_dims() ; i++) {
00760         if (i != idx) {
00761           size *= edge[i];
00762         }
00763     }
00764     delete [] edge;
00765     return size;
00766 }
00767 
00768 #define NcVar_get_index(TYPE)                                                 \
00769 long NcVar::get_index(const TYPE* key)                                        \
00770 {                                                                             \
00771    return get_index(get_dim(0), key);                                         \
00772 }                                                                             \
00773                                                                               \
00774 long NcVar::get_index(NcDim *rdim, const TYPE* key)                           \
00775 {                                                                             \
00776 if (type() != NcTypeEnum(TYPE))                                               \
00777     return -1;                                                                \
00778 if (! the_file->data_mode())                                                  \
00779     return -1;                                                                \
00780 int idx = dim_to_index(rdim);                                                 \
00781 long maxrec = get_dim(idx)->size();                                           \
00782 long maxvals = rec_size(rdim);                                                \
00783 NcValues* val;                                                                \
00784 int validx;                                                                   \
00785 for (long j=0; j<maxrec; j++) {                                               \
00786     val = get_rec(rdim,j);                                                    \
00787     if (val == NULL) return -1;                                               \
00788     for (validx = 0; validx < maxvals; validx++) {                            \
00789         if (key[validx] != val->as_ ## TYPE(validx)) break;                   \
00790         }                                                                     \
00791     delete val;                                                               \
00792     if (validx == maxvals) return j;                                          \
00793     }                                                                         \
00794 return -1;                                                                    \
00795 }
00796 
00797 
00798 NcVar_get_index(ncbyte)
00799 NcVar_get_index(char)
00800 NcVar_get_index(short)
00801 NcVar_get_index(nclong)
00802 NcVar_get_index(long)
00803 NcVar_get_index(float)
00804 NcVar_get_index(double)
00805     
00806 
00807 #define NcVar_put_array(TYPE)                                                 \
00808 NcBool NcVar::put( const TYPE* vals,                                          \
00809                      long edge0,                                              \
00810                      long edge1,                                              \
00811                      long edge2,                                              \
00812                      long edge3,                                              \
00813                      long edge4)                                              \
00814 {                                                                             \
00815     if (type() != NcTypeEnum(TYPE))                                           \
00816       return FALSE;                                                           \
00817     if (! the_file->data_mode())                                              \
00818       return FALSE;                                                           \
00819     long count[5];                                                            \
00820     count[0] = edge0;                                                         \
00821     count[1] = edge1;                                                         \
00822     count[2] = edge2;                                                         \
00823     count[3] = edge3;                                                         \
00824     count[4] = edge4;                                                         \
00825     for (int i = 0; i < 5; i++) {                                             \
00826         if (count[i]) {                                                       \
00827             if (num_dims() < i)                                               \
00828               return FALSE;                                                   \
00829         } else                                                                \
00830           break;                                                              \
00831     }                                                                         \
00832     long start[5];                                                            \
00833     for (int j = 0; j < 5; j++) {                                             \
00834      start[j] = the_cur[j];                                                   \
00835     }                                                                         \
00836     return ncvarput(the_file->id(), the_id, start, count, vals) != ncBad;     \
00837 }
00838 
00839 NcVar_put_array(ncbyte)
00840 NcVar_put_array(char)
00841 NcVar_put_array(short)
00842 NcVar_put_array(int)
00843 NcVar_put_array(long)
00844 NcVar_put_array(float)
00845 NcVar_put_array(double)
00846 
00847 #define NcVar_put_nd_array(TYPE)                                              \
00848 NcBool NcVar::put( const TYPE* vals, const long* count )                      \
00849 {                                                                             \
00850     if (type() != NcTypeEnum(TYPE))                                           \
00851       return FALSE;                                                           \
00852     if (! the_file->data_mode())                                              \
00853       return FALSE;                                                           \
00854     long start[MAX_NC_DIMS];                                                  \
00855     for (int i = 0; i < num_dims(); i++)                                      \
00856       start[i] = the_cur[i];                                                  \
00857     return ncvarput(the_file->id(), the_id, start, count, vals) != ncBad;     \
00858 }
00859 
00860 NcVar_put_nd_array(ncbyte)
00861 NcVar_put_nd_array(char)
00862 NcVar_put_nd_array(short)
00863 NcVar_put_nd_array(int)
00864 NcVar_put_nd_array(long)
00865 NcVar_put_nd_array(float)
00866 NcVar_put_nd_array(double)
00867 
00868 #define NcVar_get_array(TYPE)                                                 \
00869 NcBool NcVar::get( TYPE* vals,                                                \
00870                      long edge0,                                              \
00871                      long edge1,                                              \
00872                      long edge2,                                              \
00873                      long edge3,                                              \
00874                      long edge4) const                                        \
00875 {                                                                             \
00876     if (type() != NcTypeEnum(TYPE))                                           \
00877       return FALSE;                                                           \
00878     if (! the_file->data_mode())                                              \
00879       return FALSE;                                                           \
00880     long count[5];                                                            \
00881     count[0] = edge0;                                                         \
00882     count[1] = edge1;                                                         \
00883     count[2] = edge2;                                                         \
00884     count[3] = edge3;                                                         \
00885     count[4] = edge4;                                                         \
00886     for (int i = 0; i < 5; i++) {                                             \
00887         if (count[i]) {                                                       \
00888             if (num_dims() < i)                                               \
00889               return FALSE;                                                   \
00890         } else                                                                \
00891           break;                                                              \
00892     }                                                                         \
00893     static long start[5] = {0, 0, 0, 0, 0};                                   \
00894     for (int j = 0; j < 5; j++) {                                             \
00895      start[j] = the_cur[j];                                                   \
00896     }                                                                         \
00897     return ncvarget(the_file->id(), the_id, start, count, vals) != ncBad;     \
00898 }
00899 
00900 NcVar_get_array(ncbyte)
00901 NcVar_get_array(char)
00902 NcVar_get_array(short)
00903 NcVar_get_array(int)
00904 NcVar_get_array(long)
00905 NcVar_get_array(float)
00906 NcVar_get_array(double)
00907 
00908 #define NcVar_get_nd_array(TYPE)                                              \
00909 NcBool NcVar::get( TYPE* vals, const long* count ) const                      \
00910 {                                                                             \
00911     if (type() != NcTypeEnum(TYPE))                                           \
00912       return FALSE;                                                           \
00913     if (! the_file->data_mode())                                              \
00914       return FALSE;                                                           \
00915     long start[MAX_NC_DIMS];                                                  \
00916     for (int i = 0; i < num_dims(); i++)                                      \
00917         start[i] = the_cur[i];                                                \
00918     return ncvarget(the_file->id(), the_id, start, count, vals) != ncBad;     \
00919 }
00920 
00921 NcVar_get_nd_array(ncbyte)
00922 NcVar_get_nd_array(char)
00923 NcVar_get_nd_array(short)
00924 NcVar_get_nd_array(int)
00925 NcVar_get_nd_array(long)
00926 NcVar_get_nd_array(float)
00927 NcVar_get_nd_array(double)
00928 
00929 // If no args, set cursor to all zeros.  Else set initial elements of cursor
00930 // to args provided, rest to zeros.
00931 NcBool NcVar::set_cur(long c0, long c1, long c2, long c3, long c4)
00932 {
00933     long t[6];
00934     t[0] = c0;
00935     t[1] = c1;
00936     t[2] = c2;
00937     t[3] = c3;
00938     t[4] = c4;
00939     t[5] = -1;
00940     for(int j = 0; j < 6; j++) { // find how many parameters were used
00941         int i;
00942         if (t[j] == -1) {
00943             if (num_dims() < j)
00944               return FALSE;     // too many for variable's dimensionality
00945             for (i = 0; i < j; i++) {
00946                 if (t[i] >= get_dim(i)->size() && ! get_dim(i)->is_unlimited())
00947                   return FALSE; // too big for dimension
00948                 the_cur[i] = t[i];
00949             }
00950             for(i = j; i < num_dims(); i++)
00951               the_cur[i] = 0;
00952             return TRUE;
00953         }
00954     }
00955     return TRUE;
00956 }
00957 
00958 NcBool NcVar::set_cur(long* cur)
00959 {
00960     for(int i = 0; i < num_dims(); i++) {
00961         if (cur[i] >= get_dim(i)->size() && ! get_dim(i)->is_unlimited())
00962           return FALSE;
00963         the_cur[i] = cur[i];
00964     }
00965     return TRUE;
00966 }
00967 
00968 #define NcVar_add_scalar_att(TYPE)                                            \
00969 NcBool NcVar::add_att(NcToken aname, TYPE val)                                \
00970 {                                                                             \
00971     if (! the_file->define_mode())                                            \
00972       return FALSE;                                                           \
00973     if (ncattput(the_file->id(), the_id, aname, (nc_type) NcTypeEnum(TYPE),   \
00974                  1, &val) == ncBad)                                           \
00975       return FALSE;                                                           \
00976     return TRUE;                                                              \
00977 }                                                                             \
00978 
00979 NcVar_add_scalar_att(char)
00980 NcVar_add_scalar_att(ncbyte)
00981 NcVar_add_scalar_att(short)
00982 NcVar_add_scalar_att(int)
00983 NcVar_add_scalar_att(long)
00984 NcVar_add_scalar_att(double)
00985 
00986 NcBool NcVar::add_att(NcToken aname, float val)
00987 {
00988     if (! the_file->define_mode())
00989       return FALSE;
00990     float fval = (float) val;   // workaround for bug, val passed as double??
00991     if (ncattput(the_file->id(), the_id, aname, (nc_type) ncFloat,
00992                  1, &fval) == ncBad)
00993       return FALSE;
00994     return TRUE;
00995 }
00996 
00997 NcBool NcVar::add_att(NcToken aname, const char* val)
00998 {
00999     if (! the_file->define_mode())
01000       return FALSE;
01001     if (ncattput(the_file->id(), the_id, aname, (nc_type) ncChar,
01002                  strlen(val), val) == ncBad)
01003       return FALSE;
01004     return TRUE;
01005 }
01006 
01007 #define NcVar_add_vector_att(TYPE)                                            \
01008 NcBool NcVar::add_att(NcToken aname, int len, const TYPE* vals)               \
01009 {                                                                             \
01010     if (! the_file->define_mode())                                            \
01011       return FALSE;                                                           \
01012     if (ncattput(the_file->id(), the_id, aname, (nc_type) NcTypeEnum(TYPE),   \
01013                  len, vals) == ncBad)                                         \
01014       return FALSE;                                                           \
01015     return TRUE;                                                              \
01016 }
01017 NcVar_add_vector_att(char)
01018 NcVar_add_vector_att(ncbyte)
01019 NcVar_add_vector_att(short)
01020 NcVar_add_vector_att(int)
01021 NcVar_add_vector_att(long)
01022 NcVar_add_vector_att(float)
01023 NcVar_add_vector_att(double)
01024 
01025 NcBool NcVar::rename(NcToken newname)
01026 {
01027     if (strlen(newname) > strlen(the_name)) {
01028         if (! the_file->define_mode())
01029             return FALSE;
01030     }
01031     NcBool ret = ncvarrename(the_file->id(), the_id, newname) != ncBad;
01032     if (ret) {
01033         delete [] the_name;
01034         the_name = new char [1 + strlen(newname)];
01035         strcpy(the_name, newname);
01036     }
01037     return ret;
01038 }
01039 
01040 int NcVar::id( void ) const
01041 {
01042     return the_id;
01043 }
01044 
01045 NcBool NcVar::sync(void)
01046 {
01047     if (the_name) {
01048         delete [] the_name;
01049     }
01050     if (the_cur) {
01051         delete [] the_cur;
01052     }
01053     if (cur_rec) {
01054         delete [] cur_rec;
01055     }
01056     char nam[MAX_NC_NAME];
01057     if (the_file 
01058         && ncvarinq(the_file->id(), the_id, nam, 0, 0, 0, 0) != ncBad) {
01059         the_name = new char[1 + strlen(nam)];
01060         strcpy(the_name, nam);
01061     } else {
01062         the_name = 0;
01063         return FALSE;
01064     }
01065     init_cur(); 
01066     return TRUE;
01067 }
01068 
01069 
01070 NcVar::NcVar(NcFile* nc, int id)
01071    : NcTypedComponent(nc), the_id(id)
01072 {
01073     char nam[MAX_NC_NAME];
01074     if (the_file 
01075         && ncvarinq(the_file->id(), the_id, nam, 0, 0, 0, 0) != ncBad) {
01076         the_name = new char[1 + strlen(nam)];
01077         strcpy(the_name, nam);
01078     } else {
01079         the_name = 0;
01080     }
01081     init_cur();
01082 }
01083 
01084 int NcVar::attnum( NcToken attrname ) const
01085 {
01086     int num;
01087     for(num=0; num < num_atts(); num++) {
01088         char aname[MAX_NC_NAME];
01089         ncattname(the_file->id(), the_id, num, aname);
01090         if (strcmp(aname, attrname) == 0)
01091           break;
01092     }
01093     return num;                 // num_atts() if no such attribute
01094 }
01095 
01096 NcToken NcVar::attname( int attnum ) const // caller must delete[]
01097 {
01098     if (attnum < 0 || attnum >= num_atts())
01099       return 0;
01100     char aname[MAX_NC_NAME];
01101     if (ncattname(the_file->id(), the_id, attnum, aname) == ncBad)
01102       return 0;
01103     char* rname = new char[1 + strlen(aname)];
01104     strcpy(rname, aname);
01105     return rname;
01106 }
01107 
01108 void NcVar::init_cur( void )
01109 {
01110     the_cur = new long[MAX_NC_DIMS]; // *** don't know num_dims() yet?
01111     cur_rec = new long[MAX_NC_DIMS]; // *** don't know num_dims() yet?
01112     for(int i = 0; i < MAX_NC_DIMS; i++) { 
01113         the_cur[i] = 0; cur_rec[i] = 0; }
01114 }
01115 
01116 NcAtt::NcAtt(NcFile* nc, const NcVar* var, NcToken name)
01117    : NcTypedComponent(nc), the_variable(var)
01118 {
01119     the_name = new char[1 + strlen(name)];
01120     strcpy(the_name, name);
01121 }
01122 
01123 NcAtt::NcAtt(NcFile* nc, NcToken name)
01124    : NcTypedComponent(nc), the_variable(NULL)
01125 {
01126     the_name = new char[1 + strlen(name)];
01127     strcpy(the_name, name);
01128 }
01129 
01130 NcAtt::~NcAtt( void )
01131 {
01132     delete [] the_name;
01133 }
01134 
01135 NcToken NcAtt::name( void ) const
01136 {
01137     return the_name;
01138 }
01139 
01140 NcType NcAtt::type( void ) const
01141 {
01142     nc_type typ;
01143     ncattinq(the_file->id(), the_variable->id(), the_name, &typ, 0);
01144     return (NcType) typ;
01145 }
01146 
01147 long NcAtt::num_vals( void ) const
01148 {
01149     int len;
01150     ncattinq(the_file->id(), the_variable->id(), the_name, 0, &len);
01151     return len;
01152 }
01153 
01154 NcBool NcAtt::is_valid( void ) const
01155 {
01156     return the_file->is_valid() &&
01157       (the_variable->id() == NC_GLOBAL || the_variable->is_valid()) &&
01158         ncattinq(the_file->id(), the_variable->id(), the_name, 0, 0) != ncBad;
01159 }
01160 
01161 NcValues* NcAtt::values( void ) const
01162 {
01163     NcValues* valp = get_space();
01164     if (ncattget(the_file->id(),
01165                  the_variable->id(),
01166                  the_name,
01167                  valp->base()) == ncBad) {
01168         delete valp;
01169         return 0;
01170     }
01171         
01172     return valp;
01173 }
01174 
01175 NcBool NcAtt::rename(NcToken newname)
01176 {
01177     if (strlen(newname) > strlen(the_name)) {
01178         if (! the_file->define_mode())
01179             return FALSE;
01180     }
01181     return ncattrename(the_file->id(), the_variable->id(),
01182                        the_name, newname) != ncBad;
01183 }
01184 
01185 NcBool NcAtt::remove( void )
01186 {
01187     if (! the_file->define_mode())
01188         return FALSE;
01189     return ncattdel(the_file->id(), the_variable->id(), the_name) != ncBad;
01190 }
01191 
01192 NcError::NcError( Behavior b )
01193 {
01194     the_old_state = ncopts;     // global variable in C interface
01195     the_old_err = ncerr;        // global variable in C interface
01196     ncopts = (int) b;
01197 }
01198 
01199 NcError::~NcError( void )
01200 {
01201     ncopts = the_old_state;
01202     ncerr = the_old_err;
01203 }
01204 
01205 int NcError::get_err( void )    // returns most recent error
01206 {
01207     return ncerr;
01208 }

Generated on Thu Mar 16 18:10:07 2006 for nco by  doxygen 1.4.4