1 /*********************************************************************
2  *   Copyright 1992, University Corporation for Atmospheric Research
3  *   See netcdf/README file for copying and redistribution conditions.
4  *
5  *   Purpose:   C++ class interface for netCDF
6  *
7  *   $Header: /upc/share/CVS/netcdf-3/cxx/netcdfcpp.h,v 1.15 2009/03/10 15:20:54 russ Exp $
8  *********************************************************************/
9 
10 #ifndef NETCDF_HH
11 #define NETCDF_HH
12 
13 #include "ncvalues.h"          // arrays that know their element type
14 
15 typedef const char* NcToken;    // names for netCDF objects
16 typedef unsigned int NcBool;    // many members return 0 on failure
17 
18 class MSCPP_EXTRA NcDim;        // dimensions
19 class MSCPP_EXTRA NcVar;        // variables
20 class MSCPP_EXTRA NcAtt;        // attributes
21 class MSCPP_EXTRA NcError;
22 
23 /*
24  * ***********************************************************************
25  * A netCDF file.
26  * ***********************************************************************
27  */
28 class MSCPP_EXTRA NcFile
29 {
30   public:
31 
32     virtual ~NcFile( void );
33 
34     enum FileMode {
35 	ReadOnly,	// file exists, open read-only
36 	Write,		// file exists, open for writing
37         Replace,	// create new file, even if already exists
38 	New		// create new file, fail if already exists
39       };
40 
41     enum FileFormat {
42        Classic,         // netCDF classic format (i.e. version 1 format)
43        Offset64Bits,    // netCDF 64-bit offset format
44        Netcdf4,		// netCDF-4 using HDF5 format
45        Netcdf4Classic,	// netCDF-4 using HDF5 format using only netCDF-3 calls
46        BadFormat
47     };
48 
49     NcFile( const char * path, FileMode = ReadOnly ,
50 	    size_t *bufrsizeptr = NULL,    // optional tuning parameters
51 	    size_t initialsize = 0,
52 	    FileFormat = Classic );
53 
54     NcBool is_valid( void ) const;         // opened OK in ctr, still valid
55 
56     int num_dims( void ) const;            // number of dimensions
57     int num_vars( void ) const;            // number of variables
58     int num_atts( void ) const;            // number of (global) attributes
59 
60     NcDim* get_dim( NcToken ) const;       // dimension by name
61     NcVar* get_var( NcToken ) const;       // variable by name
62     NcAtt* get_att( NcToken ) const;       // global attribute by name
63 
64     NcDim* get_dim( int ) const;           // n-th dimension
65     NcVar* get_var( int ) const;           // n-th variable
66     NcAtt* get_att( int ) const;           // n-th global attribute
67     NcDim* rec_dim( void ) const;          // unlimited dimension, if any
68 
69     // Add new dimensions, variables, global attributes.
70     // These put the file in "define" mode, so could be expensive.
71     virtual NcDim* add_dim( NcToken dimname, long dimsize );
72     virtual NcDim* add_dim( NcToken dimname );     // unlimited
73 
74     virtual NcVar* add_var( NcToken varname, NcType type,       // scalar
75                     const NcDim* dim0=0,                // 1-dim
76                     const NcDim* dim1=0,                // 2-dim
77                     const NcDim* dim2=0,                // 3-dim
78                     const NcDim* dim3=0,                // 4-dim
79                     const NcDim* dim4=0 );              // 5-dim
80     virtual NcVar* add_var( NcToken varname, NcType type,       // n-dim
81                           int ndims, const NcDim** dims );
82 
83     NcBool add_att( NcToken attname, char );             // scalar attributes
84     NcBool add_att( NcToken attname, ncbyte );
85     NcBool add_att( NcToken attname, short );
86     NcBool add_att( NcToken attname, long );
87     NcBool add_att( NcToken attname, int );
88     NcBool add_att( NcToken attname, float );
89     NcBool add_att( NcToken attname, double );
90     NcBool add_att( NcToken attname, const char*);       // string attribute
91     NcBool add_att( NcToken attname, int, const char* ); // vector attributes
92     NcBool add_att( NcToken attname, int, const ncbyte* );
93     NcBool add_att( NcToken attname, int, const short* );
94     NcBool add_att( NcToken attname, int, const long* );
95     NcBool add_att( NcToken attname, int, const int* );
96     NcBool add_att( NcToken attname, int, const float* );
97     NcBool add_att( NcToken attname, int, const double* );
98 
99     enum FillMode {
100         Fill = NC_FILL,                    // prefill (default)
101         NoFill = NC_NOFILL,                // don't prefill
102         Bad
103       };
104 
105     NcBool set_fill( FillMode = Fill );    // set fill-mode
106     FillMode get_fill( void ) const;       // get fill-mode
107     FileFormat get_format( void ) const;   // get format version
108 
109     NcBool sync( void );                   // synchronize to disk
110     NcBool close( void );                  // to close earlier than dtr
111     NcBool abort( void );                  // back out of bad defines
112 
113     // Needed by other Nc classes, but users will not need them
114     NcBool define_mode( void ); // leaves in define mode, if possible
115     NcBool data_mode( void );   // leaves in data mode, if possible
116     int id( void ) const;       // id used by C interface
117 
118   protected:
119     int the_id;
120     int in_define_mode;
121     FillMode the_fill_mode;
122     NcDim** dimensions;
123     NcVar** variables;
124     NcVar* globalv;             // "variable" for global attributes
125 };
126 
127 /*
128  * For backward compatibility.  We used to derive NcOldFile and NcNewFile
129  * from NcFile, but that was over-zealous inheritance.
130  */
131 #define NcOldFile NcFile
132 #define NcNewFile NcFile
133 #define Clobber Replace
134 #define NoClobber New
135 
136 /*
137  * **********************************************************************
138  * A netCDF dimension, with a name and a size.  These are only created
139  * by NcFile member functions, because they cannot exist independently
140  * of an open netCDF file.
141  * **********************************************************************
142  */
143 class MSCPP_EXTRA NcDim
144 {
145   public:
146     NcToken name( void ) const;
147     long size( void ) const;
148     NcBool is_valid( void ) const;
149     NcBool is_unlimited( void ) const;
150     NcBool rename( NcToken newname );
151     int id( void ) const;
152     NcBool sync( void );
153 
154   private:
155     NcFile *the_file;		// not const because of rename
156     int the_id;
157     char *the_name;
158 
159     NcDim(NcFile*, int num);	// existing dimension
160     NcDim(NcFile*, NcToken name, long sz); // defines a new dim
161     virtual ~NcDim( void );
162 
163     // to construct dimensions, since constructor is private
164     friend class NcFile;
165 };
166 
167 
168 /*
169  * **********************************************************************
170  * Abstract base class for a netCDF variable or attribute, both of which
171  * have a name, a type, and associated values.  These only exist as
172  * components of an open netCDF file.
173  * **********************************************************************
174  */
175 class MSCPP_EXTRA NcTypedComponent
176 {
177   public:
~NcTypedComponent(void)178     virtual ~NcTypedComponent( void ) {}
179     virtual NcToken name( void ) const = 0;
180     virtual NcType type( void ) const = 0;
181     virtual NcBool is_valid( void ) const = 0;
182     virtual long num_vals( void ) const = 0;
183     virtual NcBool rename( NcToken newname ) = 0;
184     virtual NcValues* values( void ) const = 0; // block of all values
185 
186     // The following member functions provide conversions from the value
187     // type to a desired basic type.  If the value is out of range,
188     // the default "fill-value" for the appropriate type is returned.
189 
190     virtual ncbyte as_ncbyte( long n ) const;    // nth value as an unsgnd char
191     virtual char as_char( long n ) const;        // nth value as char
192     virtual short as_short( long n ) const;      // nth value as short
193     virtual int as_int( long n ) const;	         // nth value as int
194     virtual int as_nclong( long n ) const;       // nth value as nclong (deprecated)
195     virtual long as_long( long n ) const;        // nth value as long
196     virtual float as_float( long n ) const;      // nth value as floating-point
197     virtual double as_double( long n ) const;    // nth value as double
198     virtual char* as_string( long n ) const;     // nth value as string
199 
200   protected:
201     NcFile *the_file;
202     NcTypedComponent( NcFile* );
203     virtual NcValues* get_space( long numVals = 0 ) const;  // to hold values
204 };
205 
206 
207 /*
208  * **********************************************************************
209  * netCDF variables.  In addition to a name and a type, these also have
210  * a shape, given by a list of dimensions
211  * **********************************************************************
212  */
213 class MSCPP_EXTRA NcVar : public NcTypedComponent
214 {
215   public:
216     virtual ~NcVar( void );
217     NcToken name( void ) const;
218     NcType type( void ) const;
219     NcBool is_valid( void ) const;
220     int num_dims( void ) const;         // dimensionality of variable
221     NcDim* get_dim( int ) const;        // n-th dimension
222     size_t* edges( void ) const;        // dimension sizes
223     int num_atts( void ) const;         // number of attributes
224     NcAtt* get_att( NcToken ) const;    // attribute by name
225     NcAtt* get_att( int ) const;        // n-th attribute
226     long num_vals( void ) const;        // product of dimension sizes
227     NcValues* values( void ) const;     // all values
228 
229     // Put scalar or 1, ..., 5 dimensional arrays by providing enough
230     // arguments.  Arguments are edge lengths, and their number must not
231     // exceed variable's dimensionality.  Start corner is [0,0,..., 0] by
232     // default, but may be reset using the set_cur() member.  FALSE is
233     // returned if type of values does not match type for variable.
234     NcBool put( const ncbyte* vals,
235                 long c0=0, long c1=0, long c2=0, long c3=0, long c4=0 );
236     NcBool put( const char* vals,
237                 long c0=0, long c1=0, long c2=0, long c3=0, long c4=0 );
238     NcBool put( const short* vals,
239                 long c0=0, long c1=0, long c2=0, long c3=0, long c4=0 );
240     NcBool put( const int* vals,
241                 long c0=0, long c1=0, long c2=0, long c3=0, long c4=0 );
242     NcBool put( const long* vals,
243                 long c0=0, long c1=0, long c2=0, long c3=0, long c4=0 );
244     NcBool put( const float* vals,
245                 long c0=0, long c1=0, long c2=0, long c3=0, long c4=0 );
246     NcBool put( const double* vals,
247                 long c0=0, long c1=0, long c2=0, long c3=0, long c4=0 );
248 
249     // Put n-dimensional arrays, starting at [0, 0, ..., 0] by default,
250     // may be reset with set_cur().
251     NcBool put( const ncbyte* vals, const size_t* counts );
252     NcBool put( const char* vals, const size_t* counts );
253     NcBool put( const short* vals, const size_t* counts );
254     NcBool put( const int* vals, const size_t* counts );
255     NcBool put( const long* vals, const size_t* counts );
256     NcBool put( const float* vals, const size_t* counts );
257     NcBool put( const double* vals, const size_t* counts );
258 
259     // Get scalar or 1, ..., 5 dimensional arrays by providing enough
260     // arguments.  Arguments are edge lengths, and their number must not
261     // exceed variable's dimensionality.  Start corner is [0,0,..., 0] by
262     // default, but may be reset using the set_cur() member.
263     NcBool get( ncbyte* vals, long c0=0, long c1=0,
264                 long c2=0, long c3=0, long c4=0 ) const;
265     NcBool get( char* vals, long c0=0, long c1=0,
266                 long c2=0, long c3=0, long c4=0 ) const;
267     NcBool get( short* vals, long c0=0, long c1=0,
268                 long c2=0, long c3=0, long c4=0 ) const;
269     NcBool get( int* vals, long c0=0, long c1=0,
270                 long c2=0, long c3=0, long c4=0 ) const;
271     NcBool get( long* vals, long c0=0, long c1=0,
272                 long c2=0, long c3=0, long c4=0 ) const;
273     NcBool get( float* vals, long c0=0, long c1=0,
274                 long c2=0, long c3=0, long c4=0 ) const;
275     NcBool get( double* vals, long c0=0, long c1=0,
276                 long c2=0, long c3=0, long c4=0 ) const;
277 
278     // Get n-dimensional arrays, starting at [0, 0, ..., 0] by default,
279     // may be reset with set_cur().
280     NcBool get( ncbyte* vals, const size_t* counts ) const;
281     NcBool get( char* vals, const size_t* counts ) const;
282     NcBool get( short* vals, const size_t* counts ) const;
283     NcBool get( int* vals, const size_t* counts ) const;
284     NcBool get( long* vals, const size_t* counts ) const;
285     NcBool get( float* vals, const size_t* counts ) const;
286     NcBool get( double* vals, const size_t* counts ) const;
287 
288     NcBool set_cur(long c0=-1, long c1=-1, long c2=-1,
289                          long c3=-1, long c4=-1);
290     NcBool set_cur(long* cur);
291 
292     // these put file in define mode, so could be expensive
293     NcBool add_att( NcToken, char );             // add scalar attributes
294     NcBool add_att( NcToken, ncbyte );
295     NcBool add_att( NcToken, short );
296     NcBool add_att( NcToken, int );
297     NcBool add_att( NcToken, long );
298     NcBool add_att( NcToken, float );
299     NcBool add_att( NcToken, double );
300     NcBool add_att( NcToken, const char* );      // string attribute
301     NcBool add_att( NcToken, int, const char* ); // vector attributes
302     NcBool add_att( NcToken, int, const ncbyte* );
303     NcBool add_att( NcToken, int, const short* );
304     NcBool add_att( NcToken, int, const int* );
305     NcBool add_att( NcToken, int, const long* );
306     NcBool add_att( NcToken, int, const float* );
307     NcBool add_att( NcToken, int, const double* );
308 
309     NcBool rename( NcToken newname );
310 
311     long rec_size ( void );             // number of values per record
312     long rec_size ( NcDim* );           // number of values per dimension slice
313 
314     // Though following are intended for record variables, they also work
315     // for other variables, using first dimension as record dimension.
316 
317     // Get a record's worth of data
318     NcValues *get_rec(void);	        // get current record
319     NcValues *get_rec(long rec);        // get specified record
320     NcValues *get_rec(NcDim* d);        // get current dimension slice
321     NcValues *get_rec(NcDim* d, long slice); // get specified dimension slice
322 
323     // Put a record's worth of data in current record
324     NcBool put_rec( const ncbyte* vals );
325     NcBool put_rec( const char* vals );
326     NcBool put_rec( const short* vals );
327     NcBool put_rec( const int* vals );
328     NcBool put_rec( const long* vals );
329     NcBool put_rec( const float* vals );
330     NcBool put_rec( const double* vals );
331 
332     // Put a dimension slice worth of data in current dimension slice
333     NcBool put_rec( NcDim* d, const ncbyte* vals );
334     NcBool put_rec( NcDim* d, const char* vals );
335     NcBool put_rec( NcDim* d, const short* vals );
336     NcBool put_rec( NcDim* d, const int* vals );
337     NcBool put_rec( NcDim* d, const long* vals );
338     NcBool put_rec( NcDim* d, const float* vals );
339     NcBool put_rec( NcDim* d, const double* vals );
340 
341     // Put a record's worth of data in specified record
342     NcBool put_rec( const ncbyte* vals, long rec );
343     NcBool put_rec( const char* vals, long rec );
344     NcBool put_rec( const short* vals, long rec );
345     NcBool put_rec( const int* vals, long rec );
346     NcBool put_rec( const long* vals, long rec );
347     NcBool put_rec( const float* vals, long rec );
348     NcBool put_rec( const double* vals, long rec );
349 
350     // Put a dimension slice worth of data in specified dimension slice
351     NcBool put_rec( NcDim* d, const ncbyte* vals, long slice );
352     NcBool put_rec( NcDim* d, const char* vals, long slice );
353     NcBool put_rec( NcDim* d, const short* vals, long slice );
354     NcBool put_rec( NcDim* d, const int* vals, long slice );
355     NcBool put_rec( NcDim* d, const long* vals, long slice );
356     NcBool put_rec( NcDim* d, const float* vals, long slice );
357     NcBool put_rec( NcDim* d, const double* vals, long slice );
358 
359     // Get first record index corresponding to specified key value(s)
360     long get_index( const ncbyte* vals );
361     long get_index( const char* vals );
362     long get_index( const short* vals );
363     long get_index( const int* vals );
364     long get_index( const long* vals );
365     long get_index( const float* vals );
366     long get_index( const double* vals );
367 
368     // Get first index of specified dimension corresponding to key values
369     long get_index( NcDim* d, const ncbyte* vals );
370     long get_index( NcDim* d, const char* vals );
371     long get_index( NcDim* d, const short* vals );
372     long get_index( NcDim* d, const int* vals );
373     long get_index( NcDim* d, const long* vals );
374     long get_index( NcDim* d, const float* vals );
375     long get_index( NcDim* d, const double* vals );
376 
377     // Set current record
378     void set_rec ( long rec );
379     // Set current dimension slice
380     void set_rec ( NcDim* d, long slice );
381 
382     int id( void ) const;               // rarely needed, C interface id
383     NcBool sync( void );
384 
385   private:
386     int dim_to_index(NcDim* rdim);
387     int the_id;
388     long* the_cur;
389     char* the_name;
390     long* cur_rec;
391 
392     // private constructors because only an NcFile creates these
393     NcVar( void );
394     NcVar(NcFile*, int);
395 
396     int attnum( NcToken attname ) const;
397     NcToken attname( int attnum ) const;
398     void init_cur( void );
399 
400     // to make variables, since constructor is private
401   friend class NcFile;
402 };
403 
404 
405 /*
406  * **********************************************************************
407  * netCDF attributes.  In addition to a name and a type, these are each
408  * associated with a specific variable, or are global to the file.
409  * **********************************************************************
410  */
411 class MSCPP_EXTRA NcAtt : public NcTypedComponent
412 {
413   public:
414     virtual ~NcAtt( void );
415     NcToken name( void ) const;
416     NcType type( void ) const;
417     NcBool is_valid( void ) const;
418     long num_vals( void ) const;
419     NcValues* values( void ) const;
420     NcBool rename( NcToken newname );
421     NcBool remove( void );
422 
423   private:
424     const NcVar* the_variable;
425     char* the_name;
426     // protected constructors because only NcVars and NcFiles create
427     // attributes
428     NcAtt( NcFile*, const NcVar*, NcToken);
429     NcAtt( NcFile*, NcToken); // global attribute
430 
431     // To make attributes, since constructor is private
432   friend class NcFile;
433   friend NcAtt* NcVar::get_att( NcToken ) const;
434 };
435 
436 
437 /*
438  * **********************************************************************
439  * To control error handling.  Declaring an NcError object temporarily
440  * changes the error-handling behavior until the object is destroyed, at
441  * which time the previous error-handling behavior is restored.
442  * **********************************************************************
443  */
444 class MSCPP_EXTRA NcError {
445   public:
446     enum Behavior {
447         silent_nonfatal = 0,
448         silent_fatal = 1,
449         verbose_nonfatal = 2,
450         verbose_fatal = 3
451       };
452 
453     // constructor saves previous error state, sets new state
454     NcError( Behavior b = verbose_fatal );
455 
456     // destructor restores previous error state
457     virtual ~NcError( void );
458 
459     int get_err( void );                 // returns most recent error number
get_errmsg(void)460     const char* get_errmsg( void ) {return nc_strerror(get_err());}
461     static int set_err( int err );
462 
463   private:
464     int the_old_state;
465     int the_old_err;
466     static int ncopts;
467     static int ncerr;
468 };
469 
470 #endif                          /* NETCDF_HH */
471