/[escript]/trunk/escript/src/netcdf.cpp
ViewVC logotype

Annotation of /trunk/escript/src/netcdf.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1128 - (hide annotations)
Tue May 8 04:22:53 2007 UTC (12 years, 3 months ago) by gross
File size: 42378 byte(s)


1 gross 1128 /*********************************************************************
2     * Copyright 1992, University Corporation for Atmospheric Research
3     * See netcdf/README file for copying and redistribution conditions.
4     *
5     * Purpose: Implements class interface for netCDF over C interface
6     *
7     * $Header: /upc/share/CVS/netcdf-3/cxx/netcdf.cpp,v 1.15 2006/12/29 16:38:46 ed Exp $
8     *********************************************************************/
9    
10     // #include <config.h>
11     #include <string.h>
12     #include <stdlib.h>
13     #include <iostream>
14     #include "netcdfcpp.h"
15    
16     #ifndef TRUE
17     #define TRUE 1
18     #define FALSE 0
19     #endif
20    
21     static const int ncGlobal = NC_GLOBAL; // psuedo-variable for global attributes
22    
23     static const int ncBad = -1; // failure return for netCDF C interface
24    
25     NcFile::~NcFile( void )
26     {
27     (void) close();
28     }
29    
30     NcBool NcFile::is_valid( void ) const
31     {
32     return the_id != ncBad;
33     }
34    
35     int NcFile::num_dims( void ) const
36     {
37     int num = 0;
38     if (is_valid())
39     NcError::set_err(
40     nc_inq_ndims(the_id, &num)
41     );
42     return num;
43     }
44    
45     int NcFile::num_vars( void ) const
46     {
47     int num = 0;
48     if (is_valid())
49     NcError::set_err(
50     nc_inq_nvars(the_id, &num)
51     );
52     return num;
53     }
54    
55     int NcFile::num_atts( void ) const
56     {
57     int num = 0;
58     if (is_valid())
59     NcError::set_err(
60     nc_inq_natts(the_id, &num)
61     );
62     return num;
63     }
64    
65     NcDim* NcFile::get_dim( NcToken name ) const
66     {
67     int dimid;
68     if(NcError::set_err(
69     nc_inq_dimid(the_id, name, &dimid)
70     ) != NC_NOERR)
71     return 0;
72     return get_dim(dimid);
73     }
74    
75     NcVar* NcFile::get_var( NcToken name ) const
76     {
77     int varid;
78     if(NcError::set_err(
79     nc_inq_varid(the_id, name, &varid)
80     ) != NC_NOERR)
81     return 0;
82     return get_var(varid);
83     }
84    
85     NcAtt* NcFile::get_att( NcToken aname ) const
86     {
87     return is_valid() ? globalv->get_att(aname) : 0;
88     }
89    
90     NcDim* NcFile::get_dim( int i ) const
91     {
92     if (! is_valid() || i < 0 || i >= num_dims())
93     return 0;
94     return dimensions[i];
95     }
96    
97     NcVar* NcFile::get_var( int i ) const
98     {
99     if (! is_valid() || i < 0 || i >= num_vars())
100     return 0;
101     return variables[i];
102     }
103    
104     NcAtt* NcFile::get_att( int n ) const
105     {
106     return is_valid() ? globalv->get_att(n) : 0;
107     }
108    
109     NcDim* NcFile::rec_dim( ) const
110     {
111     if (! is_valid())
112     return 0;
113     int recdim;
114     if(NcError::set_err(
115     nc_inq_unlimdim(the_id, &recdim)
116     ) != NC_NOERR)
117     return 0;
118     return get_dim(recdim);
119     }
120    
121     NcDim* NcFile::add_dim(NcToken name, long size)
122     {
123     if (!is_valid() || !define_mode())
124     return 0;
125     int n = num_dims();
126     NcDim* dimp = new NcDim(this, name, size);
127     dimensions[n] = dimp; // for garbage collection on close()
128     return dimp;
129     }
130    
131     NcDim* NcFile::add_dim(NcToken name)
132     {
133     return add_dim(name, NC_UNLIMITED);
134     }
135    
136     // To create scalar, 1-dimensional, ..., 5-dimensional variables, just supply
137     // as many dimension arguments as necessary
138    
139     NcVar* NcFile::add_var(NcToken name, NcType type, // scalar to 5D var
140     const NcDim* dim0,
141     const NcDim* dim1,
142     const NcDim* dim2,
143     const NcDim* dim3,
144     const NcDim* dim4)
145     {
146     if (!is_valid() || !define_mode())
147     return 0;
148     int dims[5];
149     int ndims = 0;
150     if (dim0) {
151     ndims++;
152     dims[0] = dim0->id();
153     if (dim1) {
154     ndims++;
155     dims[1] = dim1->id();
156     if (dim2) {
157     ndims++;
158     dims[2] = dim2->id();
159     if (dim3) {
160     ndims++;
161     dims[3] = dim3->id();
162     if (dim4) {
163     ndims++;
164     dims[4] = dim4->id();
165     }
166     }
167     }
168     }
169     }
170     int n = num_vars();
171     int varid;
172     if(NcError::set_err(
173     nc_def_var(the_id, name, (nc_type) type, ndims, dims, &varid)
174     ) != NC_NOERR)
175     return 0;
176     NcVar* varp =
177     new NcVar(this, varid);
178     variables[n] = varp;
179     return varp;
180     }
181    
182     // For variables with more than 5 dimensions, use n-dimensional interface
183     // with vector of dimensions.
184    
185     NcVar* NcFile::add_var(NcToken name, NcType type, int ndims, const NcDim** dims)
186     {
187     if (!is_valid() || !define_mode())
188     return 0;
189     int* dimids = new int[ndims];
190     for (int i=0; i < ndims; i++)
191     dimids[i] = dims[i]->id();
192     int n = num_vars();
193     int varid;
194     if(NcError::set_err(
195     nc_def_var(the_id, name, (nc_type) type, ndims, dimids, &varid)
196     ) != NC_NOERR)
197     return 0;
198     NcVar* varp =
199     new NcVar(this, varid);
200     variables[n] = varp;
201     delete [] dimids;
202     return varp;
203     }
204    
205     #define NcFile_add_scalar_att(TYPE) \
206     NcBool NcFile::add_att(NcToken aname, TYPE val) \
207     { \
208     return globalv->add_att(aname, val); \
209     }
210    
211     NcFile_add_scalar_att(char)
212     NcFile_add_scalar_att(ncbyte)
213     NcFile_add_scalar_att(short)
214     NcFile_add_scalar_att(int)
215     NcFile_add_scalar_att(long)
216     NcFile_add_scalar_att(float)
217     NcFile_add_scalar_att(double)
218     NcFile_add_scalar_att(const char*)
219    
220     #define NcFile_add_vector_att(TYPE) \
221     NcBool NcFile::add_att(NcToken aname, int n, const TYPE* val) \
222     { \
223     return globalv->add_att(aname, n, val); \
224     }
225    
226     NcFile_add_vector_att(char)
227     NcFile_add_vector_att(ncbyte)
228     NcFile_add_vector_att(short)
229     NcFile_add_vector_att(int)
230     NcFile_add_vector_att(long)
231     NcFile_add_vector_att(float)
232     NcFile_add_vector_att(double)
233    
234     NcBool NcFile::set_fill( FillMode a_mode )
235     {
236     int prev_mode;
237     if (NcError::set_err(
238     nc_set_fill(the_id, a_mode, &prev_mode)
239     ) == NC_NOERR) {
240     the_fill_mode = a_mode;
241     return TRUE;
242     }
243     return FALSE;
244     }
245    
246     NcFile::FillMode NcFile::get_fill( void ) const
247     {
248     return the_fill_mode;
249     }
250    
251     NcFile::FileFormat NcFile::get_format( void ) const
252     {
253     int the_format;
254     NcError::set_err(
255     nc_inq_format(the_id, &the_format)
256     );
257     switch (the_format) {
258     case NC_FORMAT_CLASSIC:
259     return Classic;
260     case NC_FORMAT_64BIT:
261     return Offset64Bits;
262     case NC_FORMAT_NETCDF4:
263     return Netcdf4;
264     case NC_FORMAT_NETCDF4_CLASSIC:
265     return Netcdf4Classic;
266     default:
267     return BadFormat;
268     }
269     }
270    
271     NcBool NcFile::sync( void )
272     {
273     if (!data_mode())
274     return 0;
275     if (NcError::set_err(
276     nc_sync(the_id)
277     ) != NC_NOERR)
278     return 0;
279     int i;
280     for (i = 0; i < num_dims(); i++) {
281     if (dimensions[i]->is_valid()) {
282     dimensions[i]->sync();
283     } else { // someone else added a new dimension
284     dimensions[i] = new NcDim(this,i);
285     }
286     }
287     for (i = 0; i < num_vars(); i++) {
288     if (variables[i]->is_valid()) {
289     variables[i]->sync();
290     } else { // someone else added a new variable
291     variables[i] = new NcVar(this,i);
292     }
293     }
294     return 1;
295     }
296    
297     NcBool NcFile::close( void )
298     {
299     int i;
300    
301     if (the_id == ncBad)
302     return 0;
303     for (i = 0; i < num_dims(); i++)
304     delete dimensions[i];
305     for (i = 0; i < num_vars(); i++)
306     delete variables[i];
307     delete [] dimensions;
308     delete [] variables;
309     delete globalv;
310     int old_id = the_id;
311     the_id = ncBad;
312     return NcError::set_err(
313     nc_close(old_id)
314     ) == NC_NOERR;
315     }
316    
317     NcBool NcFile::abort( void )
318     {
319     return NcError::set_err(
320     nc_abort(the_id)
321     ) == NC_NOERR;
322     }
323    
324     NcBool NcFile::define_mode( void )
325     {
326     if (! is_valid())
327     return FALSE;
328     if (in_define_mode)
329     return TRUE;
330     if (NcError::set_err(
331     nc_redef(the_id)
332     ) != NC_NOERR)
333     return FALSE;
334     in_define_mode = 1;
335     return TRUE;
336     }
337    
338     NcBool NcFile::data_mode( void )
339     {
340     if (! is_valid())
341     return FALSE;
342     if (! in_define_mode)
343     return TRUE;
344     if (NcError::set_err(
345     nc_enddef(the_id)
346     ) != NC_NOERR)
347     return FALSE;
348     in_define_mode = 0;
349     return TRUE;
350     }
351    
352     int NcFile::id( void ) const
353     {
354     return the_id;
355     }
356    
357     NcFile::NcFile( const char* path, FileMode fmode,
358     size_t* chunksizeptr, size_t initialsize, FileFormat fformat )
359     {
360     NcError err(NcError::silent_nonfatal); // constructor must not fail
361    
362     int mode = NC_NOWRITE;
363     the_fill_mode = Fill;
364     int status;
365    
366     // If the user wants a 64-bit offset format, set that flag.
367     if (fformat == Offset64Bits)
368     mode |= NC_64BIT_OFFSET;
369     #ifdef USE_NETCDF4
370     else if (fformat == Netcdf4)
371     mode |= NC_NETCDF4;
372     else if (fformat == Netcdf4Classic)
373     mode |= NC_NETCDF4|NC_CLASSIC_MODEL;
374     #endif
375    
376     switch (fmode) {
377     case Write:
378     mode = NC_WRITE;
379     /*FALLTHRU*/
380     case ReadOnly:
381     // use netcdf-3 interface to permit specifying tuning parameter
382     status = NcError::set_err(
383     nc__open(path, mode, chunksizeptr, &the_id)
384     );
385     if(status != NC_NOERR)
386     {
387     NcError::set_err(status);
388     the_id = -1;
389     }
390     in_define_mode = 0;
391     break;
392     case New:
393     mode = NC_NOCLOBBER;
394     /*FALLTHRU*/
395     case Replace:
396     // use netcdf-3 interface to permit specifying tuning parameters
397     status = NcError::set_err(
398     nc__create(path, mode, initialsize,
399     chunksizeptr, &the_id)
400     );
401     if(status != NC_NOERR)
402     {
403     NcError::set_err(status);
404     the_id = -1;
405     }
406     in_define_mode = 1;
407     break;
408     default:
409     the_id = ncBad;
410     in_define_mode = 0;
411     break;
412     }
413     if (is_valid()) {
414     dimensions = new NcDim*[NC_MAX_DIMS];
415     variables = new NcVar*[NC_MAX_VARS];
416     int i;
417     for (i = 0; i < num_dims(); i++)
418     dimensions[i] = new NcDim(this, i);
419     for (i = 0; i < num_vars(); i++)
420     variables[i] = new NcVar(this, i);
421     globalv = new NcVar(this, ncGlobal);
422     } else {
423     dimensions = 0;
424     variables = 0;
425     globalv = 0;
426     }
427     }
428    
429     NcToken NcDim::name( void ) const
430     {
431     return the_name;
432     }
433    
434     long NcDim::size( void ) const
435     {
436     size_t sz = 0;
437     if (the_file)
438     NcError::set_err(
439     nc_inq_dimlen(the_file->id(), the_id, &sz)
440     );
441     return sz;
442     }
443    
444     NcBool NcDim::is_valid( void ) const
445     {
446     return the_file->is_valid() && the_id != ncBad;
447     }
448    
449     NcBool NcDim::is_unlimited( void ) const
450     {
451     if (!the_file)
452     return FALSE;
453     int recdim;
454     NcError::set_err(
455     nc_inq_unlimdim(the_file->id(), &recdim)
456     );
457     return the_id == recdim;
458     }
459    
460     NcBool NcDim::rename(NcToken newname)
461     {
462     if (strlen(newname) > strlen(the_name)) {
463     if (! the_file->define_mode())
464     return FALSE;
465     }
466     NcBool ret = NcError::set_err(
467     nc_rename_dim(the_file->id(), the_id, newname)
468     ) == NC_NOERR;
469     if (ret) {
470     delete [] the_name;
471     the_name = new char[1 + strlen(newname)];
472     strcpy(the_name, newname);
473     }
474     return ret;
475     }
476    
477     int NcDim::id( void ) const
478     {
479     return the_id;
480     }
481    
482     NcBool NcDim::sync(void)
483     {
484     char nam[NC_MAX_NAME];
485     if (the_name) {
486     delete [] the_name;
487     }
488     if (the_file && NcError::set_err(
489     nc_inq_dimname(the_file->id(), the_id, nam)
490     ) == NC_NOERR) {
491     the_name = new char[strlen(nam) + 1];
492     strcpy(the_name, nam);
493     return TRUE;
494     }
495     the_name = 0;
496     return FALSE;
497     }
498    
499     NcDim::NcDim(NcFile* nc, int id)
500     : the_file(nc), the_id(id)
501     {
502     char nam[NC_MAX_NAME];
503     if (the_file && NcError::set_err(
504     nc_inq_dimname(the_file->id(), the_id, nam)
505     ) == NC_NOERR) {
506     the_name = new char[strlen(nam) + 1];
507     strcpy(the_name, nam);
508     } else {
509     the_name = 0;
510     }
511     }
512    
513     NcDim::NcDim(NcFile* nc, NcToken name, long sz)
514     : the_file(nc)
515     {
516     size_t dimlen = sz;
517     if(NcError::set_err(
518     nc_def_dim(the_file->id(), name, dimlen, &the_id)
519     ) == NC_NOERR) {
520     the_name = new char[strlen(name) + 1];
521     strcpy(the_name, name);
522     } else {
523     the_name = 0;
524     }
525     }
526    
527     NcDim::~NcDim( void )
528     {
529     delete [] the_name;
530     }
531    
532     #define Nc_as(TYPE) name2(as_,TYPE)
533     #define NcTypedComponent_as(TYPE) \
534     TYPE NcTypedComponent::Nc_as(TYPE)( long n ) const \
535     { \
536     NcValues* tmp = values(); \
537     TYPE rval = tmp->Nc_as(TYPE)(n); \
538     delete tmp; \
539     return rval; \
540     }
541     NcTypedComponent_as(ncbyte)
542     NcTypedComponent_as(char)
543     NcTypedComponent_as(short)
544     NcTypedComponent_as(int)
545     NcTypedComponent_as(nclong)
546     NcTypedComponent_as(long)
547     NcTypedComponent_as(float)
548     NcTypedComponent_as(double)
549    
550     char* NcTypedComponent::as_string( long n ) const
551     {
552     NcValues* tmp = values();
553     char* rval = tmp->as_string(n);
554     delete tmp;
555     return rval;
556     }
557    
558     NcTypedComponent::NcTypedComponent ( NcFile* nc )
559     : the_file(nc)
560     {}
561    
562     NcValues* NcTypedComponent::get_space( long numVals ) const
563     {
564     NcValues* valp;
565     if (numVals < 1)
566     numVals = num_vals();
567     switch (type()) {
568     case ncFloat:
569     valp = new NcValues_float(numVals);
570     break;
571     case ncDouble:
572     valp = new NcValues_double(numVals);
573     break;
574     case ncInt:
575     valp = new NcValues_int(numVals);
576     break;
577     case ncShort:
578     valp = new NcValues_short(numVals);
579     break;
580     case ncByte:
581     case ncChar:
582     valp = new NcValues_char(numVals);
583     break;
584     case ncNoType:
585     default:
586     valp = 0;
587     }
588     return valp;
589     }
590    
591     NcVar::~NcVar( void )
592     {
593     delete[] the_cur;
594     delete[] cur_rec;
595     delete[] the_name;
596     }
597    
598     NcToken NcVar::name( void ) const
599     {
600     return the_name;
601     }
602    
603     NcType NcVar::type( void ) const
604     {
605     nc_type typ;
606     NcError::set_err(
607     nc_inq_vartype(the_file->id(), the_id, &typ)
608     );
609     return (NcType) typ;
610     }
611    
612     NcBool NcVar::is_valid( void ) const
613     {
614     return the_file->is_valid() && the_id != ncBad;
615     }
616    
617     int NcVar::num_dims( void ) const
618     {
619     int ndim;
620     NcError::set_err(
621     nc_inq_varndims(the_file->id(), the_id, &ndim)
622     );
623     return ndim;
624     }
625    
626     // The i-th dimension for this variable
627     NcDim* NcVar::get_dim( int i ) const
628     {
629     int ndim;
630     int dims[NC_MAX_DIMS];
631     if(NcError::set_err(
632     nc_inq_var(the_file->id(), the_id, 0, 0, &ndim, dims, 0)
633     ) != NC_NOERR ||
634     i < 0 || i >= ndim)
635     return 0;
636     return the_file->get_dim(dims[i]);
637     }
638    
639     long* NcVar::edges( void ) const // edge lengths (dimension sizes)
640     {
641     long* evec = new long[num_dims()];
642     for(int i=0; i < num_dims(); i++)
643     evec[i] = get_dim(i)->size();
644     return evec;
645     }
646    
647     int NcVar::num_atts( void ) const // handles variable and global atts
648     {
649     int natt = 0;
650     if (the_file->is_valid())
651     if (the_id == ncGlobal)
652     natt = the_file->num_atts();
653     else
654     NcError::set_err(
655     nc_inq_varnatts(the_file->id(), the_id, &natt)
656     );
657     return natt;
658     }
659    
660     NcAtt* NcVar::get_att( NcToken aname ) const
661     {
662     NcAtt* att = new NcAtt(the_file, this, aname);
663     if (! att->is_valid()) {
664     delete att;
665     return 0;
666     }
667     return att;
668     }
669    
670     NcAtt* NcVar::get_att( int n ) const
671     {
672     if (n < 0 || n >= num_atts())
673     return 0;
674     NcToken aname = attname(n);
675     NcAtt* ap = get_att(aname);
676     delete [] (char*)aname;
677     return ap;
678     }
679    
680     long NcVar::num_vals( void ) const
681     {
682     long prod = 1;
683     for (int d = 0; d < num_dims(); d++)
684     prod *= get_dim(d)->size();
685     return prod;
686     }
687    
688     NcValues* NcVar::values( void ) const
689     {
690     int ndims = num_dims();
691     size_t crnr[NC_MAX_DIMS];
692     size_t edgs[NC_MAX_DIMS];
693     for (int i = 0; i < ndims; i++) {
694     crnr[i] = 0;
695     edgs[i] = get_dim(i)->size();
696     }
697     NcValues* valp = get_space();
698     int status;
699     switch (type()) {
700     case ncFloat:
701     status = NcError::set_err(
702     nc_get_vara_float(the_file->id(), the_id, crnr, edgs,
703     (float *)valp->base())
704     );
705     break;
706     case ncDouble:
707     status = NcError::set_err(
708     nc_get_vara_double(the_file->id(), the_id, crnr, edgs,
709     (double *)valp->base())
710     );
711     break;
712     case ncInt:
713     status = NcError::set_err(
714     nc_get_vara_int(the_file->id(), the_id, crnr, edgs,
715     (int *)valp->base())
716     );
717     break;
718     case ncShort:
719     status = NcError::set_err(
720     nc_get_vara_short(the_file->id(), the_id, crnr, edgs,
721     (short *)valp->base())
722     );
723     break;
724     case ncByte:
725     status = NcError::set_err(
726     nc_get_vara_schar(the_file->id(), the_id, crnr, edgs,
727     (signed char *)valp->base())
728     );
729     break;
730     case ncChar:
731     status = NcError::set_err(
732     nc_get_vara_text(the_file->id(), the_id, crnr, edgs,
733     (char *)valp->base())
734     );
735     break;
736     case ncNoType:
737     default:
738     return 0;
739     }
740     if (status != NC_NOERR)
741     return 0;
742     return valp;
743     }
744    
745     int NcVar::dim_to_index(NcDim *rdim)
746     {
747     for (int i=0; i < num_dims() ; i++) {
748     if (strcmp(get_dim(i)->name(),rdim->name()) == 0) {
749     return i;
750     }
751     }
752     // we should fail and gripe about it here....
753     return -1;
754     }
755    
756     void NcVar::set_rec(NcDim *rdim, long slice)
757     {
758     int i = dim_to_index(rdim);
759     // we should fail and gripe about it here....
760     if (slice >= get_dim(i)->size() && ! get_dim(i)->is_unlimited())
761     return;
762     cur_rec[i] = slice;
763     return;
764     }
765    
766     void NcVar::set_rec(long rec)
767     {
768     // Since we can't ask for the record dimension here
769     // just assume [0] is it.....
770     set_rec(get_dim(0),rec);
771     return;
772     }
773    
774     NcValues* NcVar::get_rec(void)
775     {
776     return get_rec(get_dim(0), cur_rec[0]);
777     }
778    
779     NcValues* NcVar::get_rec(long rec)
780     {
781     return get_rec(get_dim(0), rec);
782     }
783    
784     NcValues* NcVar::get_rec(NcDim* rdim, long slice)
785     {
786     int idx = dim_to_index(rdim);
787     long size = num_dims();
788     size_t* start = new size_t[size];
789     long* startl = new long[size];
790     for (int i=1; i < size ; i++) {
791     start[i] = 0;
792     startl[i] = 0;
793     }
794     start[idx] = slice;
795     startl[idx] = slice;
796     NcBool result = set_cur(startl);
797     if (! result ) {
798     delete [] start;
799     delete [] startl;
800     return 0;
801     }
802    
803     long* edgel = edges();
804     size_t* edge = new size_t[size];
805     for (int i=1; i < size ; i++) {
806     edge[i] = edgel[i];
807     }
808     edge[idx] = 1;
809     edgel[idx] = 1;
810     NcValues* valp = get_space(rec_size(rdim));
811     int status;
812     switch (type()) {
813     case ncFloat:
814     status = NcError::set_err(
815     nc_get_vara_float(the_file->id(), the_id, start, edge,
816     (float *)valp->base())
817     );
818     break;
819     case ncDouble:
820     status = NcError::set_err(
821     nc_get_vara_double(the_file->id(), the_id, start, edge,
822     (double *)valp->base())
823     );
824     break;
825     case ncInt:
826     status = NcError::set_err(
827     nc_get_vara_int(the_file->id(), the_id, start, edge,
828     (int *)valp->base())
829     );
830     break;
831     case ncShort:
832     status = NcError::set_err(
833     nc_get_vara_short(the_file->id(), the_id, start, edge,
834     (short *)valp->base())
835     );
836     break;
837     case ncByte:
838     status = NcError::set_err(
839     nc_get_vara_schar(the_file->id(), the_id, start, edge,
840     (signed char *)valp->base())
841     );
842     break;
843     case ncChar:
844     status = NcError::set_err(
845     nc_get_vara_text(the_file->id(), the_id, start, edge,
846     (char *)valp->base())
847     );
848     break;
849     case ncNoType:
850     default:
851     return 0;
852     }
853     delete [] start;
854     delete [] startl;
855     delete [] edge;
856     delete [] edgel;
857     if (status != NC_NOERR) {
858     delete valp;
859     return 0;
860     }
861     return valp;
862     }
863    
864    
865     #define NcVar_put_rec(TYPE) \
866     NcBool NcVar::put_rec( const TYPE* vals) \
867     { \
868     return put_rec(get_dim(0), vals, cur_rec[0]); \
869     } \
870     \
871     NcBool NcVar::put_rec( NcDim *rdim, const TYPE* vals) \
872     { \
873     int idx = dim_to_index(rdim); \
874     return put_rec(rdim, vals, cur_rec[idx]); \
875     } \
876     \
877     NcBool NcVar::put_rec( const TYPE* vals, \
878     long rec) \
879     { \
880     return put_rec(get_dim(0), vals, rec); \
881     } \
882     \
883     NcBool NcVar::put_rec( NcDim* rdim, const TYPE* vals, \
884     long slice) \
885     { \
886     int idx = dim_to_index(rdim); \
887     long size = num_dims(); \
888     long* start = new long[size]; \
889     for (int i=1; i < size ; i++) start[i] = 0; \
890     start[idx] = slice; \
891     NcBool result = set_cur(start); \
892     delete [] start; \
893     if (! result ) \
894     return FALSE; \
895     \
896     long* edge = edges(); \
897     edge[idx] = 1; \
898     result = put(vals, edge); \
899     delete [] edge; \
900     return result; \
901     }
902    
903     NcVar_put_rec(ncbyte)
904     NcVar_put_rec(char)
905     NcVar_put_rec(short)
906     NcVar_put_rec(int)
907     NcVar_put_rec(long)
908     NcVar_put_rec(float)
909     NcVar_put_rec(double)
910    
911     long NcVar::rec_size(void) {
912     return rec_size(get_dim(0));
913     }
914    
915     long NcVar::rec_size(NcDim *rdim) {
916     int idx = dim_to_index(rdim);
917     long size = 1;
918     long* edge = edges();
919     for( int i = 0 ; i<num_dims() ; i++) {
920     if (i != idx) {
921     size *= edge[i];
922     }
923     }
924     delete [] edge;
925     return size;
926     }
927    
928     #define NcVar_get_index(TYPE) \
929     long NcVar::get_index(const TYPE* key) \
930     { \
931     return get_index(get_dim(0), key); \
932     } \
933     \
934     long NcVar::get_index(NcDim *rdim, const TYPE* key) \
935     { \
936     if (type() != NcTypeEnum(TYPE)) \
937     return -1; \
938     if (! the_file->data_mode()) \
939     return -1; \
940     int idx = dim_to_index(rdim); \
941     long maxrec = get_dim(idx)->size(); \
942     long maxvals = rec_size(rdim); \
943     NcValues* val; \
944     int validx; \
945     for (long j=0; j<maxrec; j++) { \
946     val = get_rec(rdim,j); \
947     if (val == NULL) return -1; \
948     for (validx = 0; validx < maxvals; validx++) { \
949     if (key[validx] != val->as_ ## TYPE(validx)) break; \
950     } \
951     delete val; \
952     if (validx == maxvals) return j; \
953     } \
954     return -1; \
955     }
956    
957    
958     NcVar_get_index(ncbyte)
959     NcVar_get_index(char)
960     NcVar_get_index(short)
961     NcVar_get_index(nclong)
962     NcVar_get_index(long)
963     NcVar_get_index(float)
964     NcVar_get_index(double)
965    
966     // Macros below work for short, nclong, long, float, and double, but for ncbyte
967     // and char, we must use corresponding schar, uchar, or text C functions, so in
968     // these cases macros are expanded manually.
969     #define NcVar_put_array(TYPE) \
970     NcBool NcVar::put( const TYPE* vals, \
971     long edge0, \
972     long edge1, \
973     long edge2, \
974     long edge3, \
975     long edge4) \
976     { \
977     /* no need to check type() vs. TYPE, invoked C function will do that */ \
978     if (! the_file->data_mode()) \
979     return FALSE; \
980     size_t count[5]; \
981     count[0] = edge0; \
982     count[1] = edge1; \
983     count[2] = edge2; \
984     count[3] = edge3; \
985     count[4] = edge4; \
986     for (int i = 0; i < 5; i++) { \
987     if (count[i]) { \
988     if (num_dims() < i) \
989     return FALSE; \
990     } else \
991     break; \
992     } \
993     size_t start[5]; \
994     for (int j = 0; j < 5; j++) { \
995     start[j] = the_cur[j]; \
996     } \
997     return NcError::set_err( \
998     makename2(nc_put_vara_,TYPE) (the_file->id(), the_id, start, count, vals) \
999     ) == NC_NOERR; \
1000     }
1001    
1002     NcBool NcVar::put( const ncbyte* vals,
1003     long edge0,
1004     long edge1,
1005     long edge2,
1006     long edge3,
1007     long edge4)
1008     {
1009     /* no need to check type() vs. TYPE, invoked C function will do that */
1010     if (! the_file->data_mode())
1011     return FALSE;
1012     size_t count[5];
1013     count[0] = edge0;
1014     count[1] = edge1;
1015     count[2] = edge2;
1016     count[3] = edge3;
1017     count[4] = edge4;
1018     for (int i = 0; i < 5; i++) {
1019     if (count[i]) {
1020     if (num_dims() < i)
1021     return FALSE;
1022     } else
1023     break;
1024     }
1025     size_t start[5];
1026     for (int j = 0; j < 5; j++) {
1027     start[j] = the_cur[j];
1028     }
1029     return NcError::set_err(
1030     nc_put_vara_schar (the_file->id(), the_id, start, count, vals)
1031     ) == NC_NOERR;
1032     }
1033    
1034     NcBool NcVar::put( const char* vals,
1035     long edge0,
1036     long edge1,
1037     long edge2,
1038     long edge3,
1039     long edge4)
1040     {
1041     /* no need to check type() vs. TYPE, invoked C function will do that */
1042     if (! the_file->data_mode())
1043     return FALSE;
1044     size_t count[5];
1045     count[0] = edge0;
1046     count[1] = edge1;
1047     count[2] = edge2;
1048     count[3] = edge3;
1049     count[4] = edge4;
1050     for (int i = 0; i < 5; i++) {
1051     if (count[i]) {
1052     if (num_dims() < i)
1053     return FALSE;
1054     } else
1055     break;
1056     }
1057     size_t start[5];
1058     for (int j = 0; j < 5; j++) {
1059     start[j] = the_cur[j];
1060     }
1061     return NcError::set_err(
1062     nc_put_vara_text (the_file->id(), the_id, start, count, vals)
1063     ) == NC_NOERR;
1064     }
1065    
1066     NcVar_put_array(short)
1067     NcVar_put_array(int)
1068     NcVar_put_array(long)
1069     NcVar_put_array(float)
1070     NcVar_put_array(double)
1071    
1072     #define NcVar_put_nd_array(TYPE) \
1073     NcBool NcVar::put( const TYPE* vals, const long* count ) \
1074     { \
1075     /* no need to check type() vs. TYPE, invoked C function will do that */ \
1076     if (! the_file->data_mode()) \
1077     return FALSE; \
1078     size_t start[NC_MAX_DIMS]; \
1079     for (int i = 0; i < num_dims(); i++) \
1080     start[i] = the_cur[i]; \
1081     return NcError::set_err( \
1082     makename2(nc_put_vara_,TYPE) (the_file->id(), the_id, start, (const size_t *) count, vals) \
1083     ) == NC_NOERR; \
1084     }
1085    
1086     NcBool NcVar::put( const ncbyte* vals, const long* count )
1087     {
1088     /* no need to check type() vs. TYPE, invoked C function will do that */
1089     if (! the_file->data_mode())
1090     return FALSE;
1091     size_t start[NC_MAX_DIMS];
1092     for (int i = 0; i < num_dims(); i++)
1093     start[i] = the_cur[i];
1094     return NcError::set_err(
1095     nc_put_vara_schar (the_file->id(), the_id, start, (const size_t *)count, vals)
1096     ) == NC_NOERR;
1097     }
1098    
1099     NcBool NcVar::put( const char* vals, const long* count )
1100     {
1101     /* no need to check type() vs. TYPE, invoked C function will do that */
1102     if (! the_file->data_mode())
1103     return FALSE;
1104     size_t start[NC_MAX_DIMS];
1105     for (int i = 0; i < num_dims(); i++)
1106     start[i] = the_cur[i];
1107     return NcError::set_err(
1108     nc_put_vara_text (the_file->id(), the_id, start, (const size_t *)count, vals)
1109     ) == NC_NOERR;
1110     }
1111    
1112     NcVar_put_nd_array(short)
1113     NcVar_put_nd_array(int)
1114     NcVar_put_nd_array(long)
1115     NcVar_put_nd_array(float)
1116     NcVar_put_nd_array(double)
1117    
1118     #define NcVar_get_array(TYPE) \
1119     NcBool NcVar::get( TYPE* vals, \
1120     long edge0, \
1121     long edge1, \
1122     long edge2, \
1123     long edge3, \
1124     long edge4) const \
1125     { \
1126     if (! the_file->data_mode()) \
1127     return FALSE; \
1128     size_t count[5]; \
1129     count[0] = edge0; \
1130     count[1] = edge1; \
1131     count[2] = edge2; \
1132     count[3] = edge3; \
1133     count[4] = edge4; \
1134     for (int i = 0; i < 5; i++) { \
1135     if (count[i]) { \
1136     if (num_dims() < i) \
1137     return FALSE; \
1138     } else \
1139     break; \
1140     } \
1141     size_t start[5]; \
1142     for (int j = 0; j < 5; j++) { \
1143     start[j] = the_cur[j]; \
1144     } \
1145     return NcError::set_err( \
1146     makename2(nc_get_vara_,TYPE) (the_file->id(), the_id, start, count, vals) \
1147     ) == NC_NOERR; \
1148     }
1149    
1150     NcBool NcVar::get( ncbyte* vals,
1151     long edge0,
1152     long edge1,
1153     long edge2,
1154     long edge3,
1155     long edge4) const
1156     {
1157     if (! the_file->data_mode())
1158     return FALSE;
1159     size_t count[5];
1160     count[0] = edge0;
1161     count[1] = edge1;
1162     count[2] = edge2;
1163     count[3] = edge3;
1164     count[4] = edge4;
1165     for (int i = 0; i < 5; i++) {
1166     if (count[i]) {
1167     if (num_dims() < i)
1168     return FALSE;
1169     } else
1170     break;
1171     }
1172     size_t start[5];
1173     for (int j = 0; j < 5; j++) {
1174     start[j] = the_cur[j];
1175     }
1176     return NcError::set_err(
1177     nc_get_vara_schar (the_file->id(), the_id, start, count, vals)
1178     ) == NC_NOERR;
1179     }
1180    
1181     NcBool NcVar::get( char* vals,
1182     long edge0,
1183     long edge1,
1184     long edge2,
1185     long edge3,
1186     long edge4) const
1187     {
1188     if (! the_file->data_mode())
1189     return FALSE;
1190     size_t count[5];
1191     count[0] = edge0;
1192     count[1] = edge1;
1193     count[2] = edge2;
1194     count[3] = edge3;
1195     count[4] = edge4;
1196     for (int i = 0; i < 5; i++) {
1197     if (count[i]) {
1198     if (num_dims() < i)
1199     return FALSE;
1200     } else
1201     break;
1202     }
1203     size_t start[5];
1204     for (int j = 0; j < 5; j++) {
1205     start[j] = the_cur[j];
1206     }
1207     return NcError::set_err(
1208     nc_get_vara_text (the_file->id(), the_id, start, count, vals)
1209     ) == NC_NOERR;
1210     }
1211    
1212     NcVar_get_array(short)
1213     NcVar_get_array(int)
1214     NcVar_get_array(long)
1215     NcVar_get_array(float)
1216     NcVar_get_array(double)
1217    
1218     #define NcVar_get_nd_array(TYPE) \
1219     NcBool NcVar::get( TYPE* vals, const long* count ) const \
1220     { \
1221     if (! the_file->data_mode()) \
1222     return FALSE; \
1223     size_t start[NC_MAX_DIMS]; \
1224     for (int i = 0; i < num_dims(); i++) \
1225     start[i] = the_cur[i]; \
1226     return NcError::set_err( \
1227     makename2(nc_get_vara_,TYPE) (the_file->id(), the_id, start, (const size_t *) count, vals) \
1228     ) == NC_NOERR; \
1229     }
1230    
1231     NcBool NcVar::get( ncbyte* vals, const long* count ) const
1232     {
1233     if (! the_file->data_mode())
1234     return FALSE;
1235     size_t start[NC_MAX_DIMS];
1236     for (int i = 0; i < num_dims(); i++)
1237     start[i] = the_cur[i];
1238     return nc_get_vara_schar (the_file->id(), the_id, start, (const size_t *) count, vals) == NC_NOERR;
1239     }
1240    
1241     NcBool NcVar::get( char* vals, const long* count ) const
1242     {
1243     if (! the_file->data_mode())
1244     return FALSE;
1245     size_t start[NC_MAX_DIMS];
1246     for (int i = 0; i < num_dims(); i++)
1247     start[i] = the_cur[i];
1248     return nc_get_vara_text (the_file->id(), the_id, start, (const size_t*) count, vals) == NC_NOERR;
1249     }
1250    
1251     NcVar_get_nd_array(short)
1252     NcVar_get_nd_array(int)
1253     NcVar_get_nd_array(long)
1254     NcVar_get_nd_array(float)
1255     NcVar_get_nd_array(double)
1256    
1257     // If no args, set cursor to all zeros. Else set initial elements of cursor
1258     // to args provided, rest to zeros.
1259     NcBool NcVar::set_cur(long c0, long c1, long c2, long c3, long c4)
1260     {
1261     size_t t[6];
1262     t[0] = c0;
1263     t[1] = c1;
1264     t[2] = c2;
1265     t[3] = c3;
1266     t[4] = c4;
1267     t[5] = -1;
1268     for(int j = 0; j < 6; j++) { // find how many parameters were used
1269     int i;
1270     if (t[j] == -1) {
1271     if (num_dims() < j)
1272     return FALSE; // too many for variable's dimensionality
1273     for (i = 0; i < j; i++) {
1274     if (t[i] >= get_dim(i)->size() && ! get_dim(i)->is_unlimited())
1275     return FALSE; // too big for dimension
1276     the_cur[i] = t[i];
1277     }
1278     for(i = j; i < num_dims(); i++)
1279     the_cur[i] = 0;
1280     return TRUE;
1281     }
1282     }
1283     return TRUE;
1284     }
1285    
1286     NcBool NcVar::set_cur(long* cur)
1287     {
1288     for(int i = 0; i < num_dims(); i++) {
1289     if (cur[i] >= get_dim(i)->size() && ! get_dim(i)->is_unlimited())
1290     return FALSE;
1291     the_cur[i] = cur[i];
1292     }
1293     return TRUE;
1294     }
1295    
1296     #define NcVar_add_scalar_att(TYPE) \
1297     NcBool NcVar::add_att(NcToken aname, TYPE val) \
1298     { \
1299     if (! the_file->define_mode()) \
1300     return FALSE; \
1301     if (NcError::set_err( \
1302     makename2(nc_put_att_,TYPE) (the_file->id(), the_id, aname, (nc_type) NcTypeEnum(TYPE), \
1303     1, &val) \
1304     ) != NC_NOERR) \
1305     return FALSE; \
1306     return TRUE; \
1307     }
1308    
1309     NcBool NcVar::add_att(NcToken aname, ncbyte val)
1310     {
1311     if (! the_file->define_mode())
1312     return FALSE;
1313     if (nc_put_att_schar (the_file->id(), the_id, aname, (nc_type) NcTypeEnum(ncbyte),
1314     1, &val) != NC_NOERR)
1315     return FALSE;
1316     return TRUE;
1317     }
1318    
1319     NcBool NcVar::add_att(NcToken aname, char val)
1320     {
1321     if (! the_file->define_mode())
1322     return FALSE;
1323     if (nc_put_att_text (the_file->id(), the_id, aname,
1324     1, &val) != NC_NOERR)
1325     return FALSE;
1326     return TRUE;
1327     }
1328    
1329     NcVar_add_scalar_att(short)
1330     NcVar_add_scalar_att(int)
1331     NcVar_add_scalar_att(long)
1332     NcVar_add_scalar_att(double)
1333    
1334     NcBool NcVar::add_att(NcToken aname, float val)
1335     {
1336     if (! the_file->define_mode())
1337     return FALSE;
1338     float fval = (float) val; // workaround for bug, val passed as double??
1339     if (nc_put_att_float(the_file->id(), the_id, aname, (nc_type) ncFloat,
1340     1, &fval) != NC_NOERR)
1341     return FALSE;
1342     return TRUE;
1343     }
1344    
1345     NcBool NcVar::add_att(NcToken aname, const char* val)
1346     {
1347     if (! the_file->define_mode())
1348     return FALSE;
1349     if (nc_put_att_text(the_file->id(), the_id, aname,
1350     strlen(val), val) != NC_NOERR)
1351     return FALSE;
1352     return TRUE;
1353     }
1354    
1355     #define NcVar_add_vector_att(TYPE) \
1356     NcBool NcVar::add_att(NcToken aname, int len, const TYPE* vals) \
1357     { \
1358     if (! the_file->define_mode()) \
1359     return FALSE; \
1360     if (NcError::set_err( \
1361     makename2(nc_put_att_,TYPE) (the_file->id(), the_id, aname, (nc_type) NcTypeEnum(TYPE), \
1362     len, vals) \
1363     ) != NC_NOERR) \
1364     return FALSE; \
1365     return TRUE; \
1366     }
1367    
1368     NcBool NcVar::add_att(NcToken aname, int len, const ncbyte* vals)
1369     {
1370     if (! the_file->define_mode())
1371     return FALSE;
1372     if (NcError::set_err(
1373     nc_put_att_schar (the_file->id(), the_id, aname, (nc_type) NcTypeEnum(ncbyte),
1374     len, vals)
1375     ) != NC_NOERR)
1376     return FALSE;
1377     return TRUE;
1378     }
1379    
1380     NcBool NcVar::add_att(NcToken aname, int len, const char* vals)
1381     {
1382     if (! the_file->define_mode())
1383     return FALSE;
1384     if (NcError::set_err(
1385     nc_put_att_text (the_file->id(), the_id, aname,
1386     len, vals)
1387     ) != NC_NOERR)
1388     return FALSE;
1389     return TRUE;
1390     }
1391    
1392     NcVar_add_vector_att(short)
1393     NcVar_add_vector_att(int)
1394     NcVar_add_vector_att(long)
1395     NcVar_add_vector_att(float)
1396     NcVar_add_vector_att(double)
1397    
1398     NcBool NcVar::rename(NcToken newname)
1399     {
1400     if (strlen(newname) > strlen(the_name)) {
1401     if (! the_file->define_mode())
1402     return FALSE;
1403     }
1404     NcBool ret = NcError::set_err(
1405     nc_rename_var(the_file->id(), the_id, newname)
1406     ) == NC_NOERR;
1407     if (ret) {
1408     delete [] the_name;
1409     the_name = new char [1 + strlen(newname)];
1410     strcpy(the_name, newname);
1411     }
1412     return ret;
1413     }
1414    
1415     int NcVar::id( void ) const
1416     {
1417     return the_id;
1418     }
1419    
1420     NcBool NcVar::sync(void)
1421     {
1422     if (the_name) {
1423     delete [] the_name;
1424     }
1425     if (the_cur) {
1426     delete [] the_cur;
1427     }
1428     if (cur_rec) {
1429     delete [] cur_rec;
1430     }
1431     char nam[NC_MAX_NAME];
1432     if (the_file
1433     && NcError::set_err(
1434     nc_inq_varname(the_file->id(), the_id, nam)
1435     ) == NC_NOERR) {
1436     the_name = new char[1 + strlen(nam)];
1437     strcpy(the_name, nam);
1438     } else {
1439     the_name = 0;
1440     return FALSE;
1441     }
1442     init_cur();
1443     return TRUE;
1444     }
1445    
1446    
1447     NcVar::NcVar(NcFile* nc, int id)
1448     : NcTypedComponent(nc), the_id(id)
1449     {
1450     char nam[NC_MAX_NAME];
1451     if (the_file
1452     && NcError::set_err(
1453     nc_inq_varname(the_file->id(), the_id, nam)
1454     ) == NC_NOERR) {
1455     the_name = new char[1 + strlen(nam)];
1456     strcpy(the_name, nam);
1457     } else {
1458     the_name = 0;
1459     }
1460     init_cur();
1461     }
1462    
1463     int NcVar::attnum( NcToken attrname ) const
1464     {
1465     int num;
1466     for(num=0; num < num_atts(); num++) {
1467     char aname[NC_MAX_NAME];
1468     NcError::set_err(
1469     nc_inq_attname(the_file->id(), the_id, num, aname)
1470     );
1471     if (strcmp(aname, attrname) == 0)
1472     break;
1473     }
1474     return num; // num_atts() if no such attribute
1475     }
1476    
1477     NcToken NcVar::attname( int attnum ) const // caller must delete[]
1478     {
1479     if (attnum < 0 || attnum >= num_atts())
1480     return 0;
1481     char aname[NC_MAX_NAME];
1482     if (NcError::set_err(
1483     nc_inq_attname(the_file->id(), the_id, attnum, aname)
1484     ) != NC_NOERR)
1485     return 0;
1486     char* rname = new char[1 + strlen(aname)];
1487     strcpy(rname, aname);
1488     return rname;
1489     }
1490    
1491     void NcVar::init_cur( void )
1492     {
1493     the_cur = new long[NC_MAX_DIMS]; // *** don't know num_dims() yet?
1494     cur_rec = new long[NC_MAX_DIMS]; // *** don't know num_dims() yet?
1495     for(int i = 0; i < NC_MAX_DIMS; i++) {
1496     the_cur[i] = 0; cur_rec[i] = 0; }
1497     }
1498    
1499     NcAtt::NcAtt(NcFile* nc, const NcVar* var, NcToken name)
1500     : NcTypedComponent(nc), the_variable(var)
1501     {
1502     the_name = new char[1 + strlen(name)];
1503     strcpy(the_name, name);
1504     }
1505    
1506     NcAtt::NcAtt(NcFile* nc, NcToken name)
1507     : NcTypedComponent(nc), the_variable(NULL)
1508     {
1509     the_name = new char[1 + strlen(name)];
1510     strcpy(the_name, name);
1511     }
1512    
1513     NcAtt::~NcAtt( void )
1514     {
1515     delete [] the_name;
1516     }
1517    
1518     NcToken NcAtt::name( void ) const
1519     {
1520     return the_name;
1521     }
1522    
1523     NcType NcAtt::type( void ) const
1524     {
1525     nc_type typ;
1526     NcError::set_err(
1527     nc_inq_atttype(the_file->id(), the_variable->id(), the_name, &typ)
1528     );
1529     return (NcType) typ;
1530     }
1531    
1532     long NcAtt::num_vals( void ) const
1533     {
1534     size_t len;
1535     NcError::set_err(
1536     nc_inq_attlen(the_file->id(), the_variable->id(), the_name, &len)
1537     );
1538     return len;
1539     }
1540    
1541     NcBool NcAtt::is_valid( void ) const
1542     {
1543     int num;
1544     return the_file->is_valid() &&
1545     (the_variable->id() == NC_GLOBAL || the_variable->is_valid()) &&
1546     NcError::set_err(
1547     nc_inq_attid(the_file->id(), the_variable->id(), the_name, &num)
1548     ) == NC_NOERR;
1549     }
1550    
1551     NcValues* NcAtt::values( void ) const
1552     {
1553     NcValues* valp = get_space();
1554     int status;
1555     switch (type()) {
1556     case ncFloat:
1557     status = NcError::set_err(
1558     nc_get_att_float(the_file->id(), the_variable->id(), the_name,
1559     (float *)valp->base())
1560     );
1561     break;
1562     case ncDouble:
1563     status = NcError::set_err(
1564     nc_get_att_double(the_file->id(), the_variable->id(), the_name,
1565     (double *)valp->base())
1566     );
1567     break;
1568     case ncInt:
1569     status = NcError::set_err(
1570     nc_get_att_int(the_file->id(), the_variable->id(), the_name,
1571     (int *)valp->base())
1572     );
1573     break;
1574     case ncShort:
1575     status = NcError::set_err(
1576     nc_get_att_short(the_file->id(), the_variable->id(), the_name,
1577     (short *)valp->base())
1578     );
1579     break;
1580     case ncByte:
1581     status = NcError::set_err(
1582     nc_get_att_schar(the_file->id(), the_variable->id(), the_name,
1583     (signed char *)valp->base())
1584     );
1585     break;
1586     case ncChar:
1587     status = NcError::set_err(
1588     nc_get_att_text(the_file->id(), the_variable->id(), the_name,
1589     (char *)valp->base())
1590     );
1591     break;
1592     case ncNoType:
1593     default:
1594     return 0;
1595     }
1596     if (status != NC_NOERR) {
1597     delete valp;
1598     return 0;
1599     }
1600     return valp;
1601     }
1602    
1603     NcBool NcAtt::rename(NcToken newname)
1604     {
1605     if (strlen(newname) > strlen(the_name)) {
1606     if (! the_file->define_mode())
1607     return FALSE;
1608     }
1609     return NcError::set_err(
1610     nc_rename_att(the_file->id(), the_variable->id(),
1611     the_name, newname)
1612     ) == NC_NOERR;
1613     }
1614    
1615     NcBool NcAtt::remove( void )
1616     {
1617     if (! the_file->define_mode())
1618     return FALSE;
1619     return NcError::set_err(
1620     nc_del_att(the_file->id(), the_variable->id(), the_name)
1621     ) == NC_NOERR;
1622     }
1623    
1624     NcError::NcError( Behavior b )
1625     {
1626     the_old_state = ncopts; // global variable in version 2 C interface
1627     the_old_err = ncerr; // global variable in version 2 C interface
1628     ncopts = (int) b;
1629     }
1630    
1631     NcError::~NcError( void )
1632     {
1633     ncopts = the_old_state;
1634     ncerr = the_old_err;
1635     }
1636    
1637     int NcError::get_err( void ) // returns most recent error
1638     {
1639     return ncerr;
1640     }
1641    
1642     int NcError::set_err (int err)
1643     {
1644     ncerr = err;
1645     // Check ncopts and handle appropriately
1646     if(err != NC_NOERR) {
1647     if(ncopts == verbose_nonfatal || ncopts == verbose_fatal) {
1648     std::cout << nc_strerror(err) << std::endl;
1649     }
1650     if(ncopts == silent_fatal || ncopts == verbose_fatal) {
1651     exit(ncopts);
1652     }
1653     }
1654     return err;
1655     }
1656    
1657     int NcError::ncerr = NC_NOERR;
1658     int NcError::ncopts = NcError::verbose_fatal ; // for backward compatibility

  ViewVC Help
Powered by ViewVC 1.1.26