00001
00002
00003
00004
00005
00006
00007
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;
00021
00022 static const int ncBad = -1;
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;
00112 return dimp;
00113 }
00114
00115 NcDim* NcFile::add_dim(NcToken name)
00116 {
00117 return add_dim(name, NC_UNLIMITED);
00118 }
00119
00120
00121
00122
00123 NcVar* NcFile::add_var(NcToken name, NcType type,
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
00162
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 {
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 {
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);
00320
00321 int mode = NC_NOWRITE;
00322 the_fill_mode = Fill;
00323 int status;
00324
00325
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
00339 case ReadOnly:
00340
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
00352 case Replace:
00353
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
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
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
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
00646 return -1;
00647 }
00648
00649 void NcVar::set_rec(NcDim *rdim, long slice)
00650 {
00651 int i = dim_to_index(rdim);
00652
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
00662
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
00930
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++) {
00941 int i;
00942 if (t[j] == -1) {
00943 if (num_dims() < j)
00944 return FALSE;
00945 for (i = 0; i < j; i++) {
00946 if (t[i] >= get_dim(i)->size() && ! get_dim(i)->is_unlimited())
00947 return FALSE;
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;
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;
01094 }
01095
01096 NcToken NcVar::attname( int attnum ) const
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];
01111 cur_rec = new long[MAX_NC_DIMS];
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;
01195 the_old_err = ncerr;
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 )
01206 {
01207 return ncerr;
01208 }